Blame posix/tst-fnmatch.c

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"