Home | History | Annotate | Download | only in testsuite
      1 /* Regular expression tests.
      2    Copyright (C) 2003 Free Software Foundation, Inc.
      3    This file is part of the GNU C Library.
      4    Contributed by Jakub Jelinek <jakub (at) redhat.com>, 2003.
      5 
      6    The GNU C Library is free software; you can redistribute it and/or
      7    modify it under the terms of the GNU Lesser General Public
      8    License as published by the Free Software Foundation; either
      9    version 2.1 of the License, or (at your option) any later version.
     10 
     11    The GNU C Library is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    Lesser General Public License for more details.
     15 
     16    You should have received a copy of the GNU Lesser General Public
     17    License along with the GNU C Library; if not, write to the Free
     18    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     19    02110-1301 USA.  */
     20 
     21 #ifdef HAVE_CONFIG_H
     22 #include "config.h"
     23 #endif
     24 
     25 #include <sys/types.h>
     26 #ifdef HAVE_MCHECK_H
     27 #include <mcheck.h>
     28 #endif
     29 #include <regex.h>
     30 #include <stdio.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 
     34 int
     35 main (int argc, char **argv)
     36 {
     37   int ret = 0;
     38   char *line = NULL;
     39   size_t line_len = 0;
     40   ssize_t len;
     41   FILE *f;
     42   char *pattern = NULL, *string = NULL;
     43   regmatch_t rm[20];
     44   size_t pattern_alloced = 0, string_alloced = 0;
     45   int ignorecase = 0;
     46   int pattern_valid = 0, rm_valid = 0;
     47   size_t linenum;
     48 
     49 #ifdef HAVE_MCHECK_H
     50   mtrace ();
     51 #endif
     52 
     53   if (argc < 2)
     54     {
     55       fprintf (stderr, "Missing test filename\n");
     56       return 1;
     57     }
     58 
     59   f = fopen (argv[1], "r");
     60   if (f == NULL)
     61     {
     62       fprintf (stderr, "Couldn't open %s\n", argv[1]);
     63       return 1;
     64     }
     65 
     66   if ((len = getline (&line, &line_len, f)) <= 0
     67       || strncmp (line, "# PCRE", 6) != 0)
     68     {
     69       fprintf (stderr, "Not a PCRE test file\n");
     70       fclose (f);
     71       free (line);
     72       return 1;
     73     }
     74 
     75   linenum = 1;
     76 
     77   while ((len = getline (&line, &line_len, f)) > 0)
     78     {
     79       char *p;
     80       unsigned long num;
     81 
     82       ++linenum;
     83 
     84       if (line[len - 1] == '\n')
     85 	line[--len] = '\0';
     86 
     87       if (line[0] == '#')
     88 	continue;
     89 
     90       if (line[0] == '\0')
     91 	{
     92 	  /* End of test.  */
     93 	  ignorecase = 0;
     94 	  pattern_valid = 0;
     95 	  rm_valid = 0;
     96 	  continue;
     97 	}
     98 
     99       if (line[0] == '/')
    100 	{
    101 	  /* Pattern.  */
    102 	  p = strrchr (line + 1, '/');
    103 
    104 	  pattern_valid = 0;
    105 	  rm_valid = 0;
    106 	  if (p == NULL)
    107 	    {
    108 	      printf ("%lu: Invalid pattern line: %s\n", linenum, line);
    109 	      ret = 1;
    110 	      continue;
    111 	    }
    112 
    113 	  if (p[1] == 'i' && p[2] == '\0')
    114 	    ignorecase = 1;
    115 	  else if (p[1] != '\0')
    116 	    {
    117 	      printf ("%lu: Invalid pattern line: %s\n", linenum, line);
    118 	      ret = 1;
    119 	      continue;
    120 	    }
    121 
    122 	  if (pattern_alloced < (size_t) (p - line))
    123 	    {
    124 	      pattern = realloc (pattern, p - line);
    125 	      if (pattern == NULL)
    126 		{
    127 		  printf ("%lu: Cannot record pattern: %m\n", linenum);
    128 		  ret = 1;
    129 		  break;
    130 		}
    131 	      pattern_alloced = p - line;
    132 	    }
    133 
    134 	  memcpy (pattern, line + 1, p - line - 1);
    135 	  pattern[p - line - 1] = '\0';
    136 	  pattern_valid = 1;
    137 	  continue;
    138 	}
    139 
    140       if (strncmp (line, "    ", 4) == 0)
    141 	{
    142 	  regex_t re;
    143 	  int n;
    144 
    145 	  if (!pattern_valid)
    146 	    {
    147 	      printf ("%lu: No previous valid pattern %s\n", linenum, line);
    148 	      continue;
    149 	    }
    150 
    151 	  if (string_alloced < (size_t) (len - 3))
    152 	    {
    153 	      string = realloc (string, len - 3);
    154 	      if (string == NULL)
    155 		{
    156 		  printf ("%lu: Cannot record search string: %m\n", linenum);
    157 		  ret = 1;
    158 		  break;
    159 		}
    160 	      string_alloced = len - 3;
    161 	    }
    162 
    163 	  memcpy (string, line + 4, len - 3);
    164 
    165 	  n = regcomp (&re, pattern,
    166 		       REG_EXTENDED | (ignorecase ? REG_ICASE : 0));
    167 	  if (n != 0)
    168 	    {
    169 	      char buf[500];
    170 	      regerror (n, &re, buf, sizeof (buf));
    171 	      printf ("%lu: regcomp failed for %s: %s\n",
    172 		      linenum, pattern, buf);
    173 	      ret = 1;
    174 	      continue;
    175 	    }
    176 
    177 	  if (regexec (&re, string, 20, rm, 0))
    178 	    {
    179 	      rm[0].rm_so = -1;
    180 	      rm[0].rm_eo = -1;
    181 	    }
    182 
    183 	  regfree (&re);
    184 	  rm_valid = 1;
    185 	  continue;
    186 	}
    187 
    188       if (!rm_valid)
    189 	{
    190 	  printf ("%lu: No preceeding pattern or search string\n", linenum);
    191 	  ret = 1;
    192 	  continue;
    193 	}
    194 
    195       if (strcmp (line, "No match") == 0)
    196 	{
    197 	  if (rm[0].rm_so != -1 || rm[0].rm_eo != -1)
    198 	    {
    199 	      printf ("%lu: /%s/ on %s unexpectedly matched %d..%d\n",
    200 		      linenum, pattern, string, rm[0].rm_so, rm[0].rm_eo);
    201 	      ret = 1;
    202 	    }
    203 
    204 	  continue;
    205 	}
    206 
    207       p = line;
    208       if (*p == ' ')
    209         ++p;
    210 
    211       num = strtoul (p, &p, 10);
    212       if (num >= 20 || *p != ':' || p[1] != ' ')
    213 	{
    214 	  printf ("%lu: Invalid line %s\n", linenum, line);
    215 	  ret = 1;
    216 	  continue;
    217 	}
    218 
    219       if (rm[num].rm_so == -1 || rm[num].rm_eo == -1)
    220 	{
    221 	  if (strcmp (p + 2, "<unset>") != 0)
    222 	    {
    223 	      printf ("%lu: /%s/ on %s unexpectedly failed to match register %ld %d..%d\n",
    224 		      linenum, pattern, string, num,
    225 		      rm[num].rm_so, rm[num].rm_eo);
    226 	      ret = 1;
    227 	    }
    228 	  continue;
    229 	}
    230 
    231       if (rm[num].rm_eo < rm[num].rm_so
    232 	  || rm[num].rm_eo - rm[num].rm_so != len - (p + 2 - line)
    233 	  || strncmp (p + 2, string + rm[num].rm_so,
    234 		      rm[num].rm_eo - rm[num].rm_so) != 0)
    235 	{
    236 	  printf ("%lu: /%s/ on %s unexpectedly failed to match %s for register %ld %d..%d\n",
    237 		  linenum, pattern, string, p + 2, num,
    238 		  rm[num].rm_so, rm[num].rm_eo);
    239 	  ret = 1;
    240 	  continue;
    241 	}
    242     }
    243 
    244   free (pattern);
    245   free (string);
    246   free (line);
    247   fclose (f);
    248   return ret;
    249 }
    250