/[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 87 by nigel, Sat Feb 24 21:41:21 2007 UTC revision 632 by ph10, Fri Jul 22 17:47:49 2011 UTC
# Line 6  Line 6 
6  its pattern matching. On a Unix or Win32 system it can recurse into  its pattern matching. On a Unix or Win32 system it can recurse into
7  directories.  directories.
8    
9             Copyright (c) 1997-2006 University of Cambridge             Copyright (c) 1997-2011 University of Cambridge
10    
11  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
12  Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
# Line 37  POSSIBILITY OF SUCH DAMAGE. Line 37  POSSIBILITY OF SUCH DAMAGE.
37  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
38  */  */
39    
40    #ifdef HAVE_CONFIG_H
41    #include "config.h"
42    #endif
43    
44  #include <ctype.h>  #include <ctype.h>
45  #include <locale.h>  #include <locale.h>
46  #include <stdio.h>  #include <stdio.h>
# Line 46  POSSIBILITY OF SUCH DAMAGE. Line 50  POSSIBILITY OF SUCH DAMAGE.
50    
51  #include <sys/types.h>  #include <sys/types.h>
52  #include <sys/stat.h>  #include <sys/stat.h>
53    
54    #ifdef HAVE_UNISTD_H
55  #include <unistd.h>  #include <unistd.h>
56    #endif
57    
58    #ifdef SUPPORT_LIBZ
59    #include <zlib.h>
60    #endif
61    
62    #ifdef SUPPORT_LIBBZ2
63    #include <bzlib.h>
64    #endif
65    
 #include "config.h"  
66  #include "pcre.h"  #include "pcre.h"
67    
68  #define FALSE 0  #define FALSE 0
# Line 56  POSSIBILITY OF SUCH DAMAGE. Line 70  POSSIBILITY OF SUCH DAMAGE.
70    
71  typedef int BOOL;  typedef int BOOL;
72    
 #define VERSION "4.2 09-Jan-2006"  
73  #define MAX_PATTERN_COUNT 100  #define MAX_PATTERN_COUNT 100
74    #define OFFSET_SIZE 99
75    
76  #if BUFSIZ > 8192  #if BUFSIZ > 8192
77  #define MBUFTHIRD BUFSIZ  #define MBUFTHIRD BUFSIZ
# Line 65  typedef int BOOL; Line 79  typedef int BOOL;
79  #define MBUFTHIRD 8192  #define MBUFTHIRD 8192
80  #endif  #endif
81    
   
82  /* Values for the "filenames" variable, which specifies options for file name  /* Values for the "filenames" variable, which specifies options for file name
83  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
84  all values greater than FN_DEFAULT. */  all values greater than FN_DEFAULT. */
85    
86  enum { FN_NONE, FN_DEFAULT, FN_ONLY, FN_NOMATCH_ONLY, FN_FORCE };  enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE };
87    
88    /* File reading styles */
89    
90    enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };
91    
92  /* Actions for the -d and -D options */  /* Actions for the -d and -D options */
93    
# Line 83  enum { DEE_READ, DEE_SKIP }; Line 100  enum { DEE_READ, DEE_SKIP };
100  #define PO_LINE_MATCH     0x0002  #define PO_LINE_MATCH     0x0002
101  #define PO_FIXED_STRINGS  0x0004  #define PO_FIXED_STRINGS  0x0004
102    
103    /* Line ending types */
104    
105    enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };
106    
107    /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some
108    environments), a warning is issued if the value of fwrite() is ignored.
109    Unfortunately, casting to (void) does not suppress the warning. To get round
110    this, we use a macro that compiles a fudge. Oddly, this does not also seem to
111    apply to fprintf(). */
112    
113    #define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}
114    
115    
116    
117  /*************************************************  /*************************************************
# Line 94  regular code. */ Line 123  regular code. */
123    
124  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
125  static int S_arg = -1;  static int S_arg = -1;
126    static unsigned int jfriedl_XR = 0; /* repeat regex attempt this many times */
127    static unsigned int jfriedl_XT = 0; /* replicate text this many times */
128    static const char *jfriedl_prefix = "";
129    static const char *jfriedl_postfix = "";
130  #endif  #endif
131    
132    static int  endlinetype;
133    
134  static char *colour_string = (char *)"1;31";  static char *colour_string = (char *)"1;31";
135  static char *colour_option = NULL;  static char *colour_option = NULL;
136  static char *dee_option = NULL;  static char *dee_option = NULL;
137  static char *DEE_option = NULL;  static char *DEE_option = NULL;
138    static char *newline = NULL;
139  static char *pattern_filename = NULL;  static char *pattern_filename = NULL;
140  static char *stdin_name = (char *)"(standard input)";  static char *stdin_name = (char *)"(standard input)";
141  static char *locale = NULL;  static char *locale = NULL;
# Line 107  static char *locale = NULL; Line 143  static char *locale = NULL;
143  static const unsigned char *pcretables = NULL;  static const unsigned char *pcretables = NULL;
144    
145  static int  pattern_count = 0;  static int  pattern_count = 0;
146  static pcre **pattern_list;  static pcre **pattern_list = NULL;
147  static pcre_extra **hints_list;  static pcre_extra **hints_list = NULL;
148    
149  static char *include_pattern = NULL;  static char *include_pattern = NULL;
150  static char *exclude_pattern = NULL;  static char *exclude_pattern = NULL;
151    static char *include_dir_pattern = NULL;
152    static char *exclude_dir_pattern = NULL;
153    
154  static pcre *include_compiled = NULL;  static pcre *include_compiled = NULL;
155  static pcre *exclude_compiled = NULL;  static pcre *exclude_compiled = NULL;
156    static pcre *include_dir_compiled = NULL;
157    static pcre *exclude_dir_compiled = NULL;
158    
159  static int after_context = 0;  static int after_context = 0;
160  static int before_context = 0;  static int before_context = 0;
# Line 123  static int dee_action = dee_READ; Line 163  static int dee_action = dee_READ;
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;
167  static int process_options = 0;  static int process_options = 0;
168    
169    static unsigned long int match_limit = 0;
170    static unsigned long int match_limit_recursion = 0;
171    
172  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
173  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
174    static BOOL file_offsets = FALSE;
175  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
176  static BOOL invert = FALSE;  static BOOL invert = FALSE;
177    static BOOL line_buffered = FALSE;
178    static BOOL line_offsets = FALSE;
179  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
180  static BOOL number = FALSE;  static BOOL number = FALSE;
181  static BOOL only_matching = FALSE;  static BOOL omit_zero_count = FALSE;
182    static BOOL resource_error = FALSE;
183  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
184  static BOOL silent = FALSE;  static BOOL silent = FALSE;
185    static BOOL utf8 = FALSE;
186    
187  /* Structure for options and list of them */  /* Structure for options and list of them */
188    
189  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_OP_NUMBER,  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
190         OP_PATLIST };         OP_OP_NUMBER, OP_PATLIST };
191    
192  typedef struct option_item {  typedef struct option_item {
193    int type;    int type;
# Line 151  typedef struct option_item { Line 200  typedef struct option_item {
200  /* Options without a single-letter equivalent get a negative value. This can be  /* Options without a single-letter equivalent get a negative value. This can be
201  used to identify them. */  used to identify them. */
202    
203  #define N_COLOUR    (-1)  #define N_COLOUR       (-1)
204  #define N_EXCLUDE   (-2)  #define N_EXCLUDE      (-2)
205  #define N_HELP      (-3)  #define N_EXCLUDE_DIR  (-3)
206  #define N_INCLUDE   (-4)  #define N_HELP         (-4)
207  #define N_LABEL     (-5)  #define N_INCLUDE      (-5)
208  #define N_LOCALE    (-6)  #define N_INCLUDE_DIR  (-6)
209  #define N_NULL      (-7)  #define N_LABEL        (-7)
210    #define N_LOCALE       (-8)
211    #define N_NULL         (-9)
212    #define N_LOFFSETS     (-10)
213    #define N_FOFFSETS     (-11)
214    #define N_LBUFFER      (-12)
215    #define N_M_LIMIT      (-13)
216    #define N_M_LIMIT_REC  (-14)
217    
218  static option_item optionlist[] = {  static option_item optionlist[] = {
219    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "  terminate options" },
220    { OP_NODATA,    N_HELP,   NULL,              "help",          "display this help and exit" },    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
221    { OP_NUMBER,    'A',      &after_context,    "after-context=number", "set number of following context lines" },    { OP_NUMBER,     'A',      &after_context,    "after-context=number", "set number of following context lines" },
222    { OP_NUMBER,    'B',      &before_context,   "before-context=number", "set number of prior context lines" },    { OP_NUMBER,     'B',      &before_context,   "before-context=number", "set number of prior context lines" },
223    { OP_OP_STRING, N_COLOUR, &colour_option,    "color=option",  "matched text color option" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
224    { OP_NUMBER,    'C',      &both_context,     "context=number", "set number of context lines, before & after" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
225    { OP_NODATA,    'c',      NULL,              "count",         "print only a count of matching lines per FILE" },    { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
226    { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },    { OP_NODATA,     'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
227    { 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" },
228    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },    { OP_STRING,     'd',      &dee_option,       "directories=action", "how to handle directories" },
229    { OP_PATLIST,   'e',      NULL,              "regex(p)",      "specify pattern (may be used more than once)" },    { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
230    { 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" },
231    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
232    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
233    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
234    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
235    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },    { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
236    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },    { OP_NODATA,     'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
237    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },    { OP_NODATA,     'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
238    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,     N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
239    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
240    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
241    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
242    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
243    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
244    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
245    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
246      { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
247      { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
248      { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
249      { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
250      { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
251      { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
252      { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
253      { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },
254    
255      /* These two were accidentally implemented with underscores instead of
256      hyphens in the option names. As this was not discovered for several releases,
257      the incorrect versions are left in the table for compatibility. However, the
258      --help function misses out any option that has an underscore in its name. */
259    
260      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
261      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
262    
263  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
264    { 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" },
265  #endif  #endif
# Line 210  static const char *prefix[] = { Line 283  static const char *prefix[] = {
283  static const char *suffix[] = {  static const char *suffix[] = {
284    "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };    "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };
285    
286    /* UTF-8 tables - used only when the newline setting is "any". */
287    
288    const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
289    
290    const char utf8_table4[] = {
291      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
292      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
293      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
294      3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
295    
296    
297    
298    /*************************************************
299    *         Exit from the program                  *
300    *************************************************/
301    
302    /* If there has been a resource error, give a suitable message.
303    
304    Argument:  the return code
305    Returns:   does not return
306    */
307    
308    static void
309    pcregrep_exit(int rc)
310    {
311    if (resource_error)
312      {
313      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
314        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
315      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
316      }
317    
318    exit(rc);
319    }
320    
321    
322  /*************************************************  /*************************************************
# Line 222  although at present the only ones are fo Line 329  although at present the only ones are fo
329    
330  /************* Directory scanning in Unix ***********/  /************* Directory scanning in Unix ***********/
331    
332  #if IS_UNIX  #if defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H
333  #include <sys/types.h>  #include <sys/types.h>
334  #include <sys/stat.h>  #include <sys/stat.h>
335  #include <dirent.h>  #include <dirent.h>
# Line 254  for (;;) Line 361  for (;;)
361    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
362      return dent->d_name;      return dent->d_name;
363    }    }
364  return NULL;   /* Keep compiler happy; never executed */  /* Control never reaches here */
365  }  }
366    
367  static void  static void
# Line 276  return (statbuf.st_mode & S_IFMT) == S_I Line 383  return (statbuf.st_mode & S_IFMT) == S_I
383  }  }
384    
385    
386  /************* Test stdout for being a terminal in Unix **********/  /************* Test for a terminal in Unix **********/
387    
388  static BOOL  static BOOL
389  is_stdout_tty(void)  is_stdout_tty(void)
# Line 284  is_stdout_tty(void) Line 391  is_stdout_tty(void)
391  return isatty(fileno(stdout));  return isatty(fileno(stdout));
392  }  }
393    
394    static BOOL
395    is_file_tty(FILE *f)
396    {
397    return isatty(fileno(f));
398    }
399    
400    
401  /************* Directory scanning in Win32 ***********/  /************* Directory scanning in Win32 ***********/
402    
403  /* I (Philip Hazel) have no means of testing this code. It was contributed by  /* I (Philip Hazel) have no means of testing this code. It was contributed by
404  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
405  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
406    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
407    The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
408    undefined when it is indeed undefined. */
409    
410  #elif HAVE_WIN32API  #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
411    
412  #ifndef STRICT  #ifndef STRICT
413  # define STRICT  # define STRICT
# Line 300  when it did not exist. */ Line 415  when it did not exist. */
415  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
416  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
417  #endif  #endif
418    
419    #include <windows.h>
420    
421  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
422  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
423  #endif  #endif
424    
 #include <windows.h>  
   
425  typedef struct directory_type  typedef struct directory_type
426  {  {
427  HANDLE handle;  HANDLE handle;
# Line 335  dir = (directory_type *) malloc(sizeof(* Line 451  dir = (directory_type *) malloc(sizeof(*
451  if ((pattern == NULL) || (dir == NULL))  if ((pattern == NULL) || (dir == NULL))
452    {    {
453    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
454    exit(2);    pcregrep_exit(2);
455    }    }
456  memcpy(pattern, filename, len);  memcpy(pattern, filename, len);
457  memcpy(&(pattern[len]), "\\*", 3);  memcpy(&(pattern[len]), "\\*", 3);
# Line 390  regular if they are not directories. */ Line 506  regular if they are not directories. */
506    
507  int isregfile(char *filename)  int isregfile(char *filename)
508  {  {
509  return !isdirectory(filename)  return !isdirectory(filename);
510  }  }
511    
512    
513  /************* Test stdout for being a terminal in Win32 **********/  /************* Test for a terminal in Win32 **********/
514    
515  /* I don't know how to do this; assume never */  /* I don't know how to do this; assume never */
516    
517  static BOOL  static BOOL
518  is_stdout_tty(void)  is_stdout_tty(void)
519  {  {
520  FALSE;  return FALSE;
521    }
522    
523    static BOOL
524    is_file_tty(FILE *f)
525    {
526    return FALSE;
527  }  }
528    
529    
# Line 414  FALSE; Line 536  FALSE;
536  typedef void directory_type;  typedef void directory_type;
537    
538  int isdirectory(char *filename) { return 0; }  int isdirectory(char *filename) { return 0; }
539  directory_type * opendirectory(char *filename) {}  directory_type * opendirectory(char *filename) { return (directory_type*)0;}
540  char *readdirectory(directory_type *dir) {}  char *readdirectory(directory_type *dir) { return (char*)0;}
541  void closedirectory(directory_type *dir) {}  void closedirectory(directory_type *dir) {}
542    
543    
# Line 426  void closedirectory(directory_type *dir) Line 548  void closedirectory(directory_type *dir)
548  int isregfile(char *filename) { return 1; }  int isregfile(char *filename) { return 1; }
549    
550    
551  /************* Test stdout for being a terminal when we can't do it **********/  /************* Test for a terminal when we can't do it **********/
552    
553  static BOOL  static BOOL
554  is_stdout_tty(void)  is_stdout_tty(void)
# Line 434  is_stdout_tty(void) Line 556  is_stdout_tty(void)
556  return FALSE;  return FALSE;
557  }  }
558    
559    static BOOL
560    is_file_tty(FILE *f)
561    {
562    return FALSE;
563    }
564    
565  #endif  #endif
566    
567    
568    
569  #if ! HAVE_STRERROR  #ifndef HAVE_STRERROR
570  /*************************************************  /*************************************************
571  *     Provide strerror() for non-ANSI libraries  *  *     Provide strerror() for non-ANSI libraries  *
572  *************************************************/  *************************************************/
# Line 462  return sys_errlist[n]; Line 589  return sys_errlist[n];
589    
590    
591  /*************************************************  /*************************************************
592    *            Read one line of input              *
593    *************************************************/
594    
595    /* Normally, input is read using fread() into a large buffer, so many lines may
596    be read at once. However, doing this for tty input means that no output appears
597    until a lot of input has been typed. Instead, tty input is handled line by
598    line. We cannot use fgets() for this, because it does not stop at a binary
599    zero, and therefore there is no way of telling how many characters it has read,
600    because there may be binary zeros embedded in the data.
601    
602    Arguments:
603      buffer     the buffer to read into
604      length     the maximum number of characters to read
605      f          the file
606    
607    Returns:     the number of characters read, zero at end of file
608    */
609    
610    static int
611    read_one_line(char *buffer, int length, FILE *f)
612    {
613    int c;
614    int yield = 0;
615    while ((c = fgetc(f)) != EOF)
616      {
617      buffer[yield++] = c;
618      if (c == '\n' || yield >= length) break;
619      }
620    return yield;
621    }
622    
623    
624    
625    /*************************************************
626    *             Find end of line                   *
627    *************************************************/
628    
629    /* The length of the endline sequence that is found is set via lenptr. This may
630    be zero at the very end of the file if there is no line-ending sequence there.
631    
632    Arguments:
633      p         current position in line
634      endptr    end of available data
635      lenptr    where to put the length of the eol sequence
636    
637    Returns:    pointer to the last byte of the line, including the newline byte(s)
638    */
639    
640    static char *
641    end_of_line(char *p, char *endptr, int *lenptr)
642    {
643    switch(endlinetype)
644      {
645      default:      /* Just in case */
646      case EL_LF:
647      while (p < endptr && *p != '\n') p++;
648      if (p < endptr)
649        {
650        *lenptr = 1;
651        return p + 1;
652        }
653      *lenptr = 0;
654      return endptr;
655    
656      case EL_CR:
657      while (p < endptr && *p != '\r') p++;
658      if (p < endptr)
659        {
660        *lenptr = 1;
661        return p + 1;
662        }
663      *lenptr = 0;
664      return endptr;
665    
666      case EL_CRLF:
667      for (;;)
668        {
669        while (p < endptr && *p != '\r') p++;
670        if (++p >= endptr)
671          {
672          *lenptr = 0;
673          return endptr;
674          }
675        if (*p == '\n')
676          {
677          *lenptr = 2;
678          return p + 1;
679          }
680        }
681      break;
682    
683      case EL_ANYCRLF:
684      while (p < endptr)
685        {
686        int extra = 0;
687        register int c = *((unsigned char *)p);
688    
689        if (utf8 && c >= 0xc0)
690          {
691          int gcii, gcss;
692          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
693          gcss = 6*extra;
694          c = (c & utf8_table3[extra]) << gcss;
695          for (gcii = 1; gcii <= extra; gcii++)
696            {
697            gcss -= 6;
698            c |= (p[gcii] & 0x3f) << gcss;
699            }
700          }
701    
702        p += 1 + extra;
703    
704        switch (c)
705          {
706          case 0x0a:    /* LF */
707          *lenptr = 1;
708          return p;
709    
710          case 0x0d:    /* CR */
711          if (p < endptr && *p == 0x0a)
712            {
713            *lenptr = 2;
714            p++;
715            }
716          else *lenptr = 1;
717          return p;
718    
719          default:
720          break;
721          }
722        }   /* End of loop for ANYCRLF case */
723    
724      *lenptr = 0;  /* Must have hit the end */
725      return endptr;
726    
727      case EL_ANY:
728      while (p < endptr)
729        {
730        int extra = 0;
731        register int c = *((unsigned char *)p);
732    
733        if (utf8 && c >= 0xc0)
734          {
735          int gcii, gcss;
736          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
737          gcss = 6*extra;
738          c = (c & utf8_table3[extra]) << gcss;
739          for (gcii = 1; gcii <= extra; gcii++)
740            {
741            gcss -= 6;
742            c |= (p[gcii] & 0x3f) << gcss;
743            }
744          }
745    
746        p += 1 + extra;
747    
748        switch (c)
749          {
750          case 0x0a:    /* LF */
751          case 0x0b:    /* VT */
752          case 0x0c:    /* FF */
753          *lenptr = 1;
754          return p;
755    
756          case 0x0d:    /* CR */
757          if (p < endptr && *p == 0x0a)
758            {
759            *lenptr = 2;
760            p++;
761            }
762          else *lenptr = 1;
763          return p;
764    
765          case 0x85:    /* NEL */
766          *lenptr = utf8? 2 : 1;
767          return p;
768    
769          case 0x2028:  /* LS */
770          case 0x2029:  /* PS */
771          *lenptr = 3;
772          return p;
773    
774          default:
775          break;
776          }
777        }   /* End of loop for ANY case */
778    
779      *lenptr = 0;  /* Must have hit the end */
780      return endptr;
781      }     /* End of overall switch */
782    }
783    
784    
785    
786    /*************************************************
787    *         Find start of previous line            *
788    *************************************************/
789    
790    /* This is called when looking back for before lines to print.
791    
792    Arguments:
793      p         start of the subsequent line
794      startptr  start of available data
795    
796    Returns:    pointer to the start of the previous line
797    */
798    
799    static char *
800    previous_line(char *p, char *startptr)
801    {
802    switch(endlinetype)
803      {
804      default:      /* Just in case */
805      case EL_LF:
806      p--;
807      while (p > startptr && p[-1] != '\n') p--;
808      return p;
809    
810      case EL_CR:
811      p--;
812      while (p > startptr && p[-1] != '\n') p--;
813      return p;
814    
815      case EL_CRLF:
816      for (;;)
817        {
818        p -= 2;
819        while (p > startptr && p[-1] != '\n') p--;
820        if (p <= startptr + 1 || p[-2] == '\r') return p;
821        }
822      return p;   /* But control should never get here */
823    
824      case EL_ANY:
825      case EL_ANYCRLF:
826      if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;
827      if (utf8) while ((*p & 0xc0) == 0x80) p--;
828    
829      while (p > startptr)
830        {
831        register int c;
832        char *pp = p - 1;
833    
834        if (utf8)
835          {
836          int extra = 0;
837          while ((*pp & 0xc0) == 0x80) pp--;
838          c = *((unsigned char *)pp);
839          if (c >= 0xc0)
840            {
841            int gcii, gcss;
842            extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
843            gcss = 6*extra;
844            c = (c & utf8_table3[extra]) << gcss;
845            for (gcii = 1; gcii <= extra; gcii++)
846              {
847              gcss -= 6;
848              c |= (pp[gcii] & 0x3f) << gcss;
849              }
850            }
851          }
852        else c = *((unsigned char *)pp);
853    
854        if (endlinetype == EL_ANYCRLF) switch (c)
855          {
856          case 0x0a:    /* LF */
857          case 0x0d:    /* CR */
858          return p;
859    
860          default:
861          break;
862          }
863    
864        else switch (c)
865          {
866          case 0x0a:    /* LF */
867          case 0x0b:    /* VT */
868          case 0x0c:    /* FF */
869          case 0x0d:    /* CR */
870          case 0x85:    /* NEL */
871          case 0x2028:  /* LS */
872          case 0x2029:  /* PS */
873          return p;
874    
875          default:
876          break;
877          }
878    
879        p = pp;  /* Back one character */
880        }        /* End of loop for ANY case */
881    
882      return startptr;  /* Hit start of data */
883      }     /* End of overall switch */
884    }
885    
886    
887    
888    
889    
890    /*************************************************
891  *       Print the previous "after" lines         *  *       Print the previous "after" lines         *
892  *************************************************/  *************************************************/
893    
# Line 486  if (after_context > 0 && lastmatchnumber Line 912  if (after_context > 0 && lastmatchnumber
912    int count = 0;    int count = 0;
913    while (lastmatchrestart < endptr && count++ < after_context)    while (lastmatchrestart < endptr && count++ < after_context)
914      {      {
915        int ellength;
916      char *pp = lastmatchrestart;      char *pp = lastmatchrestart;
917      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
918      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
919      while (*pp != '\n') pp++;      pp = end_of_line(pp, endptr, &ellength);
920      fwrite(lastmatchrestart, 1, pp - lastmatchrestart + 1, stdout);      FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
921      lastmatchrestart = pp + 1;      lastmatchrestart = pp;
922      }      }
923    hyphenpending = TRUE;    hyphenpending = TRUE;
924    }    }
# Line 500  if (after_context > 0 && lastmatchnumber Line 927  if (after_context > 0 && lastmatchnumber
927    
928    
929  /*************************************************  /*************************************************
930    *   Apply patterns to subject till one matches   *
931    *************************************************/
932    
933    /* This function is called to run through all patterns, looking for a match. It
934    is used multiple times for the same subject when colouring is enabled, in order
935    to find all possible matches.
936    
937    Arguments:
938      matchptr     the start of the subject
939      length       the length of the subject to match
940      startoffset  where to start matching
941      offsets      the offets vector to fill in
942      mrc          address of where to put the result of pcre_exec()
943    
944    Returns:      TRUE if there was a match
945                  FALSE if there was no match
946                  invert if there was a non-fatal error
947    */
948    
949    static BOOL
950    match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
951      int *mrc)
952    {
953    int i;
954    size_t slen = length;
955    const char *msg = "this text:\n\n";
956    if (slen > 200)
957      {
958      slen = 200;
959      msg = "text that starts:\n\n";
960      }
961    for (i = 0; i < pattern_count; i++)
962      {
963      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length,
964        startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
965      if (*mrc >= 0) return TRUE;
966      if (*mrc == PCRE_ERROR_NOMATCH) continue;
967      fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
968      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
969      fprintf(stderr, "%s", msg);
970      FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
971      fprintf(stderr, "\n\n");
972      if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)
973        resource_error = TRUE;
974      if (error_count++ > 20)
975        {
976        fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
977        pcregrep_exit(2);
978        }
979      return invert;    /* No more matching; don't show the line again */
980      }
981    
982    return FALSE;  /* No match, no errors */
983    }
984    
985    
986    
987    /*************************************************
988  *            Grep an individual file             *  *            Grep an individual file             *
989  *************************************************/  *************************************************/
990    
# Line 511  be in the middle third most of the time, Line 996  be in the middle third most of the time,
996  "before" context printing.  "before" context printing.
997    
998  Arguments:  Arguments:
999    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
1000                   the gzFile pointer when reading is via libz
1001                   the BZFILE pointer when reading is via libbz2
1002      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
1003    printname    the file name if it is to be printed for each match    printname    the file name if it is to be printed for each match
1004                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
1005                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
1006    
1007  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
1008                 1 otherwise (no matches)                 1 otherwise (no matches)
1009                   2 if there is a read error on a .bz2 file
1010  */  */
1011    
1012  static int  static int
1013  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
1014  {  {
1015  int rc = 1;  int rc = 1;
1016  int linenumber = 1;  int linenumber = 1;
1017  int lastmatchnumber = 0;  int lastmatchnumber = 0;
1018  int count = 0;  int count = 0;
1019  int offsets[99];  int filepos = 0;
1020    int offsets[OFFSET_SIZE];
1021  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
1022  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
1023  char *ptr = buffer;  char *ptr = buffer;
1024  char *endptr;  char *endptr;
1025  size_t bufflength;  size_t bufflength;
1026  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
1027    BOOL input_line_buffered = line_buffered;
1028    FILE *in = NULL;                    /* Ensure initialized */
1029    
1030    #ifdef SUPPORT_LIBZ
1031    gzFile ingz = NULL;
1032    #endif
1033    
1034    #ifdef SUPPORT_LIBBZ2
1035    BZFILE *inbz2 = NULL;
1036    #endif
1037    
1038    
1039  /* Do the first read into the start of the buffer and set up the pointer to  /* Do the first read into the start of the buffer and set up the pointer to end
1040  end of what we have. */  of what we have. In the case of libz, a non-zipped .gz file will be read as a
1041    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
1042    fail. */
1043    
1044    #ifdef SUPPORT_LIBZ
1045    if (frtype == FR_LIBZ)
1046      {
1047      ingz = (gzFile)handle;
1048      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
1049      }
1050    else
1051    #endif
1052    
1053    #ifdef SUPPORT_LIBBZ2
1054    if (frtype == FR_LIBBZ2)
1055      {
1056      inbz2 = (BZFILE *)handle;
1057      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
1058      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1059      }                                    /* without the cast it is unsigned. */
1060    else
1061    #endif
1062    
1063      {
1064      in = (FILE *)handle;
1065      if (is_file_tty(in)) input_line_buffered = TRUE;
1066      bufflength = input_line_buffered?
1067        read_one_line(buffer, 3*MBUFTHIRD, in) :
1068        fread(buffer, 1, 3*MBUFTHIRD, in);
1069      }
1070    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
1071  endptr = buffer + bufflength;  endptr = buffer + bufflength;
1072    
1073  /* Loop while the current pointer is not at the end of the file. For large  /* Loop while the current pointer is not at the end of the file. For large
# Line 548  way, the buffer is shifted left and re-f Line 1077  way, the buffer is shifted left and re-f
1077    
1078  while (ptr < endptr)  while (ptr < endptr)
1079    {    {
1080    int i;    int endlinelength;
1081    int mrc = 0;    int mrc = 0;
1082    BOOL match = FALSE;    int startoffset = 0;
1083      BOOL match;
1084      char *matchptr = ptr;
1085    char *t = ptr;    char *t = ptr;
1086    size_t length, linelength;    size_t length, linelength;
1087    
1088    /* At this point, ptr is at the start of a line. We need to find the length    /* At this point, ptr is at the start of a line. We need to find the length
1089    of the subject string to pass to pcre_exec(). In multiline mode, it is the    of the subject string to pass to pcre_exec(). In multiline mode, it is the
1090    length remainder of the data in the buffer. Otherwise, it is the length of    length remainder of the data in the buffer. Otherwise, it is the length of
1091    the next line. After matching, we always advance by the length of the next    the next line, excluding the terminating newline. After matching, we always
1092    line. In multiline mode the PCRE_FIRSTLINE option is used for compiling, so    advance by the length of the next line. In multiline mode the PCRE_FIRSTLINE
1093    that any match is constrained to be in the first line. */    option is used for compiling, so that any match is constrained to be in the
1094      first line. */
1095    linelength = 0;  
1096    while (t < endptr && *t++ != '\n') linelength++;    t = end_of_line(t, endptr, &endlinelength);
1097    length = multiline? endptr - ptr : linelength;    linelength = t - ptr - endlinelength;
1098      length = multiline? (size_t)(endptr - ptr) : linelength;
1099    /* Run through all the patterns until one matches. Note that we don't include  
1100    the final newline in the subject string. */    /* Extra processing for Jeffrey Friedl's debugging. */
1101    
1102    for (i = 0; i < pattern_count; i++)  #ifdef JFRIEDL_DEBUG
1103      {    if (jfriedl_XT || jfriedl_XR)
1104      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,    {
1105        offsets, 99);        #include <sys/time.h>
1106      if (mrc >= 0) { match = TRUE; break; }        #include <time.h>
1107      if (mrc != PCRE_ERROR_NOMATCH)        struct timeval start_time, end_time;
1108        {        struct timezone dummy;
1109        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);        int i;
1110        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);  
1111        fprintf(stderr, "this line:\n");        if (jfriedl_XT)
1112        fwrite(ptr, 1, linelength, stderr);   /* In case binary zero included */        {
1113        fprintf(stderr, "\n");            unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix);
1114        if (error_count == 0 &&            const char *orig = ptr;
1115            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))            ptr = malloc(newlen + 1);
1116          {            if (!ptr) {
1117          fprintf(stderr, "pcregrep: error %d means that a resource limit "                    printf("out of memory");
1118            "was exceeded\n", mrc);                    pcregrep_exit(2);
1119          fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");            }
1120          }            endptr = ptr;
1121        if (error_count++ > 20)            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
1122          {            for (i = 0; i < jfriedl_XT; i++) {
1123          fprintf(stderr, "pcregrep: too many errors - abandoned\n");                    strncpy(endptr, orig,  length);
1124          exit(2);                    endptr += length;
1125          }            }
1126        match = invert;    /* No more matching; don't show the line again */            strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix);
1127        break;            length = newlen;
1128        }        }
1129      }  
1130          if (gettimeofday(&start_time, &dummy) != 0)
1131                  perror("bad gettimeofday");
1132    
1133    
1134          for (i = 0; i < jfriedl_XR; i++)
1135              match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0,
1136                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1137    
1138          if (gettimeofday(&end_time, &dummy) != 0)
1139                  perror("bad gettimeofday");
1140    
1141          double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0))
1142                          -
1143                          (start_time.tv_sec + (start_time.tv_usec / 1000000.0)));
1144    
1145          printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta);
1146          return 0;
1147      }
1148    #endif
1149    
1150      /* We come back here after a match when the -o option (only_matching) is set,
1151      in order to find any further matches in the same line. */
1152    
1153      ONLY_MATCHING_RESTART:
1154    
1155      /* Run through all the patterns until one matches or there is an error other
1156      than NOMATCH. This code is in a subroutine so that it can be re-used for
1157      finding subsequent matches when colouring matched lines. */
1158    
1159      match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
1160    
1161    /* If it's a match or a not-match (as required), do what's wanted. */    /* If it's a match or a not-match (as required), do what's wanted. */
1162    
# Line 614  while (ptr < endptr) Line 1175  while (ptr < endptr)
1175      /* If all we want is a file name, there is no need to scan any more lines      /* If all we want is a file name, there is no need to scan any more lines
1176      in the file. */      in the file. */
1177    
1178      else if (filenames == FN_ONLY)      else if (filenames == FN_MATCH_ONLY)
1179        {        {
1180        fprintf(stdout, "%s\n", printname);        fprintf(stdout, "%s\n", printname);
1181        return 0;        return 0;
# Line 624  while (ptr < endptr) Line 1185  while (ptr < endptr)
1185    
1186      else if (quiet) return 0;      else if (quiet) return 0;
1187    
1188      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, or a
1189      does not pring any context. */      captured portion of it, as long as this string is not empty, and the
1190        --file-offsets and --line-offsets options output offsets for the matching
1191        substring (they both force --only-matching = 0). None of these options
1192        prints any context. Afterwards, adjust the start and length, and then jump
1193        back to look for further matches in the same line. If we are in invert
1194        mode, however, nothing is printed and we do not restart - this could still
1195        be useful because the return code is set. */
1196    
1197      else if (only_matching)      else if (only_matching >= 0)
1198        {        {
1199        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
1200        if (number) fprintf(stdout, "%d:", linenumber);          {
1201        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1202        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
1203            if (line_offsets)
1204              fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1205                offsets[1] - offsets[0]);
1206            else if (file_offsets)
1207              fprintf(stdout, "%d,%d\n",
1208                (int)(filepos + matchptr + offsets[0] - ptr),
1209                offsets[1] - offsets[0]);
1210            else if (only_matching < mrc)
1211              {
1212              int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1213              if (plen > 0)
1214                {
1215                if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1216                FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1217                if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1218                fprintf(stdout, "\n");
1219                }
1220              }
1221            else if (printname != NULL || number) fprintf(stdout, "\n");
1222            /*
1223            matchptr += offsets[1];
1224            length -= offsets[1];
1225            */
1226            match = FALSE;
1227            if (line_buffered) fflush(stdout);
1228            rc = 0;                 /* Had some success */
1229            startoffset = offsets[1];
1230            goto ONLY_MATCHING_RESTART;
1231            }
1232        }        }
1233    
1234      /* This is the default case when none of the above options is set. We print      /* This is the default case when none of the above options is set. We print
# Line 646  while (ptr < endptr) Line 1242  while (ptr < endptr)
1242    
1243        if (after_context > 0 && lastmatchnumber > 0)        if (after_context > 0 && lastmatchnumber > 0)
1244          {          {
1245            int ellength;
1246          int linecount = 0;          int linecount = 0;
1247          char *p = lastmatchrestart;          char *p = lastmatchrestart;
1248    
1249          while (p < ptr && linecount < after_context)          while (p < ptr && linecount < after_context)
1250            {            {
1251            while (*p != '\n') p++;            p = end_of_line(p, ptr, &ellength);
           p++;  
1252            linecount++;            linecount++;
1253            }            }
1254    
# Line 665  while (ptr < endptr) Line 1261  while (ptr < endptr)
1261            char *pp = lastmatchrestart;            char *pp = lastmatchrestart;
1262            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1263            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1264            while (*pp != '\n') pp++;            pp = end_of_line(pp, endptr, &ellength);
1265            fwrite(lastmatchrestart, 1, pp - lastmatchrestart + 1, stdout);            FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1266            lastmatchrestart = pp + 1;            lastmatchrestart = pp;
1267            }            }
1268          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
1269          }          }
# Line 693  while (ptr < endptr) Line 1289  while (ptr < endptr)
1289                 linecount < before_context)                 linecount < before_context)
1290            {            {
1291            linecount++;            linecount++;
1292            p--;            p = previous_line(p, buffer);
           while (p > buffer && p[-1] != '\n') p--;  
1293            }            }
1294    
1295          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 702  while (ptr < endptr) Line 1297  while (ptr < endptr)
1297    
1298          while (p < ptr)          while (p < ptr)
1299            {            {
1300              int ellength;
1301            char *pp = p;            char *pp = p;
1302            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1303            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1304            while (*pp != '\n') pp++;            pp = end_of_line(pp, endptr, &ellength);
1305            fwrite(p, 1, pp - p + 1, stdout);   /* In case binary zero */            FWRITE(p, 1, pp - p, stdout);
1306            p = pp + 1;            p = pp;
1307            }            }
1308          }          }
1309    
# Line 722  while (ptr < endptr) Line 1318  while (ptr < endptr)
1318    
1319        /* In multiline mode, we want to print to the end of the line in which        /* In multiline mode, we want to print to the end of the line in which
1320        the end of the matched string is found, so we adjust linelength and the        the end of the matched string is found, so we adjust linelength and the
1321        line number appropriately. Because the PCRE_FIRSTLINE option is set, the        line number appropriately, but only when there actually was a match
1322        start of the match will always be before the first \n character. */        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1323          the match will always be before the first newline sequence. */
1324    
1325        if (multiline)        if (multiline & !invert)
1326          {          {
1327          char *endmatch = ptr + offsets[1];          char *endmatch = ptr + offsets[1];
1328          t = ptr;          t = ptr;
1329          while (t < endmatch) { if (*t++ == '\n') linenumber++; }          while (t < endmatch)
1330          while (endmatch < endptr && *endmatch != '\n') endmatch++;            {
1331          linelength = endmatch - ptr;            t = end_of_line(t, endptr, &endlinelength);
1332              if (t < endmatch) linenumber++; else break;
1333              }
1334            linelength = t - ptr - endlinelength;
1335          }          }
1336    
1337        /*** NOTE: Use only fwrite() to output the data line, so that binary        /*** NOTE: Use only fwrite() to output the data line, so that binary
# Line 746  while (ptr < endptr) Line 1346  while (ptr < endptr)
1346          {          {
1347          int first = S_arg * 2;          int first = S_arg * 2;
1348          int last  = first + 1;          int last  = first + 1;
1349          fwrite(ptr, 1, offsets[first], stdout);          FWRITE(ptr, 1, offsets[first], stdout);
1350          fprintf(stdout, "X");          fprintf(stdout, "X");
1351          fwrite(ptr + offsets[last], 1, linelength - offsets[last], stdout);          FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1352          }          }
1353        else        else
1354  #endif  #endif
1355    
1356        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1357          matches, but not of course if the line is a non-match. */
1358    
1359        if (do_colour)        if (do_colour && !invert)
1360          {          {
1361          fwrite(ptr, 1, offsets[0], stdout);          int plength;
1362            int last_offset = 0;
1363            FWRITE(ptr, 1, offsets[0], stdout);
1364          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1365          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1366          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1367          fwrite(ptr + offsets[1], 1, linelength - offsets[1], stdout);          for (;;)
1368              {
1369              /*
1370              last_offset += offsets[1];
1371              matchptr += offsets[1];
1372              length -= offsets[1];
1373              */
1374    
1375              startoffset = offsets[1];
1376              last_offset = startoffset;
1377              if (last_offset >= linelength + endlinelength ||
1378                  !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1379                break;
1380              FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1381              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1382              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1383              fprintf(stdout, "%c[00m", 0x1b);
1384              }
1385    
1386            /* In multiline mode, we may have already printed the complete line
1387            and its line-ending characters (if they matched the pattern), so there
1388            may be no more to print. */
1389    
1390            plength = (linelength + endlinelength) - last_offset;
1391            if (plength > 0)
1392              FWRITE(ptr + last_offset, 1, plength, stdout);
1393          }          }
       else fwrite(ptr, 1, linelength, stdout);  
1394    
1395        fprintf(stdout, "\n");        /* Not colouring; no need to search for further matches */
1396    
1397          else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1398        }        }
1399    
1400      /* End of doing what has to be done for a match */      /* End of doing what has to be done for a match. If --line-buffered was
1401        given, flush the output. */
1402    
1403        if (line_buffered) fflush(stdout);
1404      rc = 0;    /* Had some success */      rc = 0;    /* Had some success */
1405    
1406      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
1407      where we are about to restart, and that line's number. */      where we are about to restart, and that line's number. */
1408    
1409      lastmatchrestart = ptr + linelength + 1;      lastmatchrestart = ptr + linelength + endlinelength;
1410      lastmatchnumber = linenumber + 1;      lastmatchnumber = linenumber + 1;
1411      }      }
1412    
1413    /* Advance to after the newline and increment the line number. */    /* For a match in multiline inverted mode (which of course did not cause
1414      anything to be printed), we have to move on to the end of the match before
1415      proceeding. */
1416    
1417      if (multiline && invert && match)
1418        {
1419        int ellength;
1420        char *endmatch = ptr + offsets[1];
1421        t = ptr;
1422        while (t < endmatch)
1423          {
1424          t = end_of_line(t, endptr, &ellength);
1425          if (t <= endmatch) linenumber++; else break;
1426          }
1427        endmatch = end_of_line(endmatch, endptr, &ellength);
1428        linelength = endmatch - ptr - ellength;
1429        }
1430    
1431      /* Advance to after the newline and increment the line number. The file
1432      offset to the current line is maintained in filepos. */
1433    
1434    ptr += linelength + 1;    ptr += linelength + endlinelength;
1435      filepos += (int)(linelength + endlinelength);
1436    linenumber++;    linenumber++;
1437    
1438      /* If input is line buffered, and the buffer is not yet full, read another
1439      line and add it into the buffer. */
1440    
1441      if (input_line_buffered && bufflength < sizeof(buffer))
1442        {
1443        int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);
1444        bufflength += add;
1445        endptr += add;
1446        }
1447    
1448    /* If we haven't yet reached the end of the file (the buffer is full), and    /* If we haven't yet reached the end of the file (the buffer is full), and
1449    the current point is in the top 1/3 of the buffer, slide the buffer down by    the current point is in the top 1/3 of the buffer, slide the buffer down by
1450    1/3 and refill it. Before we do this, if some unprinted "after" lines are    1/3 and refill it. Before we do this, if some unprinted "after" lines are
# Line 803  while (ptr < endptr) Line 1464  while (ptr < endptr)
1464    
1465      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1466      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1467      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);  
1468    #ifdef SUPPORT_LIBZ
1469        if (frtype == FR_LIBZ)
1470          bufflength = 2*MBUFTHIRD +
1471            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1472        else
1473    #endif
1474    
1475    #ifdef SUPPORT_LIBBZ2
1476        if (frtype == FR_LIBBZ2)
1477          bufflength = 2*MBUFTHIRD +
1478            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1479        else
1480    #endif
1481    
1482        bufflength = 2*MBUFTHIRD +
1483          (input_line_buffered?
1484           read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :
1485           fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));
1486      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1487    
1488      /* Adjust any last match point */      /* Adjust any last match point */
# Line 815  while (ptr < endptr) Line 1494  while (ptr < endptr)
1494  /* End of file; print final "after" lines if wanted; do_after_lines sets  /* End of file; print final "after" lines if wanted; do_after_lines sets
1495  hyphenpending if it prints something. */  hyphenpending if it prints something. */
1496    
1497  if (!only_matching && !count_only)  if (only_matching < 0 && !count_only)
1498    {    {
1499    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1500    hyphenpending |= endhyphenpending;    hyphenpending |= endhyphenpending;
# Line 834  if (filenames == FN_NOMATCH_ONLY) Line 1513  if (filenames == FN_NOMATCH_ONLY)
1513    
1514  if (count_only)  if (count_only)
1515    {    {
1516    if (printname != NULL) fprintf(stdout, "%s:", printname);    if (count > 0 || !omit_zero_count)
1517    fprintf(stdout, "%d\n", count);      {
1518        if (printname != NULL && filenames != FN_NONE)
1519          fprintf(stdout, "%s:", printname);
1520        fprintf(stdout, "%d\n", count);
1521        }
1522    }    }
1523    
1524  return rc;  return rc;
# Line 867  grep_or_recurse(char *pathname, BOOL dir Line 1550  grep_or_recurse(char *pathname, BOOL dir
1550  {  {
1551  int rc = 1;  int rc = 1;
1552  int sep;  int sep;
1553  FILE *in;  int frtype;
1554    int pathlen;
1555    void *handle;
1556    FILE *in = NULL;           /* Ensure initialized */
1557    
1558    #ifdef SUPPORT_LIBZ
1559    gzFile ingz = NULL;
1560    #endif
1561    
1562    #ifdef SUPPORT_LIBBZ2
1563    BZFILE *inbz2 = NULL;
1564    #endif
1565    
1566  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1567    
1568  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1569    {    {
1570    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1571      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1572        stdin_name : NULL);        stdin_name : NULL);
1573    }    }
1574    
   
1575  /* If the file is a directory, skip if skipping or if we are recursing, scan  /* If the file is a directory, skip if skipping or if we are recursing, scan
1576  each file within it, subject to any include or exclude patterns that were set.  each file and directory within it, subject to any include or exclude patterns
1577  The scanning code is localized so it can be made system-specific. */  that were set. The scanning code is localized so it can be made
1578    system-specific. */
1579    
1580  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1581    {    {
# Line 902  if ((sep = isdirectory(pathname)) != 0) Line 1596  if ((sep = isdirectory(pathname)) != 0)
1596    
1597      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1598        {        {
1599        int frc, blen;        int frc, nflen;
1600        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1601        blen = strlen(buffer);        nflen = (int)(strlen(nextfile));
1602    
1603        if (exclude_compiled != NULL &&        if (isdirectory(buffer))
1604            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)          {
1605          continue;          if (exclude_dir_compiled != NULL &&
1606                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1607        if (include_compiled != NULL &&            continue;
1608            pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
1609          continue;          if (include_dir_compiled != NULL &&
1610                pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1611              continue;
1612            }
1613          else
1614            {
1615            if (exclude_compiled != NULL &&
1616                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1617              continue;
1618    
1619            if (include_compiled != NULL &&
1620                pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1621              continue;
1622            }
1623    
1624        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1625        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 935  skipping was not requested. The scan pro Line 1642  skipping was not requested. The scan pro
1642  argument at top level, we don't show the file name, unless we are only showing  argument at top level, we don't show the file name, unless we are only showing
1643  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1644    
1645  in = fopen(pathname, "r");  pathlen = (int)(strlen(pathname));
1646  if (in == NULL)  
1647    /* Open using zlib if it is supported and the file name ends with .gz. */
1648    
1649    #ifdef SUPPORT_LIBZ
1650    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1651      {
1652      ingz = gzopen(pathname, "rb");
1653      if (ingz == NULL)
1654        {
1655        if (!silent)
1656          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1657            strerror(errno));
1658        return 2;
1659        }
1660      handle = (void *)ingz;
1661      frtype = FR_LIBZ;
1662      }
1663    else
1664    #endif
1665    
1666    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1667    
1668    #ifdef SUPPORT_LIBBZ2
1669    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1670      {
1671      inbz2 = BZ2_bzopen(pathname, "rb");
1672      handle = (void *)inbz2;
1673      frtype = FR_LIBBZ2;
1674      }
1675    else
1676    #endif
1677    
1678    /* Otherwise use plain fopen(). The label is so that we can come back here if
1679    an attempt to read a .bz2 file indicates that it really is a plain file. */
1680    
1681    #ifdef SUPPORT_LIBBZ2
1682    PLAIN_FILE:
1683    #endif
1684      {
1685      in = fopen(pathname, "rb");
1686      handle = (void *)in;
1687      frtype = FR_PLAIN;
1688      }
1689    
1690    /* All the opening methods return errno when they fail. */
1691    
1692    if (handle == NULL)
1693    {    {
1694    if (!silent)    if (!silent)
1695      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 944  if (in == NULL) Line 1697  if (in == NULL)
1697    return 2;    return 2;
1698    }    }
1699    
1700  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1701    
1702    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1703    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1704    
1705    /* Close in an appropriate manner. */
1706    
1707    #ifdef SUPPORT_LIBZ
1708    if (frtype == FR_LIBZ)
1709      gzclose(ingz);
1710    else
1711    #endif
1712    
1713    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1714    read failed. If the error indicates that the file isn't in fact bzipped, try
1715    again as a normal file. */
1716    
1717    #ifdef SUPPORT_LIBBZ2
1718    if (frtype == FR_LIBBZ2)
1719      {
1720      if (rc == 2)
1721        {
1722        int errnum;
1723        const char *err = BZ2_bzerror(inbz2, &errnum);
1724        if (errnum == BZ_DATA_ERROR_MAGIC)
1725          {
1726          BZ2_bzclose(inbz2);
1727          goto PLAIN_FILE;
1728          }
1729        else if (!silent)
1730          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1731            pathname, err);
1732        }
1733      BZ2_bzclose(inbz2);
1734      }
1735    else
1736    #endif
1737    
1738    /* Normal file close */
1739    
1740  fclose(in);  fclose(in);
1741    
1742    /* Pass back the yield from pcregrep(). */
1743    
1744  return rc;  return rc;
1745  }  }
1746    
# Line 968  for (op = optionlist; op->one_char != 0; Line 1761  for (op = optionlist; op->one_char != 0;
1761    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1762    }    }
1763  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1764  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1765      "options.\n");
1766  return rc;  return rc;
1767  }  }
1768    
# Line 987  option_item *op; Line 1781  option_item *op;
1781  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1782  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1783  printf("PATTERN must be present if neither -e nor -f is used.\n");  printf("PATTERN must be present if neither -e nor -f is used.\n");
1784  printf("\"-\" can be used as a file name to mean STDIN.\n\n");  printf("\"-\" can be used as a file name to mean STDIN.\n");
1785  printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
1786    #ifdef SUPPORT_LIBZ
1787    printf("Files whose names end in .gz are read using zlib.\n");
1788    #endif
1789    
1790    #ifdef SUPPORT_LIBBZ2
1791    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1792    #endif
1793    
1794    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1795    printf("Other files and the standard input are read as plain files.\n\n");
1796    #else
1797    printf("All files are read as plain files, without any interpretation.\n\n");
1798    #endif
1799    
1800    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1801  printf("Options:\n");  printf("Options:\n");
1802    
1803  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
1804    {    {
1805    int n;    int n;
1806    char s[4];    char s[4];
1807    
1808      /* Two options were accidentally implemented and documented with underscores
1809      instead of hyphens in their names, something that was not noticed for quite a
1810      few releases. When fixing this, I left the underscored versions in the list
1811      in case people were using them. However, we don't want to display them in the
1812      help data. There are no other options that contain underscores, and we do not
1813      expect ever to implement such options. Therefore, just omit any option that
1814      contains an underscore. */
1815    
1816      if (strchr(op->long_name, '_') != NULL) continue;
1817    
1818    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");
1819    printf("  %s --%s%n", s, op->long_name, &n);    n = 31 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1820    if (n < 1) n = 1;    if (n < 1) n = 1;
1821    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1822    }    }
1823    
1824  printf("\nWhen reading patterns from a file instead of using a command line option,\n");  printf("\nWhen reading patterns from a file instead of using a command line option,\n");
# Line 1023  handle_option(int letter, int options) Line 1841  handle_option(int letter, int options)
1841  {  {
1842  switch(letter)  switch(letter)
1843    {    {
1844    case N_HELP: help(); exit(0);    case N_FOFFSETS: file_offsets = TRUE; break;
1845      case N_HELP: help(); pcregrep_exit(0);
1846      case N_LOFFSETS: line_offsets = number = TRUE; break;
1847      case N_LBUFFER: line_buffered = TRUE; break;
1848    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1849    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1850    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1851    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1852    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1853    case 'l': filenames = FN_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1854    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1855    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1856    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
1857    case 'o': only_matching = TRUE; break;    case 'o': only_matching = 0; break;
1858    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1859    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1860    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
1861    case 'u': options |= PCRE_UTF8; break;    case 'u': options |= PCRE_UTF8; utf8 = TRUE; break;
1862    case 'v': invert = TRUE; break;    case 'v': invert = TRUE; break;
1863    case 'w': process_options |= PO_WORD_MATCH; break;    case 'w': process_options |= PO_WORD_MATCH; break;
1864    case 'x': process_options |= PO_LINE_MATCH; break;    case 'x': process_options |= PO_LINE_MATCH; break;
1865    
1866    case 'V':    case 'V':
1867    fprintf(stderr, "pcregrep version %s using ", VERSION);    fprintf(stderr, "pcregrep version %s\n", pcre_version());
1868    fprintf(stderr, "PCRE version %s\n", pcre_version());    pcregrep_exit(0);
   exit(0);  
1869    break;    break;
1870    
1871    default:    default:
1872    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
1873    exit(usage(2));    pcregrep_exit(usage(2));
1874    }    }
1875    
1876  return options;  return options;
# Line 1120  sprintf(buffer, "%s%.*s%s", prefix[proce Line 1940  sprintf(buffer, "%s%.*s%s", prefix[proce
1940    suffix[process_options]);    suffix[process_options]);
1941  pattern_list[pattern_count] =  pattern_list[pattern_count] =
1942    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
1943  if (pattern_list[pattern_count++] != NULL) return TRUE;  if (pattern_list[pattern_count] != NULL)
1944      {
1945      pattern_count++;
1946      return TRUE;
1947      }
1948    
1949  /* Handle compile errors */  /* Handle compile errors */
1950    
# Line 1152  return FALSE; Line 1976  return FALSE;
1976  *************************************************/  *************************************************/
1977    
1978  /* When the -F option has been used, each string may be a list of strings,  /* When the -F option has been used, each string may be a list of strings,
1979  separated by newlines. They will be matched literally.  separated by line breaks. They will be matched literally.
1980    
1981  Arguments:  Arguments:
1982    pattern        the pattern string    pattern        the pattern string
# Line 1170  compile_pattern(char *pattern, int optio Line 1994  compile_pattern(char *pattern, int optio
1994  {  {
1995  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
1996    {    {
1997      char *eop = pattern + strlen(pattern);
1998    char buffer[MBUFTHIRD];    char buffer[MBUFTHIRD];
1999    for(;;)    for(;;)
2000      {      {
2001      char *p = strchr(pattern, '\n');      int ellength;
2002      if (p == NULL)      char *p = end_of_line(pattern, eop, &ellength);
2003        if (ellength == 0)
2004        return compile_single_pattern(pattern, options, filename, count);        return compile_single_pattern(pattern, options, filename, count);
2005      sprintf(buffer, "%.*s", p - pattern, pattern);      sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern);
2006      pattern = p + 1;      pattern = p;
2007      if (!compile_single_pattern(buffer, options, filename, count))      if (!compile_single_pattern(buffer, options, filename, count))
2008        return FALSE;        return FALSE;
2009      }      }
# Line 1200  int i, j; Line 2026  int i, j;
2026  int rc = 1;  int rc = 1;
2027  int pcre_options = 0;  int pcre_options = 0;
2028  int cmd_pattern_count = 0;  int cmd_pattern_count = 0;
2029    int hint_count = 0;
2030  int errptr;  int errptr;
2031  BOOL only_one_at_top;  BOOL only_one_at_top;
2032  char *patterns[MAX_PATTERN_COUNT];  char *patterns[MAX_PATTERN_COUNT];
2033  const char *locale_from = "--locale";  const char *locale_from = "--locale";
2034  const char *error;  const char *error;
2035    
2036    /* Set the default line ending value from the default in the PCRE library;
2037    "lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf".
2038    Note that the return values from pcre_config(), though derived from the ASCII
2039    codes, are the same in EBCDIC environments, so we must use the actual values
2040    rather than escapes such as as '\r'. */
2041    
2042    (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
2043    switch(i)
2044      {
2045      default:               newline = (char *)"lf"; break;
2046      case 13:               newline = (char *)"cr"; break;
2047      case (13 << 8) | 10:   newline = (char *)"crlf"; break;
2048      case -1:               newline = (char *)"any"; break;
2049      case -2:               newline = (char *)"anycrlf"; break;
2050      }
2051    
2052  /* Process the options */  /* Process the options */
2053    
2054  for (i = 1; i < argc; i++)  for (i = 1; i < argc; i++)
# Line 1223  for (i = 1; i < argc; i++) Line 2066  for (i = 1; i < argc; i++)
2066    if (argv[i][1] == 0)    if (argv[i][1] == 0)
2067      {      {
2068      if (pattern_filename != NULL || pattern_count > 0) break;      if (pattern_filename != NULL || pattern_count > 0) break;
2069        else exit(usage(2));        else pcregrep_exit(usage(2));
2070      }      }
2071    
2072    /* Handle a long name option, or -- to terminate the options */    /* Handle a long name option, or -- to terminate the options */
# Line 1245  for (i = 1; i < argc; i++) Line 2088  for (i = 1; i < argc; i++)
2088      Some options have variations in the long name spelling: specifically, we      Some options have variations in the long name spelling: specifically, we
2089      allow "regexp" because GNU grep allows it, though I personally go along      allow "regexp" because GNU grep allows it, though I personally go along
2090      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
2091      These options are entered in the table as "regex(p)". No option is in both      These options are entered in the table as "regex(p)". Options can be in
2092      these categories, fortunately. */      both these categories. */
2093    
2094      for (op = optionlist; op->one_char != 0; op++)      for (op = optionlist; op->one_char != 0; op++)
2095        {        {
2096        char *opbra = strchr(op->long_name, '(');        char *opbra = strchr(op->long_name, '(');
2097        char *equals = strchr(op->long_name, '=');        char *equals = strchr(op->long_name, '=');
2098        if (opbra == NULL)     /* Not a (p) case */  
2099          /* Handle options with only one spelling of the name */
2100    
2101          if (opbra == NULL)     /* Does not contain '(' */
2102          {          {
2103          if (equals == NULL)  /* Not thing=data case */          if (equals == NULL)  /* Not thing=data case */
2104            {            {
# Line 1260  for (i = 1; i < argc; i++) Line 2106  for (i = 1; i < argc; i++)
2106            }            }
2107          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
2108            {            {
2109            int oplen = equals - op->long_name;            int oplen = (int)(equals - op->long_name);
2110            int arglen = (argequals == NULL)? strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)?
2111                (int)strlen(arg) : (int)(argequals - arg);
2112            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
2113              {              {
2114              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1274  for (i = 1; i < argc; i++) Line 2121  for (i = 1; i < argc; i++)
2121              }              }
2122            }            }
2123          }          }
2124        else                   /* Special case xxxx(p) */  
2125          /* Handle options with an alternate spelling of the name */
2126    
2127          else
2128          {          {
2129          char buff1[24];          char buff1[24];
2130          char buff2[24];          char buff2[24];
2131          int baselen = opbra - op->long_name;  
2132            int baselen = (int)(opbra - op->long_name);
2133            int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
2134            int arglen = (argequals == NULL || equals == NULL)?
2135              (int)strlen(arg) : (int)(argequals - arg);
2136    
2137          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
2138          sprintf(buff2, "%s%.*s", buff1, strlen(op->long_name) - baselen - 2,          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
2139            opbra + 1);  
2140          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strncmp(arg, buff1, arglen) == 0 ||
2141               strncmp(arg, buff2, arglen) == 0)
2142              {
2143              if (equals != NULL && argequals != NULL)
2144                {
2145                option_data = argequals;
2146                if (*option_data == '=')
2147                  {
2148                  option_data++;
2149                  longopwasequals = TRUE;
2150                  }
2151                }
2152            break;            break;
2153              }
2154          }          }
2155        }        }
2156    
2157      if (op->one_char == 0)      if (op->one_char == 0)
2158        {        {
2159        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
2160        exit(usage(2));        pcregrep_exit(usage(2));
2161        }        }
2162      }      }
2163    
2164      /* Jeffrey Friedl's debugging harness uses these additional options which
2165      are not in the right form for putting in the option table because they use
2166      only one hyphen, yet are more than one character long. By putting them
2167      separately here, they will not get displayed as part of the help() output,
2168      but I don't think Jeffrey will care about that. */
2169    
2170    #ifdef JFRIEDL_DEBUG
2171      else if (strcmp(argv[i], "-pre") == 0) {
2172              jfriedl_prefix = argv[++i];
2173              continue;
2174      } else if (strcmp(argv[i], "-post") == 0) {
2175              jfriedl_postfix = argv[++i];
2176              continue;
2177      } else if (strcmp(argv[i], "-XT") == 0) {
2178              sscanf(argv[++i], "%d", &jfriedl_XT);
2179              continue;
2180      } else if (strcmp(argv[i], "-XR") == 0) {
2181              sscanf(argv[++i], "%d", &jfriedl_XR);
2182              continue;
2183      }
2184    #endif
2185    
2186    
2187    /* One-char options; many that have no data may be in a single argument; we    /* One-char options; many that have no data may be in a single argument; we
2188    continue till we hit the last one or one that needs data. */    continue till we hit the last one or one that needs data. */
2189    
# Line 1304  for (i = 1; i < argc; i++) Line 2194  for (i = 1; i < argc; i++)
2194      while (*s != 0)      while (*s != 0)
2195        {        {
2196        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2197          { if (*s == op->one_char) break; }          {
2198            if (*s == op->one_char) break;
2199            }
2200        if (op->one_char == 0)        if (op->one_char == 0)
2201          {          {
2202          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2203            *s, argv[i]);            *s, argv[i]);
2204          exit(usage(2));          pcregrep_exit(usage(2));
2205          }          }
2206        if (op->type != OP_NODATA || s[1] == 0)  
2207          /* Check for a single-character option that has data: OP_OP_NUMBER
2208          is used for one that either has a numerical number or defaults, i.e. the
2209          data is optional. If a digit follows, there is data; if not, carry on
2210          with other single-character options in the same string. */
2211    
2212          option_data = s+1;
2213          if (op->type == OP_OP_NUMBER)
2214          {          {
2215          option_data = s+1;          if (isdigit((unsigned char)s[1])) break;
         break;  
2216          }          }
2217          else   /* Check for end or a dataless option */
2218            {
2219            if (op->type != OP_NODATA || s[1] == 0) break;
2220            }
2221    
2222          /* Handle a single-character option with no data, then loop for the
2223          next character in the string. */
2224    
2225        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
2226        }        }
2227      }      }
# Line 1332  for (i = 1; i < argc; i++) Line 2238  for (i = 1; i < argc; i++)
2238    
2239    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that
2240    either has a value or defaults to something. It cannot have data in a    either has a value or defaults to something. It cannot have data in a
2241    separate item. At the moment, the only such options are "colo(u)r" and    separate item. At the moment, the only such options are "colo(u)r",
2242    Jeffrey Friedl's special debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2243    
2244    if (*option_data == 0 &&    if (*option_data == 0 &&
2245        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
# Line 1343  for (i = 1; i < argc; i++) Line 2249  for (i = 1; i < argc; i++)
2249        case N_COLOUR:        case N_COLOUR:
2250        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2251        break;        break;
2252    
2253          case 'o':
2254          only_matching = 0;
2255          break;
2256    
2257  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2258        case 'S':        case 'S':
2259        S_arg = 0;        S_arg = 0;
# Line 1359  for (i = 1; i < argc; i++) Line 2270  for (i = 1; i < argc; i++)
2270      if (i >= argc - 1 || longopwasequals)      if (i >= argc - 1 || longopwasequals)
2271        {        {
2272        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);
2273        exit(usage(2));        pcregrep_exit(usage(2));
2274        }        }
2275      option_data = argv[++i];      option_data = argv[++i];
2276      }      }
# Line 1380  for (i = 1; i < argc; i++) Line 2291  for (i = 1; i < argc; i++)
2291    
2292    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2293    
2294    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2295               op->type != OP_OP_NUMBER)
2296      {      {
2297      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2298      }      }
2299    
2300      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2301      only for unpicking arguments, so just keep it simple. */
2302    
2303    else    else
2304      {      {
2305      char *endptr;      unsigned long int n = 0;
2306      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2307        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2308        while (isdigit((unsigned char)(*endptr)))
2309          n = n * 10 + (int)(*endptr++ - '0');
2310      if (*endptr != 0)      if (*endptr != 0)
2311        {        {
2312        if (longop)        if (longop)
2313          {          {
2314          char *equals = strchr(op->long_name, '=');          char *equals = strchr(op->long_name, '=');
2315          int nlen = (equals == NULL)? (int)strlen(op->long_name) :          int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2316            equals - op->long_name;            (int)(equals - op->long_name);
2317          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2318            option_data, nlen, op->long_name);            option_data, nlen, op->long_name);
2319          }          }
2320        else        else
2321          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2322            option_data, op->one_char);            option_data, op->one_char);
2323        exit(usage(2));        pcregrep_exit(usage(2));
2324        }        }
2325      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2326            *((unsigned long int *)op->dataptr) = n;
2327        else
2328            *((int *)op->dataptr) = n;
2329      }      }
2330    }    }
2331    
# Line 1416  if (both_context > 0) Line 2338  if (both_context > 0)
2338    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2339    }    }
2340    
2341    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2342    However, the latter two set only_matching. */
2343    
2344    if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2345        (file_offsets && line_offsets))
2346      {
2347      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2348        "and/or --line-offsets\n");
2349      pcregrep_exit(usage(2));
2350      }
2351    
2352    if (file_offsets || line_offsets) only_matching = 0;
2353    
2354  /* If a locale has not been provided as an option, see if the LC_CTYPE or  /* If a locale has not been provided as an option, see if the LC_CTYPE or
2355  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2356    
# Line 1465  if (colour_option != NULL && strcmp(colo Line 2400  if (colour_option != NULL && strcmp(colo
2400      }      }
2401    }    }
2402    
2403    /* Interpret the newline type; the default settings are Unix-like. */
2404    
2405    if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)
2406      {
2407      pcre_options |= PCRE_NEWLINE_CR;
2408      endlinetype = EL_CR;
2409      }
2410    else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)
2411      {
2412      pcre_options |= PCRE_NEWLINE_LF;
2413      endlinetype = EL_LF;
2414      }
2415    else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)
2416      {
2417      pcre_options |= PCRE_NEWLINE_CRLF;
2418      endlinetype = EL_CRLF;
2419      }
2420    else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0)
2421      {
2422      pcre_options |= PCRE_NEWLINE_ANY;
2423      endlinetype = EL_ANY;
2424      }
2425    else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0)
2426      {
2427      pcre_options |= PCRE_NEWLINE_ANYCRLF;
2428      endlinetype = EL_ANYCRLF;
2429      }
2430    else
2431      {
2432      fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline);
2433      return 2;
2434      }
2435    
2436  /* Interpret the text values for -d and -D */  /* Interpret the text values for -d and -D */
2437    
2438  if (dee_option != NULL)  if (dee_option != NULL)
# Line 1490  if (DEE_option != NULL) Line 2458  if (DEE_option != NULL)
2458      }      }
2459    }    }
2460    
2461  /* Check the value for Jeff Friedl's debugging option. */  /* Check the values for Jeffrey Friedl's debugging options. */
2462    
2463  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2464  if (S_arg > 9)  if (S_arg > 9)
# Line 1498  if (S_arg > 9) Line 2466  if (S_arg > 9)
2466    fprintf(stderr, "pcregrep: bad value for -S option\n");    fprintf(stderr, "pcregrep: bad value for -S option\n");
2467    return 2;    return 2;
2468    }    }
2469    if (jfriedl_XT != 0 || jfriedl_XR != 0)
2470      {
2471      if (jfriedl_XT == 0) jfriedl_XT = 1;
2472      if (jfriedl_XR == 0) jfriedl_XR = 1;
2473      }
2474  #endif  #endif
2475    
2476  /* Get memory to store the pattern and hints lists. */  /* Get memory to store the pattern and hints lists. */
# Line 1508  hints_list = (pcre_extra **)malloc(MAX_P Line 2481  hints_list = (pcre_extra **)malloc(MAX_P
2481  if (pattern_list == NULL || hints_list == NULL)  if (pattern_list == NULL || hints_list == NULL)
2482    {    {
2483    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2484    return 2;    goto EXIT2;
2485    }    }
2486    
2487  /* If no patterns were provided by -e, and there is no file provided by -f,  /* If no patterns were provided by -e, and there is no file provided by -f,
# Line 1527  for (j = 0; j < cmd_pattern_count; j++) Line 2500  for (j = 0; j < cmd_pattern_count; j++)
2500    {    {
2501    if (!compile_pattern(patterns[j], pcre_options, NULL,    if (!compile_pattern(patterns[j], pcre_options, NULL,
2502         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))
2503      return 2;      goto EXIT2;
2504    }    }
2505    
2506  /* Compile the regular expressions that are provided in a file. */  /* Compile the regular expressions that are provided in a file. */
# Line 1551  if (pattern_filename != NULL) Line 2524  if (pattern_filename != NULL)
2524        {        {
2525        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,
2526          strerror(errno));          strerror(errno));
2527        return 2;        goto EXIT2;
2528        }        }
2529      filename = pattern_filename;      filename = pattern_filename;
2530      }      }
# Line 1564  if (pattern_filename != NULL) Line 2537  if (pattern_filename != NULL)
2537      linenumber++;      linenumber++;
2538      if (buffer[0] == 0) continue;   /* Skip blank lines */      if (buffer[0] == 0) continue;   /* Skip blank lines */
2539      if (!compile_pattern(buffer, pcre_options, filename, linenumber))      if (!compile_pattern(buffer, pcre_options, filename, linenumber))
2540        return 2;        goto EXIT2;
2541      }      }
2542    
2543    if (f != stdin) fclose(f);    if (f != stdin) fclose(f);
# Line 1580  for (j = 0; j < pattern_count; j++) Line 2553  for (j = 0; j < pattern_count; j++)
2553      char s[16];      char s[16];
2554      if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);      if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);
2555      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
2556      return 2;      goto EXIT2;
2557        }
2558      hint_count++;
2559      }
2560    
2561    /* If --match-limit or --recursion-limit was set, put the value(s) into the
2562    pcre_extra block for each pattern. */
2563    
2564    if (match_limit > 0 || match_limit_recursion > 0)
2565      {
2566      for (j = 0; j < pattern_count; j++)
2567        {
2568        if (hints_list[j] == NULL)
2569          {
2570          hints_list[j] = malloc(sizeof(pcre_extra));
2571          if (hints_list[j] == NULL)
2572            {
2573            fprintf(stderr, "pcregrep: malloc failed\n");
2574            pcregrep_exit(2);
2575            }
2576          }
2577        if (match_limit > 0)
2578          {
2579          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2580          hints_list[j]->match_limit = match_limit;
2581          }
2582        if (match_limit_recursion > 0)
2583          {
2584          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2585          hints_list[j]->match_limit_recursion = match_limit_recursion;
2586          }
2587      }      }
2588    }    }
2589    
# Line 1594  if (exclude_pattern != NULL) Line 2597  if (exclude_pattern != NULL)
2597      {      {
2598      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",
2599        errptr, error);        errptr, error);
2600      return 2;      goto EXIT2;
2601      }      }
2602    }    }
2603    
# Line 1606  if (include_pattern != NULL) Line 2609  if (include_pattern != NULL)
2609      {      {
2610      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",
2611        errptr, error);        errptr, error);
2612      return 2;      goto EXIT2;
2613        }
2614      }
2615    
2616    if (exclude_dir_pattern != NULL)
2617      {
2618      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2619        pcretables);
2620      if (exclude_dir_compiled == NULL)
2621        {
2622        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2623          errptr, error);
2624        goto EXIT2;
2625        }
2626      }
2627    
2628    if (include_dir_pattern != NULL)
2629      {
2630      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2631        pcretables);
2632      if (include_dir_compiled == NULL)
2633        {
2634        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2635          errptr, error);
2636        goto EXIT2;
2637      }      }
2638    }    }
2639    
2640  /* If there are no further arguments, do the business on stdin and exit. */  /* If there are no further arguments, do the business on stdin and exit. */
2641    
2642  if (i >= argc)  if (i >= argc)
2643    return pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    {
2644      rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2645      goto EXIT;
2646      }
2647    
2648  /* Otherwise, work through the remaining arguments as files or directories.  /* Otherwise, work through the remaining arguments as files or directories.
2649  Pass in the fact that there is only one argument at top level - this suppresses  Pass in the fact that there is only one argument at top level - this suppresses
# Line 1630  for (; i < argc; i++) Line 2660  for (; i < argc; i++)
2660      else if (frc == 0 && rc == 1) rc = 0;      else if (frc == 0 && rc == 1) rc = 0;
2661    }    }
2662    
2663  return rc;  EXIT:
2664    if (pattern_list != NULL)
2665      {
2666      for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
2667      free(pattern_list);
2668      }
2669    if (hints_list != NULL)
2670      {
2671      for (i = 0; i < hint_count; i++)
2672        {
2673        if (hints_list[i] != NULL) free(hints_list[i]);
2674        }
2675      free(hints_list);
2676      }
2677    pcregrep_exit(rc);
2678    
2679    EXIT2:
2680    rc = 2;
2681    goto EXIT;
2682  }  }
2683    
2684  /* End of pcregrep */  /* End of pcregrep */

Legend:
Removed from v.87  
changed lines
  Added in v.632

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12