source: branches/libc-0.6/src/libctests/glibc/posix/tst-fnmatch.c

Last change on this file was 2135, checked in by bird, 20 years ago

libc adjustments / config.

  • Property cvs2svn:cvs-rev set to 1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
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 <sys/types.h>
28
29
30static char *next_input (char **line, int first, int last);
31static int convert_flags (const char *str);
32static char *flag_output (int flags);
33static char *escape (const char *str, size_t *reslenp, char **resbuf);
34
35
36int
37main (void)
38{
39 char *linebuf = NULL;
40 size_t linebuflen = 0;
41 int ntests = 0;
42 int nfailed = 0;
43 char *escinput = NULL;
44 size_t escinputlen = 0;
45 char *escpattern = NULL;
46 size_t escpatternlen = 0;
47 int nr = 0;
48
49 /* Read lines from stdin with the following format:
50
51 locale input-string match-string flags result
52
53 where `result' is either 0 or 1. If the first character of a
54 string is '"' we read until the next '"' and handled escaped '"'. */
55 while (! feof (stdin))
56 {
57 ssize_t n = getline (&linebuf, &linebuflen, stdin);
58 char *cp;
59 const char *locale;
60 const char *input;
61 const char *pattern;
62 const char *result_str;
63 int result;
64 const char *flags;
65 int flags_val;
66 int fnmres;
67 char numbuf[24];
68
69 if (n == -1)
70 break;
71
72 if (n == 0)
73 /* Maybe an empty line. */
74 continue;
75
76 /* Skip over all leading white spaces. */
77 cp = linebuf;
78
79 locale = next_input (&cp, 1, 0);
80 if (locale == NULL)
81 continue;
82
83 input = next_input (&cp, 0, 0);
84 if (input == NULL)
85 continue;
86
87 pattern = next_input (&cp, 0, 0);
88 if (pattern == NULL)
89 continue;
90
91 result_str = next_input (&cp, 0, 0);
92 if (result_str == NULL)
93 continue;
94
95 if (strcmp (result_str, "0") == 0)
96 result = 0;
97 else if (strcasecmp (result_str, "NOMATCH") == 0)
98 result = FNM_NOMATCH;
99 else
100 {
101 char *endp;
102 result = strtol (result_str, &endp, 0);
103 if (*endp != '\0')
104 continue;
105 }
106
107 flags = next_input (&cp, 0, 1);
108 if (flags == NULL)
109 /* We allow the flags missing. */
110 flags = "";
111
112 /* Convert the text describing the flags in a numeric value. */
113 flags_val = convert_flags (flags);
114 if (flags_val == -1)
115 /* Something went wrong. */
116 continue;
117
118 /* Now run the actual test. */
119 ++ntests;
120
121 if (setlocale (LC_COLLATE, locale) == NULL
122 || setlocale (LC_CTYPE, locale) == NULL)
123 {
124 puts ("*** Cannot set locale");
125 ++nfailed;
126 continue;
127 }
128
129 fnmres = fnmatch (pattern, input, flags_val);
130
131 printf ("%3d: fnmatch (\"%s\", \"%s\", %s) = %s%c",
132 ++nr,
133 escape (pattern, &escpatternlen, &escpattern),
134 escape (input, &escinputlen, &escinput),
135 flag_output (flags_val),
136 (fnmres == 0
137 ? "0" : (fnmres == FNM_NOMATCH
138 ? "FNM_NOMATCH"
139 : (sprintf (numbuf, "%d", fnmres), numbuf))),
140 (fnmres != 0) != (result != 0) ? ' ' : '\n');
141
142 if ((fnmres != 0) != (result != 0))
143 {
144 printf ("(FAIL, expected %s) ***\n",
145 result == 0
146 ? "0" : (result == FNM_NOMATCH
147 ? "FNM_NOMATCH"
148 : (sprintf (numbuf, "%d", result), numbuf)));
149 ++nfailed;
150 }
151 }
152
153 printf ("=====================\n%3d tests, %3d failed\n", ntests, nfailed);
154
155 free (escpattern);
156 free (escinput);
157 free (linebuf);
158
159 return nfailed != 0;
160}
161
162
163static char *
164next_input (char **line, int first, int last)
165{
166 char *cp = *line;
167 char *result;
168
169 while (*cp == ' ' || *cp == '\t')
170 ++cp;
171
172 /* We allow comment lines starting with '#'. */
173 if (first && *cp == '#')
174 return NULL;
175
176 if (*cp == '"')
177 {
178 char *wp;
179
180 result = ++cp;
181 wp = cp;
182
183 while (*cp != '"' && *cp != '\0' && *cp != '\n')
184 if (*cp == '\\')
185 {
186 if (cp[1] == '\n' || cp[1] == '\0')
187 return NULL;
188
189 ++cp;
190 if (*cp == 't')
191 *wp++ = '\t';
192 else if (*cp == 'n')
193 *wp++ = '\n';
194 else
195 *wp++ = *cp;
196
197 ++cp;
198 }
199 else
200 *wp++ = *cp++;
201
202 if (*cp != '"')
203 return NULL;
204
205 if (wp != cp)
206 *wp = '\0';
207 }
208 else
209 {
210 result = cp;
211 while (*cp != '\0' && *cp != '\n' && *cp != ' ' && *cp != '\t')
212 ++cp;
213
214 if (cp == result && ! last)
215 /* Premature end of line. */
216 return NULL;
217 }
218
219 /* Terminate and skip over the next white spaces. */
220 *cp++ = '\0';
221
222 *line = cp;
223 return result;
224}
225
226
227static int
228convert_flags (const char *str)
229{
230 int result = 0;
231
232 while (*str != '\0')
233 {
234 int len;
235
236 if (strncasecmp (str, "PATHNAME", 8) == 0
237 && (str[8] == '|' || str[8] == '\0'))
238 {
239 result |= FNM_PATHNAME;
240 len = 8;
241 }
242 else if (strncasecmp (str, "NOESCAPE", 8) == 0
243 && (str[8] == '|' || str[8] == '\0'))
244 {
245 result |= FNM_NOESCAPE;
246 len = 8;
247 }
248 else if (strncasecmp (str, "PERIOD", 6) == 0
249 && (str[6] == '|' || str[6] == '\0'))
250 {
251 result |= FNM_PERIOD;
252 len = 6;
253 }
254 else if (strncasecmp (str, "LEADING_DIR", 11) == 0
255 && (str[11] == '|' || str[11] == '\0'))
256 {
257 result |= FNM_LEADING_DIR;
258 len = 11;
259 }
260 else if (strncasecmp (str, "CASEFOLD", 8) == 0
261 && (str[8] == '|' || str[8] == '\0'))
262 {
263 result |= FNM_CASEFOLD;
264 len = 8;
265 }
266#ifdef FNM_EXTMATCH
267 else if (strncasecmp (str, "EXTMATCH", 8) == 0
268 && (str[8] == '|' || str[8] == '\0'))
269 {
270 result |= FNM_EXTMATCH;
271 len = 8;
272 }
273#else
274#warning "FNM_EXTMATCH isn't defined!"
275#endif
276 else
277 return -1;
278
279 str += len;
280 if (*str != '\0')
281 ++str;
282 }
283
284 return result;
285}
286
287
288static char *
289flag_output (int flags)
290{
291 static char buf[100];
292 int first = 1;
293 char *cp = buf;
294
295 if (flags & FNM_PATHNAME)
296 {
297 cp = stpcpy (cp, "FNM_PATHNAME");
298 first = 0;
299 }
300 if (flags & FNM_NOESCAPE)
301 {
302 if (! first)
303 *cp++ = '|';
304 cp = stpcpy (cp, "FNM_NOESCAPE");
305 first = 0;
306 }
307 if (flags & FNM_PERIOD)
308 {
309 if (! first)
310 *cp++ = '|';
311 cp = stpcpy (cp, "FNM_PERIOD");
312 first = 0;
313 }
314 if (flags & FNM_LEADING_DIR)
315 {
316 if (! first)
317 *cp++ = '|';
318 cp = stpcpy (cp, "FNM_LEADING_DIR");
319 first = 0;
320 }
321 if (flags & FNM_CASEFOLD)
322 {
323 if (! first)
324 *cp++ = '|';
325 cp = stpcpy (cp, "FNM_CASEFOLD");
326 first = 0;
327 }
328#ifdef FNM_EXTMATCH
329 if (flags & FNM_EXTMATCH)
330 {
331 if (! first)
332 *cp++ = '|';
333 cp = stpcpy (cp, "FNM_EXTMATCH");
334 first = 0;
335 }
336#else
337#warning "FNM_EXTMATCH isn't defined!"
338#endif
339 if (cp == buf)
340 *cp++ = '0';
341 *cp = '\0';
342
343 return buf;
344}
345
346
347static char *
348escape (const char *str, size_t *reslenp, char **resbufp)
349{
350 size_t reslen = *reslenp;
351 char *resbuf = *resbufp;
352 size_t len = strlen (str);
353 char *wp;
354
355 if (2 * len + 1 > reslen)
356 {
357 resbuf = (char *) realloc (resbuf, 2 * len + 1);
358 if (resbuf == NULL)
359 error (EXIT_FAILURE, errno, "while allocating buffer for printing");
360 *reslenp = 2 * len + 1;
361 *resbufp = resbuf;
362 }
363
364 wp = resbuf;
365 while (*str != '\0')
366 if (*str == '\t')
367 {
368 *wp++ = '\\';
369 *wp++ = 't';
370 ++str;
371 }
372 else if (*str == '\n')
373 {
374 *wp++ = '\\';
375 *wp++ = 'n';
376 ++str;
377 }
378 else if (*str == '"')
379 {
380 *wp++ = '\\';
381 *wp++ = '"';
382 ++str;
383 }
384 else if (*str == '\\')
385 {
386 *wp++ = '\\';
387 *wp++ = '\\';
388 ++str;
389 }
390 else
391 *wp++ = *str++;
392
393 *wp = '\0';
394
395 return resbuf;
396}
Note: See TracBrowser for help on using the repository browser.