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