VirtualBox

source: kBuild/vendor/sed/current/testsuite/tst-rxspencer.c

Last change on this file was 599, checked in by bird, 18 years ago

GNU sed 4.1.5.

File size: 12.4 KB
Line 
1/* Regular expression tests.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA. */
20
21#include "config.h"
22
23#include <sys/types.h>
24#ifdef HAVE_MCHECK_H
25#include <mcheck.h>
26#endif
27#include <regex.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <locale.h>
32#include <getopt.h>
33
34static void
35replace_special_chars (char *str)
36{
37 for (; (str = strpbrk (str, "NTSZ")) != NULL; ++str)
38 switch (*str)
39 {
40 case 'N': *str = '\n'; break;
41 case 'T': *str = '\t'; break;
42 case 'S': *str = ' '; break;
43 case 'Z': *str = '\0'; break;
44 }
45}
46
47static void
48glibc_re_syntax (char *str)
49{
50 char *p, *end = strchr (str, '\0') + 1;
51
52 /* Replace [[:<:]] with \< and [[:>:]] with \>. */
53 for (p = str; (p = strstr (p, "[[:")) != NULL; )
54 if ((p[3] == '<' || p[3] == '>') && strncmp (p + 4, ":]]", 3) == 0)
55 {
56 p[0] = '\\';
57 p[1] = p[3];
58 memmove (p + 2, p + 7, end - p - 7);
59 end -= 5;
60 p += 2;
61 }
62 else
63 p += 3;
64}
65
66static char *
67mb_replace (char *dst, const char c)
68{
69 switch (c)
70 {
71 /* Replace a with \'a and A with \'A. */
72 case 'a':
73 *dst++ = '\xc3';
74 *dst++ = '\xa1';
75 break;
76 case 'A':
77 *dst++ = '\xc3';
78 *dst++ = '\x81';
79 break;
80 /* Replace b with \v{c} and B with \v{C}. */
81 case 'b':
82 *dst++ = '\xc4';
83 *dst++ = '\x8d';
84 break;
85 case 'B':
86 *dst++ = '\xc4';
87 *dst++ = '\x8c';
88 break;
89 /* Replace c with \v{d} and C with \v{D}. */
90 case 'c':
91 *dst++ = '\xc4';
92 *dst++ = '\x8f';
93 break;
94 case 'C':
95 *dst++ = '\xc4';
96 *dst++ = '\x8e';
97 break;
98 /* Replace d with \'e and D with \'E. */
99 case 'd':
100 *dst++ = '\xc3';
101 *dst++ = '\xa9';
102 break;
103 case 'D':
104 *dst++ = '\xc3';
105 *dst++ = '\x89';
106 break;
107 }
108 return dst;
109}
110
111static char *
112mb_frob_string (const char *str, const char *letters)
113{
114 char *ret, *dst;
115 const char *src;
116
117 if (str == NULL)
118 return NULL;
119
120 ret = malloc (2 * strlen (str) + 1);
121 if (ret == NULL)
122 return NULL;
123
124 for (src = str, dst = ret; *src; ++src)
125 if (strchr (letters, *src))
126 dst = mb_replace (dst, *src);
127 else
128 *dst++ = *src;
129 *dst = '\0';
130 return ret;
131}
132
133/* Like mb_frob_string, but don't replace anything between
134 [: and :], [. and .] or [= and =]. */
135
136static char *
137mb_frob_pattern (const char *str, const char *letters)
138{
139 char *ret, *dst;
140 const char *src;
141 int in_class = 0;
142
143 if (str == NULL)
144 return NULL;
145
146 ret = malloc (2 * strlen (str) + 1);
147 if (ret == NULL)
148 return NULL;
149
150 for (src = str, dst = ret; *src; ++src)
151 if (!in_class && strchr (letters, *src))
152 dst = mb_replace (dst, *src);
153 else
154 {
155 if (!in_class && *src == '[' && strchr (":.=", src[1]))
156 in_class = 1;
157 else if (in_class && *src == ']' && strchr (":.=", src[-1]))
158 in_class = 0;
159 *dst++ = *src;
160 }
161 *dst = '\0';
162 return ret;
163}
164
165static int
166check_match (regmatch_t *rm, int idx, const char *string,
167 const char *match, const char *fail)
168{
169 if (match[0] == '-' && match[1] == '\0')
170 {
171 if (rm[idx].rm_so == -1 && rm[idx].rm_eo == -1)
172 return 0;
173 printf ("%s rm[%d] unexpectedly matched\n", fail, idx);
174 return 1;
175 }
176
177 if (rm[idx].rm_so == -1 || rm[idx].rm_eo == -1)
178 {
179 printf ("%s rm[%d] unexpectedly did not match\n", fail, idx);
180 return 1;
181 }
182
183 if (match[0] == '@')
184 {
185 if (rm[idx].rm_so != rm[idx].rm_eo)
186 {
187 printf ("%s rm[%d] not empty\n", fail, idx);
188 return 1;
189 }
190
191 if (strncmp (string + rm[idx].rm_so, match + 1, strlen (match + 1)
192 ? strlen (match + 1) : 1))
193 {
194 printf ("%s rm[%d] not matching %s\n", fail, idx, match);
195 return 1;
196 }
197 return 0;
198 }
199
200 if (rm[idx].rm_eo - rm[idx].rm_so != strlen (match)
201 || strncmp (string + rm[idx].rm_so, match,
202 rm[idx].rm_eo - rm[idx].rm_so))
203 {
204 printf ("%s rm[%d] not matching %s\n", fail, idx, match);
205 return 1;
206 }
207
208 return 0;
209}
210
211static int
212test (const char *pattern, int cflags, const char *string, int eflags,
213 char *expect, char *matches, const char *fail)
214{
215 regex_t re;
216 regmatch_t rm[10];
217 int n, ret = 0;
218
219 n = regcomp (&re, pattern, cflags);
220 if (n != 0)
221 {
222 char buf[500];
223 if (eflags == -1)
224 {
225 static struct { reg_errcode_t code; const char *name; } codes []
226#define C(x) { REG_##x, #x }
227 = { C(NOERROR), C(NOMATCH), C(BADPAT), C(ECOLLATE),
228 C(ECTYPE), C(EESCAPE), C(ESUBREG), C(EBRACK),
229 C(EPAREN), C(EBRACE), C(BADBR), C(ERANGE),
230 C(ESPACE), C(BADRPT) };
231
232 int i;
233 for (i = 0; i < sizeof (codes) / sizeof (codes[0]); ++i)
234 if (n == codes[i].code)
235 {
236 if (strcmp (string, codes[i].name))
237 {
238 printf ("%s regcomp returned REG_%s (expected REG_%s)\n",
239 fail, codes[i].name, string);
240 return 1;
241 }
242 return 0;
243 }
244
245 printf ("%s regcomp return value REG_%d\n", fail, n);
246 return 1;
247 }
248
249 regerror (n, &re, buf, sizeof (buf));
250 printf ("%s regcomp failed: %s\n", fail, buf);
251 return 1;
252 }
253
254 if (eflags == -1)
255 {
256 regfree (&re);
257
258 /* The test case file assumes something only guaranteed by the
259 rxspencer regex implementation. Namely that for empty
260 expressions regcomp() return REG_EMPTY. This is not the case
261 for us and so we ignore this error. */
262 if (strcmp (string, "EMPTY") == 0)
263 return 0;
264
265 printf ("%s regcomp unexpectedly succeeded\n", fail);
266 return 1;
267 }
268
269 if (regexec (&re, string, 10, rm, eflags))
270 {
271 regfree (&re);
272 if (expect == NULL)
273 return 0;
274 printf ("%s regexec failed\n", fail);
275 return 1;
276 }
277
278 regfree (&re);
279
280 if (expect == NULL)
281 {
282 printf ("%s regexec unexpectedly succeeded\n", fail);
283 return 1;
284 }
285
286 if (cflags & REG_NOSUB)
287 return 0;
288
289 ret = check_match (rm, 0, string, expect, fail);
290 if (matches == NULL)
291 return ret;
292
293 for (n = 1; ret == 0 && n < 10; ++n)
294 {
295 char *p = NULL;
296
297 if (matches)
298 {
299 p = strchr (matches, ',');
300 if (p != NULL)
301 *p = '\0';
302 }
303 ret = check_match (rm, n, string, matches ? matches : "-", fail);
304 if (p)
305 {
306 *p = ',';
307 matches = p + 1;
308 }
309 else
310 matches = NULL;
311 }
312
313 return ret;
314}
315
316static int
317mb_test (const char *pattern, int cflags, const char *string, int eflags,
318 char *expect, const char *matches, const char *letters,
319 const char *fail)
320{
321 char *pattern_mb = mb_frob_pattern (pattern, letters);
322 const char *string_mb
323 = eflags == -1 ? string : mb_frob_string (string, letters);
324 char *expect_mb = mb_frob_string (expect, letters);
325 char *matches_mb = mb_frob_string (matches, letters);
326 int ret = 0;
327
328 if (!pattern_mb || !string_mb
329 || (expect && !expect_mb) || (matches && !matches_mb))
330 {
331 printf ("%s %m", fail);
332 ret = 1;
333 }
334 else
335 ret = test (pattern_mb, cflags, string_mb, eflags, expect_mb,
336 matches_mb, fail);
337
338 free (matches_mb);
339 free (expect_mb);
340 if (string_mb != string)
341 free ((char *) string_mb);
342 free (pattern_mb);
343 return ret;
344}
345
346static int
347mb_tests (const char *pattern, int cflags, const char *string, int eflags,
348 char *expect, const char *matches)
349{
350 int ret = 0;
351 int i;
352 char letters[9], fail[20];
353
354 /* The tests aren't supposed to work with xdigit, since a-dA-D are
355 hex digits while \'a \'A \v{c}\v{C}\v{d}\v{D}\'e \'E are not. */
356 if (strstr (pattern, "[:xdigit:]"))
357 return 0;
358
359 /* XXX: regex ATM handles only single byte equivalence classes. */
360 if (strstr (pattern, "[[=b=]]"))
361 return 0;
362
363 for (i = 1; i < 16; ++i)
364 {
365 char *p = letters;
366 if (i & 1)
367 {
368 if (!strchr (pattern, 'a') && !strchr (string, 'a')
369 && !strchr (pattern, 'A') && !strchr (string, 'A'))
370 continue;
371 *p++ = 'a', *p++ = 'A';
372 }
373 if (i & 2)
374 {
375 if (!strchr (pattern, 'b') && !strchr (string, 'b')
376 && !strchr (pattern, 'B') && !strchr (string, 'B'))
377 continue;
378 *p++ = 'b', *p++ = 'B';
379 }
380 if (i & 4)
381 {
382 if (!strchr (pattern, 'c') && !strchr (string, 'c')
383 && !strchr (pattern, 'C') && !strchr (string, 'C'))
384 continue;
385 *p++ = 'c', *p++ = 'C';
386 }
387 if (i & 8)
388 {
389 if (!strchr (pattern, 'd') && !strchr (string, 'd')
390 && !strchr (pattern, 'D') && !strchr (string, 'D'))
391 continue;
392 *p++ = 'd', *p++ = 'D';
393 }
394 *p++ = '\0';
395 sprintf (fail, "UTF-8 %s FAIL", letters);
396 ret |= mb_test (pattern, cflags, string, eflags, expect, matches,
397 letters, fail);
398 }
399 return ret;
400}
401
402int
403main (int argc, char **argv)
404{
405 int ret = 0;
406 char *line = NULL;
407 size_t line_len = 0;
408 ssize_t len;
409 FILE *f;
410 static int test_utf8 = 0;
411 static const struct option options[] =
412 {
413 {"utf8", no_argument, &test_utf8, 1},
414 {NULL, 0, NULL, 0 }
415 };
416
417#ifdef HAVE_MCHECK_H
418 mtrace ();
419#endif
420
421 while (getopt_long (argc, argv, "", options, NULL) >= 0);
422
423 if (optind + 1 != argc)
424 {
425 fprintf (stderr, "Missing test filename\n");
426 return 1;
427 }
428
429 f = fopen (argv[optind], "r");
430 if (f == NULL)
431 {
432 fprintf (stderr, "Couldn't open %s\n", argv[optind]);
433 return 1;
434 }
435
436 while ((len = getline (&line, &line_len, f)) > 0)
437 {
438 char *pattern, *flagstr, *string, *expect, *matches, *p;
439 int cflags = REG_EXTENDED, eflags = 0, try_bre_ere = 0;
440
441 if (line[len - 1] == '\n')
442 line[len - 1] = '\0';
443
444 /* Skip comments and empty lines. */
445 if (*line == '#' || *line == '\0')
446 continue;
447
448 puts (line);
449 fflush (stdout);
450
451 pattern = strtok (line, "\t");
452 if (pattern == NULL)
453 continue;
454
455 if (strcmp (pattern, "\"\"") == 0)
456 pattern += 2;
457
458 flagstr = strtok (NULL, "\t");
459 if (flagstr == NULL)
460 continue;
461
462 string = strtok (NULL, "\t");
463 if (string == NULL)
464 continue;
465
466 if (strcmp (string, "\"\"") == 0)
467 string += 2;
468
469 for (p = flagstr; *p; ++p)
470 switch (*p)
471 {
472 case '-':
473 break;
474 case 'b':
475 cflags &= ~REG_EXTENDED;
476 break;
477 case '&':
478 try_bre_ere = 1;
479 break;
480 case 'C':
481 eflags = -1;
482 break;
483 case 'i':
484 cflags |= REG_ICASE;
485 break;
486 case 's':
487 cflags |= REG_NOSUB;
488 break;
489 case 'n':
490 cflags |= REG_NEWLINE;
491 break;
492 case '^':
493 eflags |= REG_NOTBOL;
494 break;
495 case '$':
496 eflags |= REG_NOTEOL;
497 break;
498 case 'm':
499 case 'p':
500 case '#':
501 /* Not supported. */
502 flagstr = NULL;
503 break;
504 }
505
506 if (flagstr == NULL)
507 continue;
508
509 replace_special_chars (pattern);
510 glibc_re_syntax (pattern);
511 if (eflags != -1)
512 replace_special_chars (string);
513
514 expect = strtok (NULL, "\t");
515 matches = NULL;
516 if (expect != NULL)
517 {
518 replace_special_chars (expect);
519 matches = strtok (NULL, "\t");
520 if (matches != NULL)
521 replace_special_chars (matches);
522 }
523
524 if (setlocale (LC_ALL, "C") == NULL)
525 {
526 puts ("setlocale C failed");
527 ret = 1;
528 }
529 if (test (pattern, cflags, string, eflags, expect, matches, "FAIL")
530 || (try_bre_ere
531 && test (pattern, cflags & ~REG_EXTENDED, string, eflags,
532 expect, matches, "FAIL")))
533 ret = 1;
534 else if (test_utf8)
535 {
536 if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
537 {
538 puts ("setlocale cs_CZ.UTF-8 failed");
539 ret = 1;
540 }
541 else if (test (pattern, cflags, string, eflags, expect, matches,
542 "UTF-8 FAIL")
543 || (try_bre_ere
544 && test (pattern, cflags & ~REG_EXTENDED, string,
545 eflags, expect, matches, "UTF-8 FAIL")))
546 ret = 1;
547 else if (mb_tests (pattern, cflags, string, eflags, expect, matches)
548 || (try_bre_ere
549 && mb_tests (pattern, cflags & ~REG_EXTENDED, string,
550 eflags, expect, matches)))
551 ret = 1;
552 }
553 }
554
555 free (line);
556 fclose (f);
557 return ret;
558}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette