/[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 324 by ph10, Fri Mar 7 19:48:32 2008 UTC revision 636 by ph10, Sun Jul 24 17:43:51 2011 UTC
# Line 6  Line 6 
6  its pattern matching. On a Unix or Win32 system it can recurse into  its pattern matching. On a Unix or Win32 system it can recurse into
7  directories.  directories.
8    
9             Copyright (c) 1997-2008 University of Cambridge             Copyright (c) 1997-2011 University of Cambridge
10    
11  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
12  Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
# Line 71  POSSIBILITY OF SUCH DAMAGE. Line 71  POSSIBILITY OF SUCH DAMAGE.
71  typedef int BOOL;  typedef int BOOL;
72    
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 82  typedef int BOOL; Line 83  typedef int BOOL;
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 */  /* File reading styles */
89    
# Line 103  enum { DEE_READ, DEE_SKIP }; Line 104  enum { DEE_READ, DEE_SKIP };
104    
105  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };  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 139  static pcre_extra **hints_list = NULL; Line 148  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 150  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;  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;  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;  static BOOL utf8 = FALSE;
186    
187  /* Structure for options and list of them */  /* Structure for options and list of them */
188    
189  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_OP_NUMBER,  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
190         OP_PATLIST };         OP_OP_NUMBER, OP_PATLIST };
191    
192  typedef struct option_item {  typedef struct option_item {
193    int type;    int type;
# Line 181  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_LOFFSETS  (-8)  #define N_LOCALE       (-8)
211  #define N_FOFFSETS  (-9)  #define N_NULL         (-9)
212    #define N_LOFFSETS     (-10)
213    #define N_FOFFSETS     (-11)
214    #define N_LBUFFER      (-12)
215    #define N_M_LIMIT      (-13)
216    #define N_M_LIMIT_REC  (-14)
217    
218  static option_item optionlist[] = {  static option_item optionlist[] = {
219    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "  terminate options" },
220    { OP_NODATA,    N_HELP,   NULL,              "help",          "display this help and exit" },    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
221    { OP_NUMBER,    'A',      &after_context,    "after-context=number", "set number of following context lines" },    { OP_NUMBER,     'A',      &after_context,    "after-context=number", "set number of following context lines" },
222    { OP_NUMBER,    'B',      &before_context,   "before-context=number", "set number of prior context lines" },    { OP_NUMBER,     'B',      &before_context,   "before-context=number", "set number of prior context lines" },
223    { OP_OP_STRING, N_COLOUR, &colour_option,    "color=option",  "matched text color option" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
224    { OP_NUMBER,    'C',      &both_context,     "context=number", "set number of context lines, before & after" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
225    { OP_NODATA,    'c',      NULL,              "count",         "print only a count of matching lines per FILE" },    { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
226    { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },    { OP_NODATA,     'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
227    { OP_STRING,    'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },    { OP_STRING,     'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },
228    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },    { OP_STRING,     'd',      &dee_option,       "directories=action", "how to handle directories" },
229    { OP_PATLIST,   'e',      NULL,              "regex(p)",      "specify pattern (may be used more than once)" },    { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
230    { OP_NODATA,    'F',      NULL,              "fixed_strings", "patterns are sets of newline-separated strings" },    { OP_NODATA,     'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },
231    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
232    { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },    { 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_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },    { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
240    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
241    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
242    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
243    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
244    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
245    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
246    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
247    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
248    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
249      { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
250      { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
251      { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
252      { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
253      { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },
254    
255      /* These two were accidentally implemented with underscores instead of
256      hyphens in the option names. As this was not discovered for several releases,
257      the incorrect versions are left in the table for compatibility. However, the
258      --help function misses out any option that has an underscore in its name. */
259    
260      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
261      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
262    
263  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
264    { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },    { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },
265  #endif  #endif
# Line 258  const char utf8_table4[] = { Line 296  const char utf8_table4[] = {
296    
297    
298  /*************************************************  /*************************************************
299    *         Exit from the program                  *
300    *************************************************/
301    
302    /* If there has been a resource error, give a suitable message.
303    
304    Argument:  the return code
305    Returns:   does not return
306    */
307    
308    static void
309    pcregrep_exit(int rc)
310    {
311    if (resource_error)
312      {
313      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
314        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
315      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
316      }
317    
318    exit(rc);
319    }
320    
321    
322    /*************************************************
323  *            OS-specific functions               *  *            OS-specific functions               *
324  *************************************************/  *************************************************/
325    
# Line 321  return (statbuf.st_mode & S_IFMT) == S_I Line 383  return (statbuf.st_mode & S_IFMT) == S_I
383  }  }
384    
385    
386  /************* Test stdout for being a terminal in Unix **********/  /************* Test for a terminal in Unix **********/
387    
388  static BOOL  static BOOL
389  is_stdout_tty(void)  is_stdout_tty(void)
# Line 329  is_stdout_tty(void) Line 391  is_stdout_tty(void)
391  return isatty(fileno(stdout));  return isatty(fileno(stdout));
392  }  }
393    
394    static BOOL
395    is_file_tty(FILE *f)
396    {
397    return isatty(fileno(f));
398    }
399    
400    
401  /************* Directory scanning in Win32 ***********/  /************* Directory scanning in Win32 ***********/
402    
# Line 336  return isatty(fileno(stdout)); Line 404  return isatty(fileno(stdout));
404  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
405  when it did not exist. David Byron added a patch that moved the #include of  when it did not exist. David Byron added a patch that moved the #include of
406  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
407  */  The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
408    undefined when it is indeed undefined. */
409    
410  #elif HAVE_WINDOWS_H  #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
411    
412  #ifndef STRICT  #ifndef STRICT
413  # define STRICT  # define STRICT
# Line 382  dir = (directory_type *) malloc(sizeof(* Line 451  dir = (directory_type *) malloc(sizeof(*
451  if ((pattern == NULL) || (dir == NULL))  if ((pattern == NULL) || (dir == NULL))
452    {    {
453    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
454    exit(2);    pcregrep_exit(2);
455    }    }
456  memcpy(pattern, filename, len);  memcpy(pattern, filename, len);
457  memcpy(&(pattern[len]), "\\*", 3);  memcpy(&(pattern[len]), "\\*", 3);
# Line 441  return !isdirectory(filename); Line 510  return !isdirectory(filename);
510  }  }
511    
512    
513  /************* Test stdout for being a terminal in Win32 **********/  /************* Test for a terminal in Win32 **********/
514    
515  /* I don't know how to do this; assume never */  /* I don't know how to do this; assume never */
516    
# Line 451  is_stdout_tty(void) Line 520  is_stdout_tty(void)
520  return FALSE;  return FALSE;
521  }  }
522    
523    static BOOL
524    is_file_tty(FILE *f)
525    {
526    return FALSE;
527    }
528    
529    
530  /************* Directory scanning when we can't do it ***********/  /************* Directory scanning when we can't do it ***********/
531    
# Line 473  void closedirectory(directory_type *dir) Line 548  void closedirectory(directory_type *dir)
548  int isregfile(char *filename) { return 1; }  int isregfile(char *filename) { return 1; }
549    
550    
551  /************* Test stdout for being a terminal when we can't do it **********/  /************* Test for a terminal when we can't do it **********/
552    
553  static BOOL  static BOOL
554  is_stdout_tty(void)  is_stdout_tty(void)
# Line 481  is_stdout_tty(void) Line 556  is_stdout_tty(void)
556  return FALSE;  return FALSE;
557  }  }
558    
559    static BOOL
560    is_file_tty(FILE *f)
561    {
562    return FALSE;
563    }
564    
565  #endif  #endif
566    
# Line 509  return sys_errlist[n]; Line 589  return sys_errlist[n];
589    
590    
591  /*************************************************  /*************************************************
592    *            Read one line of input              *
593    *************************************************/
594    
595    /* Normally, input is read using fread() into a large buffer, so many lines may
596    be read at once. However, doing this for tty input means that no output appears
597    until a lot of input has been typed. Instead, tty input is handled line by
598    line. We cannot use fgets() for this, because it does not stop at a binary
599    zero, and therefore there is no way of telling how many characters it has read,
600    because there may be binary zeros embedded in the data.
601    
602    Arguments:
603      buffer     the buffer to read into
604      length     the maximum number of characters to read
605      f          the file
606    
607    Returns:     the number of characters read, zero at end of file
608    */
609    
610    static int
611    read_one_line(char *buffer, int length, FILE *f)
612    {
613    int c;
614    int yield = 0;
615    while ((c = fgetc(f)) != EOF)
616      {
617      buffer[yield++] = c;
618      if (c == '\n' || yield >= length) break;
619      }
620    return yield;
621    }
622    
623    
624    
625    /*************************************************
626  *             Find end of line                   *  *             Find end of line                   *
627  *************************************************/  *************************************************/
628    
# Line 520  Arguments: Line 634  Arguments:
634    endptr    end of available data    endptr    end of available data
635    lenptr    where to put the length of the eol sequence    lenptr    where to put the length of the eol sequence
636    
637  Returns:    pointer to the last byte of the line  Returns:    pointer to the last byte of the line, including the newline byte(s)
638  */  */
639    
640  static char *  static char *
# Line 803  if (after_context > 0 && lastmatchnumber Line 917  if (after_context > 0 && lastmatchnumber
917      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
918      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
919      pp = end_of_line(pp, endptr, &ellength);      pp = end_of_line(pp, endptr, &ellength);
920      fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);      FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
921      lastmatchrestart = pp;      lastmatchrestart = pp;
922      }      }
923    hyphenpending = TRUE;    hyphenpending = TRUE;
# Line 813  if (after_context > 0 && lastmatchnumber Line 927  if (after_context > 0 && lastmatchnumber
927    
928    
929  /*************************************************  /*************************************************
930    *   Apply patterns to subject till one matches   *
931    *************************************************/
932    
933    /* This function is called to run through all patterns, looking for a match. It
934    is used multiple times for the same subject when colouring is enabled, in order
935    to find all possible matches.
936    
937    Arguments:
938      matchptr     the start of the subject
939      length       the length of the subject to match
940      startoffset  where to start matching
941      offsets      the offets vector to fill in
942      mrc          address of where to put the result of pcre_exec()
943    
944    Returns:      TRUE if there was a match
945                  FALSE if there was no match
946                  invert if there was a non-fatal error
947    */
948    
949    static BOOL
950    match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
951      int *mrc)
952    {
953    int i;
954    size_t slen = length;
955    const char *msg = "this text:\n\n";
956    if (slen > 200)
957      {
958      slen = 200;
959      msg = "text that starts:\n\n";
960      }
961    for (i = 0; i < pattern_count; i++)
962      {
963      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length,
964        startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
965      if (*mrc >= 0) return TRUE;
966      if (*mrc == PCRE_ERROR_NOMATCH) continue;
967      fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
968      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
969      fprintf(stderr, "%s", msg);
970      FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
971      fprintf(stderr, "\n\n");
972      if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)
973        resource_error = TRUE;
974      if (error_count++ > 20)
975        {
976        fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
977        pcregrep_exit(2);
978        }
979      return invert;    /* No more matching; don't show the line again */
980      }
981    
982    return FALSE;  /* No match, no errors */
983    }
984    
985    
986    
987    /*************************************************
988  *            Grep an individual file             *  *            Grep an individual file             *
989  *************************************************/  *************************************************/
990    
# Line 845  int linenumber = 1; Line 1017  int linenumber = 1;
1017  int lastmatchnumber = 0;  int lastmatchnumber = 0;
1018  int count = 0;  int count = 0;
1019  int filepos = 0;  int filepos = 0;
1020  int offsets[99];  int offsets[OFFSET_SIZE];
1021  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
1022  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
1023  char *ptr = buffer;  char *ptr = buffer;
1024  char *endptr;  char *endptr;
1025  size_t bufflength;  size_t bufflength;
1026  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
1027    BOOL input_line_buffered = line_buffered;
1028  FILE *in = NULL;                    /* Ensure initialized */  FILE *in = NULL;                    /* Ensure initialized */
1029    
1030  #ifdef SUPPORT_LIBZ  #ifdef SUPPORT_LIBZ
# Line 889  else Line 1062  else
1062    
1063    {    {
1064    in = (FILE *)handle;    in = (FILE *)handle;
1065    bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);    if (is_file_tty(in)) input_line_buffered = TRUE;
1066      bufflength = input_line_buffered?
1067        read_one_line(buffer, 3*MBUFTHIRD, in) :
1068        fread(buffer, 1, 3*MBUFTHIRD, in);
1069    }    }
1070    
1071  endptr = buffer + bufflength;  endptr = buffer + bufflength;
# Line 901  way, the buffer is shifted left and re-f Line 1077  way, the buffer is shifted left and re-f
1077    
1078  while (ptr < endptr)  while (ptr < endptr)
1079    {    {
1080    int i, endlinelength;    int endlinelength;
1081    int mrc = 0;    int mrc = 0;
1082    BOOL match = FALSE;    int startoffset = 0;
1083      BOOL match;
1084    char *matchptr = ptr;    char *matchptr = ptr;
1085    char *t = ptr;    char *t = ptr;
1086    size_t length, linelength;    size_t length, linelength;
# Line 911  while (ptr < endptr) Line 1088  while (ptr < endptr)
1088    /* At this point, ptr is at the start of a line. We need to find the length    /* At this point, ptr is at the start of a line. We need to find the length
1089    of the subject string to pass to pcre_exec(). In multiline mode, it is the    of the subject string to pass to pcre_exec(). In multiline mode, it is the
1090    length remainder of the data in the buffer. Otherwise, it is the length of    length remainder of the data in the buffer. Otherwise, it is the length of
1091    the next line. After matching, we always advance by the length of the next    the next line, excluding the terminating newline. After matching, we always
1092    line. In multiline mode the PCRE_FIRSTLINE option is used for compiling, so    advance by the length of the next line. In multiline mode the PCRE_FIRSTLINE
1093    that any match is constrained to be in the first line. */    option is used for compiling, so that any match is constrained to be in the
1094      first line. */
1095    
1096    t = end_of_line(t, endptr, &endlinelength);    t = end_of_line(t, endptr, &endlinelength);
1097    linelength = t - ptr - endlinelength;    linelength = t - ptr - endlinelength;
# Line 928  while (ptr < endptr) Line 1106  while (ptr < endptr)
1106        #include <time.h>        #include <time.h>
1107        struct timeval start_time, end_time;        struct timeval start_time, end_time;
1108        struct timezone dummy;        struct timezone dummy;
1109          int i;
1110    
1111        if (jfriedl_XT)        if (jfriedl_XT)
1112        {        {
# Line 936  while (ptr < endptr) Line 1115  while (ptr < endptr)
1115            ptr = malloc(newlen + 1);            ptr = malloc(newlen + 1);
1116            if (!ptr) {            if (!ptr) {
1117                    printf("out of memory");                    printf("out of memory");
1118                    exit(2);                    pcregrep_exit(2);
1119            }            }
1120            endptr = ptr;            endptr = ptr;
1121            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
# Line 953  while (ptr < endptr) Line 1132  while (ptr < endptr)
1132    
1133    
1134        for (i = 0; i < jfriedl_XR; i++)        for (i = 0; i < jfriedl_XR; i++)
1135            match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0, 0, offsets, 99) >= 0);            match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0,
1136                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1137    
1138        if (gettimeofday(&end_time, &dummy) != 0)        if (gettimeofday(&end_time, &dummy) != 0)
1139                perror("bad gettimeofday");                perror("bad gettimeofday");
# Line 972  while (ptr < endptr) Line 1152  while (ptr < endptr)
1152    
1153    ONLY_MATCHING_RESTART:    ONLY_MATCHING_RESTART:
1154    
1155    /* Run through all the patterns until one matches. Note that we don't include    /* Run through all the patterns until one matches or there is an error other
1156    the final newline in the subject string. */    than NOMATCH. This code is in a subroutine so that it can be re-used for
1157      finding subsequent matches when colouring matched lines. */
1158    
1159    for (i = 0; i < pattern_count; i++)    match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
     {  
     mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0, 0,  
       offsets, 99);  
     if (mrc >= 0) { match = TRUE; break; }  
     if (mrc != PCRE_ERROR_NOMATCH)  
       {  
       fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);  
       if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);  
       fprintf(stderr, "this line:\n");  
       fwrite(matchptr, 1, linelength, stderr);  /* In case binary zero included */  
       fprintf(stderr, "\n");  
       if (error_count == 0 &&  
           (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))  
         {  
         fprintf(stderr, "pcregrep: error %d means that a resource limit "  
           "was exceeded\n", mrc);  
         fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");  
         }  
       if (error_count++ > 20)  
         {  
         fprintf(stderr, "pcregrep: too many errors - abandoned\n");  
         exit(2);  
         }  
       match = invert;    /* No more matching; don't show the line again */  
       break;  
       }  
     }  
1160    
1161    /* If it's a match or a not-match (as required), do what's wanted. */    /* If it's a match or a not-match (as required), do what's wanted. */
1162    
# Line 1021  while (ptr < endptr) Line 1175  while (ptr < endptr)
1175      /* If all we want is a file name, there is no need to scan any more lines      /* If all we want is a file name, there is no need to scan any more lines
1176      in the file. */      in the file. */
1177    
1178      else if (filenames == FN_ONLY)      else if (filenames == FN_MATCH_ONLY)
1179        {        {
1180        fprintf(stdout, "%s\n", printname);        fprintf(stdout, "%s\n", printname);
1181        return 0;        return 0;
# Line 1031  while (ptr < endptr) Line 1185  while (ptr < endptr)
1185    
1186      else if (quiet) return 0;      else if (quiet) return 0;
1187    
1188      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, or a
1189      the --file-offsets and --line-offsets options output offsets for the      captured portion of it, as long as this string is not empty, and the
1190      matching substring (they both force --only-matching). None of these options      --file-offsets and --line-offsets options output offsets for the matching
1191      prints any context. Afterwards, adjust the start and length, and then jump      substring (they both force --only-matching = 0). None of these options
1192      back to look for further matches in the same line. If we are in invert      prints any context. Afterwards, adjust the start and then jump back to look
1193      mode, however, nothing is printed - this could be still useful because the      for further matches in the same line. If we are in invert mode, however,
1194      return code is set. */      nothing is printed and we do not restart - this could still be useful
1195        because the return code is set. */
1196    
1197      else if (only_matching)      else if (only_matching >= 0)
1198        {        {
1199        if (!invert)        if (!invert)
1200          {          {
1201          if (printname != NULL) fprintf(stdout, "%s:", printname);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1202          if (number) fprintf(stdout, "%d:", linenumber);          if (number) fprintf(stdout, "%d:", linenumber);
1203          if (line_offsets)          if (line_offsets)
1204            fprintf(stdout, "%d,%d", matchptr + offsets[0] - ptr,            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1205              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1206          else if (file_offsets)          else if (file_offsets)
1207            fprintf(stdout, "%d,%d", filepos + matchptr + offsets[0] - ptr,            fprintf(stdout, "%d,%d\n",
1208                (int)(filepos + matchptr + offsets[0] - ptr),
1209              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1210          else          else if (only_matching < mrc)
1211            fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            {
1212          fprintf(stdout, "\n");            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1213          matchptr += offsets[1];            if (plen > 0)
1214          length -= offsets[1];              {
1215                if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1216                FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1217                if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1218                fprintf(stdout, "\n");
1219                }
1220              }
1221            else if (printname != NULL || number) fprintf(stdout, "\n");
1222          match = FALSE;          match = FALSE;
1223            if (line_buffered) fflush(stdout);
1224            rc = 0;                      /* Had some success */
1225            startoffset = offsets[1];    /* Restart after the match */
1226          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1227          }          }
1228        }        }
# Line 1092  while (ptr < endptr) Line 1258  while (ptr < endptr)
1258            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1259            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1260            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1261            fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);            FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1262            lastmatchrestart = pp;            lastmatchrestart = pp;
1263            }            }
1264          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
# Line 1132  while (ptr < endptr) Line 1298  while (ptr < endptr)
1298            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1299            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1300            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1301            fwrite(p, 1, pp - p, stdout);            FWRITE(p, 1, pp - p, stdout);
1302            p = pp;            p = pp;
1303            }            }
1304          }          }
# Line 1152  while (ptr < endptr) Line 1318  while (ptr < endptr)
1318        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1319        the match will always be before the first newline sequence. */        the match will always be before the first newline sequence. */
1320    
1321        if (multiline)        if (multiline & !invert)
1322          {          {
1323          int ellength;          char *endmatch = ptr + offsets[1];
1324          char *endmatch = ptr;          t = ptr;
1325          if (!invert)          while (t < endmatch)
1326            {            {
1327            endmatch += offsets[1];            t = end_of_line(t, endptr, &endlinelength);
1328            t = ptr;            if (t < endmatch) linenumber++; else break;
           while (t < endmatch)  
             {  
             t = end_of_line(t, endptr, &ellength);  
             if (t <= endmatch) linenumber++; else break;  
             }  
1329            }            }
1330          endmatch = end_of_line(endmatch, endptr, &ellength);          linelength = t - ptr - endlinelength;
         linelength = endmatch - ptr - ellength;  
1331          }          }
1332    
1333        /*** 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 1182  while (ptr < endptr) Line 1342  while (ptr < endptr)
1342          {          {
1343          int first = S_arg * 2;          int first = S_arg * 2;
1344          int last  = first + 1;          int last  = first + 1;
1345          fwrite(ptr, 1, offsets[first], stdout);          FWRITE(ptr, 1, offsets[first], stdout);
1346          fprintf(stdout, "X");          fprintf(stdout, "X");
1347          fwrite(ptr + offsets[last], 1, linelength - offsets[last], stdout);          FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1348          }          }
1349        else        else
1350  #endif  #endif
1351    
1352        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1353          matches, but not of course if the line is a non-match. */
1354    
1355        if (do_colour)        if (do_colour && !invert)
1356          {          {
1357          fwrite(ptr, 1, offsets[0], stdout);          int plength;
1358            FWRITE(ptr, 1, offsets[0], stdout);
1359          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1360          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1361          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1362          fwrite(ptr + offsets[1], 1, (linelength + endlinelength) - offsets[1],          for (;;)
1363            stdout);            {
1364              startoffset = offsets[1];
1365              if (startoffset >= linelength + endlinelength ||
1366                  !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1367                break;
1368              FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1369              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1370              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1371              fprintf(stdout, "%c[00m", 0x1b);
1372              }
1373    
1374            /* In multiline mode, we may have already printed the complete line
1375            and its line-ending characters (if they matched the pattern), so there
1376            may be no more to print. */
1377    
1378            plength = (linelength + endlinelength) - startoffset;
1379            if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout);
1380          }          }
1381        else fwrite(ptr, 1, linelength + endlinelength, stdout);  
1382          /* 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
# Line 1236  while (ptr < endptr) Line 1419  while (ptr < endptr)
1419    offset to the current line is maintained in filepos. */    offset to the current line is maintained in filepos. */
1420    
1421    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1422    filepos += linelength + endlinelength;    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 1273  while (ptr < endptr) Line 1466  while (ptr < endptr)
1466      else      else
1467  #endif  #endif
1468    
1469      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      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 1286  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 1305  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 1361  if (strcmp(pathname, "-") == 0) Line 1560  if (strcmp(pathname, "-") == 0)
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 1385  if ((sep = isdirectory(pathname)) != 0) Line 1585  if ((sep = isdirectory(pathname)) != 0)
1585        {        {
1586        int frc, nflen;        int frc, nflen;
1587        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1588        nflen = strlen(nextfile);        nflen = (int)(strlen(nextfile));
1589    
1590        if (!isdirectory(buffer))        if (isdirectory(buffer))
1591          {          {
1592            if (exclude_dir_compiled != NULL &&
1593                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1594              continue;
1595    
1596            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 &&          if (exclude_compiled != NULL &&
1603              pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)              pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1604            continue;            continue;
1605    
1606          if (include_compiled != NULL &&          if (include_compiled != NULL &&
1607              pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)              pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1608            continue;            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 1419  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  pathlen = strlen(pathname);  pathlen = (int)(strlen(pathname));
1633    
1634  /* Open using zlib if it is supported and the file name ends with .gz. */  /* Open using zlib if it is supported and the file name ends with .gz. */
1635    
# Line 1459  an attempt to read a .bz2 file indicates Line 1669  an attempt to read a .bz2 file indicates
1669  PLAIN_FILE:  PLAIN_FILE:
1670  #endif  #endif
1671    {    {
1672    in = fopen(pathname, "r");    in = fopen(pathname, "rb");
1673    handle = (void *)in;    handle = (void *)in;
1674    frtype = FR_PLAIN;    frtype = FR_PLAIN;
1675    }    }
# Line 1581  for (op = optionlist; op->one_char != 0; Line 1791  for (op = optionlist; op->one_char != 0;
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    n = 30 - printf("  %s --%s", s, op->long_name);    n = 31 - printf("  %s --%s", s, op->long_name);
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 1608  handle_option(int letter, int options) Line 1829  handle_option(int letter, int options)
1829  switch(letter)  switch(letter)
1830    {    {
1831    case N_FOFFSETS: file_offsets = TRUE; break;    case N_FOFFSETS: file_offsets = TRUE; break;
1832    case N_HELP: help(); exit(0);    case N_HELP: help(); pcregrep_exit(0);
1833    case N_LOFFSETS: line_offsets = number = TRUE; break;    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;
# Line 1630  switch(letter) Line 1852  switch(letter)
1852    
1853    case 'V':    case 'V':
1854    fprintf(stderr, "pcregrep version %s\n", pcre_version());    fprintf(stderr, "pcregrep version %s\n", pcre_version());
1855    exit(0);    pcregrep_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 1800  const char *error; Line 2022  const char *error;
2022    
2023  /* Set the default line ending value from the default in the PCRE library;  /* 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".  "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);  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
2030  switch(i)  switch(i)
2031    {    {
2032    default:                 newline = (char *)"lf"; break;    default:               newline = (char *)"lf"; break;
2033    case '\r':               newline = (char *)"cr"; break;    case 13:               newline = (char *)"cr"; break;
2034    case ('\r' << 8) | '\n': newline = (char *)"crlf"; break;    case (13 << 8) | 10:   newline = (char *)"crlf"; break;
2035    case -1:                 newline = (char *)"any"; break;    case -1:               newline = (char *)"any"; break;
2036    case -2:                 newline = (char *)"anycrlf"; break;    case -2:               newline = (char *)"anycrlf"; break;
2037    }    }
2038    
2039  /* Process the options */  /* Process the options */
# Line 1829  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 1851  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 1866  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)? (int)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 1880  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,          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
2126            (int)strlen(op->long_name) - baselen - 2, 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    /* 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    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    only one hyphen, yet are more than one character long. By putting them
# Line 1934  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    
2194          /* Check for a single-character option that has data: OP_OP_NUMBER
2195          is used for one that either has a numerical number or defaults, i.e. the
2196          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        if (op->type != OP_NODATA || s[1] == 0)        else   /* Check for end or a dataless option */
2205          {          {
2206          option_data = s+1;          if (op->type != OP_NODATA || s[1] == 0) break;
         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 1962  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 -S 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 1973  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 1989  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 2010  for (i = 1; i < argc; i++) Line 2278  for (i = 1; i < argc; i++)
2278    
2279    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2280    
2281    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2282               op->type != OP_OP_NUMBER)
2283      {      {
2284      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2285      }      }
2286    
2287      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2288      only for unpicking arguments, so just keep it simple. */
2289    
2290    else    else
2291      {      {
2292      char *endptr;      unsigned long int n = 0;
2293      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2294        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2295        while (isdigit((unsigned char)(*endptr)))
2296          n = n * 10 + (int)(*endptr++ - '0');
2297      if (*endptr != 0)      if (*endptr != 0)
2298        {        {
2299        if (longop)        if (longop)
2300          {          {
2301          char *equals = strchr(op->long_name, '=');          char *equals = strchr(op->long_name, '=');
2302          int nlen = (equals == NULL)? (int)strlen(op->long_name) :          int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2303            equals - op->long_name;            (int)(equals - op->long_name);
2304          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2305            option_data, nlen, op->long_name);            option_data, nlen, op->long_name);
2306          }          }
2307        else        else
2308          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2309            option_data, op->one_char);            option_data, op->one_char);
2310        exit(usage(2));        pcregrep_exit(usage(2));
2311        }        }
2312      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2313            *((unsigned long int *)op->dataptr) = n;
2314        else
2315            *((int *)op->dataptr) = n;
2316      }      }
2317    }    }
2318    
# Line 2047  if (both_context > 0) Line 2326  if (both_context > 0)
2326    }    }
2327    
2328  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2329  However, the latter two set the only_matching flag. */  However, the latter two set only_matching. */
2330    
2331  if ((only_matching && (file_offsets || line_offsets)) ||  if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2332      (file_offsets && line_offsets))      (file_offsets && line_offsets))
2333    {    {
2334    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2335      "and/or --line-offsets\n");      "and/or --line-offsets\n");
2336    exit(usage(2));    pcregrep_exit(usage(2));
2337    }    }
2338    
2339  if (file_offsets || line_offsets) only_matching = TRUE;  if (file_offsets || line_offsets) only_matching = 0;
2340    
2341  /* 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
2342  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
# Line 2266  for (j = 0; j < pattern_count; j++) Line 2545  for (j = 0; j < pattern_count; j++)
2545    hint_count++;    hint_count++;
2546    }    }
2547    
2548    /* If --match-limit or --recursion-limit was set, put the value(s) into the
2549    pcre_extra block for each pattern. */
2550    
2551    if (match_limit > 0 || match_limit_recursion > 0)
2552      {
2553      for (j = 0; j < pattern_count; j++)
2554        {
2555        if (hints_list[j] == NULL)
2556          {
2557          hints_list[j] = malloc(sizeof(pcre_extra));
2558          if (hints_list[j] == NULL)
2559            {
2560            fprintf(stderr, "pcregrep: malloc failed\n");
2561            pcregrep_exit(2);
2562            }
2563          }
2564        if (match_limit > 0)
2565          {
2566          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2567          hints_list[j]->match_limit = match_limit;
2568          }
2569        if (match_limit_recursion > 0)
2570          {
2571          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2572          hints_list[j]->match_limit_recursion = match_limit_recursion;
2573          }
2574        }
2575      }
2576    
2577  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2578    
2579  if (exclude_pattern != NULL)  if (exclude_pattern != NULL)
# Line 2292  if (include_pattern != NULL) Line 2600  if (include_pattern != NULL)
2600      }      }
2601    }    }
2602    
2603    if (exclude_dir_pattern != NULL)
2604      {
2605      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2606        pcretables);
2607      if (exclude_dir_compiled == NULL)
2608        {
2609        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2610          errptr, error);
2611        goto EXIT2;
2612        }
2613      }
2614    
2615    if (include_dir_pattern != NULL)
2616      {
2617      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2618        pcretables);
2619      if (include_dir_compiled == NULL)
2620        {
2621        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2622          errptr, error);
2623        goto EXIT2;
2624        }
2625      }
2626    
2627  /* 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. */
2628    
2629  if (i >= argc)  if (i >= argc)
# Line 2323  if (pattern_list != NULL) Line 2655  if (pattern_list != NULL)
2655    }    }
2656  if (hints_list != NULL)  if (hints_list != NULL)
2657    {    {
2658    for (i = 0; i < hint_count; i++) free(hints_list[i]);    for (i = 0; i < hint_count; i++)
2659        {
2660        if (hints_list[i] != NULL) free(hints_list[i]);
2661        }
2662    free(hints_list);    free(hints_list);
2663    }    }
2664  return rc;  pcregrep_exit(rc);
2665    
2666  EXIT2:  EXIT2:
2667  rc = 2;  rc = 2;

Legend:
Removed from v.324  
changed lines
  Added in v.636

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12