/[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 420 by ph10, Wed Aug 12 17:32:27 2009 UTC revision 632 by ph10, Fri Jul 22 17:47:49 2011 UTC
# Line 6  Line 6 
6  its pattern matching. On a Unix or Win32 system it can recurse into  its pattern matching. On a Unix or Win32 system it can recurse into
7  directories.  directories.
8    
9             Copyright (c) 1997-2009 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 104  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 155  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 omit_zero_count = FALSE;  static BOOL omit_zero_count = FALSE;
182  static BOOL only_matching = FALSE;  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 198  used to identify them. */ Line 211  used to identify them. */
211  #define N_NULL         (-9)  #define N_NULL         (-9)
212  #define N_LOFFSETS     (-10)  #define N_LOFFSETS     (-10)
213  #define N_FOFFSETS     (-11)  #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" },    { 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" },    { 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 268  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 331  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 339  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 346  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 392  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 451  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 461  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 483  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 491  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 519  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 530  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 813  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 831  is used multiple times for the same subj Line 935  is used multiple times for the same subj
935  to find all possible matches.  to find all possible matches.
936    
937  Arguments:  Arguments:
938    matchptr    the start of the subject    matchptr     the start of the subject
939    length      the length of the subject to match    length       the length of the subject to match
940    offsets     the offets vector to fill in    startoffset  where to start matching
941    mrc         address of where to put the result of pcre_exec()    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  Returns:      TRUE if there was a match
945                FALSE if there was no match                FALSE if there was no match
# Line 842  Returns: TRUE if there was a match Line 947  Returns: TRUE if there was a match
947  */  */
948    
949  static BOOL  static BOOL
950  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)  match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
951      int *mrc)
952  {  {
953  int i;  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++)  for (i = 0; i < pattern_count; i++)
962    {    {
963    *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0,    *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length,
964      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);      startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
965    if (*mrc >= 0) return TRUE;    if (*mrc >= 0) return TRUE;
966    if (*mrc == PCRE_ERROR_NOMATCH) continue;    if (*mrc == PCRE_ERROR_NOMATCH) continue;
967    fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
968    if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);    if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
969    fprintf(stderr, "this text:\n");    fprintf(stderr, "%s", msg);
970    fwrite(matchptr, 1, length, stderr);  /* In case binary zero included */    FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
971    fprintf(stderr, "\n");    fprintf(stderr, "\n\n");
972    if (error_count == 0 &&    if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)
973        (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT))      resource_error = TRUE;
     {  
     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");  
     }  
974    if (error_count++ > 20)    if (error_count++ > 20)
975      {      {
976      fprintf(stderr, "pcregrep: too many errors - abandoned\n");      fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
977      exit(2);      pcregrep_exit(2);
978      }      }
979    return invert;    /* No more matching; don't show the line again */    return invert;    /* No more matching; don't show the line again */
980    }    }
# Line 916  char *ptr = buffer; Line 1024  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 953  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 967  while (ptr < endptr) Line 1079  while (ptr < endptr)
1079    {    {
1080    int endlinelength;    int endlinelength;
1081    int mrc = 0;    int mrc = 0;
1082      int startoffset = 0;
1083    BOOL match;    BOOL match;
1084    char *matchptr = ptr;    char *matchptr = ptr;
1085    char *t = ptr;    char *t = ptr;
# Line 1002  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 1043  while (ptr < endptr) Line 1156  while (ptr < endptr)
1156    than NOMATCH. This code is in a subroutine so that it can be re-used for    than NOMATCH. This code is in a subroutine so that it can be re-used for
1157    finding subsequent matches when colouring matched lines. */    finding subsequent matches when colouring matched lines. */
1158    
1159    match = match_patterns(matchptr, length, offsets, &mrc);    match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
1160    
1161    /* If it's a match or a not-match (as required), do what's wanted. */    /* If it's a match or a not-match (as required), do what's wanted. */
1162    
# Line 1072  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        substring (they both force --only-matching = 0). None of these options
1192      prints any context. Afterwards, adjust the start and length, and then jump      prints any context. Afterwards, adjust the start and length, and then jump
1193      back to look for further matches in the same line. If we are in invert      back to look for further matches in the same line. If we are in invert
1194      mode, however, nothing is printed - this could be still useful because the      mode, however, nothing is printed and we do not restart - this could still
1195      return code is set. */      be useful 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", (int)(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", (int)(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            {            {
1212            if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1213            fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            if (plen > 0)
1214            if (do_colour) fprintf(stdout, "%c[00m", 0x1b);              {
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          fprintf(stdout, "\n");          else if (printname != NULL || number) fprintf(stdout, "\n");
1222            /*
1223          matchptr += offsets[1];          matchptr += offsets[1];
1224          length -= offsets[1];          length -= offsets[1];
1225            */
1226          match = FALSE;          match = FALSE;
1227            if (line_buffered) fflush(stdout);
1228            rc = 0;                 /* Had some success */
1229            startoffset = offsets[1];
1230          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1231          }          }
1232        }        }
# Line 1137  while (ptr < endptr) Line 1262  while (ptr < endptr)
1262            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1263            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1264            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1265            fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);            FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1266            lastmatchrestart = pp;            lastmatchrestart = pp;
1267            }            }
1268          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
# Line 1177  while (ptr < endptr) Line 1302  while (ptr < endptr)
1302            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1303            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1304            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1305            fwrite(p, 1, pp - p, stdout);            FWRITE(p, 1, pp - p, stdout);
1306            p = pp;            p = pp;
1307            }            }
1308          }          }
# Line 1197  while (ptr < endptr) Line 1322  while (ptr < endptr)
1322        (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
1323        the match will always be before the first newline sequence. */        the match will always be before the first newline sequence. */
1324    
1325        if (multiline)        if (multiline & !invert)
1326          {          {
1327          int ellength;          char *endmatch = ptr + offsets[1];
1328          char *endmatch = ptr;          t = ptr;
1329          if (!invert)          while (t < endmatch)
1330            {            {
1331            endmatch += offsets[1];            t = end_of_line(t, endptr, &endlinelength);
1332            t = ptr;            if (t < endmatch) linenumber++; else break;
           while (t < endmatch)  
             {  
             t = end_of_line(t, endptr, &ellength);  
             if (t <= endmatch) linenumber++; else break;  
             }  
1333            }            }
1334          endmatch = end_of_line(endmatch, endptr, &ellength);          linelength = t - ptr - endlinelength;
         linelength = endmatch - ptr - ellength;  
1335          }          }
1336    
1337        /*** NOTE: Use only fwrite() to output the data line, so that binary        /*** NOTE: Use only fwrite() to output the data line, so that binary
# Line 1227  while (ptr < endptr) Line 1346  while (ptr < endptr)
1346          {          {
1347          int first = S_arg * 2;          int first = S_arg * 2;
1348          int last  = first + 1;          int last  = first + 1;
1349          fwrite(ptr, 1, offsets[first], stdout);          FWRITE(ptr, 1, offsets[first], stdout);
1350          fprintf(stdout, "X");          fprintf(stdout, "X");
1351          fwrite(ptr + offsets[last], 1, linelength - offsets[last], stdout);          FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1352          }          }
1353        else        else
1354  #endif  #endif
1355    
1356        /* We have to split the line(s) up if colouring, and search for further        /* We have to split the line(s) up if colouring, and search for further
1357        matches. */        matches, but not of course if the line is a non-match. */
1358    
1359        if (do_colour)        if (do_colour && !invert)
1360          {          {
1361            int plength;
1362          int last_offset = 0;          int last_offset = 0;
1363          fwrite(ptr, 1, offsets[0], stdout);          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          for (;;)          for (;;)
1368            {            {
1369              /*
1370            last_offset += offsets[1];            last_offset += offsets[1];
1371            matchptr += offsets[1];            matchptr += offsets[1];
1372            length -= offsets[1];            length -= offsets[1];
1373            if (!match_patterns(matchptr, length, offsets, &mrc)) break;            */
1374            fwrite(matchptr, 1, offsets[0], stdout);  
1375              startoffset = offsets[1];
1376              last_offset = startoffset;
1377              if (last_offset >= linelength + endlinelength ||
1378                  !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1379                break;
1380              FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1381            fprintf(stdout, "%c[%sm", 0x1b, colour_string);            fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1382            fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1383            fprintf(stdout, "%c[00m", 0x1b);            fprintf(stdout, "%c[00m", 0x1b);
1384            }            }
1385          fwrite(ptr + last_offset, 1, (linelength + endlinelength) - last_offset,  
1386            stdout);          /* In multiline mode, we may have already printed the complete line
1387            and its line-ending characters (if they matched the pattern), so there
1388            may be no more to print. */
1389    
1390            plength = (linelength + endlinelength) - last_offset;
1391            if (plength > 0)
1392              FWRITE(ptr + last_offset, 1, plength, stdout);
1393          }          }
1394    
1395        /* Not colouring; no need to search for further matches */        /* Not colouring; no need to search for further matches */
1396    
1397        else fwrite(ptr, 1, linelength + endlinelength, stdout);        else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1398        }        }
1399    
1400      /* End of doing what has to be done for a match */      /* End of doing what has to be done for a match. If --line-buffered was
1401        given, flush the output. */
1402    
1403        if (line_buffered) fflush(stdout);
1404      rc = 0;    /* Had some success */      rc = 0;    /* Had some success */
1405    
1406      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
# Line 1297  while (ptr < endptr) Line 1432  while (ptr < endptr)
1432    offset to the current line is maintained in filepos. */    offset to the current line is maintained in filepos. */
1433    
1434    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1435    filepos += linelength + endlinelength;    filepos += (int)(linelength + endlinelength);
1436    linenumber++;    linenumber++;
1437    
1438      /* If input is line buffered, and the buffer is not yet full, read another
1439      line and add it into the buffer. */
1440    
1441      if (input_line_buffered && bufflength < sizeof(buffer))
1442        {
1443        int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);
1444        bufflength += add;
1445        endptr += add;
1446        }
1447    
1448    /* If we haven't yet reached the end of the file (the buffer is full), and    /* If we haven't yet reached the end of the file (the buffer is full), and
1449    the current point is in the top 1/3 of the buffer, slide the buffer down by    the current point is in the top 1/3 of the buffer, slide the buffer down by
1450    1/3 and refill it. Before we do this, if some unprinted "after" lines are    1/3 and refill it. Before we do this, if some unprinted "after" lines are
# Line 1334  while (ptr < endptr) Line 1479  while (ptr < endptr)
1479      else      else
1480  #endif  #endif
1481    
1482      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD +
1483          (input_line_buffered?
1484           read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :
1485           fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));
1486      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1487    
1488      /* Adjust any last match point */      /* Adjust any last match point */
# Line 1347  while (ptr < endptr) Line 1494  while (ptr < endptr)
1494  /* End of file; print final "after" lines if wanted; do_after_lines sets  /* End of file; print final "after" lines if wanted; do_after_lines sets
1495  hyphenpending if it prints something. */  hyphenpending if it prints something. */
1496    
1497  if (!only_matching && !count_only)  if (only_matching < 0 && !count_only)
1498    {    {
1499    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1500    hyphenpending |= endhyphenpending;    hyphenpending |= endhyphenpending;
# Line 1367  if (filenames == FN_NOMATCH_ONLY) Line 1514  if (filenames == FN_NOMATCH_ONLY)
1514  if (count_only)  if (count_only)
1515    {    {
1516    if (count > 0 || !omit_zero_count)    if (count > 0 || !omit_zero_count)
1517      {      {
1518      if (printname != NULL && filenames != FN_NONE)      if (printname != NULL && filenames != FN_NONE)
1519        fprintf(stdout, "%s:", printname);        fprintf(stdout, "%s:", printname);
1520      fprintf(stdout, "%d\n", count);      fprintf(stdout, "%d\n", count);
1521      }      }
1522    }    }
1523    
1524  return rc;  return rc;
# Line 1451  if ((sep = isdirectory(pathname)) != 0) Line 1598  if ((sep = isdirectory(pathname)) != 0)
1598        {        {
1599        int frc, nflen;        int frc, nflen;
1600        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1601        nflen = strlen(nextfile);        nflen = (int)(strlen(nextfile));
1602    
1603        if (isdirectory(buffer))        if (isdirectory(buffer))
1604          {          {
# Line 1495  skipping was not requested. The scan pro Line 1642  skipping was not requested. The scan pro
1642  argument at top level, we don't show the file name, unless we are only showing  argument at top level, we don't show the file name, unless we are only showing
1643  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1644    
1645  pathlen = strlen(pathname);  pathlen = (int)(strlen(pathname));
1646    
1647  /* 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. */
1648    
# Line 1657  for (op = optionlist; op->one_char != 0; Line 1804  for (op = optionlist; op->one_char != 0;
1804    {    {
1805    int n;    int n;
1806    char s[4];    char s[4];
1807    
1808      /* Two options were accidentally implemented and documented with underscores
1809      instead of hyphens in their names, something that was not noticed for quite a
1810      few releases. When fixing this, I left the underscored versions in the list
1811      in case people were using them. However, we don't want to display them in the
1812      help data. There are no other options that contain underscores, and we do not
1813      expect ever to implement such options. Therefore, just omit any option that
1814      contains an underscore. */
1815    
1816      if (strchr(op->long_name, '_') != NULL) continue;
1817    
1818    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");
1819    n = 30 - printf("  %s --%s", s, op->long_name);    n = 31 - printf("  %s --%s", s, op->long_name);
1820    if (n < 1) n = 1;    if (n < 1) n = 1;
1821    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1822    }    }
1823    
1824  printf("\nWhen reading patterns from a file instead of using a command line option,\n");  printf("\nWhen reading patterns from a file instead of using a command line option,\n");
# Line 1684  handle_option(int letter, int options) Line 1842  handle_option(int letter, int options)
1842  switch(letter)  switch(letter)
1843    {    {
1844    case N_FOFFSETS: file_offsets = TRUE; break;    case N_FOFFSETS: file_offsets = TRUE; break;
1845    case N_HELP: help(); exit(0);    case N_HELP: help(); pcregrep_exit(0);
1846    case N_LOFFSETS: line_offsets = number = TRUE; break;    case N_LOFFSETS: line_offsets = number = TRUE; break;
1847      case N_LBUFFER: line_buffered = TRUE; break;
1848    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1849    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1850    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
# Line 1695  switch(letter) Line 1854  switch(letter)
1854    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1855    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1856    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
1857    case 'o': only_matching = TRUE; break;    case 'o': only_matching = 0; break;
1858    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1859    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1860    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
# Line 1706  switch(letter) Line 1865  switch(letter)
1865    
1866    case 'V':    case 'V':
1867    fprintf(stderr, "pcregrep version %s\n", pcre_version());    fprintf(stderr, "pcregrep version %s\n", pcre_version());
1868    exit(0);    pcregrep_exit(0);
1869    break;    break;
1870    
1871    default:    default:
1872    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
1873    exit(usage(2));    pcregrep_exit(usage(2));
1874    }    }
1875    
1876  return options;  return options;
# Line 1907  for (i = 1; i < argc; i++) Line 2066  for (i = 1; i < argc; i++)
2066    if (argv[i][1] == 0)    if (argv[i][1] == 0)
2067      {      {
2068      if (pattern_filename != NULL || pattern_count > 0) break;      if (pattern_filename != NULL || pattern_count > 0) break;
2069        else exit(usage(2));        else pcregrep_exit(usage(2));
2070      }      }
2071    
2072    /* Handle a long name option, or -- to terminate the options */    /* Handle a long name option, or -- to terminate the options */
# Line 1929  for (i = 1; i < argc; i++) Line 2088  for (i = 1; i < argc; i++)
2088      Some options have variations in the long name spelling: specifically, we      Some options have variations in the long name spelling: specifically, we
2089      allow "regexp" because GNU grep allows it, though I personally go along      allow "regexp" because GNU grep allows it, though I personally go along
2090      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
2091      These options are entered in the table as "regex(p)". No option is in both      These options are entered in the table as "regex(p)". Options can be in
2092      these categories, fortunately. */      both these categories. */
2093    
2094      for (op = optionlist; op->one_char != 0; op++)      for (op = optionlist; op->one_char != 0; op++)
2095        {        {
2096        char *opbra = strchr(op->long_name, '(');        char *opbra = strchr(op->long_name, '(');
2097        char *equals = strchr(op->long_name, '=');        char *equals = strchr(op->long_name, '=');
2098        if (opbra == NULL)     /* Not a (p) case */  
2099          /* Handle options with only one spelling of the name */
2100    
2101          if (opbra == NULL)     /* Does not contain '(' */
2102          {          {
2103          if (equals == NULL)  /* Not thing=data case */          if (equals == NULL)  /* Not thing=data case */
2104            {            {
# Line 1944  for (i = 1; i < argc; i++) Line 2106  for (i = 1; i < argc; i++)
2106            }            }
2107          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
2108            {            {
2109            int oplen = equals - op->long_name;            int oplen = (int)(equals - op->long_name);
2110            int arglen = (argequals == NULL)? (int)strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)?
2111                (int)strlen(arg) : (int)(argequals - arg);
2112            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
2113              {              {
2114              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1958  for (i = 1; i < argc; i++) Line 2121  for (i = 1; i < argc; i++)
2121              }              }
2122            }            }
2123          }          }
2124        else                   /* Special case xxxx(p) */  
2125          /* Handle options with an alternate spelling of the name */
2126    
2127          else
2128          {          {
2129          char buff1[24];          char buff1[24];
2130          char buff2[24];          char buff2[24];
2131          int baselen = opbra - op->long_name;  
2132            int baselen = (int)(opbra - op->long_name);
2133            int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
2134            int arglen = (argequals == NULL || equals == NULL)?
2135              (int)strlen(arg) : (int)(argequals - arg);
2136    
2137          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
2138          sprintf(buff2, "%s%.*s", buff1,          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
2139            (int)strlen(op->long_name) - baselen - 2, opbra + 1);  
2140          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strncmp(arg, buff1, arglen) == 0 ||
2141               strncmp(arg, buff2, arglen) == 0)
2142              {
2143              if (equals != NULL && argequals != NULL)
2144                {
2145                option_data = argequals;
2146                if (*option_data == '=')
2147                  {
2148                  option_data++;
2149                  longopwasequals = TRUE;
2150                  }
2151                }
2152            break;            break;
2153              }
2154          }          }
2155        }        }
2156    
2157      if (op->one_char == 0)      if (op->one_char == 0)
2158        {        {
2159        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
2160        exit(usage(2));        pcregrep_exit(usage(2));
2161        }        }
2162      }      }
2163    
   
2164    /* Jeffrey Friedl's debugging harness uses these additional options which    /* Jeffrey Friedl's debugging harness uses these additional options which
2165    are not in the right form for putting in the option table because they use    are not in the right form for putting in the option table because they use
2166    only one hyphen, yet are more than one character long. By putting them    only one hyphen, yet are more than one character long. By putting them
# Line 2012  for (i = 1; i < argc; i++) Line 2194  for (i = 1; i < argc; i++)
2194      while (*s != 0)      while (*s != 0)
2195        {        {
2196        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2197          { if (*s == op->one_char) break; }          {
2198            if (*s == op->one_char) break;
2199            }
2200        if (op->one_char == 0)        if (op->one_char == 0)
2201          {          {
2202          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2203            *s, argv[i]);            *s, argv[i]);
2204          exit(usage(2));          pcregrep_exit(usage(2));
2205          }          }
2206        if (op->type != OP_NODATA || s[1] == 0)  
2207          /* Check for a single-character option that has data: OP_OP_NUMBER
2208          is used for one that either has a numerical number or defaults, i.e. the
2209          data is optional. If a digit follows, there is data; if not, carry on
2210          with other single-character options in the same string. */
2211    
2212          option_data = s+1;
2213          if (op->type == OP_OP_NUMBER)
2214            {
2215            if (isdigit((unsigned char)s[1])) break;
2216            }
2217          else   /* Check for end or a dataless option */
2218          {          {
2219          option_data = s+1;          if (op->type != OP_NODATA || s[1] == 0) break;
         break;  
2220          }          }
2221    
2222          /* Handle a single-character option with no data, then loop for the
2223          next character in the string. */
2224    
2225        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
2226        }        }
2227      }      }
# Line 2040  for (i = 1; i < argc; i++) Line 2238  for (i = 1; i < argc; i++)
2238    
2239    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that
2240    either has a value or defaults to something. It cannot have data in a    either has a value or defaults to something. It cannot have data in a
2241    separate item. At the moment, the only such options are "colo(u)r" and    separate item. At the moment, the only such options are "colo(u)r",
2242    Jeffrey Friedl's special -S debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2243    
2244    if (*option_data == 0 &&    if (*option_data == 0 &&
2245        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
# Line 2051  for (i = 1; i < argc; i++) Line 2249  for (i = 1; i < argc; i++)
2249        case N_COLOUR:        case N_COLOUR:
2250        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2251        break;        break;
2252    
2253          case 'o':
2254          only_matching = 0;
2255          break;
2256    
2257  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2258        case 'S':        case 'S':
2259        S_arg = 0;        S_arg = 0;
# Line 2067  for (i = 1; i < argc; i++) Line 2270  for (i = 1; i < argc; i++)
2270      if (i >= argc - 1 || longopwasequals)      if (i >= argc - 1 || longopwasequals)
2271        {        {
2272        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);
2273        exit(usage(2));        pcregrep_exit(usage(2));
2274        }        }
2275      option_data = argv[++i];      option_data = argv[++i];
2276      }      }
# Line 2088  for (i = 1; i < argc; i++) Line 2291  for (i = 1; i < argc; i++)
2291    
2292    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2293    
2294    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2295               op->type != OP_OP_NUMBER)
2296      {      {
2297      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2298      }      }
2299    
2300      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2301      only for unpicking arguments, so just keep it simple. */
2302    
2303    else    else
2304      {      {
2305      char *endptr;      unsigned long int n = 0;
2306      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2307        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2308        while (isdigit((unsigned char)(*endptr)))
2309          n = n * 10 + (int)(*endptr++ - '0');
2310      if (*endptr != 0)      if (*endptr != 0)
2311        {        {
2312        if (longop)        if (longop)
2313          {          {
2314          char *equals = strchr(op->long_name, '=');          char *equals = strchr(op->long_name, '=');
2315          int nlen = (equals == NULL)? (int)strlen(op->long_name) :          int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2316            equals - op->long_name;            (int)(equals - op->long_name);
2317          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2318            option_data, nlen, op->long_name);            option_data, nlen, op->long_name);
2319          }          }
2320        else        else
2321          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2322            option_data, op->one_char);            option_data, op->one_char);
2323        exit(usage(2));        pcregrep_exit(usage(2));
2324        }        }
2325      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2326            *((unsigned long int *)op->dataptr) = n;
2327        else
2328            *((int *)op->dataptr) = n;
2329      }      }
2330    }    }
2331    
# Line 2125  if (both_context > 0) Line 2339  if (both_context > 0)
2339    }    }
2340    
2341  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2342  However, the latter two set the only_matching flag. */  However, the latter two set only_matching. */
2343    
2344  if ((only_matching && (file_offsets || line_offsets)) ||  if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2345      (file_offsets && line_offsets))      (file_offsets && line_offsets))
2346    {    {
2347    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2348      "and/or --line-offsets\n");      "and/or --line-offsets\n");
2349    exit(usage(2));    pcregrep_exit(usage(2));
2350    }    }
2351    
2352  if (file_offsets || line_offsets) only_matching = TRUE;  if (file_offsets || line_offsets) only_matching = 0;
2353    
2354  /* If a locale has not been provided as an option, see if the LC_CTYPE or  /* If a locale has not been provided as an option, see if the LC_CTYPE or
2355  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
# Line 2344  for (j = 0; j < pattern_count; j++) Line 2558  for (j = 0; j < pattern_count; j++)
2558    hint_count++;    hint_count++;
2559    }    }
2560    
2561    /* If --match-limit or --recursion-limit was set, put the value(s) into the
2562    pcre_extra block for each pattern. */
2563    
2564    if (match_limit > 0 || match_limit_recursion > 0)
2565      {
2566      for (j = 0; j < pattern_count; j++)
2567        {
2568        if (hints_list[j] == NULL)
2569          {
2570          hints_list[j] = malloc(sizeof(pcre_extra));
2571          if (hints_list[j] == NULL)
2572            {
2573            fprintf(stderr, "pcregrep: malloc failed\n");
2574            pcregrep_exit(2);
2575            }
2576          }
2577        if (match_limit > 0)
2578          {
2579          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2580          hints_list[j]->match_limit = match_limit;
2581          }
2582        if (match_limit_recursion > 0)
2583          {
2584          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2585          hints_list[j]->match_limit_recursion = match_limit_recursion;
2586          }
2587        }
2588      }
2589    
2590  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2591    
2592  if (exclude_pattern != NULL)  if (exclude_pattern != NULL)
# Line 2425  if (pattern_list != NULL) Line 2668  if (pattern_list != NULL)
2668    }    }
2669  if (hints_list != NULL)  if (hints_list != NULL)
2670    {    {
2671    for (i = 0; i < hint_count; i++) free(hints_list[i]);    for (i = 0; i < hint_count; i++)
2672        {
2673        if (hints_list[i] != NULL) free(hints_list[i]);
2674        }
2675    free(hints_list);    free(hints_list);
2676    }    }
2677  return rc;  pcregrep_exit(rc);
2678    
2679  EXIT2:  EXIT2:
2680  rc = 2;  rc = 2;

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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12