/[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 571 by ph10, Tue Nov 16 17:51:37 2010 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-2010 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    
# 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" },
# Line 165  static option_item optionlist[] = { Line 221  static option_item optionlist[] = {
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_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
225    { OP_NUMBER,    'C',      &both_context,     "context=number", "set number of context lines, before & after" },    { OP_NUMBER,    'C',      &both_context,     "context=number", "set number of context lines, before & after" },
226    { OP_NODATA,    'c',      NULL,              "count",         "print only a count of matching lines per FILE" },    { OP_NODATA,    'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
   { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },  
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,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
233    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
234    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
235    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
236    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
237    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
238    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
239      { OP_NODATA,    N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
240      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
241    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
242      { OP_NUMBER,    N_M_LIMIT,&match_limit,      "match-limit=number", "set PCRE match limit option" },
243      { OP_NUMBER,    N_M_LIMIT_REC,&match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
244    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
245      { 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" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
247    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_OP_NUMBER, 'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
248    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
249    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },
250    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { 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" },    { 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  /*************************************************  /*************************************************
# Line 222  although at present the only ones are fo Line 305  although at present the only ones are fo
305    
306  /************* Directory scanning in Unix ***********/  /************* Directory scanning in Unix ***********/
307    
308  #if IS_UNIX  #if defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H
309  #include <sys/types.h>  #include <sys/types.h>
310  #include <sys/stat.h>  #include <sys/stat.h>
311  #include <dirent.h>  #include <dirent.h>
# Line 254  for (;;) Line 337  for (;;)
337    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
338      return dent->d_name;      return dent->d_name;
339    }    }
340  return NULL;   /* Keep compiler happy; never executed */  /* Control never reaches here */
341  }  }
342    
343  static void  static void
# Line 276  return (statbuf.st_mode & S_IFMT) == S_I Line 359  return (statbuf.st_mode & S_IFMT) == S_I
359  }  }
360    
361    
362  /************* Test stdout for being a terminal in Unix **********/  /************* Test for a terminal in Unix **********/
363    
364  static BOOL  static BOOL
365  is_stdout_tty(void)  is_stdout_tty(void)
# Line 284  is_stdout_tty(void) Line 367  is_stdout_tty(void)
367  return isatty(fileno(stdout));  return isatty(fileno(stdout));
368  }  }
369    
370    static BOOL
371    is_file_tty(FILE *f)
372    {
373    return isatty(fileno(f));
374    }
375    
376    
377  /************* Directory scanning in Win32 ***********/  /************* Directory scanning in Win32 ***********/
378    
379  /* 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
380  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
381  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
382    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
383    The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
384    undefined when it is indeed undefined. */
385    
386    #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
 #elif HAVE_WIN32API  
387    
388  #ifndef STRICT  #ifndef STRICT
389  # define STRICT  # define STRICT
# Line 300  when it did not exist. */ Line 391  when it did not exist. */
391  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
392  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
393  #endif  #endif
394    
395    #include <windows.h>
396    
397  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
398  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
399  #endif  #endif
400    
 #include <windows.h>  
   
401  typedef struct directory_type  typedef struct directory_type
402  {  {
403  HANDLE handle;  HANDLE handle;
# Line 335  dir = (directory_type *) malloc(sizeof(* Line 427  dir = (directory_type *) malloc(sizeof(*
427  if ((pattern == NULL) || (dir == NULL))  if ((pattern == NULL) || (dir == NULL))
428    {    {
429    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
430    exit(2);    pcregrep_exit(2);
431    }    }
432  memcpy(pattern, filename, len);  memcpy(pattern, filename, len);
433  memcpy(&(pattern[len]), "\\*", 3);  memcpy(&(pattern[len]), "\\*", 3);
# Line 390  regular if they are not directories. */ Line 482  regular if they are not directories. */
482    
483  int isregfile(char *filename)  int isregfile(char *filename)
484  {  {
485  return !isdirectory(filename)  return !isdirectory(filename);
486  }  }
487    
488    
489  /************* Test stdout for being a terminal in Win32 **********/  /************* Test for a terminal in Win32 **********/
490    
491  /* I don't know how to do this; assume never */  /* I don't know how to do this; assume never */
492    
493  static BOOL  static BOOL
494  is_stdout_tty(void)  is_stdout_tty(void)
495  {  {
496  FALSE;  return FALSE;
497    }
498    
499    static BOOL
500    is_file_tty(FILE *f)
501    {
502    return FALSE;
503  }  }
504    
505    
# Line 414  FALSE; Line 512  FALSE;
512  typedef void directory_type;  typedef void directory_type;
513    
514  int isdirectory(char *filename) { return 0; }  int isdirectory(char *filename) { return 0; }
515  directory_type * opendirectory(char *filename) {}  directory_type * opendirectory(char *filename) { return (directory_type*)0;}
516  char *readdirectory(directory_type *dir) {}  char *readdirectory(directory_type *dir) { return (char*)0;}
517  void closedirectory(directory_type *dir) {}  void closedirectory(directory_type *dir) {}
518    
519    
# Line 426  void closedirectory(directory_type *dir) Line 524  void closedirectory(directory_type *dir)
524  int isregfile(char *filename) { return 1; }  int isregfile(char *filename) { return 1; }
525    
526    
527  /************* Test stdout for being a terminal when we can't do it **********/  /************* Test for a terminal when we can't do it **********/
528    
529  static BOOL  static BOOL
530  is_stdout_tty(void)  is_stdout_tty(void)
# Line 434  is_stdout_tty(void) Line 532  is_stdout_tty(void)
532  return FALSE;  return FALSE;
533  }  }
534    
535    static BOOL
536    is_file_tty(FILE *f)
537    {
538    return FALSE;
539    }
540    
541  #endif  #endif
542    
543    
544    
545  #if ! HAVE_STRERROR  #ifndef HAVE_STRERROR
546  /*************************************************  /*************************************************
547  *     Provide strerror() for non-ANSI libraries  *  *     Provide strerror() for non-ANSI libraries  *
548  *************************************************/  *************************************************/
# Line 462  return sys_errlist[n]; Line 565  return sys_errlist[n];
565    
566    
567  /*************************************************  /*************************************************
568    *         Exit from the program                  *
569    *************************************************/
570    
571    /* If there has been a resource error, give a suitable message.
572    
573    Argument:  the return code
574    Returns:   does not return
575    */
576    
577    static void
578    pcregrep_exit(int rc)
579    {
580    if (resource_error)
581      {
582      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
583        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
584      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
585      }
586    
587    exit(rc);
588    }
589    
590    
591    
592    /*************************************************
593    *            Read one line of input              *
594    *************************************************/
595    
596    /* Normally, input is read using fread() into a large buffer, so many lines may
597    be read at once. However, doing this for tty input means that no output appears
598    until a lot of input has been typed. Instead, tty input is handled line by
599    line. We cannot use fgets() for this, because it does not stop at a binary
600    zero, and therefore there is no way of telling how many characters it has read,
601    because there may be binary zeros embedded in the data.
602    
603    Arguments:
604      buffer     the buffer to read into
605      length     the maximum number of characters to read
606      f          the file
607    
608    Returns:     the number of characters read, zero at end of file
609    */
610    
611    static int
612    read_one_line(char *buffer, int length, FILE *f)
613    {
614    int c;
615    int yield = 0;
616    while ((c = fgetc(f)) != EOF)
617      {
618      buffer[yield++] = c;
619      if (c == '\n' || yield >= length) break;
620      }
621    return yield;
622    }
623    
624    
625    
626    /*************************************************
627    *             Find end of line                   *
628    *************************************************/
629    
630    /* The length of the endline sequence that is found is set via lenptr. This may
631    be zero at the very end of the file if there is no line-ending sequence there.
632    
633    Arguments:
634      p         current position in line
635      endptr    end of available data
636      lenptr    where to put the length of the eol sequence
637    
638    Returns:    pointer to the last byte of the line
639    */
640    
641    static char *
642    end_of_line(char *p, char *endptr, int *lenptr)
643    {
644    switch(endlinetype)
645      {
646      default:      /* Just in case */
647      case EL_LF:
648      while (p < endptr && *p != '\n') p++;
649      if (p < endptr)
650        {
651        *lenptr = 1;
652        return p + 1;
653        }
654      *lenptr = 0;
655      return endptr;
656    
657      case EL_CR:
658      while (p < endptr && *p != '\r') p++;
659      if (p < endptr)
660        {
661        *lenptr = 1;
662        return p + 1;
663        }
664      *lenptr = 0;
665      return endptr;
666    
667      case EL_CRLF:
668      for (;;)
669        {
670        while (p < endptr && *p != '\r') p++;
671        if (++p >= endptr)
672          {
673          *lenptr = 0;
674          return endptr;
675          }
676        if (*p == '\n')
677          {
678          *lenptr = 2;
679          return p + 1;
680          }
681        }
682      break;
683    
684      case EL_ANYCRLF:
685      while (p < endptr)
686        {
687        int extra = 0;
688        register int c = *((unsigned char *)p);
689    
690        if (utf8 && c >= 0xc0)
691          {
692          int gcii, gcss;
693          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
694          gcss = 6*extra;
695          c = (c & utf8_table3[extra]) << gcss;
696          for (gcii = 1; gcii <= extra; gcii++)
697            {
698            gcss -= 6;
699            c |= (p[gcii] & 0x3f) << gcss;
700            }
701          }
702    
703        p += 1 + extra;
704    
705        switch (c)
706          {
707          case 0x0a:    /* LF */
708          *lenptr = 1;
709          return p;
710    
711          case 0x0d:    /* CR */
712          if (p < endptr && *p == 0x0a)
713            {
714            *lenptr = 2;
715            p++;
716            }
717          else *lenptr = 1;
718          return p;
719    
720          default:
721          break;
722          }
723        }   /* End of loop for ANYCRLF case */
724    
725      *lenptr = 0;  /* Must have hit the end */
726      return endptr;
727    
728      case EL_ANY:
729      while (p < endptr)
730        {
731        int extra = 0;
732        register int c = *((unsigned char *)p);
733    
734        if (utf8 && c >= 0xc0)
735          {
736          int gcii, gcss;
737          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
738          gcss = 6*extra;
739          c = (c & utf8_table3[extra]) << gcss;
740          for (gcii = 1; gcii <= extra; gcii++)
741            {
742            gcss -= 6;
743            c |= (p[gcii] & 0x3f) << gcss;
744            }
745          }
746    
747        p += 1 + extra;
748    
749        switch (c)
750          {
751          case 0x0a:    /* LF */
752          case 0x0b:    /* VT */
753          case 0x0c:    /* FF */
754          *lenptr = 1;
755          return p;
756    
757          case 0x0d:    /* CR */
758          if (p < endptr && *p == 0x0a)
759            {
760            *lenptr = 2;
761            p++;
762            }
763          else *lenptr = 1;
764          return p;
765    
766          case 0x85:    /* NEL */
767          *lenptr = utf8? 2 : 1;
768          return p;
769    
770          case 0x2028:  /* LS */
771          case 0x2029:  /* PS */
772          *lenptr = 3;
773          return p;
774    
775          default:
776          break;
777          }
778        }   /* End of loop for ANY case */
779    
780      *lenptr = 0;  /* Must have hit the end */
781      return endptr;
782      }     /* End of overall switch */
783    }
784    
785    
786    
787    /*************************************************
788    *         Find start of previous line            *
789    *************************************************/
790    
791    /* This is called when looking back for before lines to print.
792    
793    Arguments:
794      p         start of the subsequent line
795      startptr  start of available data
796    
797    Returns:    pointer to the start of the previous line
798    */
799    
800    static char *
801    previous_line(char *p, char *startptr)
802    {
803    switch(endlinetype)
804      {
805      default:      /* Just in case */
806      case EL_LF:
807      p--;
808      while (p > startptr && p[-1] != '\n') p--;
809      return p;
810    
811      case EL_CR:
812      p--;
813      while (p > startptr && p[-1] != '\n') p--;
814      return p;
815    
816      case EL_CRLF:
817      for (;;)
818        {
819        p -= 2;
820        while (p > startptr && p[-1] != '\n') p--;
821        if (p <= startptr + 1 || p[-2] == '\r') return p;
822        }
823      return p;   /* But control should never get here */
824    
825      case EL_ANY:
826      case EL_ANYCRLF:
827      if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;
828      if (utf8) while ((*p & 0xc0) == 0x80) p--;
829    
830      while (p > startptr)
831        {
832        register int c;
833        char *pp = p - 1;
834    
835        if (utf8)
836          {
837          int extra = 0;
838          while ((*pp & 0xc0) == 0x80) pp--;
839          c = *((unsigned char *)pp);
840          if (c >= 0xc0)
841            {
842            int gcii, gcss;
843            extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
844            gcss = 6*extra;
845            c = (c & utf8_table3[extra]) << gcss;
846            for (gcii = 1; gcii <= extra; gcii++)
847              {
848              gcss -= 6;
849              c |= (pp[gcii] & 0x3f) << gcss;
850              }
851            }
852          }
853        else c = *((unsigned char *)pp);
854    
855        if (endlinetype == EL_ANYCRLF) switch (c)
856          {
857          case 0x0a:    /* LF */
858          case 0x0d:    /* CR */
859          return p;
860    
861          default:
862          break;
863          }
864    
865        else switch (c)
866          {
867          case 0x0a:    /* LF */
868          case 0x0b:    /* VT */
869          case 0x0c:    /* FF */
870          case 0x0d:    /* CR */
871          case 0x85:    /* NEL */
872          case 0x2028:  /* LS */
873          case 0x2029:  /* PS */
874          return p;
875    
876          default:
877          break;
878          }
879    
880        p = pp;  /* Back one character */
881        }        /* End of loop for ANY case */
882    
883      return startptr;  /* Hit start of data */
884      }     /* End of overall switch */
885    }
886    
887    
888    
889    
890    
891    /*************************************************
892  *       Print the previous "after" lines         *  *       Print the previous "after" lines         *
893  *************************************************/  *************************************************/
894    
# Line 486  if (after_context > 0 && lastmatchnumber Line 913  if (after_context > 0 && lastmatchnumber
913    int count = 0;    int count = 0;
914    while (lastmatchrestart < endptr && count++ < after_context)    while (lastmatchrestart < endptr && count++ < after_context)
915      {      {
916        int ellength;
917      char *pp = lastmatchrestart;      char *pp = lastmatchrestart;
918      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
919      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
920      while (*pp != '\n') pp++;      pp = end_of_line(pp, endptr, &ellength);
921      fwrite(lastmatchrestart, 1, pp - lastmatchrestart + 1, stdout);      FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
922      lastmatchrestart = pp + 1;      lastmatchrestart = pp;
923      }      }
924    hyphenpending = TRUE;    hyphenpending = TRUE;
925    }    }
# Line 500  if (after_context > 0 && lastmatchnumber Line 928  if (after_context > 0 && lastmatchnumber
928    
929    
930  /*************************************************  /*************************************************
931    *   Apply patterns to subject till one matches   *
932    *************************************************/
933    
934    /* This function is called to run through all patterns, looking for a match. It
935    is used multiple times for the same subject when colouring is enabled, in order
936    to find all possible matches.
937    
938    Arguments:
939      matchptr    the start of the subject
940      length      the length of the subject to match
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 *offsets, int *mrc)
951    {
952    int i;
953    size_t slen = length;
954    const char *msg = "this text:\n\n";
955    if (slen > 200)
956      {
957      slen = 200;
958      msg = "text that starts:\n\n";
959      }
960    for (i = 0; i < pattern_count; i++)
961      {
962      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length, 0,
963        PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
964      if (*mrc >= 0) return TRUE;
965      if (*mrc == PCRE_ERROR_NOMATCH) continue;
966      fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
967      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
968      fprintf(stderr, "%s", msg);
969      FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
970      fprintf(stderr, "\n\n");
971      if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)
972        resource_error = TRUE;
973      if (error_count++ > 20)
974        {
975        fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
976        pcregrep_exit(2);
977        }
978      return invert;    /* No more matching; don't show the line again */
979      }
980    
981    return FALSE;  /* No match, no errors */
982    }
983    
984    
985    
986    /*************************************************
987  *            Grep an individual file             *  *            Grep an individual file             *
988  *************************************************/  *************************************************/
989    
# Line 511  be in the middle third most of the time, Line 995  be in the middle third most of the time,
995  "before" context printing.  "before" context printing.
996    
997  Arguments:  Arguments:
998    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
999                   the gzFile pointer when reading is via libz
1000                   the BZFILE pointer when reading is via libbz2
1001      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
1002    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
1003                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
1004                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
1005    
1006  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
1007                 1 otherwise (no matches)                 1 otherwise (no matches)
1008                   2 if there is a read error on a .bz2 file
1009  */  */
1010    
1011  static int  static int
1012  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
1013  {  {
1014  int rc = 1;  int rc = 1;
1015  int linenumber = 1;  int linenumber = 1;
1016  int lastmatchnumber = 0;  int lastmatchnumber = 0;
1017  int count = 0;  int count = 0;
1018  int offsets[99];  int filepos = 0;
1019    int offsets[OFFSET_SIZE];
1020  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
1021  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
1022  char *ptr = buffer;  char *ptr = buffer;
1023  char *endptr;  char *endptr;
1024  size_t bufflength;  size_t bufflength;
1025  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
1026    BOOL input_line_buffered = line_buffered;
1027    FILE *in = NULL;                    /* Ensure initialized */
1028    
1029    #ifdef SUPPORT_LIBZ
1030    gzFile ingz = NULL;
1031    #endif
1032    
1033  /* Do the first read into the start of the buffer and set up the pointer to  #ifdef SUPPORT_LIBBZ2
1034  end of what we have. */  BZFILE *inbz2 = NULL;
1035    #endif
1036    
1037    
1038    /* Do the first read into the start of the buffer and set up the pointer to end
1039    of what we have. In the case of libz, a non-zipped .gz file will be read as a
1040    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
1041    fail. */
1042    
1043    #ifdef SUPPORT_LIBZ
1044    if (frtype == FR_LIBZ)
1045      {
1046      ingz = (gzFile)handle;
1047      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
1048      }
1049    else
1050    #endif
1051    
1052    #ifdef SUPPORT_LIBBZ2
1053    if (frtype == FR_LIBBZ2)
1054      {
1055      inbz2 = (BZFILE *)handle;
1056      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
1057      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1058      }                                    /* without the cast it is unsigned. */
1059    else
1060    #endif
1061    
1062      {
1063      in = (FILE *)handle;
1064      if (is_file_tty(in)) input_line_buffered = TRUE;
1065      bufflength = input_line_buffered?
1066        read_one_line(buffer, 3*MBUFTHIRD, in) :
1067        fread(buffer, 1, 3*MBUFTHIRD, in);
1068      }
1069    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
1070  endptr = buffer + bufflength;  endptr = buffer + bufflength;
1071    
1072  /* 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 1076  way, the buffer is shifted left and re-f
1076    
1077  while (ptr < endptr)  while (ptr < endptr)
1078    {    {
1079    int i;    int endlinelength;
1080    int mrc = 0;    int mrc = 0;
1081    BOOL match = FALSE;    BOOL match;
1082      char *matchptr = ptr;
1083    char *t = ptr;    char *t = ptr;
1084    size_t length, linelength;    size_t length, linelength;
1085    
1086    /* 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
1087    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
1088    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
1089    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
1090    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
1091    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
1092      first line. */
1093    linelength = 0;  
1094    while (t < endptr && *t++ != '\n') linelength++;    t = end_of_line(t, endptr, &endlinelength);
1095    length = multiline? endptr - ptr : linelength;    linelength = t - ptr - endlinelength;
1096      length = multiline? (size_t)(endptr - ptr) : linelength;
1097    /* Run through all the patterns until one matches. Note that we don't include  
1098    the final newline in the subject string. */    /* Extra processing for Jeffrey Friedl's debugging. */
1099    
1100    for (i = 0; i < pattern_count; i++)  #ifdef JFRIEDL_DEBUG
1101      {    if (jfriedl_XT || jfriedl_XR)
1102      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,    {
1103        offsets, 99);        #include <sys/time.h>
1104      if (mrc >= 0) { match = TRUE; break; }        #include <time.h>
1105      if (mrc != PCRE_ERROR_NOMATCH)        struct timeval start_time, end_time;
1106        {        struct timezone dummy;
1107        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);        int i;
1108        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);  
1109        fprintf(stderr, "this line:\n");        if (jfriedl_XT)
1110        fwrite(ptr, 1, linelength, stderr);   /* In case binary zero included */        {
1111        fprintf(stderr, "\n");            unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix);
1112        if (error_count == 0 &&            const char *orig = ptr;
1113            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))            ptr = malloc(newlen + 1);
1114          {            if (!ptr) {
1115          fprintf(stderr, "pcregrep: error %d means that a resource limit "                    printf("out of memory");
1116            "was exceeded\n", mrc);                    pcregrep_exit(2);
1117          fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");            }
1118          }            endptr = ptr;
1119        if (error_count++ > 20)            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
1120          {            for (i = 0; i < jfriedl_XT; i++) {
1121          fprintf(stderr, "pcregrep: too many errors - abandoned\n");                    strncpy(endptr, orig,  length);
1122          exit(2);                    endptr += length;
1123          }            }
1124        match = invert;    /* No more matching; don't show the line again */            strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix);
1125        break;            length = newlen;
1126        }        }
1127      }  
1128          if (gettimeofday(&start_time, &dummy) != 0)
1129                  perror("bad gettimeofday");
1130    
1131    
1132          for (i = 0; i < jfriedl_XR; i++)
1133              match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0,
1134                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1135    
1136          if (gettimeofday(&end_time, &dummy) != 0)
1137                  perror("bad gettimeofday");
1138    
1139          double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0))
1140                          -
1141                          (start_time.tv_sec + (start_time.tv_usec / 1000000.0)));
1142    
1143          printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta);
1144          return 0;
1145      }
1146    #endif
1147    
1148      /* We come back here after a match when the -o option (only_matching) is set,
1149      in order to find any further matches in the same line. */
1150    
1151      ONLY_MATCHING_RESTART:
1152    
1153      /* Run through all the patterns until one matches or there is an error other
1154      than NOMATCH. This code is in a subroutine so that it can be re-used for
1155      finding subsequent matches when colouring matched lines. */
1156    
1157      match = match_patterns(matchptr, length, offsets, &mrc);
1158    
1159    /* 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. */
1160    
# Line 614  while (ptr < endptr) Line 1173  while (ptr < endptr)
1173      /* 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
1174      in the file. */      in the file. */
1175    
1176      else if (filenames == FN_ONLY)      else if (filenames == FN_MATCH_ONLY)
1177        {        {
1178        fprintf(stdout, "%s\n", printname);        fprintf(stdout, "%s\n", printname);
1179        return 0;        return 0;
# Line 624  while (ptr < endptr) Line 1183  while (ptr < endptr)
1183    
1184      else if (quiet) return 0;      else if (quiet) return 0;
1185    
1186      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, or a
1187      does not pring any context. */      captured portion of it, as long as this string is not empty, and the
1188        --file-offsets and --line-offsets options output offsets for the matching
1189        substring (they both force --only-matching = 0). None of these options
1190        prints any context. Afterwards, adjust the start and length, and then jump
1191        back to look for further matches in the same line. If we are in invert
1192        mode, however, nothing is printed and we do not restart - this could still
1193        be useful because the return code is set. */
1194    
1195      else if (only_matching)      else if (only_matching >= 0)
1196        {        {
1197        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
1198        if (number) fprintf(stdout, "%d:", linenumber);          {
1199        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1200        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
1201            if (line_offsets)
1202              fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1203                offsets[1] - offsets[0]);
1204            else if (file_offsets)
1205              fprintf(stdout, "%d,%d\n",
1206                (int)(filepos + matchptr + offsets[0] - ptr),
1207                offsets[1] - offsets[0]);
1208            else if (only_matching < mrc)
1209              {
1210              int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1211              if (plen > 0)
1212                {
1213                if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1214                FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1215                if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1216                fprintf(stdout, "\n");
1217                }
1218              }
1219            else if (printname != NULL || number) fprintf(stdout, "\n");
1220            matchptr += offsets[1];
1221            length -= offsets[1];
1222            match = FALSE;
1223            if (line_buffered) fflush(stdout);
1224            rc = 0;    /* Had some success */
1225            goto ONLY_MATCHING_RESTART;
1226            }
1227        }        }
1228    
1229      /* 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 1237  while (ptr < endptr)
1237    
1238        if (after_context > 0 && lastmatchnumber > 0)        if (after_context > 0 && lastmatchnumber > 0)
1239          {          {
1240            int ellength;
1241          int linecount = 0;          int linecount = 0;
1242          char *p = lastmatchrestart;          char *p = lastmatchrestart;
1243    
1244          while (p < ptr && linecount < after_context)          while (p < ptr && linecount < after_context)
1245            {            {
1246            while (*p != '\n') p++;            p = end_of_line(p, ptr, &ellength);
           p++;  
1247            linecount++;            linecount++;
1248            }            }
1249    
# Line 665  while (ptr < endptr) Line 1256  while (ptr < endptr)
1256            char *pp = lastmatchrestart;            char *pp = lastmatchrestart;
1257            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1258            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1259            while (*pp != '\n') pp++;            pp = end_of_line(pp, endptr, &ellength);
1260            fwrite(lastmatchrestart, 1, pp - lastmatchrestart + 1, stdout);            FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1261            lastmatchrestart = pp + 1;            lastmatchrestart = pp;
1262            }            }
1263          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
1264          }          }
# Line 693  while (ptr < endptr) Line 1284  while (ptr < endptr)
1284                 linecount < before_context)                 linecount < before_context)
1285            {            {
1286            linecount++;            linecount++;
1287            p--;            p = previous_line(p, buffer);
           while (p > buffer && p[-1] != '\n') p--;  
1288            }            }
1289    
1290          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 702  while (ptr < endptr) Line 1292  while (ptr < endptr)
1292    
1293          while (p < ptr)          while (p < ptr)
1294            {            {
1295              int ellength;
1296            char *pp = p;            char *pp = p;
1297            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1298            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1299            while (*pp != '\n') pp++;            pp = end_of_line(pp, endptr, &ellength);
1300            fwrite(p, 1, pp - p + 1, stdout);   /* In case binary zero */            FWRITE(p, 1, pp - p, stdout);
1301            p = pp + 1;            p = pp;
1302            }            }
1303          }          }
1304    
# Line 722  while (ptr < endptr) Line 1313  while (ptr < endptr)
1313    
1314        /* 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
1315        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
1316        line number appropriately. Because the PCRE_FIRSTLINE option is set, the        line number appropriately, but only when there actually was a match
1317        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
1318          the match will always be before the first newline sequence. */
1319    
1320        if (multiline)        if (multiline)
1321          {          {
1322          char *endmatch = ptr + offsets[1];          int ellength;
1323          t = ptr;          char *endmatch = ptr;
1324          while (t < endmatch) { if (*t++ == '\n') linenumber++; }          if (!invert)
1325          while (endmatch < endptr && *endmatch != '\n') endmatch++;            {
1326          linelength = endmatch - ptr;            endmatch += offsets[1];
1327              t = ptr;
1328              while (t < endmatch)
1329                {
1330                t = end_of_line(t, endptr, &ellength);
1331                if (t <= endmatch) linenumber++; else break;
1332                }
1333              }
1334            endmatch = end_of_line(endmatch, endptr, &ellength);
1335            linelength = endmatch - ptr - ellength;
1336          }          }
1337    
1338        /*** 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 1347  while (ptr < endptr)
1347          {          {
1348          int first = S_arg * 2;          int first = S_arg * 2;
1349          int last  = first + 1;          int last  = first + 1;
1350          fwrite(ptr, 1, offsets[first], stdout);          FWRITE(ptr, 1, offsets[first], stdout);
1351          fprintf(stdout, "X");          fprintf(stdout, "X");
1352          fwrite(ptr + offsets[last], 1, linelength - offsets[last], stdout);          FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1353          }          }
1354        else        else
1355  #endif  #endif
1356    
1357        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1358          matches. */
1359    
1360        if (do_colour)        if (do_colour)
1361          {          {
1362          fwrite(ptr, 1, offsets[0], stdout);          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              last_offset += offsets[1];
1370              matchptr += offsets[1];
1371              length -= offsets[1];
1372              if (!match_patterns(matchptr, length, offsets, &mrc)) break;
1373              FWRITE(matchptr, 1, offsets[0], stdout);
1374              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1375              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1376              fprintf(stdout, "%c[00m", 0x1b);
1377              }
1378            FWRITE(ptr + last_offset, 1,
1379              (linelength + endlinelength) - last_offset, stdout);
1380          }          }
       else fwrite(ptr, 1, linelength, stdout);  
1381    
1382        fprintf(stdout, "\n");        /* Not colouring; no need to search for further matches */
1383    
1384          else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1385        }        }
1386    
1387      /* 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
1388        given, flush the output. */
1389    
1390        if (line_buffered) fflush(stdout);
1391      rc = 0;    /* Had some success */      rc = 0;    /* Had some success */
1392    
1393      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
1394      where we are about to restart, and that line's number. */      where we are about to restart, and that line's number. */
1395    
1396      lastmatchrestart = ptr + linelength + 1;      lastmatchrestart = ptr + linelength + endlinelength;
1397      lastmatchnumber = linenumber + 1;      lastmatchnumber = linenumber + 1;
1398      }      }
1399    
1400    /* Advance to after the newline and increment the line number. */    /* For a match in multiline inverted mode (which of course did not cause
1401      anything to be printed), we have to move on to the end of the match before
1402      proceeding. */
1403    
1404      if (multiline && invert && match)
1405        {
1406        int ellength;
1407        char *endmatch = ptr + offsets[1];
1408        t = ptr;
1409        while (t < endmatch)
1410          {
1411          t = end_of_line(t, endptr, &ellength);
1412          if (t <= endmatch) linenumber++; else break;
1413          }
1414        endmatch = end_of_line(endmatch, endptr, &ellength);
1415        linelength = endmatch - ptr - ellength;
1416        }
1417    
1418      /* Advance to after the newline and increment the line number. The file
1419      offset to the current line is maintained in filepos. */
1420    
1421    ptr += linelength + 1;    ptr += linelength + endlinelength;
1422      filepos += (int)(linelength + endlinelength);
1423    linenumber++;    linenumber++;
1424    
1425      /* If input is line buffered, and the buffer is not yet full, read another
1426      line and add it into the buffer. */
1427    
1428      if (input_line_buffered && bufflength < sizeof(buffer))
1429        {
1430        int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);
1431        bufflength += add;
1432        endptr += add;
1433        }
1434    
1435    /* 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
1436    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
1437    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 1451  while (ptr < endptr)
1451    
1452      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1453      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1454      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);  
1455    #ifdef SUPPORT_LIBZ
1456        if (frtype == FR_LIBZ)
1457          bufflength = 2*MBUFTHIRD +
1458            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1459        else
1460    #endif
1461    
1462    #ifdef SUPPORT_LIBBZ2
1463        if (frtype == FR_LIBBZ2)
1464          bufflength = 2*MBUFTHIRD +
1465            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1466        else
1467    #endif
1468    
1469        bufflength = 2*MBUFTHIRD +
1470          (input_line_buffered?
1471           read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :
1472           fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));
1473      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1474    
1475      /* Adjust any last match point */      /* Adjust any last match point */
# Line 815  while (ptr < endptr) Line 1481  while (ptr < endptr)
1481  /* 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
1482  hyphenpending if it prints something. */  hyphenpending if it prints something. */
1483    
1484  if (!only_matching && !count_only)  if (only_matching < 0 && !count_only)
1485    {    {
1486    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1487    hyphenpending |= endhyphenpending;    hyphenpending |= endhyphenpending;
# Line 834  if (filenames == FN_NOMATCH_ONLY) Line 1500  if (filenames == FN_NOMATCH_ONLY)
1500    
1501  if (count_only)  if (count_only)
1502    {    {
1503    if (printname != NULL) fprintf(stdout, "%s:", printname);    if (count > 0 || !omit_zero_count)
1504    fprintf(stdout, "%d\n", count);      {
1505        if (printname != NULL && filenames != FN_NONE)
1506          fprintf(stdout, "%s:", printname);
1507        fprintf(stdout, "%d\n", count);
1508        }
1509    }    }
1510    
1511  return rc;  return rc;
# Line 867  grep_or_recurse(char *pathname, BOOL dir Line 1537  grep_or_recurse(char *pathname, BOOL dir
1537  {  {
1538  int rc = 1;  int rc = 1;
1539  int sep;  int sep;
1540  FILE *in;  int frtype;
1541    int pathlen;
1542    void *handle;
1543    FILE *in = NULL;           /* Ensure initialized */
1544    
1545    #ifdef SUPPORT_LIBZ
1546    gzFile ingz = NULL;
1547    #endif
1548    
1549    #ifdef SUPPORT_LIBBZ2
1550    BZFILE *inbz2 = NULL;
1551    #endif
1552    
1553  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1554    
1555  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1556    {    {
1557    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1558      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1559        stdin_name : NULL);        stdin_name : NULL);
1560    }    }
1561    
   
1562  /* 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
1563  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
1564  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
1565    system-specific. */
1566    
1567  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1568    {    {
# Line 902  if ((sep = isdirectory(pathname)) != 0) Line 1583  if ((sep = isdirectory(pathname)) != 0)
1583    
1584      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1585        {        {
1586        int frc, blen;        int frc, nflen;
1587        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1588        blen = strlen(buffer);        nflen = (int)(strlen(nextfile));
1589    
1590        if (exclude_compiled != NULL &&        if (isdirectory(buffer))
1591            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)          {
1592          continue;          if (exclude_dir_compiled != NULL &&
1593                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1594        if (include_compiled != NULL &&            continue;
1595            pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
1596          continue;          if (include_dir_compiled != NULL &&
1597                pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1598              continue;
1599            }
1600          else
1601            {
1602            if (exclude_compiled != NULL &&
1603                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1604              continue;
1605    
1606            if (include_compiled != NULL &&
1607                pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1608              continue;
1609            }
1610    
1611        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1612        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 935  skipping was not requested. The scan pro Line 1629  skipping was not requested. The scan pro
1629  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
1630  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1631    
1632  in = fopen(pathname, "r");  pathlen = (int)(strlen(pathname));
1633  if (in == NULL)  
1634    /* Open using zlib if it is supported and the file name ends with .gz. */
1635    
1636    #ifdef SUPPORT_LIBZ
1637    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1638      {
1639      ingz = gzopen(pathname, "rb");
1640      if (ingz == NULL)
1641        {
1642        if (!silent)
1643          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1644            strerror(errno));
1645        return 2;
1646        }
1647      handle = (void *)ingz;
1648      frtype = FR_LIBZ;
1649      }
1650    else
1651    #endif
1652    
1653    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1654    
1655    #ifdef SUPPORT_LIBBZ2
1656    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1657      {
1658      inbz2 = BZ2_bzopen(pathname, "rb");
1659      handle = (void *)inbz2;
1660      frtype = FR_LIBBZ2;
1661      }
1662    else
1663    #endif
1664    
1665    /* Otherwise use plain fopen(). The label is so that we can come back here if
1666    an attempt to read a .bz2 file indicates that it really is a plain file. */
1667    
1668    #ifdef SUPPORT_LIBBZ2
1669    PLAIN_FILE:
1670    #endif
1671      {
1672      in = fopen(pathname, "rb");
1673      handle = (void *)in;
1674      frtype = FR_PLAIN;
1675      }
1676    
1677    /* All the opening methods return errno when they fail. */
1678    
1679    if (handle == NULL)
1680    {    {
1681    if (!silent)    if (!silent)
1682      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 1684  if (in == NULL)
1684    return 2;    return 2;
1685    }    }
1686    
1687  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1688    
1689    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1690    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1691    
1692    /* Close in an appropriate manner. */
1693    
1694    #ifdef SUPPORT_LIBZ
1695    if (frtype == FR_LIBZ)
1696      gzclose(ingz);
1697    else
1698    #endif
1699    
1700    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1701    read failed. If the error indicates that the file isn't in fact bzipped, try
1702    again as a normal file. */
1703    
1704    #ifdef SUPPORT_LIBBZ2
1705    if (frtype == FR_LIBBZ2)
1706      {
1707      if (rc == 2)
1708        {
1709        int errnum;
1710        const char *err = BZ2_bzerror(inbz2, &errnum);
1711        if (errnum == BZ_DATA_ERROR_MAGIC)
1712          {
1713          BZ2_bzclose(inbz2);
1714          goto PLAIN_FILE;
1715          }
1716        else if (!silent)
1717          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1718            pathname, err);
1719        }
1720      BZ2_bzclose(inbz2);
1721      }
1722    else
1723    #endif
1724    
1725    /* Normal file close */
1726    
1727  fclose(in);  fclose(in);
1728    
1729    /* Pass back the yield from pcregrep(). */
1730    
1731  return rc;  return rc;
1732  }  }
1733    
# Line 968  for (op = optionlist; op->one_char != 0; Line 1748  for (op = optionlist; op->one_char != 0;
1748    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1749    }    }
1750  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1751  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1752      "options.\n");
1753  return rc;  return rc;
1754  }  }
1755    
# Line 987  option_item *op; Line 1768  option_item *op;
1768  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1769  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1770  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");
1771  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");
1772  printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
1773    #ifdef SUPPORT_LIBZ
1774    printf("Files whose names end in .gz are read using zlib.\n");
1775    #endif
1776    
1777    #ifdef SUPPORT_LIBBZ2
1778    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1779    #endif
1780    
1781    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1782    printf("Other files and the standard input are read as plain files.\n\n");
1783    #else
1784    printf("All files are read as plain files, without any interpretation.\n\n");
1785    #endif
1786    
1787    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1788  printf("Options:\n");  printf("Options:\n");
1789    
1790  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
1791    {    {
1792    int n;    int n;
1793    char s[4];    char s[4];
1794    
1795      /* Two options were accidentally implemented and documented with underscores
1796      instead of hyphens in their names, something that was not noticed for quite a
1797      few releases. When fixing this, I left the underscored versions in the list
1798      in case people were using them. However, we don't want to display them in the
1799      help data. There are no other options that contain underscores, and we do not
1800      expect ever to implement such options. Therefore, just omit any option that
1801      contains an underscore. */
1802    
1803      if (strchr(op->long_name, '_') != NULL) continue;
1804    
1805    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, "   ");
1806    printf("  %s --%s%n", s, op->long_name, &n);    n = 31 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1807    if (n < 1) n = 1;    if (n < 1) n = 1;
1808    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1809    }    }
1810    
1811  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 1828  handle_option(int letter, int options)
1828  {  {
1829  switch(letter)  switch(letter)
1830    {    {
1831    case N_HELP: help(); exit(0);    case N_FOFFSETS: file_offsets = TRUE; break;
1832      case N_HELP: help(); pcregrep_exit(0);
1833      case N_LOFFSETS: line_offsets = number = TRUE; break;
1834      case N_LBUFFER: line_buffered = TRUE; break;
1835    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1836    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1837    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1838    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1839    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1840    case 'l': filenames = FN_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1841    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1842    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1843    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
1844    case 'o': only_matching = TRUE; break;    case 'o': only_matching = 0; break;
1845    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1846    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1847    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
1848    case 'u': options |= PCRE_UTF8; break;    case 'u': options |= PCRE_UTF8; utf8 = TRUE; break;
1849    case 'v': invert = TRUE; break;    case 'v': invert = TRUE; break;
1850    case 'w': process_options |= PO_WORD_MATCH; break;    case 'w': process_options |= PO_WORD_MATCH; break;
1851    case 'x': process_options |= PO_LINE_MATCH; break;    case 'x': process_options |= PO_LINE_MATCH; break;
1852    
1853    case 'V':    case 'V':
1854    fprintf(stderr, "pcregrep version %s using ", VERSION);    fprintf(stderr, "pcregrep version %s\n", pcre_version());
1855    fprintf(stderr, "PCRE version %s\n", pcre_version());    pcregrep_exit(0);
   exit(0);  
1856    break;    break;
1857    
1858    default:    default:
1859    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
1860    exit(usage(2));    pcregrep_exit(usage(2));
1861    }    }
1862    
1863  return options;  return options;
# Line 1120  sprintf(buffer, "%s%.*s%s", prefix[proce Line 1927  sprintf(buffer, "%s%.*s%s", prefix[proce
1927    suffix[process_options]);    suffix[process_options]);
1928  pattern_list[pattern_count] =  pattern_list[pattern_count] =
1929    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
1930  if (pattern_list[pattern_count++] != NULL) return TRUE;  if (pattern_list[pattern_count] != NULL)
1931      {
1932      pattern_count++;
1933      return TRUE;
1934      }
1935    
1936  /* Handle compile errors */  /* Handle compile errors */
1937    
# Line 1152  return FALSE; Line 1963  return FALSE;
1963  *************************************************/  *************************************************/
1964    
1965  /* 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,
1966  separated by newlines. They will be matched literally.  separated by line breaks. They will be matched literally.
1967    
1968  Arguments:  Arguments:
1969    pattern        the pattern string    pattern        the pattern string
# Line 1170  compile_pattern(char *pattern, int optio Line 1981  compile_pattern(char *pattern, int optio
1981  {  {
1982  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
1983    {    {
1984      char *eop = pattern + strlen(pattern);
1985    char buffer[MBUFTHIRD];    char buffer[MBUFTHIRD];
1986    for(;;)    for(;;)
1987      {      {
1988      char *p = strchr(pattern, '\n');      int ellength;
1989      if (p == NULL)      char *p = end_of_line(pattern, eop, &ellength);
1990        if (ellength == 0)
1991        return compile_single_pattern(pattern, options, filename, count);        return compile_single_pattern(pattern, options, filename, count);
1992      sprintf(buffer, "%.*s", p - pattern, pattern);      sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern);
1993      pattern = p + 1;      pattern = p;
1994      if (!compile_single_pattern(buffer, options, filename, count))      if (!compile_single_pattern(buffer, options, filename, count))
1995        return FALSE;        return FALSE;
1996      }      }
# Line 1200  int i, j; Line 2013  int i, j;
2013  int rc = 1;  int rc = 1;
2014  int pcre_options = 0;  int pcre_options = 0;
2015  int cmd_pattern_count = 0;  int cmd_pattern_count = 0;
2016    int hint_count = 0;
2017  int errptr;  int errptr;
2018  BOOL only_one_at_top;  BOOL only_one_at_top;
2019  char *patterns[MAX_PATTERN_COUNT];  char *patterns[MAX_PATTERN_COUNT];
2020  const char *locale_from = "--locale";  const char *locale_from = "--locale";
2021  const char *error;  const char *error;
2022    
2023    /* Set the default line ending value from the default in the PCRE library;
2024    "lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf".
2025    Note that the return values from pcre_config(), though derived from the ASCII
2026    codes, are the same in EBCDIC environments, so we must use the actual values
2027    rather than escapes such as as '\r'. */
2028    
2029    (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
2030    switch(i)
2031      {
2032      default:               newline = (char *)"lf"; break;
2033      case 13:               newline = (char *)"cr"; break;
2034      case (13 << 8) | 10:   newline = (char *)"crlf"; break;
2035      case -1:               newline = (char *)"any"; break;
2036      case -2:               newline = (char *)"anycrlf"; break;
2037      }
2038    
2039  /* Process the options */  /* Process the options */
2040    
2041  for (i = 1; i < argc; i++)  for (i = 1; i < argc; i++)
# Line 1223  for (i = 1; i < argc; i++) Line 2053  for (i = 1; i < argc; i++)
2053    if (argv[i][1] == 0)    if (argv[i][1] == 0)
2054      {      {
2055      if (pattern_filename != NULL || pattern_count > 0) break;      if (pattern_filename != NULL || pattern_count > 0) break;
2056        else exit(usage(2));        else pcregrep_exit(usage(2));
2057      }      }
2058    
2059    /* 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 2075  for (i = 1; i < argc; i++)
2075      Some options have variations in the long name spelling: specifically, we      Some options have variations in the long name spelling: specifically, we
2076      allow "regexp" because GNU grep allows it, though I personally go along      allow "regexp" because GNU grep allows it, though I personally go along
2077      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
2078      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
2079      these categories, fortunately. */      both these categories. */
2080    
2081      for (op = optionlist; op->one_char != 0; op++)      for (op = optionlist; op->one_char != 0; op++)
2082        {        {
2083        char *opbra = strchr(op->long_name, '(');        char *opbra = strchr(op->long_name, '(');
2084        char *equals = strchr(op->long_name, '=');        char *equals = strchr(op->long_name, '=');
2085        if (opbra == NULL)     /* Not a (p) case */  
2086          /* Handle options with only one spelling of the name */
2087    
2088          if (opbra == NULL)     /* Does not contain '(' */
2089          {          {
2090          if (equals == NULL)  /* Not thing=data case */          if (equals == NULL)  /* Not thing=data case */
2091            {            {
# Line 1260  for (i = 1; i < argc; i++) Line 2093  for (i = 1; i < argc; i++)
2093            }            }
2094          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
2095            {            {
2096            int oplen = equals - op->long_name;            int oplen = (int)(equals - op->long_name);
2097            int arglen = (argequals == NULL)? strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)?
2098                (int)strlen(arg) : (int)(argequals - arg);
2099            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
2100              {              {
2101              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1274  for (i = 1; i < argc; i++) Line 2108  for (i = 1; i < argc; i++)
2108              }              }
2109            }            }
2110          }          }
2111        else                   /* Special case xxxx(p) */  
2112          /* Handle options with an alternate spelling of the name */
2113    
2114          else
2115          {          {
2116          char buff1[24];          char buff1[24];
2117          char buff2[24];          char buff2[24];
2118          int baselen = opbra - op->long_name;  
2119            int baselen = (int)(opbra - op->long_name);
2120            int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
2121            int arglen = (argequals == NULL || equals == NULL)?
2122              (int)strlen(arg) : (int)(argequals - arg);
2123    
2124          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
2125          sprintf(buff2, "%s%.*s", buff1, strlen(op->long_name) - baselen - 2,          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
2126            opbra + 1);  
2127          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strncmp(arg, buff1, arglen) == 0 ||
2128               strncmp(arg, buff2, arglen) == 0)
2129              {
2130              if (equals != NULL && argequals != NULL)
2131                {
2132                option_data = argequals;
2133                if (*option_data == '=')
2134                  {
2135                  option_data++;
2136                  longopwasequals = TRUE;
2137                  }
2138                }
2139            break;            break;
2140              }
2141          }          }
2142        }        }
2143    
2144      if (op->one_char == 0)      if (op->one_char == 0)
2145        {        {
2146        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
2147        exit(usage(2));        pcregrep_exit(usage(2));
2148        }        }
2149      }      }
2150    
2151      /* Jeffrey Friedl's debugging harness uses these additional options which
2152      are not in the right form for putting in the option table because they use
2153      only one hyphen, yet are more than one character long. By putting them
2154      separately here, they will not get displayed as part of the help() output,
2155      but I don't think Jeffrey will care about that. */
2156    
2157    #ifdef JFRIEDL_DEBUG
2158      else if (strcmp(argv[i], "-pre") == 0) {
2159              jfriedl_prefix = argv[++i];
2160              continue;
2161      } else if (strcmp(argv[i], "-post") == 0) {
2162              jfriedl_postfix = argv[++i];
2163              continue;
2164      } else if (strcmp(argv[i], "-XT") == 0) {
2165              sscanf(argv[++i], "%d", &jfriedl_XT);
2166              continue;
2167      } else if (strcmp(argv[i], "-XR") == 0) {
2168              sscanf(argv[++i], "%d", &jfriedl_XR);
2169              continue;
2170      }
2171    #endif
2172    
2173    
2174    /* 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
2175    continue till we hit the last one or one that needs data. */    continue till we hit the last one or one that needs data. */
2176    
# Line 1304  for (i = 1; i < argc; i++) Line 2181  for (i = 1; i < argc; i++)
2181      while (*s != 0)      while (*s != 0)
2182        {        {
2183        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2184          { if (*s == op->one_char) break; }          {
2185            if (*s == op->one_char) break;
2186            }
2187        if (op->one_char == 0)        if (op->one_char == 0)
2188          {          {
2189          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2190            *s, argv[i]);            *s, argv[i]);
2191          exit(usage(2));          pcregrep_exit(usage(2));
2192          }          }
2193        if (op->type != OP_NODATA || s[1] == 0)  
2194          {        /* Check for a single-character option that has data: OP_OP_NUMBER
2195          option_data = s+1;        is used for one that either has a numerical number or defaults, i.e. the
2196          break;        data is optional. If a digit follows, there is data; if not, carry on
2197          with other single-character options in the same string. */
2198    
2199          option_data = s+1;
2200          if (op->type == OP_OP_NUMBER)
2201            {
2202            if (isdigit((unsigned char)s[1])) break;
2203          }          }
2204          else   /* Check for end or a dataless option */
2205            {
2206            if (op->type != OP_NODATA || s[1] == 0) break;
2207            }
2208    
2209          /* Handle a single-character option with no data, then loop for the
2210          next character in the string. */
2211    
2212        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
2213        }        }
2214      }      }
# Line 1332  for (i = 1; i < argc; i++) Line 2225  for (i = 1; i < argc; i++)
2225    
2226    /* 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
2227    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
2228    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",
2229    Jeffrey Friedl's special debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2230    
2231    if (*option_data == 0 &&    if (*option_data == 0 &&
2232        (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 2236  for (i = 1; i < argc; i++)
2236        case N_COLOUR:        case N_COLOUR:
2237        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2238        break;        break;
2239    
2240          case 'o':
2241          only_matching = 0;
2242          break;
2243    
2244  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2245        case 'S':        case 'S':
2246        S_arg = 0;        S_arg = 0;
# Line 1359  for (i = 1; i < argc; i++) Line 2257  for (i = 1; i < argc; i++)
2257      if (i >= argc - 1 || longopwasequals)      if (i >= argc - 1 || longopwasequals)
2258        {        {
2259        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);
2260        exit(usage(2));        pcregrep_exit(usage(2));
2261        }        }
2262      option_data = argv[++i];      option_data = argv[++i];
2263      }      }
# Line 1384  for (i = 1; i < argc; i++) Line 2282  for (i = 1; i < argc; i++)
2282      {      {
2283      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2284      }      }
2285    
2286      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2287      only for unpicking arguments, so just keep it simple. */
2288    
2289    else    else
2290      {      {
2291      char *endptr;      unsigned long int n = 0;
2292      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2293        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2294        while (isdigit((unsigned char)(*endptr)))
2295          n = n * 10 + (int)(*endptr++ - '0');
2296      if (*endptr != 0)      if (*endptr != 0)
2297        {        {
2298        if (longop)        if (longop)
2299          {          {
2300          char *equals = strchr(op->long_name, '=');          char *equals = strchr(op->long_name, '=');
2301          int nlen = (equals == NULL)? (int)strlen(op->long_name) :          int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2302            equals - op->long_name;            (int)(equals - op->long_name);
2303          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2304            option_data, nlen, op->long_name);            option_data, nlen, op->long_name);
2305          }          }
2306        else        else
2307          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2308            option_data, op->one_char);            option_data, op->one_char);
2309        exit(usage(2));        pcregrep_exit(usage(2));
2310        }        }
2311      *((int *)op->dataptr) = n;      *((int *)op->dataptr) = n;
2312      }      }
# Line 1416  if (both_context > 0) Line 2321  if (both_context > 0)
2321    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2322    }    }
2323    
2324    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2325    However, the latter two set only_matching. */
2326    
2327    if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2328        (file_offsets && line_offsets))
2329      {
2330      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2331        "and/or --line-offsets\n");
2332      pcregrep_exit(usage(2));
2333      }
2334    
2335    if (file_offsets || line_offsets) only_matching = 0;
2336    
2337  /* 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
2338  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2339    
# Line 1465  if (colour_option != NULL && strcmp(colo Line 2383  if (colour_option != NULL && strcmp(colo
2383      }      }
2384    }    }
2385    
2386    /* Interpret the newline type; the default settings are Unix-like. */
2387    
2388    if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)
2389      {
2390      pcre_options |= PCRE_NEWLINE_CR;
2391      endlinetype = EL_CR;
2392      }
2393    else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)
2394      {
2395      pcre_options |= PCRE_NEWLINE_LF;
2396      endlinetype = EL_LF;
2397      }
2398    else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)
2399      {
2400      pcre_options |= PCRE_NEWLINE_CRLF;
2401      endlinetype = EL_CRLF;
2402      }
2403    else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0)
2404      {
2405      pcre_options |= PCRE_NEWLINE_ANY;
2406      endlinetype = EL_ANY;
2407      }
2408    else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0)
2409      {
2410      pcre_options |= PCRE_NEWLINE_ANYCRLF;
2411      endlinetype = EL_ANYCRLF;
2412      }
2413    else
2414      {
2415      fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline);
2416      return 2;
2417      }
2418    
2419  /* Interpret the text values for -d and -D */  /* Interpret the text values for -d and -D */
2420    
2421  if (dee_option != NULL)  if (dee_option != NULL)
# Line 1490  if (DEE_option != NULL) Line 2441  if (DEE_option != NULL)
2441      }      }
2442    }    }
2443    
2444  /* Check the value for Jeff Friedl's debugging option. */  /* Check the values for Jeffrey Friedl's debugging options. */
2445    
2446  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2447  if (S_arg > 9)  if (S_arg > 9)
# Line 1498  if (S_arg > 9) Line 2449  if (S_arg > 9)
2449    fprintf(stderr, "pcregrep: bad value for -S option\n");    fprintf(stderr, "pcregrep: bad value for -S option\n");
2450    return 2;    return 2;
2451    }    }
2452    if (jfriedl_XT != 0 || jfriedl_XR != 0)
2453      {
2454      if (jfriedl_XT == 0) jfriedl_XT = 1;
2455      if (jfriedl_XR == 0) jfriedl_XR = 1;
2456      }
2457  #endif  #endif
2458    
2459  /* 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 2464  hints_list = (pcre_extra **)malloc(MAX_P
2464  if (pattern_list == NULL || hints_list == NULL)  if (pattern_list == NULL || hints_list == NULL)
2465    {    {
2466    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2467    return 2;    goto EXIT2;
2468    }    }
2469    
2470  /* 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 2483  for (j = 0; j < cmd_pattern_count; j++)
2483    {    {
2484    if (!compile_pattern(patterns[j], pcre_options, NULL,    if (!compile_pattern(patterns[j], pcre_options, NULL,
2485         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))
2486      return 2;      goto EXIT2;
2487    }    }
2488    
2489  /* 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 2507  if (pattern_filename != NULL)
2507        {        {
2508        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,
2509          strerror(errno));          strerror(errno));
2510        return 2;        goto EXIT2;
2511        }        }
2512      filename = pattern_filename;      filename = pattern_filename;
2513      }      }
# Line 1564  if (pattern_filename != NULL) Line 2520  if (pattern_filename != NULL)
2520      linenumber++;      linenumber++;
2521      if (buffer[0] == 0) continue;   /* Skip blank lines */      if (buffer[0] == 0) continue;   /* Skip blank lines */
2522      if (!compile_pattern(buffer, pcre_options, filename, linenumber))      if (!compile_pattern(buffer, pcre_options, filename, linenumber))
2523        return 2;        goto EXIT2;
2524      }      }
2525    
2526    if (f != stdin) fclose(f);    if (f != stdin) fclose(f);
# Line 1580  for (j = 0; j < pattern_count; j++) Line 2536  for (j = 0; j < pattern_count; j++)
2536      char s[16];      char s[16];
2537      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);
2538      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
2539      return 2;      goto EXIT2;
2540      }      }
2541      hint_count++;
2542    }    }
2543    
2544    /* If --match-limit or --recursion-limit was set, put the value(s) into the
2545    pcre_extra block for each pattern. */
2546    
2547    if (match_limit > 0 || match_limit_recursion > 0)
2548      {
2549      for (j = 0; j < pattern_count; j++)
2550        {
2551        if (hints_list[j] == NULL)
2552          {
2553          hints_list[j] = malloc(sizeof(pcre_extra));
2554          if (hints_list[j] == NULL)
2555            {
2556            fprintf(stderr, "pcregrep: malloc failed\n");
2557            pcregrep_exit(2);
2558            }
2559          }
2560        if (match_limit > 0)
2561          {
2562          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2563          hints_list[j]->match_limit = match_limit;
2564          }
2565        if (match_limit_recursion > 0)
2566          {
2567          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2568          hints_list[j]->match_limit_recursion = match_limit_recursion;
2569          }
2570        }
2571      }
2572    
2573  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2574    
# Line 1594  if (exclude_pattern != NULL) Line 2580  if (exclude_pattern != NULL)
2580      {      {
2581      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",
2582        errptr, error);        errptr, error);
2583      return 2;      goto EXIT2;
2584      }      }
2585    }    }
2586    
# Line 1606  if (include_pattern != NULL) Line 2592  if (include_pattern != NULL)
2592      {      {
2593      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",
2594        errptr, error);        errptr, error);
2595      return 2;      goto EXIT2;
2596        }
2597      }
2598    
2599    if (exclude_dir_pattern != NULL)
2600      {
2601      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2602        pcretables);
2603      if (exclude_dir_compiled == NULL)
2604        {
2605        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2606          errptr, error);
2607        goto EXIT2;
2608        }
2609      }
2610    
2611    if (include_dir_pattern != NULL)
2612      {
2613      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2614        pcretables);
2615      if (include_dir_compiled == NULL)
2616        {
2617        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2618          errptr, error);
2619        goto EXIT2;
2620      }      }
2621    }    }
2622    
2623  /* 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. */
2624    
2625  if (i >= argc)  if (i >= argc)
2626    return pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    {
2627      rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2628      goto EXIT;
2629      }
2630    
2631  /* Otherwise, work through the remaining arguments as files or directories.  /* Otherwise, work through the remaining arguments as files or directories.
2632  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 2643  for (; i < argc; i++)
2643      else if (frc == 0 && rc == 1) rc = 0;      else if (frc == 0 && rc == 1) rc = 0;
2644    }    }
2645    
2646  return rc;  EXIT:
2647    if (pattern_list != NULL)
2648      {
2649      for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
2650      free(pattern_list);
2651      }
2652    if (hints_list != NULL)
2653      {
2654      for (i = 0; i < hint_count; i++)
2655        {
2656        if (hints_list[i] != NULL) free(hints_list[i]);
2657        }
2658      free(hints_list);
2659      }
2660    pcregrep_exit(rc);
2661    
2662    EXIT2:
2663    rc = 2;
2664    goto EXIT;
2665  }  }
2666    
2667  /* End of pcregrep */  /* End of pcregrep */

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

  ViewVC Help
Powered by ViewVC 1.1.5