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 |
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 |
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 (lineptr: &line, n: &line_len, stream: f)) > 0) |
99 | { |
100 | char *p, *q; |
101 | int i; |
102 | |
103 | if (line[len - 1] == '\n') |
104 | line[--len] = '\0'; |
105 | |
106 | puts (s: 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 (src: pattern, pattern: 1); |
163 | if (string != NULL) |
164 | frob_escapes (src: string, pattern: 0); |
165 | |
166 | n = regcomp (preg: &re, pattern: pattern, cflags: flags); |
167 | if (n != 0) |
168 | { |
169 | if (string != NULL) |
170 | { |
171 | char buf[500]; |
172 | regerror (errcode: n, preg: &re, errbuf: buf, errbuf_size: sizeof (buf)); |
173 | printf (format: "FAIL regcomp unexpectedly failed: %s\n" , |
174 | buf); |
175 | ret = 1; |
176 | } |
177 | continue; |
178 | } |
179 | else if (string == NULL) |
180 | { |
181 | regfree (preg: &re); |
182 | puts (s: "FAIL regcomp unpexpectedly succeeded" ); |
183 | ret = 1; |
184 | continue; |
185 | } |
186 | |
187 | if (regexec (preg: &re, String: string, nmatch: 20, pmatch: rm, eflags: 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 (preg: &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 (format: "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 (ptr: line); |
223 | fclose (f); |
224 | return ret; |
225 | } |
226 | |