|
Packit |
6c4009 |
/* Tests for fnmatch function.
|
|
Packit |
6c4009 |
Copyright (C) 2000-2018 Free Software Foundation, Inc.
|
|
Packit |
6c4009 |
This file is part of the GNU C Library.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is free software; you can redistribute it and/or
|
|
Packit |
6c4009 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License as published by the Free Software Foundation; either
|
|
Packit |
6c4009 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is distributed in the hope that it will be useful,
|
|
Packit |
6c4009 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6c4009 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6c4009 |
Lesser General Public License for more details.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License along with the GNU C Library; if not, see
|
|
Packit |
6c4009 |
<http://www.gnu.org/licenses/>. */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#include <errno.h>
|
|
Packit |
6c4009 |
#include <error.h>
|
|
Packit |
6c4009 |
#include <fnmatch.h>
|
|
Packit |
6c4009 |
#include <locale.h>
|
|
Packit |
6c4009 |
#include <stdio.h>
|
|
Packit |
6c4009 |
#include <stdlib.h>
|
|
Packit |
6c4009 |
#include <string.h>
|
|
Packit |
6c4009 |
#include <sys/types.h>
|
|
Packit |
6c4009 |
#include <mcheck.h>
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
static char *next_input (char **line, int first, int last);
|
|
Packit |
6c4009 |
static int convert_flags (const char *str);
|
|
Packit |
6c4009 |
static char *flag_output (int flags);
|
|
Packit |
6c4009 |
static char *escape (const char *str, size_t *reslenp, char **resbuf);
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
static int
|
|
Packit |
6c4009 |
do_test (void)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
char *linebuf = NULL;
|
|
Packit |
6c4009 |
size_t linebuflen = 0;
|
|
Packit |
6c4009 |
int ntests = 0;
|
|
Packit |
6c4009 |
int nfailed = 0;
|
|
Packit |
6c4009 |
char *escinput = NULL;
|
|
Packit |
6c4009 |
size_t escinputlen = 0;
|
|
Packit |
6c4009 |
char *escpattern = NULL;
|
|
Packit |
6c4009 |
size_t escpatternlen = 0;
|
|
Packit |
6c4009 |
int nr = 0;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
mtrace ();
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Read lines from stdin with the following format:
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
locale input-string match-string flags result
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
where `result' is either 0 or 1. If the first character of a
|
|
Packit |
6c4009 |
string is '"' we read until the next '"' and handled escaped '"'. */
|
|
Packit |
6c4009 |
while (! feof (stdin))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
ssize_t n = getline (&linebuf, &linebuflen, stdin);
|
|
Packit |
6c4009 |
char *cp;
|
|
Packit |
6c4009 |
const char *locale;
|
|
Packit |
6c4009 |
const char *input;
|
|
Packit |
6c4009 |
const char *pattern;
|
|
Packit |
6c4009 |
const char *result_str;
|
|
Packit |
6c4009 |
int result;
|
|
Packit |
6c4009 |
const char *flags;
|
|
Packit |
6c4009 |
int flags_val;
|
|
Packit |
6c4009 |
int fnmres;
|
|
Packit |
6c4009 |
char numbuf[24];
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (n == -1)
|
|
Packit |
6c4009 |
break;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (n == 0)
|
|
Packit |
6c4009 |
/* Maybe an empty line. */
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Skip over all leading white spaces. */
|
|
Packit |
6c4009 |
cp = linebuf;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
locale = next_input (&cp, 1, 0);
|
|
Packit |
6c4009 |
if (locale == NULL)
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
input = next_input (&cp, 0, 0);
|
|
Packit |
6c4009 |
if (input == NULL)
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
pattern = next_input (&cp, 0, 0);
|
|
Packit |
6c4009 |
if (pattern == NULL)
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
result_str = next_input (&cp, 0, 0);
|
|
Packit |
6c4009 |
if (result_str == NULL)
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (strcmp (result_str, "0") == 0)
|
|
Packit |
6c4009 |
result = 0;
|
|
Packit |
6c4009 |
else if (strcasecmp (result_str, "NOMATCH") == 0)
|
|
Packit |
6c4009 |
result = FNM_NOMATCH;
|
|
Packit |
6c4009 |
else
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
char *endp;
|
|
Packit |
6c4009 |
result = strtol (result_str, &endp, 0);
|
|
Packit |
6c4009 |
if (*endp != '\0')
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
flags = next_input (&cp, 0, 1);
|
|
Packit |
6c4009 |
if (flags == NULL)
|
|
Packit |
6c4009 |
/* We allow the flags missing. */
|
|
Packit |
6c4009 |
flags = "";
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Convert the text describing the flags in a numeric value. */
|
|
Packit |
6c4009 |
flags_val = convert_flags (flags);
|
|
Packit |
6c4009 |
if (flags_val == -1)
|
|
Packit |
6c4009 |
/* Something went wrong. */
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Now run the actual test. */
|
|
Packit |
6c4009 |
++ntests;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (setlocale (LC_COLLATE, locale) == NULL
|
|
Packit |
6c4009 |
|| setlocale (LC_CTYPE, locale) == NULL)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
puts ("*** Cannot set locale");
|
|
Packit |
6c4009 |
++nfailed;
|
|
Packit |
6c4009 |
continue;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
fnmres = fnmatch (pattern, input, flags_val);
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
printf ("%3d: fnmatch (\"%s\", \"%s\", %s) = %s%c",
|
|
Packit |
6c4009 |
++nr,
|
|
Packit |
6c4009 |
escape (pattern, &escpatternlen, &escpattern),
|
|
Packit |
6c4009 |
escape (input, &escinputlen, &escinput),
|
|
Packit |
6c4009 |
flag_output (flags_val),
|
|
Packit |
6c4009 |
(fnmres == 0
|
|
Packit |
6c4009 |
? "0" : (fnmres == FNM_NOMATCH
|
|
Packit |
6c4009 |
? "FNM_NOMATCH"
|
|
Packit |
6c4009 |
: (sprintf (numbuf, "%d", fnmres), numbuf))),
|
|
Packit |
6c4009 |
(fnmres != 0) != (result != 0) ? ' ' : '\n');
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if ((fnmres != 0) != (result != 0))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
printf ("(FAIL, expected %s) ***\n",
|
|
Packit |
6c4009 |
result == 0
|
|
Packit |
6c4009 |
? "0" : (result == FNM_NOMATCH
|
|
Packit |
6c4009 |
? "FNM_NOMATCH"
|
|
Packit |
6c4009 |
: (sprintf (numbuf, "%d", result), numbuf)));
|
|
Packit |
6c4009 |
++nfailed;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
printf ("=====================\n%3d tests, %3d failed\n", ntests, nfailed);
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
free (escpattern);
|
|
Packit |
6c4009 |
free (escinput);
|
|
Packit |
6c4009 |
free (linebuf);
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
return nfailed != 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
static char *
|
|
Packit |
6c4009 |
next_input (char **line, int first, int last)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
char *cp = *line;
|
|
Packit |
6c4009 |
char *result;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
while (*cp == ' ' || *cp == '\t')
|
|
Packit |
6c4009 |
++cp;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* We allow comment lines starting with '#'. */
|
|
Packit |
6c4009 |
if (first && *cp == '#')
|
|
Packit |
6c4009 |
return NULL;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (*cp == '"')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
char *wp;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
result = ++cp;
|
|
Packit |
6c4009 |
wp = cp;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
while (*cp != '"' && *cp != '\0' && *cp != '\n')
|
|
Packit |
6c4009 |
if (*cp == '\\')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (cp[1] == '\n' || cp[1] == '\0')
|
|
Packit |
6c4009 |
return NULL;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
++cp;
|
|
Packit |
6c4009 |
if (*cp == 't')
|
|
Packit |
6c4009 |
*wp++ = '\t';
|
|
Packit |
6c4009 |
else if (*cp == 'n')
|
|
Packit |
6c4009 |
*wp++ = '\n';
|
|
Packit |
6c4009 |
else
|
|
Packit |
6c4009 |
*wp++ = *cp;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
++cp;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else
|
|
Packit |
6c4009 |
*wp++ = *cp++;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (*cp != '"')
|
|
Packit |
6c4009 |
return NULL;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (wp != cp)
|
|
Packit |
6c4009 |
*wp = '\0';
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result = cp;
|
|
Packit |
6c4009 |
while (*cp != '\0' && *cp != '\n' && *cp != ' ' && *cp != '\t')
|
|
Packit |
6c4009 |
++cp;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (cp == result && ! last)
|
|
Packit |
6c4009 |
/* Premature end of line. */
|
|
Packit |
6c4009 |
return NULL;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Terminate and skip over the next white spaces. */
|
|
Packit |
6c4009 |
*cp++ = '\0';
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
*line = cp;
|
|
Packit |
6c4009 |
return result;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
static int
|
|
Packit |
6c4009 |
convert_flags (const char *str)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
int result = 0;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
while (*str != '\0')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
int len;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (strncasecmp (str, "PATHNAME", 8) == 0
|
|
Packit |
6c4009 |
&& (str[8] == '|' || str[8] == '\0'))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result |= FNM_PATHNAME;
|
|
Packit |
6c4009 |
len = 8;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (strncasecmp (str, "NOESCAPE", 8) == 0
|
|
Packit |
6c4009 |
&& (str[8] == '|' || str[8] == '\0'))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result |= FNM_NOESCAPE;
|
|
Packit |
6c4009 |
len = 8;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (strncasecmp (str, "PERIOD", 6) == 0
|
|
Packit |
6c4009 |
&& (str[6] == '|' || str[6] == '\0'))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result |= FNM_PERIOD;
|
|
Packit |
6c4009 |
len = 6;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (strncasecmp (str, "LEADING_DIR", 11) == 0
|
|
Packit |
6c4009 |
&& (str[11] == '|' || str[11] == '\0'))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result |= FNM_LEADING_DIR;
|
|
Packit |
6c4009 |
len = 11;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (strncasecmp (str, "CASEFOLD", 8) == 0
|
|
Packit |
6c4009 |
&& (str[8] == '|' || str[8] == '\0'))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result |= FNM_CASEFOLD;
|
|
Packit |
6c4009 |
len = 8;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (strncasecmp (str, "EXTMATCH", 8) == 0
|
|
Packit |
6c4009 |
&& (str[8] == '|' || str[8] == '\0'))
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
result |= FNM_EXTMATCH;
|
|
Packit |
6c4009 |
len = 8;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else
|
|
Packit |
6c4009 |
return -1;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
str += len;
|
|
Packit |
6c4009 |
if (*str != '\0')
|
|
Packit |
6c4009 |
++str;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
return result;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
static char *
|
|
Packit |
6c4009 |
flag_output (int flags)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
static char buf[100];
|
|
Packit |
6c4009 |
int first = 1;
|
|
Packit |
6c4009 |
char *cp = buf;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (flags & FNM_PATHNAME)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
cp = stpcpy (cp, "FNM_PATHNAME");
|
|
Packit |
6c4009 |
first = 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
if (flags & FNM_NOESCAPE)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (! first)
|
|
Packit |
6c4009 |
*cp++ = '|';
|
|
Packit |
6c4009 |
cp = stpcpy (cp, "FNM_NOESCAPE");
|
|
Packit |
6c4009 |
first = 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
if (flags & FNM_PERIOD)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (! first)
|
|
Packit |
6c4009 |
*cp++ = '|';
|
|
Packit |
6c4009 |
cp = stpcpy (cp, "FNM_PERIOD");
|
|
Packit |
6c4009 |
first = 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
if (flags & FNM_LEADING_DIR)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (! first)
|
|
Packit |
6c4009 |
*cp++ = '|';
|
|
Packit |
6c4009 |
cp = stpcpy (cp, "FNM_LEADING_DIR");
|
|
Packit |
6c4009 |
first = 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
if (flags & FNM_CASEFOLD)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (! first)
|
|
Packit |
6c4009 |
*cp++ = '|';
|
|
Packit |
6c4009 |
cp = stpcpy (cp, "FNM_CASEFOLD");
|
|
Packit |
6c4009 |
first = 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
if (flags & FNM_EXTMATCH)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (! first)
|
|
Packit |
6c4009 |
*cp++ = '|';
|
|
Packit |
6c4009 |
cp = stpcpy (cp, "FNM_EXTMATCH");
|
|
Packit |
6c4009 |
first = 0;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
if (cp == buf)
|
|
Packit |
6c4009 |
*cp++ = '0';
|
|
Packit |
6c4009 |
*cp = '\0';
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
return buf;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
static char *
|
|
Packit |
6c4009 |
escape (const char *str, size_t *reslenp, char **resbufp)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
size_t reslen = *reslenp;
|
|
Packit |
6c4009 |
char *resbuf = *resbufp;
|
|
Packit |
6c4009 |
size_t len = strlen (str);
|
|
Packit |
6c4009 |
char *wp;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if (2 * len + 1 > reslen)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
resbuf = (char *) realloc (resbuf, 2 * len + 1);
|
|
Packit |
6c4009 |
if (resbuf == NULL)
|
|
Packit |
6c4009 |
error (EXIT_FAILURE, errno, "while allocating buffer for printing");
|
|
Packit |
6c4009 |
*reslenp = 2 * len + 1;
|
|
Packit |
6c4009 |
*resbufp = resbuf;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
wp = resbuf;
|
|
Packit |
6c4009 |
while (*str != '\0')
|
|
Packit |
6c4009 |
if (*str == '\t')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
*wp++ = '\\';
|
|
Packit |
6c4009 |
*wp++ = 't';
|
|
Packit |
6c4009 |
++str;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (*str == '\n')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
*wp++ = '\\';
|
|
Packit |
6c4009 |
*wp++ = 'n';
|
|
Packit |
6c4009 |
++str;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (*str == '"')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
*wp++ = '\\';
|
|
Packit |
6c4009 |
*wp++ = '"';
|
|
Packit |
6c4009 |
++str;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else if (*str == '\\')
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
*wp++ = '\\';
|
|
Packit |
6c4009 |
*wp++ = '\\';
|
|
Packit |
6c4009 |
++str;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
else
|
|
Packit |
6c4009 |
*wp++ = *str++;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
*wp = '\0';
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
return resbuf;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#define TEST_FUNCTION do_test ()
|
|
Packit |
6c4009 |
#include "../test-skeleton.c"
|