]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.c
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / test / misc / tst-fnmatch.c
1 /* Tests for fnmatch function.
2    Copyright (C) 2000, 2001 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <error.h>
22 #include <fnmatch.h>
23 #include <locale.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <sys/types.h>
29
30
31 static char *next_input (char **line, int first, int last);
32 static int convert_flags (const char *str);
33 static char *flag_output (int flags);
34 static char *escape (const char *str, size_t *reslenp, char **resbuf);
35
36
37 int str_isalpha(const char *str)
38 {
39         size_t i = strlen(str);
40         while (i--)
41                 if (isascii(str[i]) == 0)
42                         return 0;
43         return 1;
44 }
45 int str_has_funk(const char *str, const char x)
46 {
47         size_t i, max = strlen(str);
48         for (i=0; i+1<max; ++i)
49                 if (str[i] == '[' && str[i+1] == x)
50                         return 1;
51         return 0;
52 }
53
54
55 int
56 main (void)
57 {
58   char *linebuf = NULL;
59   size_t linebuflen = 0;
60   int ntests = 0;
61   int nfailed = 0;
62   int nskipped = 0;
63   char *escinput = NULL;
64   size_t escinputlen = 0;
65   char *escpattern = NULL;
66   size_t escpatternlen = 0;
67   int nr = 0;
68
69   /* Read lines from stdin with the following format:
70
71        locale  input-string  match-string  flags  result
72
73      where `result' is either 0 or 1.  If the first character of a
74      string is '"' we read until the next '"' and handled escaped '"'.  */
75   while (! feof (stdin))
76     {
77       ssize_t n = getline (&linebuf, &linebuflen, stdin);
78       char *cp;
79       const char *locale;
80       const char *input;
81       const char *pattern;
82       const char *result_str;
83       int result;
84       const char *flags;
85       int flags_val;
86       int fnmres;
87       char numbuf[24];
88
89       if (n == -1)
90         break;
91
92       if (n == 0)
93         /* Maybe an empty line.  */
94         continue;
95
96       /* Skip over all leading white spaces.  */
97       cp = linebuf;
98
99       locale = next_input (&cp, 1, 0);
100       if (locale == NULL)
101         continue;
102
103       input = next_input (&cp, 0, 0);
104       if (input == NULL)
105         continue;
106
107       pattern = next_input (&cp, 0, 0);
108       if (pattern == NULL)
109         continue;
110
111       result_str = next_input (&cp, 0, 0);
112       if (result_str == NULL)
113         continue;
114
115       if (strcmp (result_str, "0") == 0)
116         result = 0;
117       else if  (strcasecmp (result_str, "NOMATCH") == 0)
118         result = FNM_NOMATCH;
119       else
120         {
121           char *endp;
122           result = strtol (result_str, &endp, 0);
123           if (*endp != '\0')
124             continue;
125         }
126
127       flags = next_input (&cp, 0, 1);
128       if (flags == NULL)
129         /* We allow the flags missing.  */
130         flags = "";
131
132       /* Convert the text describing the flags in a numeric value.  */
133       flags_val = convert_flags (flags);
134       if (flags_val == -1)
135         /* Something went wrong.  */
136         continue;
137
138       /* Now run the actual test.  */
139       ++ntests;
140
141 #ifdef __UCLIBC_HAS_XLOCALE__
142       if (setlocale (LC_COLLATE, locale) == NULL
143           || setlocale (LC_CTYPE, locale) == NULL)
144         {
145           puts ("*** Cannot set locale");
146           ++nfailed;
147           continue;
148         }
149 #else
150       /* skip non-ascii strings */
151       if (!str_isalpha(pattern) || !str_isalpha(input))
152         {
153           ++nskipped;
154           printf("%3d: fnmatch (\"%s\", \"%s\"): SKIP multibyte test (requires locale support)\n", ++nr, pattern, input);
155           continue;
156         }
157       /* skip collating symbols */
158       if (str_has_funk(pattern, '.') || str_has_funk(input, '.'))
159         {
160           ++nskipped;
161           printf("%3d: fnmatch (\"%s\", \"%s\"): SKIP collating symbol test (requires locale support)\n", ++nr, pattern, input);
162           continue;
163         }
164       /* skip equivalence class expressions */
165       if (str_has_funk(pattern, '=') || str_has_funk(input, '='))
166         {
167           ++nskipped;
168           printf("%3d: fnmatch (\"%s\", \"%s\"): SKIP equivalence class test (requires locale support)\n", ++nr, pattern, input);
169           continue;
170         }
171 #endif
172
173       fnmres = fnmatch (pattern, input, flags_val);
174
175       printf ("%3d: fnmatch (\"%s\", \"%s\", %s) = %s%c",
176               ++nr,
177               escape (pattern, &escpatternlen, &escpattern),
178               escape (input, &escinputlen, &escinput),
179               flag_output (flags_val),
180               (fnmres == 0
181                ? "0" : (fnmres == FNM_NOMATCH
182                         ? "FNM_NOMATCH"
183                         : (sprintf (numbuf, "%d", fnmres), numbuf))),
184               (fnmres != 0) != (result != 0) ? ' ' : '\n');
185
186       if ((fnmres != 0) != (result != 0))
187         {
188           printf ("(FAIL, expected %s) ***\n",
189                   result == 0
190                   ? "0" : (result == FNM_NOMATCH
191                            ? "FNM_NOMATCH"
192                            : (sprintf (numbuf, "%d", result), numbuf)));
193           ++nfailed;
194         }
195     }
196
197   printf ("=====================\n%3d tests, %3d failed, %3d skipped\n", ntests, nfailed, nskipped);
198
199   free (escpattern);
200   free (escinput);
201   free (linebuf);
202
203   return nfailed != 0;
204 }
205
206
207 static char *
208 next_input (char **line, int first, int last)
209 {
210   char *cp = *line;
211   char *result;
212
213   while (*cp == ' ' || *cp == '\t')
214     ++cp;
215
216   /* We allow comment lines starting with '#'.  */
217   if (first && *cp == '#')
218     return NULL;
219
220   if (*cp == '"')
221     {
222       char *wp;
223
224       result = ++cp;
225       wp = cp;
226
227       while (*cp != '"' && *cp != '\0' && *cp != '\n')
228         if (*cp == '\\')
229           {
230             if (cp[1] == '\n' || cp[1] == '\0')
231               return NULL;
232
233             ++cp;
234             if (*cp == 't')
235               *wp++ = '\t';
236             else if (*cp == 'n')
237               *wp++ = '\n';
238             else
239               *wp++ = *cp;
240
241             ++cp;
242           }
243         else
244           *wp++ = *cp++;
245
246       if (*cp != '"')
247         return NULL;
248
249       if (wp != cp)
250         *wp = '\0';
251     }
252   else
253     {
254       result = cp;
255       while (*cp != '\0' && *cp != '\n' && *cp != ' ' && *cp != '\t')
256         ++cp;
257
258       if (cp == result && ! last)
259         /* Premature end of line.  */
260         return NULL;
261     }
262
263   /* Terminate and skip over the next white spaces.  */
264   *cp++ = '\0';
265
266   *line = cp;
267   return result;
268 }
269
270
271 static int
272 convert_flags (const char *str)
273 {
274   int result = 0;
275
276   while (*str != '\0')
277     {
278       int len;
279
280       if (strncasecmp (str, "PATHNAME", 8) == 0
281           && (str[8] == '|' || str[8] == '\0'))
282         {
283           result |= FNM_PATHNAME;
284           len = 8;
285         }
286       else if (strncasecmp (str, "NOESCAPE", 8) == 0
287                && (str[8] == '|' || str[8] == '\0'))
288         {
289           result |= FNM_NOESCAPE;
290           len = 8;
291         }
292       else if (strncasecmp (str, "PERIOD", 6) == 0
293                && (str[6] == '|' || str[6] == '\0'))
294         {
295           result |= FNM_PERIOD;
296           len = 6;
297         }
298 #ifdef FNM_LEADING_DIR
299       else if (strncasecmp (str, "LEADING_DIR", 11) == 0
300                && (str[11] == '|' || str[11] == '\0'))
301         {
302           result |= FNM_LEADING_DIR;
303           len = 11;
304         }
305 #endif
306 #ifdef FNM_CASEFOLD
307       else if (strncasecmp (str, "CASEFOLD", 8) == 0
308                && (str[8] == '|' || str[8] == '\0'))
309         {
310           result |= FNM_CASEFOLD;
311           len = 8;
312         }
313 #endif
314 #ifdef FNM_EXTMATCH
315       else if (strncasecmp (str, "EXTMATCH", 8) == 0
316                && (str[8] == '|' || str[8] == '\0'))
317         {
318           result |= FNM_EXTMATCH;
319           len = 8;
320         }
321 #endif
322       else
323         return -1;
324
325       str += len;
326       if (*str != '\0')
327         ++str;
328     }
329
330   return result;
331 }
332
333
334 static char *
335 flag_output (int flags)
336 {
337   static char buf[100];
338   int first = 1;
339   char *cp = buf;
340
341   if (flags & FNM_PATHNAME)
342     {
343       cp = stpcpy (cp, "FNM_PATHNAME");
344       first = 0;
345     }
346   if (flags & FNM_NOESCAPE)
347     {
348       if (! first)
349         *cp++ = '|';
350       cp = stpcpy (cp, "FNM_NOESCAPE");
351       first = 0;
352     }
353   if (flags & FNM_PERIOD)
354     {
355       if (! first)
356         *cp++ = '|';
357       cp = stpcpy (cp, "FNM_PERIOD");
358       first = 0;
359     }
360 #ifdef FNM_LEADING_DIR
361   if (flags & FNM_LEADING_DIR)
362     {
363       if (! first)
364         *cp++ = '|';
365       cp = stpcpy (cp, "FNM_LEADING_DIR");
366       first = 0;
367     }
368 #endif
369 #ifdef FNM_CASEFOLD
370   if (flags & FNM_CASEFOLD)
371     {
372       if (! first)
373         *cp++ = '|';
374       cp = stpcpy (cp, "FNM_CASEFOLD");
375       first = 0;
376     }
377 #endif
378 #ifdef FNM_EXTMATCH
379   if (flags & FNM_EXTMATCH)
380     {
381       if (! first)
382         *cp++ = '|';
383       cp = stpcpy (cp, "FNM_EXTMATCH");
384       first = 0;
385     }
386 #endif
387   if (cp == buf)
388     *cp++ = '0';
389   *cp = '\0';
390
391   return buf;
392 }
393
394
395 static char *
396 escape (const char *str, size_t *reslenp, char **resbufp)
397 {
398   size_t reslen = *reslenp;
399   char *resbuf = *resbufp;
400   size_t len = strlen (str);
401   char *wp;
402
403   if (2 * len + 1 > reslen)
404     {
405       resbuf = (char *) realloc (resbuf, 2 * len + 1);
406       if (resbuf == NULL)
407         error (EXIT_FAILURE, errno, "while allocating buffer for printing");
408       *reslenp = 2 * len + 1;
409       *resbufp = resbuf;
410     }
411
412   wp = resbuf;
413   while (*str != '\0')
414     if (*str == '\t')
415       {
416         *wp++ = '\\';
417         *wp++ = 't';
418         ++str;
419       }
420     else if (*str == '\n')
421       {
422         *wp++ = '\\';
423         *wp++ = 'n';
424         ++str;
425       }
426     else if (*str == '"')
427       {
428         *wp++ = '\\';
429         *wp++ = '"';
430         ++str;
431       }
432     else if (*str == '\\')
433       {
434         *wp++ = '\\';
435         *wp++ = '\\';
436         ++str;
437       }
438     else
439       *wp++ = *str++;
440
441   *wp = '\0';
442
443   return resbuf;
444 }