| 70 |
|
|
| 71 |
typedef int BOOL; |
typedef int BOOL; |
| 72 |
|
|
|
#define MAX_PATTERN_COUNT 100 |
|
| 73 |
#define OFFSET_SIZE 99 |
#define OFFSET_SIZE 99 |
| 74 |
|
|
| 75 |
#if BUFSIZ > 8192 |
#if BUFSIZ > 8192 |
| 76 |
#define PATBUFSIZE BUFSIZ |
#define MAXPATLEN BUFSIZ |
| 77 |
#else |
#else |
| 78 |
#define PATBUFSIZE 8192 |
#define MAXPATLEN 8192 |
| 79 |
#endif |
#endif |
| 80 |
|
|
| 81 |
|
#define PATBUFSIZE (MAXPATLEN + 10) /* Allows for prefix+suffix */ |
| 82 |
|
|
| 83 |
/* Values for the "filenames" variable, which specifies options for file name |
/* Values for the "filenames" variable, which specifies options for file name |
| 84 |
output. The order is important; it is assumed that a file name is wanted for |
output. The order is important; it is assumed that a file name is wanted for |
| 85 |
all values greater than FN_DEFAULT. */ |
all values greater than FN_DEFAULT. */ |
| 140 |
static char *colour_option = NULL; |
static char *colour_option = NULL; |
| 141 |
static char *dee_option = NULL; |
static char *dee_option = NULL; |
| 142 |
static char *DEE_option = NULL; |
static char *DEE_option = NULL; |
| 143 |
|
static char *locale = NULL; |
| 144 |
static char *main_buffer = NULL; |
static char *main_buffer = NULL; |
| 145 |
static char *newline = NULL; |
static char *newline = NULL; |
|
static char *pattern_filename = NULL; |
|
| 146 |
static char *stdin_name = (char *)"(standard input)"; |
static char *stdin_name = (char *)"(standard input)"; |
|
static char *locale = NULL; |
|
| 147 |
|
|
| 148 |
static const unsigned char *pcretables = NULL; |
static const unsigned char *pcretables = NULL; |
| 149 |
|
|
|
static int pattern_count = 0; |
|
|
static pcre **pattern_list = NULL; |
|
|
static pcre_extra **hints_list = NULL; |
|
|
|
|
|
static char *file_list = NULL; |
|
|
static char *include_pattern = NULL; |
|
|
static char *exclude_pattern = NULL; |
|
|
static char *include_dir_pattern = NULL; |
|
|
static char *exclude_dir_pattern = NULL; |
|
|
|
|
|
static pcre *include_compiled = NULL; |
|
|
static pcre *exclude_compiled = NULL; |
|
|
static pcre *include_dir_compiled = NULL; |
|
|
static pcre *exclude_dir_compiled = NULL; |
|
|
|
|
| 150 |
static int after_context = 0; |
static int after_context = 0; |
| 151 |
static int before_context = 0; |
static int before_context = 0; |
| 152 |
static int binary_files = BIN_BINARY; |
static int binary_files = BIN_BINARY; |
| 153 |
static int both_context = 0; |
static int both_context = 0; |
| 154 |
static int bufthird = PCREGREP_BUFSIZE; |
static int bufthird = PCREGREP_BUFSIZE; |
| 155 |
static int bufsize = 3*PCREGREP_BUFSIZE; |
static int bufsize = 3*PCREGREP_BUFSIZE; |
| 156 |
|
|
| 157 |
|
#if defined HAVE_WINDOWS_H && HAVE_WINDOWS_H |
| 158 |
|
static int dee_action = dee_SKIP; |
| 159 |
|
#else |
| 160 |
static int dee_action = dee_READ; |
static int dee_action = dee_READ; |
| 161 |
|
#endif |
| 162 |
|
|
| 163 |
static int DEE_action = DEE_READ; |
static int DEE_action = DEE_READ; |
| 164 |
static int error_count = 0; |
static int error_count = 0; |
| 165 |
static int filenames = FN_DEFAULT; |
static int filenames = FN_DEFAULT; |
| 166 |
static int only_matching = -1; |
static int only_matching = -1; |
| 167 |
|
static int pcre_options = 0; |
| 168 |
static int process_options = 0; |
static int process_options = 0; |
| 169 |
|
|
| 170 |
#ifdef SUPPORT_PCREGREP_JIT |
#ifdef SUPPORT_PCREGREP_JIT |
| 191 |
static BOOL silent = FALSE; |
static BOOL silent = FALSE; |
| 192 |
static BOOL utf8 = FALSE; |
static BOOL utf8 = FALSE; |
| 193 |
|
|
| 194 |
|
/* Structure for list of file names (for -f and --{in,ex}clude-from) */ |
| 195 |
|
|
| 196 |
|
typedef struct fnstr { |
| 197 |
|
struct fnstr *next; |
| 198 |
|
char *name; |
| 199 |
|
} fnstr; |
| 200 |
|
|
| 201 |
|
static fnstr *exclude_from = NULL; |
| 202 |
|
static fnstr *exclude_from_last = NULL; |
| 203 |
|
static fnstr *include_from = NULL; |
| 204 |
|
static fnstr *include_from_last = NULL; |
| 205 |
|
|
| 206 |
|
static fnstr *file_lists = NULL; |
| 207 |
|
static fnstr *file_lists_last = NULL; |
| 208 |
|
static fnstr *pattern_files = NULL; |
| 209 |
|
static fnstr *pattern_files_last = NULL; |
| 210 |
|
|
| 211 |
|
/* Structure for holding the two variables that describe a file name chain. */ |
| 212 |
|
|
| 213 |
|
typedef struct fndatastr { |
| 214 |
|
fnstr **anchor; |
| 215 |
|
fnstr **lastptr; |
| 216 |
|
} fndatastr; |
| 217 |
|
|
| 218 |
|
static fndatastr exclude_from_data = { &exclude_from, &exclude_from_last }; |
| 219 |
|
static fndatastr include_from_data = { &include_from, &include_from_last }; |
| 220 |
|
static fndatastr file_lists_data = { &file_lists, &file_lists_last }; |
| 221 |
|
static fndatastr pattern_files_data = { &pattern_files, &pattern_files_last }; |
| 222 |
|
|
| 223 |
|
/* Structure for pattern and its compiled form; used for matching patterns and |
| 224 |
|
also for include/exclude patterns. */ |
| 225 |
|
|
| 226 |
|
typedef struct patstr { |
| 227 |
|
struct patstr *next; |
| 228 |
|
char *string; |
| 229 |
|
pcre *compiled; |
| 230 |
|
pcre_extra *hint; |
| 231 |
|
} patstr; |
| 232 |
|
|
| 233 |
|
static patstr *patterns = NULL; |
| 234 |
|
static patstr *patterns_last = NULL; |
| 235 |
|
static patstr *include_patterns = NULL; |
| 236 |
|
static patstr *include_patterns_last = NULL; |
| 237 |
|
static patstr *exclude_patterns = NULL; |
| 238 |
|
static patstr *exclude_patterns_last = NULL; |
| 239 |
|
static patstr *include_dir_patterns = NULL; |
| 240 |
|
static patstr *include_dir_patterns_last = NULL; |
| 241 |
|
static patstr *exclude_dir_patterns = NULL; |
| 242 |
|
static patstr *exclude_dir_patterns_last = NULL; |
| 243 |
|
|
| 244 |
|
/* Structure holding the two variables that describe a pattern chain. A pointer |
| 245 |
|
to such structures is used for each appropriate option. */ |
| 246 |
|
|
| 247 |
|
typedef struct patdatastr { |
| 248 |
|
patstr **anchor; |
| 249 |
|
patstr **lastptr; |
| 250 |
|
} patdatastr; |
| 251 |
|
|
| 252 |
|
static patdatastr match_patdata = { &patterns, &patterns_last }; |
| 253 |
|
static patdatastr include_patdata = { &include_patterns, &include_patterns_last }; |
| 254 |
|
static patdatastr exclude_patdata = { &exclude_patterns, &exclude_patterns_last }; |
| 255 |
|
static patdatastr include_dir_patdata = { &include_dir_patterns, &include_dir_patterns_last }; |
| 256 |
|
static patdatastr exclude_dir_patdata = { &exclude_dir_patterns, &exclude_dir_patterns_last }; |
| 257 |
|
|
| 258 |
|
static patstr **incexlist[4] = { &include_patterns, &exclude_patterns, |
| 259 |
|
&include_dir_patterns, &exclude_dir_patterns }; |
| 260 |
|
|
| 261 |
|
static const char *incexname[4] = { "--include", "--exclude", |
| 262 |
|
"--include-dir", "--exclude-dir" }; |
| 263 |
|
|
| 264 |
/* Structure for options and list of them */ |
/* Structure for options and list of them */ |
| 265 |
|
|
| 266 |
enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER, |
enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER, |
| 267 |
OP_OP_NUMBER, OP_PATLIST, OP_BINFILES }; |
OP_OP_NUMBER, OP_PATLIST, OP_FILELIST, OP_BINFILES }; |
| 268 |
|
|
| 269 |
typedef struct option_item { |
typedef struct option_item { |
| 270 |
int type; |
int type; |
| 295 |
#define N_NOJIT (-16) |
#define N_NOJIT (-16) |
| 296 |
#define N_FILE_LIST (-17) |
#define N_FILE_LIST (-17) |
| 297 |
#define N_BINARY_FILES (-18) |
#define N_BINARY_FILES (-18) |
| 298 |
|
#define N_EXCLUDE_FROM (-19) |
| 299 |
|
#define N_INCLUDE_FROM (-20) |
| 300 |
|
|
| 301 |
static option_item optionlist[] = { |
static option_item optionlist[] = { |
| 302 |
{ OP_NODATA, N_NULL, NULL, "", "terminate options" }, |
{ OP_NODATA, N_NULL, NULL, "", "terminate options" }, |
| 312 |
{ OP_NODATA, 'c', NULL, "count", "print only a count of matching lines per FILE" }, |
{ OP_NODATA, 'c', NULL, "count", "print only a count of matching lines per FILE" }, |
| 313 |
{ OP_STRING, 'D', &DEE_option, "devices=action","how to handle devices, FIFOs, and sockets" }, |
{ OP_STRING, 'D', &DEE_option, "devices=action","how to handle devices, FIFOs, and sockets" }, |
| 314 |
{ OP_STRING, 'd', &dee_option, "directories=action", "how to handle directories" }, |
{ OP_STRING, 'd', &dee_option, "directories=action", "how to handle directories" }, |
| 315 |
{ OP_PATLIST, 'e', NULL, "regex(p)=pattern", "specify pattern (may be used more than once)" }, |
{ OP_PATLIST, 'e', &match_patdata, "regex(p)=pattern", "specify pattern (may be used more than once)" }, |
| 316 |
{ OP_NODATA, 'F', NULL, "fixed-strings", "patterns are sets of newline-separated strings" }, |
{ OP_NODATA, 'F', NULL, "fixed-strings", "patterns are sets of newline-separated strings" }, |
| 317 |
{ OP_STRING, 'f', &pattern_filename, "file=path", "read patterns from file" }, |
{ OP_FILELIST, 'f', &pattern_files_data, "file=path", "read patterns from file" }, |
| 318 |
{ OP_STRING, N_FILE_LIST, &file_list, "file-list=path","read files to search from file" }, |
{ OP_FILELIST, N_FILE_LIST, &file_lists_data, "file-list=path","read files to search from file" }, |
| 319 |
{ OP_NODATA, N_FOFFSETS, NULL, "file-offsets", "output file offsets, not text" }, |
{ OP_NODATA, N_FOFFSETS, NULL, "file-offsets", "output file offsets, not text" }, |
| 320 |
{ OP_NODATA, 'H', NULL, "with-filename", "force the prefixing filename on output" }, |
{ OP_NODATA, 'H', NULL, "with-filename", "force the prefixing filename on output" }, |
| 321 |
{ OP_NODATA, 'h', NULL, "no-filename", "suppress the prefixing filename on output" }, |
{ OP_NODATA, 'h', NULL, "no-filename", "suppress the prefixing filename on output" }, |
| 340 |
{ OP_OP_NUMBER, 'o', &only_matching, "only-matching=n", "show only the part of the line that matched" }, |
{ OP_OP_NUMBER, 'o', &only_matching, "only-matching=n", "show only the part of the line that matched" }, |
| 341 |
{ OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, |
{ OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, |
| 342 |
{ OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" }, |
{ OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" }, |
| 343 |
{ OP_STRING, N_EXCLUDE,&exclude_pattern, "exclude=pattern","exclude matching files when recursing" }, |
{ OP_PATLIST, N_EXCLUDE,&exclude_patdata, "exclude=pattern","exclude matching files when recursing" }, |
| 344 |
{ OP_STRING, N_INCLUDE,&include_pattern, "include=pattern","include matching files when recursing" }, |
{ OP_PATLIST, N_INCLUDE,&include_patdata, "include=pattern","include matching files when recursing" }, |
| 345 |
{ OP_STRING, N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" }, |
{ OP_PATLIST, N_EXCLUDE_DIR,&exclude_dir_patdata, "exclude-dir=pattern","exclude matching directories when recursing" }, |
| 346 |
{ OP_STRING, N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" }, |
{ OP_PATLIST, N_INCLUDE_DIR,&include_dir_patdata, "include-dir=pattern","include matching directories when recursing" }, |
| 347 |
|
{ OP_FILELIST, N_EXCLUDE_FROM,&exclude_from_data, "exclude-from=path", "read exclude list from file" }, |
| 348 |
|
{ OP_FILELIST, N_INCLUDE_FROM,&include_from_data, "include-from=path", "read include list from file" }, |
| 349 |
|
|
| 350 |
/* These two were accidentally implemented with underscores instead of |
/* These two were accidentally implemented with underscores instead of |
| 351 |
hyphens in the option names. As this was not discovered for several releases, |
hyphens in the option names. As this was not discovered for several releases, |
| 352 |
the incorrect versions are left in the table for compatibility. However, the |
the incorrect versions are left in the table for compatibility. However, the |
| 353 |
--help function misses out any option that has an underscore in its name. */ |
--help function misses out any option that has an underscore in its name. */ |
| 354 |
|
|
| 355 |
{ OP_STRING, N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" }, |
{ OP_PATLIST, N_EXCLUDE_DIR,&exclude_dir_patdata, "exclude_dir=pattern","exclude matching directories when recursing" }, |
| 356 |
{ OP_STRING, N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" }, |
{ OP_PATLIST, N_INCLUDE_DIR,&include_dir_patdata, "include_dir=pattern","include matching directories when recursing" }, |
| 357 |
|
|
| 358 |
#ifdef JFRIEDL_DEBUG |
#ifdef JFRIEDL_DEBUG |
| 359 |
{ OP_OP_NUMBER, 'S', &S_arg, "jeffS", "replace matched (sub)string with X" }, |
{ OP_OP_NUMBER, 'S', &S_arg, "jeffS", "replace matched (sub)string with X" }, |
| 370 |
/* Tables for prefixing and suffixing patterns, according to the -w, -x, and -F |
/* Tables for prefixing and suffixing patterns, according to the -w, -x, and -F |
| 371 |
options. These set the 1, 2, and 4 bits in process_options, respectively. Note |
options. These set the 1, 2, and 4 bits in process_options, respectively. Note |
| 372 |
that the combination of -w and -x has the same effect as -x on its own, so we |
that the combination of -w and -x has the same effect as -x on its own, so we |
| 373 |
can treat them as the same. */ |
can treat them as the same. Note that the MAXPATLEN macro assumes the longest |
| 374 |
|
prefix+suffix is 10 characters; if anything longer is added, it must be |
| 375 |
|
adjusted. */ |
| 376 |
|
|
| 377 |
static const char *prefix[] = { |
static const char *prefix[] = { |
| 378 |
"", "\\b", "^(?:", "^(?:", "\\Q", "\\b\\Q", "^(?:\\Q", "^(?:\\Q" }; |
"", "\\b", "^(?:", "^(?:", "\\Q", "\\b\\Q", "^(?:\\Q", "^(?:\\Q" }; |
| 393 |
|
|
| 394 |
|
|
| 395 |
/************************************************* |
/************************************************* |
| 396 |
|
* Add item to chain of patterns * |
| 397 |
|
*************************************************/ |
| 398 |
|
|
| 399 |
|
/* Used to add an item onto a chain, or just return an unconnected item if the |
| 400 |
|
"after" argument is NULL. |
| 401 |
|
|
| 402 |
|
Arguments: |
| 403 |
|
s pattern string to add |
| 404 |
|
after if not NULL points to item to insert after |
| 405 |
|
|
| 406 |
|
Returns: new pattern block, or NULL after malloc failure |
| 407 |
|
*/ |
| 408 |
|
|
| 409 |
|
static patstr * |
| 410 |
|
add_pattern(char *s, patstr *after) |
| 411 |
|
{ |
| 412 |
|
patstr *p = (patstr *)malloc(sizeof(patstr)); |
| 413 |
|
if (p == NULL) |
| 414 |
|
{ |
| 415 |
|
fprintf(stderr, "pcregrep: malloc failed\n"); |
| 416 |
|
return NULL; |
| 417 |
|
} |
| 418 |
|
if (strlen(s) > MAXPATLEN) |
| 419 |
|
{ |
| 420 |
|
fprintf(stderr, "pcregrep: pattern is too long (limit is %d bytes)\n", |
| 421 |
|
MAXPATLEN); |
| 422 |
|
return NULL; |
| 423 |
|
} |
| 424 |
|
p->next = NULL; |
| 425 |
|
p->string = s; |
| 426 |
|
p->compiled = NULL; |
| 427 |
|
p->hint = NULL; |
| 428 |
|
|
| 429 |
|
if (after != NULL) |
| 430 |
|
{ |
| 431 |
|
p->next = after->next; |
| 432 |
|
after->next = p; |
| 433 |
|
} |
| 434 |
|
return p; |
| 435 |
|
} |
| 436 |
|
|
| 437 |
|
|
| 438 |
|
/************************************************* |
| 439 |
|
* Free chain of patterns * |
| 440 |
|
*************************************************/ |
| 441 |
|
|
| 442 |
|
/* Used for several chains of patterns. |
| 443 |
|
|
| 444 |
|
Argument: pointer to start of chain |
| 445 |
|
Returns: nothing |
| 446 |
|
*/ |
| 447 |
|
|
| 448 |
|
static void |
| 449 |
|
free_pattern_chain(patstr *pc) |
| 450 |
|
{ |
| 451 |
|
while (pc != NULL) |
| 452 |
|
{ |
| 453 |
|
patstr *p = pc; |
| 454 |
|
pc = p->next; |
| 455 |
|
if (p->hint != NULL) pcre_free_study(p->hint); |
| 456 |
|
if (p->compiled != NULL) pcre_free(p->compiled); |
| 457 |
|
free(p); |
| 458 |
|
} |
| 459 |
|
} |
| 460 |
|
|
| 461 |
|
|
| 462 |
|
/************************************************* |
| 463 |
|
* Free chain of file names * |
| 464 |
|
*************************************************/ |
| 465 |
|
|
| 466 |
|
/* |
| 467 |
|
Argument: pointer to start of chain |
| 468 |
|
Returns: nothing |
| 469 |
|
*/ |
| 470 |
|
|
| 471 |
|
static void |
| 472 |
|
free_file_chain(fnstr *fn) |
| 473 |
|
{ |
| 474 |
|
while (fn != NULL) |
| 475 |
|
{ |
| 476 |
|
fnstr *f = fn; |
| 477 |
|
fn = f->next; |
| 478 |
|
free(f); |
| 479 |
|
} |
| 480 |
|
} |
| 481 |
|
|
| 482 |
|
|
| 483 |
|
/************************************************* |
| 484 |
* Exit from the program * |
* Exit from the program * |
| 485 |
*************************************************/ |
*************************************************/ |
| 486 |
|
|
| 521 |
#include <dirent.h> |
#include <dirent.h> |
| 522 |
|
|
| 523 |
typedef DIR directory_type; |
typedef DIR directory_type; |
| 524 |
|
#define FILESEP '/' |
| 525 |
|
|
| 526 |
static int |
static int |
| 527 |
isdirectory(char *filename) |
isdirectory(char *filename) |
| 529 |
struct stat statbuf; |
struct stat statbuf; |
| 530 |
if (stat(filename, &statbuf) < 0) |
if (stat(filename, &statbuf) < 0) |
| 531 |
return 0; /* In the expectation that opening as a file will fail */ |
return 0; /* In the expectation that opening as a file will fail */ |
| 532 |
return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0; |
return (statbuf.st_mode & S_IFMT) == S_IFDIR; |
| 533 |
} |
} |
| 534 |
|
|
| 535 |
static directory_type * |
static directory_type * |
| 616 |
WIN32_FIND_DATA data; |
WIN32_FIND_DATA data; |
| 617 |
} directory_type; |
} directory_type; |
| 618 |
|
|
| 619 |
|
#DEFINE FILESEP '/' |
| 620 |
|
|
| 621 |
int |
int |
| 622 |
isdirectory(char *filename) |
isdirectory(char *filename) |
| 623 |
{ |
{ |
| 624 |
DWORD attr = GetFileAttributes(filename); |
DWORD attr = GetFileAttributes(filename); |
| 625 |
if (attr == INVALID_FILE_ATTRIBUTES) |
if (attr == INVALID_FILE_ATTRIBUTES) |
| 626 |
return 0; |
return 0; |
| 627 |
return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) ? '/' : 0; |
return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; |
| 628 |
} |
} |
| 629 |
|
|
| 630 |
directory_type * |
directory_type * |
| 635 |
directory_type *dir; |
directory_type *dir; |
| 636 |
DWORD err; |
DWORD err; |
| 637 |
len = strlen(filename); |
len = strlen(filename); |
| 638 |
pattern = (char *) malloc(len + 3); |
pattern = (char *)malloc(len + 3); |
| 639 |
dir = (directory_type *) malloc(sizeof(*dir)); |
dir = (directory_type *)malloc(sizeof(*dir)); |
| 640 |
if ((pattern == NULL) || (dir == NULL)) |
if ((pattern == NULL) || (dir == NULL)) |
| 641 |
{ |
{ |
| 642 |
fprintf(stderr, "pcregrep: malloc failed\n"); |
fprintf(stderr, "pcregrep: malloc failed\n"); |
| 722 |
|
|
| 723 |
#else |
#else |
| 724 |
|
|
| 725 |
|
#DEFINE FILESEP 0; |
| 726 |
typedef void directory_type; |
typedef void directory_type; |
| 727 |
|
|
| 728 |
int isdirectory(char *filename) { return 0; } |
int isdirectory(char *filename) { return 0; } |
| 779 |
|
|
| 780 |
|
|
| 781 |
/************************************************* |
/************************************************* |
| 782 |
|
* Test exclude/includes * |
| 783 |
|
*************************************************/ |
| 784 |
|
|
| 785 |
|
/* If any exclude pattern matches, the path is excluded. Otherwise, unless |
| 786 |
|
there are no includes, the path must match an include pattern. |
| 787 |
|
|
| 788 |
|
Arguments: |
| 789 |
|
path the path to be matched |
| 790 |
|
ip the chain of include patterns |
| 791 |
|
ep the chain of exclude patterns |
| 792 |
|
|
| 793 |
|
Returns: TRUE if the path is not excluded |
| 794 |
|
*/ |
| 795 |
|
|
| 796 |
|
static BOOL |
| 797 |
|
test_incexc(char *path, patstr *ip, patstr *ep) |
| 798 |
|
{ |
| 799 |
|
int plen = strlen(path); |
| 800 |
|
|
| 801 |
|
for (; ep != NULL; ep = ep->next) |
| 802 |
|
{ |
| 803 |
|
if (pcre_exec(ep->compiled, NULL, path, plen, 0, 0, NULL, 0) >= 0) |
| 804 |
|
return FALSE; |
| 805 |
|
} |
| 806 |
|
|
| 807 |
|
if (ip == NULL) return TRUE; |
| 808 |
|
|
| 809 |
|
for (; ip != NULL; ip = ip->next) |
| 810 |
|
{ |
| 811 |
|
if (pcre_exec(ip->compiled, NULL, path, plen, 0, 0, NULL, 0) >= 0) |
| 812 |
|
return TRUE; |
| 813 |
|
} |
| 814 |
|
|
| 815 |
|
return FALSE; |
| 816 |
|
} |
| 817 |
|
|
| 818 |
|
|
| 819 |
|
|
| 820 |
|
/************************************************* |
| 821 |
* Read one line of input * |
* Read one line of input * |
| 822 |
*************************************************/ |
*************************************************/ |
| 823 |
|
|
| 1134 |
Returns: nothing |
Returns: nothing |
| 1135 |
*/ |
*/ |
| 1136 |
|
|
| 1137 |
static void do_after_lines(int lastmatchnumber, char *lastmatchrestart, |
static void |
| 1138 |
char *endptr, char *printname) |
do_after_lines(int lastmatchnumber, char *lastmatchrestart, char *endptr, |
| 1139 |
|
char *printname) |
| 1140 |
{ |
{ |
| 1141 |
if (after_context > 0 && lastmatchnumber > 0) |
if (after_context > 0 && lastmatchnumber > 0) |
| 1142 |
{ |
{ |
| 1183 |
{ |
{ |
| 1184 |
int i; |
int i; |
| 1185 |
size_t slen = length; |
size_t slen = length; |
| 1186 |
|
patstr *p = patterns; |
| 1187 |
const char *msg = "this text:\n\n"; |
const char *msg = "this text:\n\n"; |
| 1188 |
|
|
| 1189 |
if (slen > 200) |
if (slen > 200) |
| 1190 |
{ |
{ |
| 1191 |
slen = 200; |
slen = 200; |
| 1192 |
msg = "text that starts:\n\n"; |
msg = "text that starts:\n\n"; |
| 1193 |
} |
} |
| 1194 |
for (i = 0; i < pattern_count; i++) |
for (i = 1; p != NULL; p = p->next, i++) |
| 1195 |
{ |
{ |
| 1196 |
*mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length, |
*mrc = pcre_exec(p->compiled, p->hint, matchptr, (int)length, |
| 1197 |
startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE); |
startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE); |
| 1198 |
if (*mrc >= 0) return TRUE; |
if (*mrc >= 0) return TRUE; |
| 1199 |
if (*mrc == PCRE_ERROR_NOMATCH) continue; |
if (*mrc == PCRE_ERROR_NOMATCH) continue; |
| 1200 |
fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc); |
fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc); |
| 1201 |
if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1); |
if (patterns->next != NULL) fprintf(stderr, "pattern number %d to ", i); |
| 1202 |
fprintf(stderr, "%s", msg); |
fprintf(stderr, "%s", msg); |
| 1203 |
FWRITE(matchptr, 1, slen, stderr); /* In case binary zero included */ |
FWRITE(matchptr, 1, slen, stderr); /* In case binary zero included */ |
| 1204 |
fprintf(stderr, "\n\n"); |
fprintf(stderr, "\n\n"); |
| 1393 |
|
|
| 1394 |
|
|
| 1395 |
for (i = 0; i < jfriedl_XR; i++) |
for (i = 0; i < jfriedl_XR; i++) |
| 1396 |
match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0, |
match = (pcre_exec(patterns->compiled, patterns->hint, ptr, length, 0, |
| 1397 |
PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0); |
PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0); |
| 1398 |
|
|
| 1399 |
if (gettimeofday(&end_time, &dummy) != 0) |
if (gettimeofday(&end_time, &dummy) != 0) |
| 1796 |
dir_recurse TRUE if recursing is wanted (-r or -drecurse) |
dir_recurse TRUE if recursing is wanted (-r or -drecurse) |
| 1797 |
only_one_at_top TRUE if the path is the only one at toplevel |
only_one_at_top TRUE if the path is the only one at toplevel |
| 1798 |
|
|
| 1799 |
Returns: 0 if there was at least one match |
Returns: -1 the file/directory was skipped |
| 1800 |
|
0 if there was at least one match |
| 1801 |
1 if there were no matches |
1 if there were no matches |
| 1802 |
2 there was some kind of error |
2 there was some kind of error |
| 1803 |
|
|
| 1808 |
grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top) |
grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top) |
| 1809 |
{ |
{ |
| 1810 |
int rc = 1; |
int rc = 1; |
|
int sep; |
|
| 1811 |
int frtype; |
int frtype; |
| 1812 |
void *handle; |
void *handle; |
| 1813 |
|
char *lastcomp; |
| 1814 |
FILE *in = NULL; /* Ensure initialized */ |
FILE *in = NULL; /* Ensure initialized */ |
| 1815 |
|
|
| 1816 |
#ifdef SUPPORT_LIBZ |
#ifdef SUPPORT_LIBZ |
| 1834 |
stdin_name : NULL); |
stdin_name : NULL); |
| 1835 |
} |
} |
| 1836 |
|
|
| 1837 |
/* If the file is a directory, skip if skipping or if we are recursing, scan |
/* Inclusion and exclusion: --include-dir and --exclude-dir apply only to |
| 1838 |
each file and directory within it, subject to any include or exclude patterns |
directories, whereas --include and --exclude apply to everything else. The test |
| 1839 |
that were set. The scanning code is localized so it can be made |
is against the final component of the path. */ |
| 1840 |
system-specific. */ |
|
| 1841 |
|
lastcomp = strrchr(pathname, FILESEP); |
| 1842 |
|
lastcomp = (lastcomp == NULL)? pathname : lastcomp + 1; |
| 1843 |
|
|
| 1844 |
|
/* If the file is a directory, skip if not recursing or if explicitly excluded. |
| 1845 |
|
Otherwise, scan the directory and recurse for each path within it. The scanning |
| 1846 |
|
code is localized so it can be made system-specific. */ |
| 1847 |
|
|
| 1848 |
|
if (isdirectory(pathname)) |
| 1849 |
|
{ |
| 1850 |
|
if (dee_action == dee_SKIP || |
| 1851 |
|
!test_incexc(lastcomp, include_dir_patterns, exclude_dir_patterns)) |
| 1852 |
|
return -1; |
| 1853 |
|
|
|
if ((sep = isdirectory(pathname)) != 0) |
|
|
{ |
|
|
if (dee_action == dee_SKIP) return 1; |
|
| 1854 |
if (dee_action == dee_RECURSE) |
if (dee_action == dee_RECURSE) |
| 1855 |
{ |
{ |
| 1856 |
char buffer[1024]; |
char buffer[1024]; |
| 1867 |
|
|
| 1868 |
while ((nextfile = readdirectory(dir)) != NULL) |
while ((nextfile = readdirectory(dir)) != NULL) |
| 1869 |
{ |
{ |
| 1870 |
int frc, nflen; |
int frc; |
| 1871 |
sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile); |
sprintf(buffer, "%.512s%c%.128s", pathname, FILESEP, nextfile); |
|
nflen = (int)(strlen(nextfile)); |
|
|
|
|
|
if (isdirectory(buffer)) |
|
|
{ |
|
|
if (exclude_dir_compiled != NULL && |
|
|
pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0) |
|
|
continue; |
|
|
|
|
|
if (include_dir_compiled != NULL && |
|
|
pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0) |
|
|
continue; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (exclude_compiled != NULL && |
|
|
pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0) |
|
|
continue; |
|
|
|
|
|
if (include_compiled != NULL && |
|
|
pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0) |
|
|
continue; |
|
|
} |
|
|
|
|
| 1872 |
frc = grep_or_recurse(buffer, dir_recurse, FALSE); |
frc = grep_or_recurse(buffer, dir_recurse, FALSE); |
| 1873 |
if (frc > 1) rc = frc; |
if (frc > 1) rc = frc; |
| 1874 |
else if (frc == 0 && rc == 1) rc = 0; |
else if (frc == 0 && rc == 1) rc = 0; |
| 1880 |
} |
} |
| 1881 |
|
|
| 1882 |
/* If the file is not a directory and not a regular file, skip it if that's |
/* If the file is not a directory and not a regular file, skip it if that's |
| 1883 |
been requested. */ |
been requested. Otherwise, check for explicit include/exclude. */ |
| 1884 |
|
|
| 1885 |
else if (!isregfile(pathname) && DEE_action == DEE_SKIP) return 1; |
else if ((!isregfile(pathname) && DEE_action == DEE_SKIP) || |
| 1886 |
|
!test_incexc(lastcomp, include_patterns, exclude_patterns)) |
| 1887 |
|
return -1; |
| 1888 |
|
|
| 1889 |
/* Control reaches here if we have a regular file, or if we have a directory |
/* Control reaches here if we have a regular file, or if we have a directory |
| 1890 |
and recursion or skipping was not requested, or if we have anything else and |
and recursion or skipping was not requested, or if we have anything else and |
| 2085 |
printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE); |
printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE); |
| 2086 |
printf("When reading patterns or file names from a file, trailing white\n"); |
printf("When reading patterns or file names from a file, trailing white\n"); |
| 2087 |
printf("space is removed and blank lines are ignored.\n"); |
printf("space is removed and blank lines are ignored.\n"); |
| 2088 |
printf("There is a maximum of %d patterns, each of maximum size %d bytes.\n", |
printf("The maximum size of any pattern is %d bytes.\n", MAXPATLEN); |
|
MAX_PATTERN_COUNT, PATBUFSIZE); |
|
| 2089 |
|
|
| 2090 |
printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n"); |
printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n"); |
| 2091 |
printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n"); |
printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n"); |
| 2129 |
case 'x': process_options |= PO_LINE_MATCH; break; |
case 'x': process_options |= PO_LINE_MATCH; break; |
| 2130 |
|
|
| 2131 |
case 'V': |
case 'V': |
| 2132 |
fprintf(stderr, "pcregrep version %s\n", pcre_version()); |
fprintf(stdout, "pcregrep version %s\n", pcre_version()); |
| 2133 |
pcregrep_exit(0); |
pcregrep_exit(0); |
| 2134 |
break; |
break; |
| 2135 |
|
|
| 2173 |
* Compile a single pattern * |
* Compile a single pattern * |
| 2174 |
*************************************************/ |
*************************************************/ |
| 2175 |
|
|
| 2176 |
/* When the -F option has been used, this is called for each substring. |
/* Do nothing if the pattern has already been compiled. This is the case for |
| 2177 |
Otherwise it's called for each supplied pattern. |
include/exclude patterns read from a file. |
| 2178 |
|
|
| 2179 |
|
When the -F option has been used, each "pattern" may be a list of strings, |
| 2180 |
|
separated by line breaks. They will be matched literally. We split such a |
| 2181 |
|
string and compile the first substring, inserting an additional block into the |
| 2182 |
|
pattern chain. |
| 2183 |
|
|
| 2184 |
Arguments: |
Arguments: |
| 2185 |
pattern the pattern string |
p points to the pattern block |
| 2186 |
options the PCRE options |
options the PCRE options |
| 2187 |
filename the file name, or NULL for a command-line pattern |
popts the processing options |
| 2188 |
|
fromfile TRUE if the pattern was read from a file |
| 2189 |
|
fromtext file name or identifying text (e.g. "include") |
| 2190 |
count 0 if this is the only command line pattern, or |
count 0 if this is the only command line pattern, or |
| 2191 |
number of the command line pattern, or |
number of the command line pattern, or |
| 2192 |
linenumber for a pattern from a file |
linenumber for a pattern from a file |
| 2195 |
*/ |
*/ |
| 2196 |
|
|
| 2197 |
static BOOL |
static BOOL |
| 2198 |
compile_single_pattern(char *pattern, int options, char *filename, int count) |
compile_pattern(patstr *p, int options, int popts, int fromfile, |
| 2199 |
|
const char *fromtext, int count) |
| 2200 |
{ |
{ |
| 2201 |
char buffer[PATBUFSIZE]; |
char buffer[PATBUFSIZE]; |
| 2202 |
const char *error; |
const char *error; |
| 2203 |
|
char *ps = p->string; |
| 2204 |
|
int patlen = strlen(ps); |
| 2205 |
int errptr; |
int errptr; |
| 2206 |
|
|
| 2207 |
if (pattern_count >= MAX_PATTERN_COUNT) |
if (p->compiled != NULL) return TRUE; |
|
{ |
|
|
fprintf(stderr, "pcregrep: Too many %spatterns (max %d)\n", |
|
|
(filename == NULL)? "command-line " : "", MAX_PATTERN_COUNT); |
|
|
return FALSE; |
|
|
} |
|
| 2208 |
|
|
| 2209 |
sprintf(buffer, "%s%.*s%s", prefix[process_options], bufthird, pattern, |
if ((popts & PO_FIXED_STRINGS) != 0) |
|
suffix[process_options]); |
|
|
pattern_list[pattern_count] = |
|
|
pcre_compile(buffer, options, &error, &errptr, pcretables); |
|
|
if (pattern_list[pattern_count] != NULL) |
|
| 2210 |
{ |
{ |
| 2211 |
pattern_count++; |
int ellength; |
| 2212 |
return TRUE; |
char *eop = ps + patlen; |
| 2213 |
|
char *pe = end_of_line(ps, eop, &ellength); |
| 2214 |
|
|
| 2215 |
|
if (ellength != 0) |
| 2216 |
|
{ |
| 2217 |
|
if (add_pattern(pe, p) == NULL) return FALSE; |
| 2218 |
|
patlen = (int)(pe - ps - ellength); |
| 2219 |
|
} |
| 2220 |
} |
} |
| 2221 |
|
|
| 2222 |
|
sprintf(buffer, "%s%.*s%s", prefix[popts], patlen, ps, suffix[popts]); |
| 2223 |
|
p->compiled = pcre_compile(buffer, options, &error, &errptr, pcretables); |
| 2224 |
|
if (p->compiled != NULL) return TRUE; |
| 2225 |
|
|
| 2226 |
/* Handle compile errors */ |
/* Handle compile errors */ |
| 2227 |
|
|
| 2228 |
errptr -= (int)strlen(prefix[process_options]); |
errptr -= (int)strlen(prefix[popts]); |
| 2229 |
if (errptr > (int)strlen(pattern)) errptr = (int)strlen(pattern); |
if (errptr > patlen) errptr = patlen; |
| 2230 |
|
|
| 2231 |
if (filename == NULL) |
if (fromfile) |
| 2232 |
{ |
{ |
| 2233 |
if (count == 0) |
fprintf(stderr, "pcregrep: Error in regex in line %d of %s " |
| 2234 |
fprintf(stderr, "pcregrep: Error in command-line regex " |
"at offset %d: %s\n", count, fromtext, errptr, error); |
|
"at offset %d: %s\n", errptr, error); |
|
|
else |
|
|
fprintf(stderr, "pcregrep: Error in %s command-line regex " |
|
|
"at offset %d: %s\n", ordin(count), errptr, error); |
|
| 2235 |
} |
} |
| 2236 |
else |
else |
| 2237 |
{ |
{ |
| 2238 |
fprintf(stderr, "pcregrep: Error in regex in line %d of %s " |
if (count == 0) |
| 2239 |
"at offset %d: %s\n", count, filename, errptr, error); |
fprintf(stderr, "pcregrep: Error in %s regex at offset %d: %s\n", |
| 2240 |
|
fromtext, errptr, error); |
| 2241 |
|
else |
| 2242 |
|
fprintf(stderr, "pcregrep: Error in %s %s regex at offset %d: %s\n", |
| 2243 |
|
ordin(count), fromtext, errptr, error); |
| 2244 |
} |
} |
| 2245 |
|
|
| 2246 |
return FALSE; |
return FALSE; |
| 2249 |
|
|
| 2250 |
|
|
| 2251 |
/************************************************* |
/************************************************* |
| 2252 |
* Compile one supplied pattern * |
* Read and compile a file of patterns * |
| 2253 |
*************************************************/ |
*************************************************/ |
| 2254 |
|
|
| 2255 |
/* When the -F option has been used, each string may be a list of strings, |
/* This is used for --filelist, --include-from, and --exclude-from. |
|
separated by line breaks. They will be matched literally. |
|
| 2256 |
|
|
| 2257 |
Arguments: |
Arguments: |
| 2258 |
pattern the pattern string |
name the name of the file; "-" is stdin |
| 2259 |
options the PCRE options |
patptr pointer to the pattern chain anchor |
| 2260 |
filename the file name, or NULL for a command-line pattern |
patlastptr pointer to the last pattern pointer |
| 2261 |
count 0 if this is the only command line pattern, or |
popts the process options to pass to pattern_compile() |
|
number of the command line pattern, or |
|
|
linenumber for a pattern from a file |
|
| 2262 |
|
|
| 2263 |
Returns: TRUE on success, FALSE after an error |
Returns: TRUE if all went well |
| 2264 |
*/ |
*/ |
| 2265 |
|
|
| 2266 |
static BOOL |
static BOOL |
| 2267 |
compile_pattern(char *pattern, int options, char *filename, int count) |
read_pattern_file(char *name, patstr **patptr, patstr **patlastptr, int popts) |
| 2268 |
{ |
{ |
| 2269 |
if ((process_options & PO_FIXED_STRINGS) != 0) |
int linenumber = 0; |
| 2270 |
|
FILE *f; |
| 2271 |
|
char *filename; |
| 2272 |
|
char buffer[PATBUFSIZE]; |
| 2273 |
|
|
| 2274 |
|
if (strcmp(name, "-") == 0) |
| 2275 |
{ |
{ |
| 2276 |
char *eop = pattern + strlen(pattern); |
f = stdin; |
| 2277 |
char buffer[PATBUFSIZE]; |
filename = stdin_name; |
| 2278 |
|
} |
| 2279 |
|
else |
| 2280 |
|
{ |
| 2281 |
|
f = fopen(name, "r"); |
| 2282 |
|
if (f == NULL) |
| 2283 |
|
{ |
| 2284 |
|
fprintf(stderr, "pcregrep: Failed to open %s: %s\n", name, strerror(errno)); |
| 2285 |
|
return FALSE; |
| 2286 |
|
} |
| 2287 |
|
filename = name; |
| 2288 |
|
} |
| 2289 |
|
|
| 2290 |
|
while (fgets(buffer, PATBUFSIZE, f) != NULL) |
| 2291 |
|
{ |
| 2292 |
|
char *s = buffer + (int)strlen(buffer); |
| 2293 |
|
while (s > buffer && isspace((unsigned char)(s[-1]))) s--; |
| 2294 |
|
*s = 0; |
| 2295 |
|
linenumber++; |
| 2296 |
|
if (buffer[0] == 0) continue; /* Skip blank lines */ |
| 2297 |
|
|
| 2298 |
|
/* Note: this call to add_pattern() puts a pointer to the local variable |
| 2299 |
|
"buffer" into the pattern chain. However, that pointer is used only when |
| 2300 |
|
compiling the pattern, which happens immediately below, so we flatten it |
| 2301 |
|
afterwards, as a precaution against any later code trying to use it. */ |
| 2302 |
|
|
| 2303 |
|
*patlastptr = add_pattern(buffer, *patlastptr); |
| 2304 |
|
if (*patlastptr == NULL) return FALSE; |
| 2305 |
|
if (*patptr == NULL) *patptr = *patlastptr; |
| 2306 |
|
|
| 2307 |
|
/* This loop is needed because compiling a "pattern" when -F is set may add |
| 2308 |
|
on additional literal patterns if the original contains a newline. In the |
| 2309 |
|
common case, it never will, because fgets() stops at a newline. However, |
| 2310 |
|
the -N option can be used to give pcregrep a different newline setting. */ |
| 2311 |
|
|
| 2312 |
for(;;) |
for(;;) |
| 2313 |
{ |
{ |
| 2314 |
int ellength; |
if (!compile_pattern(*patlastptr, pcre_options, popts, TRUE, filename, |
| 2315 |
char *p = end_of_line(pattern, eop, &ellength); |
linenumber)) |
|
if (ellength == 0) |
|
|
return compile_single_pattern(pattern, options, filename, count); |
|
|
sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern); |
|
|
pattern = p; |
|
|
if (!compile_single_pattern(buffer, options, filename, count)) |
|
| 2316 |
return FALSE; |
return FALSE; |
| 2317 |
|
(*patlastptr)->string = NULL; /* Insurance */ |
| 2318 |
|
if ((*patlastptr)->next == NULL) break; |
| 2319 |
|
*patlastptr = (*patlastptr)->next; |
| 2320 |
} |
} |
| 2321 |
} |
} |
| 2322 |
else return compile_single_pattern(pattern, options, filename, count); |
|
| 2323 |
|
if (f != stdin) fclose(f); |
| 2324 |
|
return TRUE; |
| 2325 |
} |
} |
| 2326 |
|
|
| 2327 |
|
|
| 2337 |
{ |
{ |
| 2338 |
int i, j; |
int i, j; |
| 2339 |
int rc = 1; |
int rc = 1; |
|
int pcre_options = 0; |
|
|
int cmd_pattern_count = 0; |
|
|
int hint_count = 0; |
|
|
int errptr; |
|
| 2340 |
BOOL only_one_at_top; |
BOOL only_one_at_top; |
| 2341 |
char *patterns[MAX_PATTERN_COUNT]; |
patstr *cp; |
| 2342 |
|
fnstr *fn; |
| 2343 |
const char *locale_from = "--locale"; |
const char *locale_from = "--locale"; |
| 2344 |
const char *error; |
const char *error; |
| 2345 |
|
|
| 2379 |
|
|
| 2380 |
if (argv[i][1] == 0) |
if (argv[i][1] == 0) |
| 2381 |
{ |
{ |
| 2382 |
if (pattern_filename != NULL || pattern_count > 0) break; |
if (pattern_files != NULL || patterns != NULL) break; |
| 2383 |
else pcregrep_exit(usage(2)); |
else pcregrep_exit(usage(2)); |
| 2384 |
} |
} |
| 2385 |
|
|
| 2589 |
option_data = argv[++i]; |
option_data = argv[++i]; |
| 2590 |
} |
} |
| 2591 |
|
|
| 2592 |
/* If the option type is OP_PATLIST, it's the -e option, which can be called |
/* If the option type is OP_PATLIST, it's the -e option, or one of the |
| 2593 |
multiple times to create a list of patterns. */ |
include/exclude options, which can be called multiple times to create lists |
| 2594 |
|
of patterns. */ |
| 2595 |
|
|
| 2596 |
if (op->type == OP_PATLIST) |
if (op->type == OP_PATLIST) |
| 2597 |
{ |
{ |
| 2598 |
if (cmd_pattern_count >= MAX_PATTERN_COUNT) |
patdatastr *pd = (patdatastr *)op->dataptr; |
| 2599 |
|
*(pd->lastptr) = add_pattern(option_data, *(pd->lastptr)); |
| 2600 |
|
if (*(pd->lastptr) == NULL) goto EXIT2; |
| 2601 |
|
if (*(pd->anchor) == NULL) *(pd->anchor) = *(pd->lastptr); |
| 2602 |
|
} |
| 2603 |
|
|
| 2604 |
|
/* If the option type is OP_FILELIST, it's one of the options that names a |
| 2605 |
|
file. */ |
| 2606 |
|
|
| 2607 |
|
else if (op->type == OP_FILELIST) |
| 2608 |
|
{ |
| 2609 |
|
fndatastr *fd = (fndatastr *)op->dataptr; |
| 2610 |
|
fn = (fnstr *)malloc(sizeof(fnstr)); |
| 2611 |
|
if (fn == NULL) |
| 2612 |
{ |
{ |
| 2613 |
fprintf(stderr, "pcregrep: Too many command-line patterns (max %d)\n", |
fprintf(stderr, "pcregrep: malloc failed\n"); |
| 2614 |
MAX_PATTERN_COUNT); |
goto EXIT2; |
|
return 2; |
|
| 2615 |
} |
} |
| 2616 |
patterns[cmd_pattern_count++] = option_data; |
fn->next = NULL; |
| 2617 |
|
fn->name = option_data; |
| 2618 |
|
if (*(fd->anchor) == NULL) |
| 2619 |
|
*(fd->anchor) = fn; |
| 2620 |
|
else |
| 2621 |
|
(*(fd->lastptr))->next = fn; |
| 2622 |
|
*(fd->lastptr) = fn; |
| 2623 |
} |
} |
| 2624 |
|
|
| 2625 |
/* Handle OP_BINARY_FILES */ |
/* Handle OP_BINARY_FILES */ |
| 2834 |
} |
} |
| 2835 |
#endif |
#endif |
| 2836 |
|
|
| 2837 |
/* Get memory for the main buffer, and to store the pattern and hints lists. */ |
/* Get memory for the main buffer. */ |
| 2838 |
|
|
| 2839 |
bufsize = 3*bufthird; |
bufsize = 3*bufthird; |
| 2840 |
main_buffer = (char *)malloc(bufsize); |
main_buffer = (char *)malloc(bufsize); |
|
pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *)); |
|
|
hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *)); |
|
| 2841 |
|
|
| 2842 |
if (main_buffer == NULL || pattern_list == NULL || hints_list == NULL) |
if (main_buffer == NULL) |
| 2843 |
{ |
{ |
| 2844 |
fprintf(stderr, "pcregrep: malloc failed\n"); |
fprintf(stderr, "pcregrep: malloc failed\n"); |
| 2845 |
goto EXIT2; |
goto EXIT2; |
| 2846 |
} |
} |
| 2847 |
|
|
| 2848 |
/* If no patterns were provided by -e, and there is no file provided by -f, |
/* If no patterns were provided by -e, and there are no files provided by -f, |
| 2849 |
the first argument is the one and only pattern, and it must exist. */ |
the first argument is the one and only pattern, and it must exist. */ |
| 2850 |
|
|
| 2851 |
if (cmd_pattern_count == 0 && pattern_filename == NULL) |
if (patterns == NULL && pattern_files == NULL) |
| 2852 |
{ |
{ |
| 2853 |
if (i >= argc) return usage(2); |
if (i >= argc) return usage(2); |
| 2854 |
patterns[cmd_pattern_count++] = argv[i++]; |
patterns = patterns_last = add_pattern(argv[i++], NULL); |
| 2855 |
|
if (patterns == NULL) goto EXIT2; |
| 2856 |
} |
} |
| 2857 |
|
|
| 2858 |
/* Compile the patterns that were provided on the command line, either by |
/* Compile the patterns that were provided on the command line, either by |
| 2859 |
multiple uses of -e or as a single unkeyed pattern. */ |
multiple uses of -e or as a single unkeyed pattern. We cannot do this until |
| 2860 |
|
after all the command-line options are read so that we know which PCRE options |
| 2861 |
|
to use. When -F is used, compile_pattern() may add another block into the |
| 2862 |
|
chain, so we must not access the next pointer till after the compile. */ |
| 2863 |
|
|
| 2864 |
for (j = 0; j < cmd_pattern_count; j++) |
for (j = 1, cp = patterns; cp != NULL; j++, cp = cp->next) |
| 2865 |
{ |
{ |
| 2866 |
if (!compile_pattern(patterns[j], pcre_options, NULL, |
if (!compile_pattern(cp, pcre_options, process_options, FALSE, "command-line", |
| 2867 |
(j == 0 && cmd_pattern_count == 1)? 0 : j + 1)) |
(j == 1 && patterns->next == NULL)? 0 : j)) |
| 2868 |
goto EXIT2; |
goto EXIT2; |
| 2869 |
} |
} |
| 2870 |
|
|
| 2871 |
/* Compile the regular expressions that are provided in a file. */ |
/* Read and compile the regular expressions that are provided in files. */ |
| 2872 |
|
|
| 2873 |
if (pattern_filename != NULL) |
for (fn = pattern_files; fn != NULL; fn = fn->next) |
| 2874 |
{ |
{ |
| 2875 |
int linenumber = 0; |
if (!read_pattern_file(fn->name, &patterns, &patterns_last, process_options)) |
| 2876 |
FILE *f; |
goto EXIT2; |
| 2877 |
char *filename; |
} |
|
char buffer[PATBUFSIZE]; |
|
|
|
|
|
if (strcmp(pattern_filename, "-") == 0) |
|
|
{ |
|
|
f = stdin; |
|
|
filename = stdin_name; |
|
|
} |
|
|
else |
|
|
{ |
|
|
f = fopen(pattern_filename, "r"); |
|
|
if (f == NULL) |
|
|
{ |
|
|
fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename, |
|
|
strerror(errno)); |
|
|
goto EXIT2; |
|
|
} |
|
|
filename = pattern_filename; |
|
|
} |
|
|
|
|
|
while (fgets(buffer, PATBUFSIZE, f) != NULL) |
|
|
{ |
|
|
char *s = buffer + (int)strlen(buffer); |
|
|
while (s > buffer && isspace((unsigned char)(s[-1]))) s--; |
|
|
*s = 0; |
|
|
linenumber++; |
|
|
if (buffer[0] == 0) continue; /* Skip blank lines */ |
|
|
if (!compile_pattern(buffer, pcre_options, filename, linenumber)) |
|
|
goto EXIT2; |
|
|
} |
|
|
|
|
|
if (f != stdin) fclose(f); |
|
|
} |
|
| 2878 |
|
|
| 2879 |
/* Study the regular expressions, as we will be running them many times. Unless |
/* Study the regular expressions, as we will be running them many times. Unless |
| 2880 |
JIT has been explicitly disabled, arrange a stack for it to use. */ |
JIT has been explicitly disabled, arrange a stack for it to use. */ |
| 2884 |
jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024); |
jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024); |
| 2885 |
#endif |
#endif |
| 2886 |
|
|
| 2887 |
for (j = 0; j < pattern_count; j++) |
for (j = 1, cp = patterns; cp != NULL; j++, cp = cp->next) |
| 2888 |
{ |
{ |
| 2889 |
hints_list[j] = pcre_study(pattern_list[j], study_options, &error); |
cp->hint = pcre_study(cp->compiled, study_options, &error); |
| 2890 |
if (error != NULL) |
if (error != NULL) |
| 2891 |
{ |
{ |
| 2892 |
char s[16]; |
char s[16]; |
| 2893 |
if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j); |
if (patterns->next == NULL) s[0] = 0; else sprintf(s, " number %d", j); |
| 2894 |
fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error); |
fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error); |
| 2895 |
goto EXIT2; |
goto EXIT2; |
| 2896 |
} |
} |
|
hint_count++; |
|
| 2897 |
#ifdef SUPPORT_PCREGREP_JIT |
#ifdef SUPPORT_PCREGREP_JIT |
| 2898 |
if (jit_stack != NULL && hints_list[j] != NULL) |
if (jit_stack != NULL && cp->hint != NULL) |
| 2899 |
pcre_assign_jit_stack(hints_list[j], NULL, jit_stack); |
pcre_assign_jit_stack(cp->hint, NULL, jit_stack); |
| 2900 |
#endif |
#endif |
| 2901 |
} |
} |
| 2902 |
|
|
| 2905 |
|
|
| 2906 |
if (match_limit > 0 || match_limit_recursion > 0) |
if (match_limit > 0 || match_limit_recursion > 0) |
| 2907 |
{ |
{ |
| 2908 |
for (j = 0; j < pattern_count; j++) |
for (cp = patterns; cp != NULL; cp = cp->next) |
| 2909 |
{ |
{ |
| 2910 |
if (hints_list[j] == NULL) |
if (cp->hint == NULL) |
| 2911 |
{ |
{ |
| 2912 |
hints_list[j] = malloc(sizeof(pcre_extra)); |
cp->hint = (pcre_extra *)malloc(sizeof(pcre_extra)); |
| 2913 |
if (hints_list[j] == NULL) |
if (cp->hint == NULL) |
| 2914 |
{ |
{ |
| 2915 |
fprintf(stderr, "pcregrep: malloc failed\n"); |
fprintf(stderr, "pcregrep: malloc failed\n"); |
| 2916 |
pcregrep_exit(2); |
pcregrep_exit(2); |
| 2918 |
} |
} |
| 2919 |
if (match_limit > 0) |
if (match_limit > 0) |
| 2920 |
{ |
{ |
| 2921 |
hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT; |
cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT; |
| 2922 |
hints_list[j]->match_limit = match_limit; |
cp->hint->match_limit = match_limit; |
| 2923 |
} |
} |
| 2924 |
if (match_limit_recursion > 0) |
if (match_limit_recursion > 0) |
| 2925 |
{ |
{ |
| 2926 |
hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; |
cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; |
| 2927 |
hints_list[j]->match_limit_recursion = match_limit_recursion; |
cp->hint->match_limit_recursion = match_limit_recursion; |
| 2928 |
} |
} |
| 2929 |
} |
} |
| 2930 |
} |
} |
| 2931 |
|
|
| 2932 |
/* If there are include or exclude patterns, compile them. */ |
/* If there are include or exclude patterns read from the command line, compile |
| 2933 |
|
them. -F, -w, and -x do not apply, so the third argument of compile_pattern is |
| 2934 |
|
0. */ |
| 2935 |
|
|
| 2936 |
if (exclude_pattern != NULL) |
for (j = 0; j < 4; j++) |
| 2937 |
{ |
{ |
| 2938 |
exclude_compiled = pcre_compile(exclude_pattern, 0, &error, &errptr, |
int k; |
| 2939 |
pcretables); |
for (k = 1, cp = *(incexlist[j]); cp != NULL; k++, cp = cp->next) |
|
if (exclude_compiled == NULL) |
|
| 2940 |
{ |
{ |
| 2941 |
fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n", |
if (!compile_pattern(cp, pcre_options, 0, FALSE, incexname[j], |
| 2942 |
errptr, error); |
(k == 1 && cp->next == NULL)? 0 : k)) |
| 2943 |
goto EXIT2; |
goto EXIT2; |
| 2944 |
} |
} |
| 2945 |
} |
} |
| 2946 |
|
|
| 2947 |
if (include_pattern != NULL) |
/* Read and compile include/exclude patterns from files. */ |
| 2948 |
|
|
| 2949 |
|
for (fn = include_from; fn != NULL; fn = fn->next) |
| 2950 |
{ |
{ |
| 2951 |
include_compiled = pcre_compile(include_pattern, 0, &error, &errptr, |
if (!read_pattern_file(fn->name, &include_patterns, &include_patterns_last, 0)) |
|
pcretables); |
|
|
if (include_compiled == NULL) |
|
|
{ |
|
|
fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n", |
|
|
errptr, error); |
|
| 2952 |
goto EXIT2; |
goto EXIT2; |
|
} |
|
| 2953 |
} |
} |
| 2954 |
|
|
| 2955 |
if (exclude_dir_pattern != NULL) |
for (fn = exclude_from; fn != NULL; fn = fn->next) |
| 2956 |
{ |
{ |
| 2957 |
exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr, |
if (!read_pattern_file(fn->name, &exclude_patterns, &exclude_patterns_last, 0)) |
|
pcretables); |
|
|
if (exclude_dir_compiled == NULL) |
|
|
{ |
|
|
fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n", |
|
|
errptr, error); |
|
| 2958 |
goto EXIT2; |
goto EXIT2; |
|
} |
|
| 2959 |
} |
} |
| 2960 |
|
|
| 2961 |
if (include_dir_pattern != NULL) |
/* If there are no files that contain lists of files to search, and there are |
| 2962 |
|
no file arguments, search stdin, and then exit. */ |
| 2963 |
|
|
| 2964 |
|
if (file_lists == NULL && i >= argc) |
| 2965 |
{ |
{ |
| 2966 |
include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr, |
rc = pcregrep(stdin, FR_PLAIN, stdin_name, |
| 2967 |
pcretables); |
(filenames > FN_DEFAULT)? stdin_name : NULL); |
| 2968 |
if (include_dir_compiled == NULL) |
goto EXIT; |
|
{ |
|
|
fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n", |
|
|
errptr, error); |
|
|
goto EXIT2; |
|
|
} |
|
| 2969 |
} |
} |
| 2970 |
|
|
| 2971 |
/* If a file that contains a list of files to search has been specified, read |
/* If any files that contains a list of files to search have been specified, |
| 2972 |
it line by line and search the given files. Otherwise, if there are no further |
read them line by line and search the given files. */ |
|
arguments, do the business on stdin and exit. */ |
|
| 2973 |
|
|
| 2974 |
if (file_list != NULL) |
for (fn = file_lists; fn != NULL; fn = fn->next) |
| 2975 |
{ |
{ |
| 2976 |
char buffer[PATBUFSIZE]; |
char buffer[PATBUFSIZE]; |
| 2977 |
FILE *fl; |
FILE *fl; |
| 2978 |
if (strcmp(file_list, "-") == 0) fl = stdin; else |
if (strcmp(fn->name, "-") == 0) fl = stdin; else |
| 2979 |
{ |
{ |
| 2980 |
fl = fopen(file_list, "rb"); |
fl = fopen(fn->name, "rb"); |
| 2981 |
if (fl == NULL) |
if (fl == NULL) |
| 2982 |
{ |
{ |
| 2983 |
fprintf(stderr, "pcregrep: Failed to open %s: %s\n", file_list, |
fprintf(stderr, "pcregrep: Failed to open %s: %s\n", fn->name, |
| 2984 |
strerror(errno)); |
strerror(errno)); |
| 2985 |
goto EXIT2; |
goto EXIT2; |
| 2986 |
} |
} |
| 2998 |
else if (frc == 0 && rc == 1) rc = 0; |
else if (frc == 0 && rc == 1) rc = 0; |
| 2999 |
} |
} |
| 3000 |
} |
} |
| 3001 |
if (fl != stdin) fclose (fl); |
if (fl != stdin) fclose(fl); |
| 3002 |
} |
} |
| 3003 |
|
|
| 3004 |
/* Do this only if there was no file list (and no file arguments). */ |
/* After handling file-list, work through remaining arguments. Pass in the fact |
| 3005 |
|
that there is only one argument at top level - this suppresses the file name if |
| 3006 |
|
the argument is not a directory and filenames are not otherwise forced. */ |
| 3007 |
|
|
| 3008 |
else if (i >= argc) |
only_one_at_top = i == argc - 1 && file_lists == NULL; |
|
{ |
|
|
rc = pcregrep(stdin, FR_PLAIN, stdin_name, |
|
|
(filenames > FN_DEFAULT)? stdin_name : NULL); |
|
|
goto EXIT; |
|
|
} |
|
|
|
|
|
/* After handling file-list or if there are remaining arguments, work through |
|
|
them as files or directories. Pass in the fact that there is only one argument |
|
|
at top level - this suppresses the file name if the argument is not a directory |
|
|
and filenames are not otherwise forced. */ |
|
|
|
|
|
only_one_at_top = i == argc - 1 && file_list == NULL; |
|
| 3009 |
|
|
| 3010 |
for (; i < argc; i++) |
for (; i < argc; i++) |
| 3011 |
{ |
{ |
| 3019 |
#ifdef SUPPORT_PCREGREP_JIT |
#ifdef SUPPORT_PCREGREP_JIT |
| 3020 |
if (jit_stack != NULL) pcre_jit_stack_free(jit_stack); |
if (jit_stack != NULL) pcre_jit_stack_free(jit_stack); |
| 3021 |
#endif |
#endif |
| 3022 |
|
|
| 3023 |
if (main_buffer != NULL) free(main_buffer); |
if (main_buffer != NULL) free(main_buffer); |
| 3024 |
if (pattern_list != NULL) |
|
| 3025 |
{ |
free_pattern_chain(patterns); |
| 3026 |
for (i = 0; i < pattern_count; i++) free(pattern_list[i]); |
free_pattern_chain(include_patterns); |
| 3027 |
free(pattern_list); |
free_pattern_chain(include_dir_patterns); |
| 3028 |
} |
free_pattern_chain(exclude_patterns); |
| 3029 |
if (hints_list != NULL) |
free_pattern_chain(exclude_dir_patterns); |
| 3030 |
{ |
|
| 3031 |
for (i = 0; i < hint_count; i++) |
free_file_chain(exclude_from); |
| 3032 |
{ |
free_file_chain(include_from); |
| 3033 |
if (hints_list[i] != NULL) pcre_free_study(hints_list[i]); |
free_file_chain(pattern_files); |
| 3034 |
} |
free_file_chain(file_lists); |
| 3035 |
free(hints_list); |
|
|
} |
|
| 3036 |
pcregrep_exit(rc); |
pcregrep_exit(rc); |
| 3037 |
|
|
| 3038 |
EXIT2: |
EXIT2: |