/[pcre]/code/trunk/pcregrep.c
ViewVC logotype

Diff of /code/trunk/pcregrep.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1002 by ph10, Sat Jun 2 11:03:06 2012 UTC revision 1003 by ph10, Wed Aug 15 16:45:36 2012 UTC
# Line 70  POSSIBILITY OF SUCH DAMAGE. Line 70  POSSIBILITY OF SUCH DAMAGE.
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. */
# Line 139  static char *colour_string = (char *)"1; Line 140  static char *colour_string = (char *)"1;
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
# Line 199  static BOOL quiet = FALSE; Line 191  static BOOL quiet = FALSE;
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;
# Line 233  used to identify them. */ Line 295  used to identify them. */
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" },
# Line 248  static option_item optionlist[] = { Line 312  static option_item optionlist[] = {
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" },
# Line 276  static option_item optionlist[] = { Line 340  static option_item optionlist[] = {
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" },
# Line 304  static option_item optionlist[] = { Line 370  static option_item optionlist[] = {
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" };
# Line 325  const char utf8_table4[] = { Line 393  const char utf8_table4[] = {
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    
# Line 365  although at present the only ones are fo Line 521  although at present the only ones are fo
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)
# Line 372  isdirectory(char *filename) Line 529  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 *
# Line 459  BOOL first; Line 616  BOOL first;
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 *
# Line 476  char *pattern; Line 635  char *pattern;
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");
# Line 563  return FALSE; Line 722  return FALSE;
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; }
# Line 619  return sys_errlist[n]; Line 779  return sys_errlist[n];
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    
# Line 935  Arguments: Line 1134  Arguments:
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    {    {
# Line 983  match_patterns(char *matchptr, size_t le Line 1183  match_patterns(char *matchptr, size_t le
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");
# Line 1191  while (ptr < endptr) Line 1393  while (ptr < endptr)
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)
# Line 1594  Arguments: Line 1796  Arguments:
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    
# Line 1605  static int Line 1808  static int
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
# Line 1631  if (strcmp(pathname, "-") == 0) Line 1834  if (strcmp(pathname, "-") == 0)
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];
# Line 1655  if ((sep = isdirectory(pathname)) != 0) Line 1867  if ((sep = isdirectory(pathname)) != 0)
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;
# Line 1691  if ((sep = isdirectory(pathname)) != 0) Line 1880  if ((sep = isdirectory(pathname)) != 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
# Line 1894  printf("\nNumbers may be followed by K o Line 2085  printf("\nNumbers may be followed by K o
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");
# Line 1939  switch(letter) Line 2129  switch(letter)
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    
# Line 1983  return buffer; Line 2173  return buffer;
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
# Line 1998  Returns: TRUE on success, FALSE Line 2195  Returns: TRUE on success, FALSE
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;
# Line 2047  return FALSE; Line 2249  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    
# Line 2099  main(int argc, char **argv) Line 2337  main(int argc, char **argv)
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    
# Line 2144  for (i = 1; i < argc; i++) Line 2379  for (i = 1; i < argc; i++)
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    
# Line 2354  for (i = 1; i < argc; i++) Line 2589  for (i = 1; i < argc; i++)
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 */
# Line 2580  if (jfriedl_XT != 0 || jfriedl_XR != 0) Line 2834  if (jfriedl_XT != 0 || jfriedl_XR != 0)
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. */
# Line 2660  if ((study_options & PCRE_STUDY_JIT_COMP Line 2884  if ((study_options & PCRE_STUDY_JIT_COMP
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    
# Line 2682  pcre_extra block for each pattern. */ Line 2905  pcre_extra block for each pattern. */
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);
# Line 2695  if (match_limit > 0 || match_limit_recur Line 2918  if (match_limit > 0 || match_limit_recur
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        }        }
# Line 2787  if (file_list != NULL) Line 2998  if (file_list != NULL)
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    {    {
# Line 2818  EXIT: Line 3019  EXIT:
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:

Legend:
Removed from v.1002  
changed lines
  Added in v.1003

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12