/[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 283 by ph10, Fri Dec 7 19:59:19 2007 UTC revision 558 by ph10, Tue Oct 26 15:26:45 2010 UTC
# Line 6  Line 6 
6  its pattern matching. On a Unix or Win32 system it can recurse into  its pattern matching. On a Unix or Win32 system it can recurse into
7  directories.  directories.
8    
9             Copyright (c) 1997-2007 University of Cambridge             Copyright (c) 1997-2010 University of Cambridge
10    
11  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
12  Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
# Line 55  POSSIBILITY OF SUCH DAMAGE. Line 55  POSSIBILITY OF SUCH DAMAGE.
55  #include <unistd.h>  #include <unistd.h>
56  #endif  #endif
57    
58    #ifdef SUPPORT_LIBZ
59    #include <zlib.h>
60    #endif
61    
62    #ifdef SUPPORT_LIBBZ2
63    #include <bzlib.h>
64    #endif
65    
66  #include "pcre.h"  #include "pcre.h"
67    
68  #define FALSE 0  #define FALSE 0
# Line 63  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 74  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 */
89    
90    enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };
91    
92  /* Actions for the -d and -D options */  /* Actions for the -d and -D options */
93    
# Line 91  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 127  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 145  static BOOL do_colour = FALSE; Line 170  static BOOL do_colour = FALSE;
170  static BOOL file_offsets = FALSE;  static BOOL file_offsets = FALSE;
171  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
172  static BOOL invert = FALSE;  static BOOL invert = FALSE;
173    static BOOL line_buffered = FALSE;
174  static BOOL line_offsets = FALSE;  static BOOL line_offsets = FALSE;
175  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
176  static BOOL number = FALSE;  static BOOL number = FALSE;
177    static BOOL omit_zero_count = FALSE;
178  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
179  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
180  static BOOL silent = FALSE;  static BOOL silent = FALSE;
# Line 169  typedef struct option_item { Line 196  typedef struct option_item {
196  /* 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
197  used to identify them. */  used to identify them. */
198    
199  #define N_COLOUR    (-1)  #define N_COLOUR       (-1)
200  #define N_EXCLUDE   (-2)  #define N_EXCLUDE      (-2)
201  #define N_HELP      (-3)  #define N_EXCLUDE_DIR  (-3)
202  #define N_INCLUDE   (-4)  #define N_HELP         (-4)
203  #define N_LABEL     (-5)  #define N_INCLUDE      (-5)
204  #define N_LOCALE    (-6)  #define N_INCLUDE_DIR  (-6)
205  #define N_NULL      (-7)  #define N_LABEL        (-7)
206  #define N_LOFFSETS  (-8)  #define N_LOCALE       (-8)
207  #define N_FOFFSETS  (-9)  #define N_NULL         (-9)
208    #define N_LOFFSETS     (-10)
209    #define N_FOFFSETS     (-11)
210    #define N_LBUFFER      (-12)
211    
212  static option_item optionlist[] = {  static option_item optionlist[] = {
213    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 190  static option_item optionlist[] = { Line 220  static option_item optionlist[] = {
220    { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },    { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
221    { 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" },
222    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },
223    { 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)" },
224    { 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" },
225    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
226    { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },    { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
227    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
# Line 200  static option_item optionlist[] = { Line 230  static option_item optionlist[] = {
230    { 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" },
231    { 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" },
232    { 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" },
233      { OP_NODATA,    N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
234    { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },    { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
235    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
236    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
# Line 210  static option_item optionlist[] = { Line 241  static option_item optionlist[] = {
241    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },
242    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
243    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
244      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
245      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
246  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
247    { 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" },
248  #endif  #endif
# Line 309  return (statbuf.st_mode & S_IFMT) == S_I Line 342  return (statbuf.st_mode & S_IFMT) == S_I
342  }  }
343    
344    
345  /************* Test stdout for being a terminal in Unix **********/  /************* Test for a terminal in Unix **********/
346    
347  static BOOL  static BOOL
348  is_stdout_tty(void)  is_stdout_tty(void)
# Line 317  is_stdout_tty(void) Line 350  is_stdout_tty(void)
350  return isatty(fileno(stdout));  return isatty(fileno(stdout));
351  }  }
352    
353    static BOOL
354    is_file_tty(FILE *f)
355    {
356    return isatty(fileno(f));
357    }
358    
359    
360  /************* Directory scanning in Win32 ***********/  /************* Directory scanning in Win32 ***********/
361    
362  /* I (Philip Hazel) have no means of testing this code. It was contributed by  /* I (Philip Hazel) have no means of testing this code. It was contributed by
363  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
364  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
365  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
366  */  The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
367    undefined when it is indeed undefined. */
368    
369  #elif HAVE_WINDOWS_H  #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
370    
371  #ifndef STRICT  #ifndef STRICT
372  # define STRICT  # define STRICT
# Line 429  return !isdirectory(filename); Line 469  return !isdirectory(filename);
469  }  }
470    
471    
472  /************* Test stdout for being a terminal in Win32 **********/  /************* Test for a terminal in Win32 **********/
473    
474  /* I don't know how to do this; assume never */  /* I don't know how to do this; assume never */
475    
# Line 439  is_stdout_tty(void) Line 479  is_stdout_tty(void)
479  return FALSE;  return FALSE;
480  }  }
481    
482    static BOOL
483    is_file_tty(FILE *f)
484    {
485    return FALSE;
486    }
487    
488    
489  /************* Directory scanning when we can't do it ***********/  /************* Directory scanning when we can't do it ***********/
490    
# Line 461  void closedirectory(directory_type *dir) Line 507  void closedirectory(directory_type *dir)
507  int isregfile(char *filename) { return 1; }  int isregfile(char *filename) { return 1; }
508    
509    
510  /************* Test stdout for being a terminal when we can't do it **********/  /************* Test for a terminal when we can't do it **********/
511    
512  static BOOL  static BOOL
513  is_stdout_tty(void)  is_stdout_tty(void)
# Line 469  is_stdout_tty(void) Line 515  is_stdout_tty(void)
515  return FALSE;  return FALSE;
516  }  }
517    
518    static BOOL
519    is_file_tty(FILE *f)
520    {
521    return FALSE;
522    }
523    
524  #endif  #endif
525    
# Line 497  return sys_errlist[n]; Line 548  return sys_errlist[n];
548    
549    
550  /*************************************************  /*************************************************
551    *            Read one line of input              *
552    *************************************************/
553    
554    /* Normally, input is read using fread() into a large buffer, so many lines may
555    be read at once. However, doing this for tty input means that no output appears
556    until a lot of input has been typed. Instead, tty input is handled line by
557    line. We cannot use fgets() for this, because it does not stop at a binary
558    zero, and therefore there is no way of telling how many characters it has read,
559    because there may be binary zeros embedded in the data.
560    
561    Arguments:
562      buffer     the buffer to read into
563      length     the maximum number of characters to read
564      f          the file
565    
566    Returns:     the number of characters read, zero at end of file
567    */
568    
569    static int
570    read_one_line(char *buffer, int length, FILE *f)
571    {
572    int c;
573    int yield = 0;
574    while ((c = fgetc(f)) != EOF)
575      {
576      buffer[yield++] = c;
577      if (c == '\n' || yield >= length) break;
578      }
579    return yield;
580    }
581    
582    
583    
584    /*************************************************
585  *             Find end of line                   *  *             Find end of line                   *
586  *************************************************/  *************************************************/
587    
# Line 791  if (after_context > 0 && lastmatchnumber Line 876  if (after_context > 0 && lastmatchnumber
876      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
877      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
878      pp = end_of_line(pp, endptr, &ellength);      pp = end_of_line(pp, endptr, &ellength);
879      fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);      FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
880      lastmatchrestart = pp;      lastmatchrestart = pp;
881      }      }
882    hyphenpending = TRUE;    hyphenpending = TRUE;
# Line 801  if (after_context > 0 && lastmatchnumber Line 886  if (after_context > 0 && lastmatchnumber
886    
887    
888  /*************************************************  /*************************************************
889    *   Apply patterns to subject till one matches   *
890    *************************************************/
891    
892    /* This function is called to run through all patterns, looking for a match. It
893    is used multiple times for the same subject when colouring is enabled, in order
894    to find all possible matches.
895    
896    Arguments:
897      matchptr    the start of the subject
898      length      the length of the subject to match
899      offsets     the offets vector to fill in
900      mrc         address of where to put the result of pcre_exec()
901    
902    Returns:      TRUE if there was a match
903                  FALSE if there was no match
904                  invert if there was a non-fatal error
905    */
906    
907    static BOOL
908    match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)
909    {
910    int i;
911    for (i = 0; i < pattern_count; i++)
912      {
913      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length, 0,
914        PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
915      if (*mrc >= 0) return TRUE;
916      if (*mrc == PCRE_ERROR_NOMATCH) continue;
917      fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);
918      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
919      fprintf(stderr, "this text:\n");
920      FWRITE(matchptr, 1, length, stderr);   /* In case binary zero included */
921      fprintf(stderr, "\n");
922      if (error_count == 0 &&
923          (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT))
924        {
925        fprintf(stderr, "pcregrep: error %d means that a resource limit "
926          "was exceeded\n", *mrc);
927        fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");
928        }
929      if (error_count++ > 20)
930        {
931        fprintf(stderr, "pcregrep: too many errors - abandoned\n");
932        exit(2);
933        }
934      return invert;    /* No more matching; don't show the line again */
935      }
936    
937    return FALSE;  /* No match, no errors */
938    }
939    
940    
941    
942    /*************************************************
943  *            Grep an individual file             *  *            Grep an individual file             *
944  *************************************************/  *************************************************/
945    
# Line 812  be in the middle third most of the time, Line 951  be in the middle third most of the time,
951  "before" context printing.  "before" context printing.
952    
953  Arguments:  Arguments:
954    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
955                   the gzFile pointer when reading is via libz
956                   the BZFILE pointer when reading is via libbz2
957      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
958    printname    the file name if it is to be printed for each match    printname    the file name if it is to be printed for each match
959                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
960                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
961    
962  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
963                 1 otherwise (no matches)                 1 otherwise (no matches)
964                   2 if there is a read error on a .bz2 file
965  */  */
966    
967  static int  static int
968  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
969  {  {
970  int rc = 1;  int rc = 1;
971  int linenumber = 1;  int linenumber = 1;
972  int lastmatchnumber = 0;  int lastmatchnumber = 0;
973  int count = 0;  int count = 0;
974  int filepos = 0;  int filepos = 0;
975  int offsets[99];  int offsets[OFFSET_SIZE];
976  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
977  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
978  char *ptr = buffer;  char *ptr = buffer;
979  char *endptr;  char *endptr;
980  size_t bufflength;  size_t bufflength;
981  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
982    BOOL input_line_buffered = line_buffered;
983    FILE *in = NULL;                    /* Ensure initialized */
984    
985    #ifdef SUPPORT_LIBZ
986    gzFile ingz = NULL;
987    #endif
988    
989    #ifdef SUPPORT_LIBBZ2
990    BZFILE *inbz2 = NULL;
991    #endif
992    
993    
994    /* Do the first read into the start of the buffer and set up the pointer to end
995    of what we have. In the case of libz, a non-zipped .gz file will be read as a
996    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
997    fail. */
998    
999    #ifdef SUPPORT_LIBZ
1000    if (frtype == FR_LIBZ)
1001      {
1002      ingz = (gzFile)handle;
1003      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
1004      }
1005    else
1006    #endif
1007    
1008  /* Do the first read into the start of the buffer and set up the pointer to  #ifdef SUPPORT_LIBBZ2
1009  end of what we have. */  if (frtype == FR_LIBBZ2)
1010      {
1011      inbz2 = (BZFILE *)handle;
1012      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
1013      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1014      }                                    /* without the cast it is unsigned. */
1015    else
1016    #endif
1017    
1018      {
1019      in = (FILE *)handle;
1020      if (is_file_tty(in)) input_line_buffered = TRUE;
1021      bufflength = input_line_buffered?
1022        read_one_line(buffer, 3*MBUFTHIRD, in) :
1023        fread(buffer, 1, 3*MBUFTHIRD, in);
1024      }
1025    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
1026  endptr = buffer + bufflength;  endptr = buffer + bufflength;
1027    
1028  /* Loop while the current pointer is not at the end of the file. For large  /* Loop while the current pointer is not at the end of the file. For large
# Line 850  way, the buffer is shifted left and re-f Line 1032  way, the buffer is shifted left and re-f
1032    
1033  while (ptr < endptr)  while (ptr < endptr)
1034    {    {
1035    int i, endlinelength;    int endlinelength;
1036    int mrc = 0;    int mrc = 0;
1037    BOOL match = FALSE;    BOOL match;
1038    char *matchptr = ptr;    char *matchptr = ptr;
1039    char *t = ptr;    char *t = ptr;
1040    size_t length, linelength;    size_t length, linelength;
1041    
1042    /* 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
1043    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
1044    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
1045    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
1046    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
1047    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
1048      first line. */
1049    
1050    t = end_of_line(t, endptr, &endlinelength);    t = end_of_line(t, endptr, &endlinelength);
1051    linelength = t - ptr - endlinelength;    linelength = t - ptr - endlinelength;
# Line 877  while (ptr < endptr) Line 1060  while (ptr < endptr)
1060        #include <time.h>        #include <time.h>
1061        struct timeval start_time, end_time;        struct timeval start_time, end_time;
1062        struct timezone dummy;        struct timezone dummy;
1063          int i;
1064    
1065        if (jfriedl_XT)        if (jfriedl_XT)
1066        {        {
# Line 902  while (ptr < endptr) Line 1086  while (ptr < endptr)
1086    
1087    
1088        for (i = 0; i < jfriedl_XR; i++)        for (i = 0; i < jfriedl_XR; i++)
1089            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,
1090                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1091    
1092        if (gettimeofday(&end_time, &dummy) != 0)        if (gettimeofday(&end_time, &dummy) != 0)
1093                perror("bad gettimeofday");                perror("bad gettimeofday");
# Line 916  while (ptr < endptr) Line 1101  while (ptr < endptr)
1101    }    }
1102  #endif  #endif
1103    
1104    /* We come back here after a match when the -o option (only_matching) is set,    /* We come back here after a match when the -o option (only_matching) is set,
1105    in order to find any further matches in the same line. */    in order to find any further matches in the same line. */
   
   ONLY_MATCHING_RESTART:  
1106    
1107    /* Run through all the patterns until one matches. Note that we don't include    ONLY_MATCHING_RESTART:
   the final newline in the subject string. */  
1108    
1109    for (i = 0; i < pattern_count; i++)    /* Run through all the patterns until one matches or there is an error other
1110      {    than NOMATCH. This code is in a subroutine so that it can be re-used for
1111      mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0, 0,    finding subsequent matches when colouring matched lines. */
1112        offsets, 99);  
1113      if (mrc >= 0) { match = TRUE; break; }    match = match_patterns(matchptr, length, offsets, &mrc);
     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;  
       }  
     }  
1114    
1115    /* 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. */
1116    
# Line 970  while (ptr < endptr) Line 1129  while (ptr < endptr)
1129      /* 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
1130      in the file. */      in the file. */
1131    
1132      else if (filenames == FN_ONLY)      else if (filenames == FN_MATCH_ONLY)
1133        {        {
1134        fprintf(stdout, "%s\n", printname);        fprintf(stdout, "%s\n", printname);
1135        return 0;        return 0;
# Line 981  while (ptr < endptr) Line 1140  while (ptr < endptr)
1140      else if (quiet) return 0;      else if (quiet) return 0;
1141    
1142      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
1143      the --file-offsets and --line-offsets options output offsets for the      the --file-offsets and --line-offsets options output offsets for the
1144      matching substring (they both force --only-matching). None of these options      matching substring (they both force --only-matching). None of these options
1145      prints any context. Afterwards, adjust the start and length, and then jump      prints any context. Afterwards, adjust the start and length, and then jump
1146      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
# Line 991  while (ptr < endptr) Line 1150  while (ptr < endptr)
1150      else if (only_matching)      else if (only_matching)
1151        {        {
1152        if (!invert)        if (!invert)
1153          {          {
1154          if (printname != NULL) fprintf(stdout, "%s:", printname);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1155          if (number) fprintf(stdout, "%d:", linenumber);          if (number) fprintf(stdout, "%d:", linenumber);
1156          if (line_offsets)          if (line_offsets)
1157            fprintf(stdout, "%d,%d", matchptr + offsets[0] - ptr,            fprintf(stdout, "%d,%d", (int)(matchptr + offsets[0] - ptr),
1158              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1159          else if (file_offsets)          else if (file_offsets)
1160            fprintf(stdout, "%d,%d", filepos + matchptr + offsets[0] - ptr,            fprintf(stdout, "%d,%d", (int)(filepos + matchptr + offsets[0] - ptr),
1161              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1162          else          else
1163            fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            {
1164              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1165              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1166              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1167              }
1168          fprintf(stdout, "\n");          fprintf(stdout, "\n");
1169          matchptr += offsets[1];          matchptr += offsets[1];
1170          length -= offsets[1];          length -= offsets[1];
1171          match = FALSE;          match = FALSE;
1172          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1173          }          }
1174        }        }
1175    
1176      /* This is the default case when none of the above options is set. We print      /* This is the default case when none of the above options is set. We print
# Line 1041  while (ptr < endptr) Line 1204  while (ptr < endptr)
1204            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1205            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1206            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1207            fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);            FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1208            lastmatchrestart = pp;            lastmatchrestart = pp;
1209            }            }
1210          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
# Line 1081  while (ptr < endptr) Line 1244  while (ptr < endptr)
1244            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1245            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1246            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1247            fwrite(p, 1, pp - p, stdout);            FWRITE(p, 1, pp - p, stdout);
1248            p = pp;            p = pp;
1249            }            }
1250          }          }
# Line 1131  while (ptr < endptr) Line 1294  while (ptr < endptr)
1294          {          {
1295          int first = S_arg * 2;          int first = S_arg * 2;
1296          int last  = first + 1;          int last  = first + 1;
1297          fwrite(ptr, 1, offsets[first], stdout);          FWRITE(ptr, 1, offsets[first], stdout);
1298          fprintf(stdout, "X");          fprintf(stdout, "X");
1299          fwrite(ptr + offsets[last], 1, linelength - offsets[last], stdout);          FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1300          }          }
1301        else        else
1302  #endif  #endif
1303    
1304        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1305          matches. */
1306    
1307        if (do_colour)        if (do_colour)
1308          {          {
1309          fwrite(ptr, 1, offsets[0], stdout);          int last_offset = 0;
1310            FWRITE(ptr, 1, offsets[0], stdout);
1311          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1312          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1313          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1314          fwrite(ptr + offsets[1], 1, (linelength + endlinelength) - offsets[1],          for (;;)
1315            stdout);            {
1316              last_offset += offsets[1];
1317              matchptr += offsets[1];
1318              length -= offsets[1];
1319              if (!match_patterns(matchptr, length, offsets, &mrc)) break;
1320              FWRITE(matchptr, 1, offsets[0], stdout);
1321              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1322              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1323              fprintf(stdout, "%c[00m", 0x1b);
1324              }
1325            FWRITE(ptr + last_offset, 1,
1326              (linelength + endlinelength) - last_offset, stdout);
1327          }          }
1328        else fwrite(ptr, 1, linelength + endlinelength, stdout);  
1329          /* Not colouring; no need to search for further matches */
1330    
1331          else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1332        }        }
1333    
1334      /* 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
1335        given, flush the output. */
1336    
1337        if (line_buffered) fflush(stdout);
1338      rc = 0;    /* Had some success */      rc = 0;    /* Had some success */
1339    
1340      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
# Line 1181  while (ptr < endptr) Line 1362  while (ptr < endptr)
1362      linelength = endmatch - ptr - ellength;      linelength = endmatch - ptr - ellength;
1363      }      }
1364    
1365    /* Advance to after the newline and increment the line number. The file    /* Advance to after the newline and increment the line number. The file
1366    offset to the current line is maintained in filepos. */    offset to the current line is maintained in filepos. */
1367    
1368    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1369    filepos += linelength + endlinelength;    filepos += (int)(linelength + endlinelength);
1370    linenumber++;    linenumber++;
1371    
1372      /* If input is line buffered, and the buffer is not yet full, read another
1373      line and add it into the buffer. */
1374    
1375      if (input_line_buffered && bufflength < sizeof(buffer))
1376        {
1377        int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);
1378        bufflength += add;
1379        endptr += add;
1380        }
1381    
1382    /* 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
1383    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
1384    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 1207  while (ptr < endptr) Line 1398  while (ptr < endptr)
1398    
1399      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1400      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1401      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);  
1402    #ifdef SUPPORT_LIBZ
1403        if (frtype == FR_LIBZ)
1404          bufflength = 2*MBUFTHIRD +
1405            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1406        else
1407    #endif
1408    
1409    #ifdef SUPPORT_LIBBZ2
1410        if (frtype == FR_LIBBZ2)
1411          bufflength = 2*MBUFTHIRD +
1412            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1413        else
1414    #endif
1415    
1416        bufflength = 2*MBUFTHIRD +
1417          (input_line_buffered?
1418           read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :
1419           fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));
1420      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1421    
1422      /* Adjust any last match point */      /* Adjust any last match point */
# Line 1238  if (filenames == FN_NOMATCH_ONLY) Line 1447  if (filenames == FN_NOMATCH_ONLY)
1447    
1448  if (count_only)  if (count_only)
1449    {    {
1450    if (printname != NULL) fprintf(stdout, "%s:", printname);    if (count > 0 || !omit_zero_count)
1451    fprintf(stdout, "%d\n", count);      {
1452        if (printname != NULL && filenames != FN_NONE)
1453          fprintf(stdout, "%s:", printname);
1454        fprintf(stdout, "%d\n", count);
1455        }
1456    }    }
1457    
1458  return rc;  return rc;
# Line 1271  grep_or_recurse(char *pathname, BOOL dir Line 1484  grep_or_recurse(char *pathname, BOOL dir
1484  {  {
1485  int rc = 1;  int rc = 1;
1486  int sep;  int sep;
1487  FILE *in;  int frtype;
1488    int pathlen;
1489    void *handle;
1490    FILE *in = NULL;           /* Ensure initialized */
1491    
1492    #ifdef SUPPORT_LIBZ
1493    gzFile ingz = NULL;
1494    #endif
1495    
1496    #ifdef SUPPORT_LIBBZ2
1497    BZFILE *inbz2 = NULL;
1498    #endif
1499    
1500  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1501    
1502  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1503    {    {
1504    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1505      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1506        stdin_name : NULL);        stdin_name : NULL);
1507    }    }
1508    
   
1509  /* 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
1510  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
1511  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
1512    system-specific. */
1513    
1514  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1515    {    {
# Line 1306  if ((sep = isdirectory(pathname)) != 0) Line 1530  if ((sep = isdirectory(pathname)) != 0)
1530    
1531      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1532        {        {
1533        int frc, blen;        int frc, nflen;
1534        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1535        blen = strlen(buffer);        nflen = (int)(strlen(nextfile));
1536    
1537          if (isdirectory(buffer))
1538            {
1539            if (exclude_dir_compiled != NULL &&
1540                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1541              continue;
1542    
1543        if (exclude_compiled != NULL &&          if (include_dir_compiled != NULL &&
1544            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)              pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1545          continue;            continue;
1546            }
1547        if (include_compiled != NULL &&        else
1548            pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)          {
1549          continue;          if (exclude_compiled != NULL &&
1550                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1551              continue;
1552    
1553            if (include_compiled != NULL &&
1554                pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1555              continue;
1556            }
1557    
1558        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1559        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 1339  skipping was not requested. The scan pro Line 1576  skipping was not requested. The scan pro
1576  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
1577  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1578    
1579  in = fopen(pathname, "r");  pathlen = (int)(strlen(pathname));
1580  if (in == NULL)  
1581    /* Open using zlib if it is supported and the file name ends with .gz. */
1582    
1583    #ifdef SUPPORT_LIBZ
1584    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1585      {
1586      ingz = gzopen(pathname, "rb");
1587      if (ingz == NULL)
1588        {
1589        if (!silent)
1590          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1591            strerror(errno));
1592        return 2;
1593        }
1594      handle = (void *)ingz;
1595      frtype = FR_LIBZ;
1596      }
1597    else
1598    #endif
1599    
1600    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1601    
1602    #ifdef SUPPORT_LIBBZ2
1603    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1604      {
1605      inbz2 = BZ2_bzopen(pathname, "rb");
1606      handle = (void *)inbz2;
1607      frtype = FR_LIBBZ2;
1608      }
1609    else
1610    #endif
1611    
1612    /* Otherwise use plain fopen(). The label is so that we can come back here if
1613    an attempt to read a .bz2 file indicates that it really is a plain file. */
1614    
1615    #ifdef SUPPORT_LIBBZ2
1616    PLAIN_FILE:
1617    #endif
1618      {
1619      in = fopen(pathname, "rb");
1620      handle = (void *)in;
1621      frtype = FR_PLAIN;
1622      }
1623    
1624    /* All the opening methods return errno when they fail. */
1625    
1626    if (handle == NULL)
1627    {    {
1628    if (!silent)    if (!silent)
1629      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 1348  if (in == NULL) Line 1631  if (in == NULL)
1631    return 2;    return 2;
1632    }    }
1633    
1634  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1635    
1636    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1637    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1638    
1639    /* Close in an appropriate manner. */
1640    
1641    #ifdef SUPPORT_LIBZ
1642    if (frtype == FR_LIBZ)
1643      gzclose(ingz);
1644    else
1645    #endif
1646    
1647    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1648    read failed. If the error indicates that the file isn't in fact bzipped, try
1649    again as a normal file. */
1650    
1651    #ifdef SUPPORT_LIBBZ2
1652    if (frtype == FR_LIBBZ2)
1653      {
1654      if (rc == 2)
1655        {
1656        int errnum;
1657        const char *err = BZ2_bzerror(inbz2, &errnum);
1658        if (errnum == BZ_DATA_ERROR_MAGIC)
1659          {
1660          BZ2_bzclose(inbz2);
1661          goto PLAIN_FILE;
1662          }
1663        else if (!silent)
1664          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1665            pathname, err);
1666        }
1667      BZ2_bzclose(inbz2);
1668      }
1669    else
1670    #endif
1671    
1672    /* Normal file close */
1673    
1674  fclose(in);  fclose(in);
1675    
1676    /* Pass back the yield from pcregrep(). */
1677    
1678  return rc;  return rc;
1679  }  }
1680    
# Line 1392  option_item *op; Line 1715  option_item *op;
1715  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1716  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1717  printf("PATTERN must be present if neither -e nor -f is used.\n");  printf("PATTERN must be present if neither -e nor -f is used.\n");
1718  printf("\"-\" can be used as a file name to mean STDIN.\n\n");  printf("\"-\" can be used as a file name to mean STDIN.\n");
1719  printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
1720    #ifdef SUPPORT_LIBZ
1721    printf("Files whose names end in .gz are read using zlib.\n");
1722    #endif
1723    
1724    #ifdef SUPPORT_LIBBZ2
1725    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1726    #endif
1727    
1728    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1729    printf("Other files and the standard input are read as plain files.\n\n");
1730    #else
1731    printf("All files are read as plain files, without any interpretation.\n\n");
1732    #endif
1733    
1734    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1735  printf("Options:\n");  printf("Options:\n");
1736    
1737  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
# Line 1402  for (op = optionlist; op->one_char != 0; Line 1739  for (op = optionlist; op->one_char != 0;
1739    int n;    int n;
1740    char s[4];    char s[4];
1741    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, "   ");
1742    printf("  %s --%s%n", s, op->long_name, &n);    n = 30 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1743    if (n < 1) n = 1;    if (n < 1) n = 1;
1744    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                    ", op->help_text);
1745    }    }
# Line 1428  handle_option(int letter, int options) Line 1764  handle_option(int letter, int options)
1764  {  {
1765  switch(letter)  switch(letter)
1766    {    {
1767    case N_FOFFSETS: file_offsets = TRUE; break;    case N_FOFFSETS: file_offsets = TRUE; break;
1768    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1769    case N_LOFFSETS: line_offsets = number = TRUE; break;    case N_LOFFSETS: line_offsets = number = TRUE; break;
1770      case N_LBUFFER: line_buffered = TRUE; break;
1771    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1772    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1773    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1774    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1775    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1776    case 'l': filenames = FN_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1777    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1778    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1779    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
# Line 1621  const char *error; Line 1958  const char *error;
1958    
1959  /* 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;
1960  "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".
1961  */  Note that the return values from pcre_config(), though derived from the ASCII
1962    codes, are the same in EBCDIC environments, so we must use the actual values
1963    rather than escapes such as as '\r'. */
1964    
1965  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
1966  switch(i)  switch(i)
1967    {    {
1968    default:                 newline = (char *)"lf"; break;    default:               newline = (char *)"lf"; break;
1969    case '\r':               newline = (char *)"cr"; break;    case 13:               newline = (char *)"cr"; break;
1970    case ('\r' << 8) | '\n': newline = (char *)"crlf"; break;    case (13 << 8) | 10:   newline = (char *)"crlf"; break;
1971    case -1:                 newline = (char *)"any"; break;    case -1:               newline = (char *)"any"; break;
1972    case -2:                 newline = (char *)"anycrlf"; break;    case -2:               newline = (char *)"anycrlf"; break;
1973    }    }
1974    
1975  /* Process the options */  /* Process the options */
# Line 1672  for (i = 1; i < argc; i++) Line 2011  for (i = 1; i < argc; i++)
2011      Some options have variations in the long name spelling: specifically, we      Some options have variations in the long name spelling: specifically, we
2012      allow "regexp" because GNU grep allows it, though I personally go along      allow "regexp" because GNU grep allows it, though I personally go along
2013      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
2014      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
2015      these categories, fortunately. */      both these categories. */
2016    
2017      for (op = optionlist; op->one_char != 0; op++)      for (op = optionlist; op->one_char != 0; op++)
2018        {        {
2019        char *opbra = strchr(op->long_name, '(');        char *opbra = strchr(op->long_name, '(');
2020        char *equals = strchr(op->long_name, '=');        char *equals = strchr(op->long_name, '=');
2021        if (opbra == NULL)     /* Not a (p) case */  
2022          /* Handle options with only one spelling of the name */
2023    
2024          if (opbra == NULL)     /* Does not contain '(' */
2025          {          {
2026          if (equals == NULL)  /* Not thing=data case */          if (equals == NULL)  /* Not thing=data case */
2027            {            {
# Line 1687  for (i = 1; i < argc; i++) Line 2029  for (i = 1; i < argc; i++)
2029            }            }
2030          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
2031            {            {
2032            int oplen = equals - op->long_name;            int oplen = (int)(equals - op->long_name);
2033            int arglen = (argequals == NULL)? (int)strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)?
2034                (int)strlen(arg) : (int)(argequals - arg);
2035            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
2036              {              {
2037              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1701  for (i = 1; i < argc; i++) Line 2044  for (i = 1; i < argc; i++)
2044              }              }
2045            }            }
2046          }          }
2047        else                   /* Special case xxxx(p) */  
2048          /* Handle options with an alternate spelling of the name */
2049    
2050          else
2051          {          {
2052          char buff1[24];          char buff1[24];
2053          char buff2[24];          char buff2[24];
2054          int baselen = opbra - op->long_name;  
2055            int baselen = (int)(opbra - op->long_name);
2056            int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
2057            int arglen = (argequals == NULL || equals == NULL)?
2058              (int)strlen(arg) : (int)(argequals - arg);
2059    
2060          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
2061          sprintf(buff2, "%s%.*s", buff1,          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
2062            (int)strlen(op->long_name) - baselen - 2, opbra + 1);  
2063          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strncmp(arg, buff1, arglen) == 0 ||
2064               strncmp(arg, buff2, arglen) == 0)
2065              {
2066              if (equals != NULL && argequals != NULL)
2067                {
2068                option_data = argequals;
2069                if (*option_data == '=')
2070                  {
2071                  option_data++;
2072                  longopwasequals = TRUE;
2073                  }
2074                }
2075            break;            break;
2076              }
2077          }          }
2078        }        }
2079    
# Line 1721  for (i = 1; i < argc; i++) Line 2084  for (i = 1; i < argc; i++)
2084        }        }
2085      }      }
2086    
   
2087    /* Jeffrey Friedl's debugging harness uses these additional options which    /* Jeffrey Friedl's debugging harness uses these additional options which
2088    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
2089    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 1835  for (i = 1; i < argc; i++) Line 2197  for (i = 1; i < argc; i++)
2197      {      {
2198      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2199      }      }
2200    
2201      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2202      only for unpicking arguments, so just keep it simple. */
2203    
2204    else    else
2205      {      {
2206      char *endptr;      int n = 0;
2207      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2208        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2209        while (isdigit((unsigned char)(*endptr)))
2210          n = n * 10 + (int)(*endptr++ - '0');
2211      if (*endptr != 0)      if (*endptr != 0)
2212        {        {
2213        if (longop)        if (longop)
2214          {          {
2215          char *equals = strchr(op->long_name, '=');          char *equals = strchr(op->long_name, '=');
2216          int nlen = (equals == NULL)? (int)strlen(op->long_name) :          int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2217            equals - op->long_name;            (int)(equals - op->long_name);
2218          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2219            option_data, nlen, op->long_name);            option_data, nlen, op->long_name);
2220          }          }
# Line 1866  if (both_context > 0) Line 2235  if (both_context > 0)
2235    if (after_context == 0) after_context = both_context;    if (after_context == 0) after_context = both_context;
2236    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2237    }    }
2238    
2239  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2240  However, the latter two set the only_matching flag. */  However, the latter two set the only_matching flag. */
2241    
2242  if ((only_matching && (file_offsets || line_offsets)) ||  if ((only_matching && (file_offsets || line_offsets)) ||
2243      (file_offsets && line_offsets))      (file_offsets && line_offsets))
2244    {    {
2245    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2246      "and/or --line-offsets\n");      "and/or --line-offsets\n");
2247    exit(usage(2));    exit(usage(2));
2248    }    }
2249    
2250  if (file_offsets || line_offsets) only_matching = TRUE;  if (file_offsets || line_offsets) only_matching = TRUE;
2251    
2252  /* 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
2253  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
# Line 2113  if (include_pattern != NULL) Line 2482  if (include_pattern != NULL)
2482      }      }
2483    }    }
2484    
2485    if (exclude_dir_pattern != NULL)
2486      {
2487      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2488        pcretables);
2489      if (exclude_dir_compiled == NULL)
2490        {
2491        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2492          errptr, error);
2493        goto EXIT2;
2494        }
2495      }
2496    
2497    if (include_dir_pattern != NULL)
2498      {
2499      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2500        pcretables);
2501      if (include_dir_compiled == NULL)
2502        {
2503        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2504          errptr, error);
2505        goto EXIT2;
2506        }
2507      }
2508    
2509  /* 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. */
2510    
2511  if (i >= argc)  if (i >= argc)
2512    {    {
2513    rc = pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2514    goto EXIT;    goto EXIT;
2515    }    }
2516    

Legend:
Removed from v.283  
changed lines
  Added in v.558

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12