1 /* Regular expression tests.
2    Copyright (C) 2003-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <sys/types.h>
20 #include <mcheck.h>
21 #include <regex.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 void
frob_escapes(char * src,int pattern)27 frob_escapes (char *src, int pattern)
28 {
29   char *dst;
30 
31   for (dst = src; *src != '\0'; dst++, src++)
32     {
33       if (*src == '\\')
34 	{
35 	  switch (src[1])
36 	    {
37 	    case 't':
38 	      src++;
39 	      *dst = '\t';
40 	      continue;
41 	    case 'n':
42 	      src++;
43 	      *dst = '\n';
44 	      continue;
45 	    case 'r':
46 	      src++;
47 	      *dst = '\r';
48 	      continue;
49 	    case '\\':
50 	    case '^':
51 	    case '{':
52 	    case '|':
53 	    case '}':
54 	      if (!pattern)
55 		{
56 		  src++;
57 		  *dst = *src;
58 		  continue;
59 		}
60 	      break;
61 	    }
62 	}
63       if (src != dst)
64 	*dst = *src;
65     }
66   *dst = '\0';
67 }
68 
69 int
main(int argc,char ** argv)70 main (int argc, char **argv)
71 {
72   int ret = 0, n;
73   char *line = NULL;
74   size_t line_len = 0;
75   ssize_t len;
76   FILE *f;
77   char *pattern, *string;
78   int flags = REG_EXTENDED;
79   int eflags = 0;
80   regex_t re;
81   regmatch_t rm[20];
82 
83   mtrace ();
84 
85   if (argc < 2)
86     {
87       fprintf (stderr, "Missing test filename\n");
88       return 1;
89     }
90 
91   f = fopen (argv[1], "r");
92   if (f == NULL)
93     {
94       fprintf (stderr, "Couldn't open %s\n", argv[1]);
95       return 1;
96     }
97 
98   while ((len = getline (&line, &line_len, f)) > 0)
99     {
100       char *p, *q;
101       int i;
102 
103       if (line[len - 1] == '\n')
104 	line[--len] = '\0';
105 
106       puts (line);
107 
108       if (line[0] == ';')
109 	continue;
110 
111       if (line[0] == '\0')
112 	continue;
113 
114       if (line[0] == '-')
115 	{
116 	  if (strstr (line, "REG_BASIC"))
117 	    flags = 0;
118 	  else
119 	    flags = REG_EXTENDED;
120 	  if (strstr (line, "REG_ICASE"))
121 	    flags |= REG_ICASE;
122 	  if (strstr (line, "REG_NEWLINE"))
123 	    flags |= REG_NEWLINE;
124 	  eflags = 0;
125 	  if (strstr (line, "REG_NOTBOL"))
126 	    eflags |= REG_NOTBOL;
127 	  if (strstr (line, "REG_NOTEOL"))
128 	    eflags |= REG_NOTEOL;
129 	  continue;
130 	}
131 
132       pattern = line + strspn (line, " \t");
133       if (*pattern == '\0')
134 	continue;
135       p = pattern + strcspn (pattern, " \t");
136       if (*p == '\0')
137 	continue;
138       *p++ = '\0';
139 
140       string = p + strspn (p, " \t");
141       if (*string == '\0')
142 	continue;
143       if (*string == '"')
144 	{
145 	  string++;
146 	  p = strchr (string, '"');
147 	  if (p == NULL)
148 	    continue;
149 	  *p++ = '\0';
150 	}
151       else
152 	{
153 	  p = string + strcspn (string, " \t");
154 	  if (*string == '!')
155 	    string = NULL;
156 	  else if (*p == '\0')
157 	    continue;
158 	  else
159 	    *p++ = '\0';
160 	}
161 
162       frob_escapes (pattern, 1);
163       if (string != NULL)
164 	frob_escapes (string, 0);
165 
166       n = regcomp (&re, pattern, flags);
167       if (n != 0)
168 	{
169 	  if (string != NULL)
170 	    {
171 	      char buf[500];
172 	      regerror (n, &re, buf, sizeof (buf));
173 	      printf ("FAIL regcomp unexpectedly failed: %s\n",
174 		      buf);
175 	      ret = 1;
176 	    }
177 	  continue;
178 	}
179       else if (string == NULL)
180 	{
181 	  regfree (&re);
182 	  puts ("FAIL regcomp unpexpectedly succeeded");
183 	  ret = 1;
184 	  continue;
185 	}
186 
187       if (regexec (&re, string, 20, rm, eflags))
188 	{
189 	  for (i = 0; i < 20; ++i)
190 	    {
191 	      rm[i].rm_so = -1;
192 	      rm[i].rm_eo = -1;
193 	    }
194 	}
195 
196       regfree (&re);
197 
198       for (i = 0; i < 20 && *p != '\0'; ++i)
199 	{
200 	  int rm_so, rm_eo;
201 
202 	  rm_so = strtol (p, &q, 10);
203 	  if (p == q)
204 	    break;
205 	  p = q;
206 
207 	  rm_eo = strtol (p, &q, 10);
208 	  if (p == q)
209 	    break;
210 	  p = q;
211 
212 	  if (rm[i].rm_so != rm_so || rm[i].rm_eo != rm_eo)
213 	    {
214 	      printf ("FAIL rm[%d] %d..%d != expected %d..%d\n",
215 		      i, rm[i].rm_so, rm[i].rm_eo, rm_so, rm_eo);
216 	      ret = 1;
217 	      break;
218 	    }
219 	}
220     }
221 
222   free (line);
223   fclose (f);
224   return ret;
225 }
226