1 /* Tests for fnmatch function.
2 Copyright (C) 2000-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
26 #include <sys/types.h>
30 static char *next_input (char **line, int first, int last);
31 static int convert_flags (const char *str);
32 static char *flag_output (int flags);
33 static char *escape (const char *str, size_t *reslenp, char **resbuf);
40 size_t linebuflen = 0;
43 char *escinput = NULL;
44 size_t escinputlen = 0;
45 char *escpattern = NULL;
46 size_t escpatternlen = 0;
51 /* Read lines from stdin with the following format:
53 locale input-string match-string flags result
55 where `result' is either 0 or 1. If the first character of a
56 string is '"' we read until the next '"' and handled escaped '"'. */
57 while (! feof (stdin))
59 ssize_t n = getline (&linebuf, &linebuflen, stdin);
64 const char *result_str;
75 /* Maybe an empty line. */
78 /* Skip over all leading white spaces. */
81 locale = next_input (&cp, 1, 0);
85 input = next_input (&cp, 0, 0);
89 pattern = next_input (&cp, 0, 0);
93 result_str = next_input (&cp, 0, 0);
94 if (result_str == NULL)
97 if (strcmp (result_str, "0") == 0)
99 else if (strcasecmp (result_str, "NOMATCH") == 0)
100 result = FNM_NOMATCH;
104 result = strtol (result_str, &endp, 0);
109 flags = next_input (&cp, 0, 1);
111 /* We allow the flags missing. */
114 /* Convert the text describing the flags in a numeric value. */
115 flags_val = convert_flags (flags);
117 /* Something went wrong. */
120 /* Now run the actual test. */
123 if (setlocale (LC_COLLATE, locale) == NULL
124 || setlocale (LC_CTYPE, locale) == NULL)
126 puts ("*** Cannot set locale");
131 fnmres = fnmatch (pattern, input, flags_val);
133 printf ("%3d: fnmatch (\"%s\", \"%s\", %s) = %s%c",
135 escape (pattern, &escpatternlen, &escpattern),
136 escape (input, &escinputlen, &escinput),
137 flag_output (flags_val),
139 ? "0" : (fnmres == FNM_NOMATCH
141 : (sprintf (numbuf, "%d", fnmres), numbuf))),
142 (fnmres != 0) != (result != 0) ? ' ' : '\n');
144 if ((fnmres != 0) != (result != 0))
146 printf ("(FAIL, expected %s) ***\n",
148 ? "0" : (result == FNM_NOMATCH
150 : (sprintf (numbuf, "%d", result), numbuf)));
155 printf ("=====================\n%3d tests, %3d failed\n", ntests, nfailed);
166 next_input (char **line, int first, int last)
171 while (*cp == ' ' || *cp == '\t')
174 /* We allow comment lines starting with '#'. */
175 if (first && *cp == '#')
185 while (*cp != '"' && *cp != '\0' && *cp != '\n')
188 if (cp[1] == '\n' || cp[1] == '\0')
196 else if (*cp >= '0' && *cp <= '7')
200 while (ndigits < 3 && *cp >= '0' && *cp <= '7')
203 cval += (*cp++) - '0';
226 while (*cp != '\0' && *cp != '\n' && *cp != ' ' && *cp != '\t')
229 if (cp == result && ! last)
230 /* Premature end of line. */
234 /* Terminate and skip over the next white spaces. */
243 convert_flags (const char *str)
251 if (strncasecmp (str, "PATHNAME", 8) == 0
252 && (str[8] == '|' || str[8] == '\0'))
254 result |= FNM_PATHNAME;
257 else if (strncasecmp (str, "NOESCAPE", 8) == 0
258 && (str[8] == '|' || str[8] == '\0'))
260 result |= FNM_NOESCAPE;
263 else if (strncasecmp (str, "PERIOD", 6) == 0
264 && (str[6] == '|' || str[6] == '\0'))
266 result |= FNM_PERIOD;
269 else if (strncasecmp (str, "LEADING_DIR", 11) == 0
270 && (str[11] == '|' || str[11] == '\0'))
272 result |= FNM_LEADING_DIR;
275 else if (strncasecmp (str, "CASEFOLD", 8) == 0
276 && (str[8] == '|' || str[8] == '\0'))
278 result |= FNM_CASEFOLD;
281 else if (strncasecmp (str, "EXTMATCH", 8) == 0
282 && (str[8] == '|' || str[8] == '\0'))
284 result |= FNM_EXTMATCH;
300 flag_output (int flags)
302 static char buf[100];
306 if (flags & FNM_PATHNAME)
308 cp = stpcpy (cp, "FNM_PATHNAME");
311 if (flags & FNM_NOESCAPE)
315 cp = stpcpy (cp, "FNM_NOESCAPE");
318 if (flags & FNM_PERIOD)
322 cp = stpcpy (cp, "FNM_PERIOD");
325 if (flags & FNM_LEADING_DIR)
329 cp = stpcpy (cp, "FNM_LEADING_DIR");
332 if (flags & FNM_CASEFOLD)
336 cp = stpcpy (cp, "FNM_CASEFOLD");
339 if (flags & FNM_EXTMATCH)
343 cp = stpcpy (cp, "FNM_EXTMATCH");
355 escape (const char *str, size_t *reslenp, char **resbufp)
357 size_t reslen = *reslenp;
358 char *resbuf = *resbufp;
359 size_t len = strlen (str);
362 if (2 * len + 1 > reslen)
364 resbuf = (char *) realloc (resbuf, 2 * len + 1);
366 error (EXIT_FAILURE, errno, "while allocating buffer for printing");
367 *reslenp = 2 * len + 1;
379 else if (*str == '\n')
385 else if (*str == '"')
391 else if (*str == '\\')
405 #define TEST_FUNCTION do_test ()
406 #include "../test-skeleton.c"