mirror of git://sourceware.org/git/glibc.git
				
				
				
			
		
			
				
	
	
		
			227 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Regular expression tests.
 | |
|    Copyright (C) 2003-2018 Free Software Foundation, Inc.
 | |
|    This file is part of the GNU C Library.
 | |
|    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 | |
| 
 | |
|    The GNU C Library is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU Lesser General Public
 | |
|    License as published by the Free Software Foundation; either
 | |
|    version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|    The GNU C Library is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|    Lesser General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU Lesser General Public
 | |
|    License along with the GNU C Library; if not, see
 | |
|    <http://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <mcheck.h>
 | |
| #include <regex.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| void
 | |
| frob_escapes (char *src, int pattern)
 | |
| {
 | |
|   char *dst;
 | |
| 
 | |
|   for (dst = src; *src != '\0'; dst++, src++)
 | |
|     {
 | |
|       if (*src == '\\')
 | |
| 	{
 | |
| 	  switch (src[1])
 | |
| 	    {
 | |
| 	    case 't':
 | |
| 	      src++;
 | |
| 	      *dst = '\t';
 | |
| 	      continue;
 | |
| 	    case 'n':
 | |
| 	      src++;
 | |
| 	      *dst = '\n';
 | |
| 	      continue;
 | |
| 	    case 'r':
 | |
| 	      src++;
 | |
| 	      *dst = '\r';
 | |
| 	      continue;
 | |
| 	    case '\\':
 | |
| 	    case '^':
 | |
| 	    case '{':
 | |
| 	    case '|':
 | |
| 	    case '}':
 | |
| 	      if (!pattern)
 | |
| 		{
 | |
| 		  src++;
 | |
| 		  *dst = *src;
 | |
| 		  continue;
 | |
| 		}
 | |
| 	      break;
 | |
| 	    }
 | |
| 	}
 | |
|       if (src != dst)
 | |
| 	*dst = *src;
 | |
|     }
 | |
|   *dst = '\0';
 | |
| }
 | |
| 
 | |
| int
 | |
| main (int argc, char **argv)
 | |
| {
 | |
|   int ret = 0, n;
 | |
|   char *line = NULL;
 | |
|   size_t line_len = 0;
 | |
|   ssize_t len;
 | |
|   FILE *f;
 | |
|   char *pattern, *string;
 | |
|   int flags = REG_EXTENDED;
 | |
|   int eflags = 0;
 | |
|   regex_t re;
 | |
|   regmatch_t rm[20];
 | |
| 
 | |
|   mtrace ();
 | |
| 
 | |
|   if (argc < 2)
 | |
|     {
 | |
|       fprintf (stderr, "Missing test filename\n");
 | |
|       return 1;
 | |
|     }
 | |
| 
 | |
|   f = fopen (argv[1], "r");
 | |
|   if (f == NULL)
 | |
|     {
 | |
|       fprintf (stderr, "Couldn't open %s\n", argv[1]);
 | |
|       return 1;
 | |
|     }
 | |
| 
 | |
|   while ((len = getline (&line, &line_len, f)) > 0)
 | |
|     {
 | |
|       char *p, *q;
 | |
|       int i;
 | |
| 
 | |
|       if (line[len - 1] == '\n')
 | |
| 	line[--len] = '\0';
 | |
| 
 | |
|       puts (line);
 | |
| 
 | |
|       if (line[0] == ';')
 | |
| 	continue;
 | |
| 
 | |
|       if (line[0] == '\0')
 | |
| 	continue;
 | |
| 
 | |
|       if (line[0] == '-')
 | |
| 	{
 | |
| 	  if (strstr (line, "REG_BASIC"))
 | |
| 	    flags = 0;
 | |
| 	  else
 | |
| 	    flags = REG_EXTENDED;
 | |
| 	  if (strstr (line, "REG_ICASE"))
 | |
| 	    flags |= REG_ICASE;
 | |
| 	  if (strstr (line, "REG_NEWLINE"))
 | |
| 	    flags |= REG_NEWLINE;
 | |
| 	  eflags = 0;
 | |
| 	  if (strstr (line, "REG_NOTBOL"))
 | |
| 	    eflags |= REG_NOTBOL;
 | |
| 	  if (strstr (line, "REG_NOTEOL"))
 | |
| 	    eflags |= REG_NOTEOL;
 | |
| 	  continue;
 | |
| 	}
 | |
| 
 | |
|       pattern = line + strspn (line, " \t");
 | |
|       if (*pattern == '\0')
 | |
| 	continue;
 | |
|       p = pattern + strcspn (pattern, " \t");
 | |
|       if (*p == '\0')
 | |
| 	continue;
 | |
|       *p++ = '\0';
 | |
| 
 | |
|       string = p + strspn (p, " \t");
 | |
|       if (*string == '\0')
 | |
| 	continue;
 | |
|       if (*string == '"')
 | |
| 	{
 | |
| 	  string++;
 | |
| 	  p = strchr (string, '"');
 | |
| 	  if (p == NULL)
 | |
| 	    continue;
 | |
| 	  *p++ = '\0';
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  p = string + strcspn (string, " \t");
 | |
| 	  if (*string == '!')
 | |
| 	    string = NULL;
 | |
| 	  else if (*p == '\0')
 | |
| 	    continue;
 | |
| 	  else
 | |
| 	    *p++ = '\0';
 | |
| 	}
 | |
| 
 | |
|       frob_escapes (pattern, 1);
 | |
|       if (string != NULL)
 | |
| 	frob_escapes (string, 0);
 | |
| 
 | |
|       n = regcomp (&re, pattern, flags);
 | |
|       if (n != 0)
 | |
| 	{
 | |
| 	  if (string != NULL)
 | |
| 	    {
 | |
| 	      char buf[500];
 | |
| 	      regerror (n, &re, buf, sizeof (buf));
 | |
| 	      printf ("FAIL regcomp unexpectedly failed: %s\n",
 | |
| 		      buf);
 | |
| 	      ret = 1;
 | |
| 	    }
 | |
| 	  continue;
 | |
| 	}
 | |
|       else if (string == NULL)
 | |
| 	{
 | |
| 	  regfree (&re);
 | |
| 	  puts ("FAIL regcomp unpexpectedly succeeded");
 | |
| 	  ret = 1;
 | |
| 	  continue;
 | |
| 	}
 | |
| 
 | |
|       if (regexec (&re, string, 20, rm, eflags))
 | |
| 	{
 | |
| 	  for (i = 0; i < 20; ++i)
 | |
| 	    {
 | |
| 	      rm[i].rm_so = -1;
 | |
| 	      rm[i].rm_eo = -1;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
|       regfree (&re);
 | |
| 
 | |
|       for (i = 0; i < 20 && *p != '\0'; ++i)
 | |
| 	{
 | |
| 	  int rm_so, rm_eo;
 | |
| 
 | |
| 	  rm_so = strtol (p, &q, 10);
 | |
| 	  if (p == q)
 | |
| 	    break;
 | |
| 	  p = q;
 | |
| 
 | |
| 	  rm_eo = strtol (p, &q, 10);
 | |
| 	  if (p == q)
 | |
| 	    break;
 | |
| 	  p = q;
 | |
| 
 | |
| 	  if (rm[i].rm_so != rm_so || rm[i].rm_eo != rm_eo)
 | |
| 	    {
 | |
| 	      printf ("FAIL rm[%d] %d..%d != expected %d..%d\n",
 | |
| 		      i, rm[i].rm_so, rm[i].rm_eo, rm_so, rm_eo);
 | |
| 	      ret = 1;
 | |
| 	      break;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   free (line);
 | |
|   fclose (f);
 | |
|   return ret;
 | |
| }
 |