/[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 199 by ph10, Tue Jul 31 14:39:09 2007 UTC revision 515 by ph10, Tue May 4 09:12:25 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 38  POSSIBILITY OF SUCH DAMAGE. Line 38  POSSIBILITY OF SUCH DAMAGE.
38  */  */
39    
40  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
41  #include <config.h>  #include "config.h"
42  #endif  #endif
43    
44  #include <ctype.h>  #include <ctype.h>
# Line 55  POSSIBILITY OF SUCH DAMAGE. Line 55  POSSIBILITY OF SUCH DAMAGE.
55  #include <unistd.h>  #include <unistd.h>
56  #endif  #endif
57    
58  #include <pcre.h>  #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"
67    
68  #define FALSE 0  #define FALSE 0
69  #define TRUE 1  #define TRUE 1
# 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 142  static int process_options = 0; Line 167  static int process_options = 0;
167    
168  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
169  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
170    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_offsets = FALSE;
174  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
175  static BOOL number = FALSE;  static BOOL number = FALSE;
176    static BOOL omit_zero_count = FALSE;
177  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
178  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
179  static BOOL silent = FALSE;  static BOOL silent = FALSE;
# Line 167  typedef struct option_item { Line 195  typedef struct option_item {
195  /* 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
196  used to identify them. */  used to identify them. */
197    
198  #define N_COLOUR    (-1)  #define N_COLOUR       (-1)
199  #define N_EXCLUDE   (-2)  #define N_EXCLUDE      (-2)
200  #define N_HELP      (-3)  #define N_EXCLUDE_DIR  (-3)
201  #define N_INCLUDE   (-4)  #define N_HELP         (-4)
202  #define N_LABEL     (-5)  #define N_INCLUDE      (-5)
203  #define N_LOCALE    (-6)  #define N_INCLUDE_DIR  (-6)
204  #define N_NULL      (-7)  #define N_LABEL        (-7)
205    #define N_LOCALE       (-8)
206    #define N_NULL         (-9)
207    #define N_LOFFSETS     (-10)
208    #define N_FOFFSETS     (-11)
209    
210  static option_item optionlist[] = {  static option_item optionlist[] = {
211    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 186  static option_item optionlist[] = { Line 218  static option_item optionlist[] = {
218    { 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" },
219    { 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" },
220    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },
221    { 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)" },
222    { 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" },
223    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
224      { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
225    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
226    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
227    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
228    { 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" },
229    { 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" },
230    { 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" },
231      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
232    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
233    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
234    { OP_STRING,    'N',      &newline,          "newline=type",  "specify newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
235    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
236    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },
237    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
238    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },
239    { 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" },
240    { 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" },
241      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
242      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
243  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
244    { 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" },
245  #endif  #endif
# Line 316  return isatty(fileno(stdout)); Line 352  return isatty(fileno(stdout));
352    
353  /* 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
354  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
355  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
356    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
357    */
358    
359  #elif HAVE_WINDOWS_H  #elif HAVE_WINDOWS_H
360    
# Line 327  when it did not exist. */ Line 364  when it did not exist. */
364  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
365  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
366  #endif  #endif
367    
368    #include <windows.h>
369    
370  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
371  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
372  #endif  #endif
373    
 #include <windows.h>  
   
374  typedef struct directory_type  typedef struct directory_type
375  {  {
376  HANDLE handle;  HANDLE handle;
# Line 417  regular if they are not directories. */ Line 455  regular if they are not directories. */
455    
456  int isregfile(char *filename)  int isregfile(char *filename)
457  {  {
458  return !isdirectory(filename)  return !isdirectory(filename);
459  }  }
460    
461    
# Line 428  return !isdirectory(filename) Line 466  return !isdirectory(filename)
466  static BOOL  static BOOL
467  is_stdout_tty(void)  is_stdout_tty(void)
468  {  {
469  FALSE;  return FALSE;
470  }  }
471    
472    
# Line 783  if (after_context > 0 && lastmatchnumber Line 821  if (after_context > 0 && lastmatchnumber
821      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
822      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
823      pp = end_of_line(pp, endptr, &ellength);      pp = end_of_line(pp, endptr, &ellength);
824      fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);      FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
825      lastmatchrestart = pp;      lastmatchrestart = pp;
826      }      }
827    hyphenpending = TRUE;    hyphenpending = TRUE;
# Line 793  if (after_context > 0 && lastmatchnumber Line 831  if (after_context > 0 && lastmatchnumber
831    
832    
833  /*************************************************  /*************************************************
834    *   Apply patterns to subject till one matches   *
835    *************************************************/
836    
837    /* This function is called to run through all patterns, looking for a match. It
838    is used multiple times for the same subject when colouring is enabled, in order
839    to find all possible matches.
840    
841    Arguments:
842      matchptr    the start of the subject
843      length      the length of the subject to match
844      offsets     the offets vector to fill in
845      mrc         address of where to put the result of pcre_exec()
846    
847    Returns:      TRUE if there was a match
848                  FALSE if there was no match
849                  invert if there was a non-fatal error
850    */
851    
852    static BOOL
853    match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)
854    {
855    int i;
856    for (i = 0; i < pattern_count; i++)
857      {
858      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0,
859        PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
860      if (*mrc >= 0) return TRUE;
861      if (*mrc == PCRE_ERROR_NOMATCH) continue;
862      fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);
863      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
864      fprintf(stderr, "this text:\n");
865      FWRITE(matchptr, 1, length, stderr);   /* In case binary zero included */
866      fprintf(stderr, "\n");
867      if (error_count == 0 &&
868          (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT))
869        {
870        fprintf(stderr, "pcregrep: error %d means that a resource limit "
871          "was exceeded\n", *mrc);
872        fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");
873        }
874      if (error_count++ > 20)
875        {
876        fprintf(stderr, "pcregrep: too many errors - abandoned\n");
877        exit(2);
878        }
879      return invert;    /* No more matching; don't show the line again */
880      }
881    
882    return FALSE;  /* No match, no errors */
883    }
884    
885    
886    
887    /*************************************************
888  *            Grep an individual file             *  *            Grep an individual file             *
889  *************************************************/  *************************************************/
890    
# Line 804  be in the middle third most of the time, Line 896  be in the middle third most of the time,
896  "before" context printing.  "before" context printing.
897    
898  Arguments:  Arguments:
899    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
900                   the gzFile pointer when reading is via libz
901                   the BZFILE pointer when reading is via libbz2
902      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
903    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
904                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
905                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
906    
907  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
908                 1 otherwise (no matches)                 1 otherwise (no matches)
909                   2 if there is a read error on a .bz2 file
910  */  */
911    
912  static int  static int
913  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
914  {  {
915  int rc = 1;  int rc = 1;
916  int linenumber = 1;  int linenumber = 1;
917  int lastmatchnumber = 0;  int lastmatchnumber = 0;
918  int count = 0;  int count = 0;
919  int offsets[99];  int filepos = 0;
920    int offsets[OFFSET_SIZE];
921  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
922  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
923  char *ptr = buffer;  char *ptr = buffer;
924  char *endptr;  char *endptr;
925  size_t bufflength;  size_t bufflength;
926  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
927    FILE *in = NULL;                    /* Ensure initialized */
928    
929    #ifdef SUPPORT_LIBZ
930    gzFile ingz = NULL;
931    #endif
932    
933  /* Do the first read into the start of the buffer and set up the pointer to  #ifdef SUPPORT_LIBBZ2
934  end of what we have. */  BZFILE *inbz2 = NULL;
935    #endif
936    
937    
938    /* Do the first read into the start of the buffer and set up the pointer to end
939    of what we have. In the case of libz, a non-zipped .gz file will be read as a
940    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
941    fail. */
942    
943    #ifdef SUPPORT_LIBZ
944    if (frtype == FR_LIBZ)
945      {
946      ingz = (gzFile)handle;
947      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
948      }
949    else
950    #endif
951    
952    #ifdef SUPPORT_LIBBZ2
953    if (frtype == FR_LIBBZ2)
954      {
955      inbz2 = (BZFILE *)handle;
956      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
957      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
958      }                                    /* without the cast it is unsigned. */
959    else
960    #endif
961    
962      {
963      in = (FILE *)handle;
964      bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);
965      }
966    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
967  endptr = buffer + bufflength;  endptr = buffer + bufflength;
968    
969  /* 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 841  way, the buffer is shifted left and re-f Line 973  way, the buffer is shifted left and re-f
973    
974  while (ptr < endptr)  while (ptr < endptr)
975    {    {
976    int i, endlinelength;    int endlinelength;
977    int mrc = 0;    int mrc = 0;
978    BOOL match = FALSE;    BOOL match;
979      char *matchptr = ptr;
980    char *t = ptr;    char *t = ptr;
981    size_t length, linelength;    size_t length, linelength;
982    
983    /* 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
984    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
985    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
986    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
987    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
988    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
989      first line. */
990    
991    t = end_of_line(t, endptr, &endlinelength);    t = end_of_line(t, endptr, &endlinelength);
992    linelength = t - ptr - endlinelength;    linelength = t - ptr - endlinelength;
# Line 867  while (ptr < endptr) Line 1001  while (ptr < endptr)
1001        #include <time.h>        #include <time.h>
1002        struct timeval start_time, end_time;        struct timeval start_time, end_time;
1003        struct timezone dummy;        struct timezone dummy;
1004          int i;
1005    
1006        if (jfriedl_XT)        if (jfriedl_XT)
1007        {        {
# Line 892  while (ptr < endptr) Line 1027  while (ptr < endptr)
1027    
1028    
1029        for (i = 0; i < jfriedl_XR; i++)        for (i = 0; i < jfriedl_XR; i++)
1030            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,
1031                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1032    
1033        if (gettimeofday(&end_time, &dummy) != 0)        if (gettimeofday(&end_time, &dummy) != 0)
1034                perror("bad gettimeofday");                perror("bad gettimeofday");
# Line 906  while (ptr < endptr) Line 1042  while (ptr < endptr)
1042    }    }
1043  #endif  #endif
1044    
1045      /* We come back here after a match when the -o option (only_matching) is set,
1046      in order to find any further matches in the same line. */
1047    
1048    /* Run through all the patterns until one matches. Note that we don't include    ONLY_MATCHING_RESTART:
   the final newline in the subject string. */  
1049    
1050    for (i = 0; i < pattern_count; i++)    /* Run through all the patterns until one matches or there is an error other
1051      {    than NOMATCH. This code is in a subroutine so that it can be re-used for
1052      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,    finding subsequent matches when colouring matched lines. */
1053        offsets, 99);  
1054      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(ptr, 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;  
       }  
     }  
1055    
1056    /* 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. */
1057    
# Line 956  while (ptr < endptr) Line 1070  while (ptr < endptr)
1070      /* 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
1071      in the file. */      in the file. */
1072    
1073      else if (filenames == FN_ONLY)      else if (filenames == FN_MATCH_ONLY)
1074        {        {
1075        fprintf(stdout, "%s\n", printname);        fprintf(stdout, "%s\n", printname);
1076        return 0;        return 0;
# Line 967  while (ptr < endptr) Line 1081  while (ptr < endptr)
1081      else if (quiet) return 0;      else if (quiet) return 0;
1082    
1083      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
1084      does not pring any context. */      the --file-offsets and --line-offsets options output offsets for the
1085        matching substring (they both force --only-matching). None of these options
1086        prints any context. Afterwards, adjust the start and length, and then jump
1087        back to look for further matches in the same line. If we are in invert
1088        mode, however, nothing is printed - this could be still useful because the
1089        return code is set. */
1090    
1091      else if (only_matching)      else if (only_matching)
1092        {        {
1093        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
1094        if (number) fprintf(stdout, "%d:", linenumber);          {
1095        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1096        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
1097            if (line_offsets)
1098              fprintf(stdout, "%d,%d", (int)(matchptr + offsets[0] - ptr),
1099                offsets[1] - offsets[0]);
1100            else if (file_offsets)
1101              fprintf(stdout, "%d,%d", (int)(filepos + matchptr + offsets[0] - ptr),
1102                offsets[1] - offsets[0]);
1103            else
1104              {
1105              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1106              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1107              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1108              }
1109            fprintf(stdout, "\n");
1110            matchptr += offsets[1];
1111            length -= offsets[1];
1112            match = FALSE;
1113            goto ONLY_MATCHING_RESTART;
1114            }
1115        }        }
1116    
1117      /* 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 1008  while (ptr < endptr) Line 1145  while (ptr < endptr)
1145            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1146            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1147            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1148            fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);            FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1149            lastmatchrestart = pp;            lastmatchrestart = pp;
1150            }            }
1151          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
# Line 1048  while (ptr < endptr) Line 1185  while (ptr < endptr)
1185            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1186            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1187            pp = end_of_line(pp, endptr, &ellength);            pp = end_of_line(pp, endptr, &ellength);
1188            fwrite(p, 1, pp - p, stdout);            FWRITE(p, 1, pp - p, stdout);
1189            p = pp;            p = pp;
1190            }            }
1191          }          }
# Line 1064  while (ptr < endptr) Line 1201  while (ptr < endptr)
1201    
1202        /* In multiline mode, we want to print to the end of the line in which        /* In multiline mode, we want to print to the end of the line in which
1203        the end of the matched string is found, so we adjust linelength and the        the end of the matched string is found, so we adjust linelength and the
1204        line number appropriately. Because the PCRE_FIRSTLINE option is set, the        line number appropriately, but only when there actually was a match
1205        start of the match will always be before the first newline sequence. */        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1206          the match will always be before the first newline sequence. */
1207    
1208        if (multiline)        if (multiline)
1209          {          {
1210          int ellength;          int ellength;
1211          char *endmatch = ptr + offsets[1];          char *endmatch = ptr;
1212          t = ptr;          if (!invert)
         while (t < endmatch)  
1213            {            {
1214            t = end_of_line(t, endptr, &ellength);            endmatch += offsets[1];
1215            if (t <= endmatch) linenumber++; else break;            t = ptr;
1216              while (t < endmatch)
1217                {
1218                t = end_of_line(t, endptr, &ellength);
1219                if (t <= endmatch) linenumber++; else break;
1220                }
1221            }            }
1222          endmatch = end_of_line(endmatch, endptr, &ellength);          endmatch = end_of_line(endmatch, endptr, &ellength);
1223          linelength = endmatch - ptr - ellength;          linelength = endmatch - ptr - ellength;
# Line 1093  while (ptr < endptr) Line 1235  while (ptr < endptr)
1235          {          {
1236          int first = S_arg * 2;          int first = S_arg * 2;
1237          int last  = first + 1;          int last  = first + 1;
1238          fwrite(ptr, 1, offsets[first], stdout);          FWRITE(ptr, 1, offsets[first], stdout);
1239          fprintf(stdout, "X");          fprintf(stdout, "X");
1240          fwrite(ptr + offsets[last], 1, linelength - offsets[last], stdout);          FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1241          }          }
1242        else        else
1243  #endif  #endif
1244    
1245        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1246          matches. */
1247    
1248        if (do_colour)        if (do_colour)
1249          {          {
1250          fwrite(ptr, 1, offsets[0], stdout);          int last_offset = 0;
1251            FWRITE(ptr, 1, offsets[0], stdout);
1252          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1253          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1254          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1255          fwrite(ptr + offsets[1], 1, linelength - offsets[1], stdout);          for (;;)
1256              {
1257              last_offset += offsets[1];
1258              matchptr += offsets[1];
1259              length -= offsets[1];
1260              if (!match_patterns(matchptr, length, offsets, &mrc)) break;
1261              FWRITE(matchptr, 1, offsets[0], stdout);
1262              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1263              FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1264              fprintf(stdout, "%c[00m", 0x1b);
1265              }
1266            FWRITE(ptr + last_offset, 1,
1267              (linelength + endlinelength) - last_offset, stdout);
1268          }          }
1269        else fwrite(ptr, 1, linelength + endlinelength, stdout);  
1270          /* Not colouring; no need to search for further matches */
1271    
1272          else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1273        }        }
1274    
1275      /* End of doing what has to be done for a match */      /* End of doing what has to be done for a match */
# Line 1124  while (ptr < endptr) Line 1283  while (ptr < endptr)
1283      lastmatchnumber = linenumber + 1;      lastmatchnumber = linenumber + 1;
1284      }      }
1285    
1286    /* Advance to after the newline and increment the line number. */    /* For a match in multiline inverted mode (which of course did not cause
1287      anything to be printed), we have to move on to the end of the match before
1288      proceeding. */
1289    
1290      if (multiline && invert && match)
1291        {
1292        int ellength;
1293        char *endmatch = ptr + offsets[1];
1294        t = ptr;
1295        while (t < endmatch)
1296          {
1297          t = end_of_line(t, endptr, &ellength);
1298          if (t <= endmatch) linenumber++; else break;
1299          }
1300        endmatch = end_of_line(endmatch, endptr, &ellength);
1301        linelength = endmatch - ptr - ellength;
1302        }
1303    
1304      /* Advance to after the newline and increment the line number. The file
1305      offset to the current line is maintained in filepos. */
1306    
1307    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1308      filepos += linelength + endlinelength;
1309    linenumber++;    linenumber++;
1310    
1311    /* 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
# Line 1148  while (ptr < endptr) Line 1327  while (ptr < endptr)
1327    
1328      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1329      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1330    
1331    #ifdef SUPPORT_LIBZ
1332        if (frtype == FR_LIBZ)
1333          bufflength = 2*MBUFTHIRD +
1334            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1335        else
1336    #endif
1337    
1338    #ifdef SUPPORT_LIBBZ2
1339        if (frtype == FR_LIBBZ2)
1340          bufflength = 2*MBUFTHIRD +
1341            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1342        else
1343    #endif
1344    
1345      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);
1346    
1347      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1348    
1349      /* Adjust any last match point */      /* Adjust any last match point */
# Line 1179  if (filenames == FN_NOMATCH_ONLY) Line 1374  if (filenames == FN_NOMATCH_ONLY)
1374    
1375  if (count_only)  if (count_only)
1376    {    {
1377    if (printname != NULL) fprintf(stdout, "%s:", printname);    if (count > 0 || !omit_zero_count)
1378    fprintf(stdout, "%d\n", count);      {
1379        if (printname != NULL && filenames != FN_NONE)
1380          fprintf(stdout, "%s:", printname);
1381        fprintf(stdout, "%d\n", count);
1382        }
1383    }    }
1384    
1385  return rc;  return rc;
# Line 1212  grep_or_recurse(char *pathname, BOOL dir Line 1411  grep_or_recurse(char *pathname, BOOL dir
1411  {  {
1412  int rc = 1;  int rc = 1;
1413  int sep;  int sep;
1414  FILE *in;  int frtype;
1415    int pathlen;
1416    void *handle;
1417    FILE *in = NULL;           /* Ensure initialized */
1418    
1419    #ifdef SUPPORT_LIBZ
1420    gzFile ingz = NULL;
1421    #endif
1422    
1423    #ifdef SUPPORT_LIBBZ2
1424    BZFILE *inbz2 = NULL;
1425    #endif
1426    
1427  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1428    
1429  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1430    {    {
1431    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1432      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1433        stdin_name : NULL);        stdin_name : NULL);
1434    }    }
1435    
   
1436  /* 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
1437  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
1438  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
1439    system-specific. */
1440    
1441  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1442    {    {
# Line 1247  if ((sep = isdirectory(pathname)) != 0) Line 1457  if ((sep = isdirectory(pathname)) != 0)
1457    
1458      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1459        {        {
1460        int frc, blen;        int frc, nflen;
1461        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1462        blen = strlen(buffer);        nflen = strlen(nextfile);
1463    
1464          if (isdirectory(buffer))
1465            {
1466            if (exclude_dir_compiled != NULL &&
1467                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1468              continue;
1469    
1470        if (exclude_compiled != NULL &&          if (include_dir_compiled != NULL &&
1471            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)
1472          continue;            continue;
1473            }
1474        if (include_compiled != NULL &&        else
1475            pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)          {
1476          continue;          if (exclude_compiled != NULL &&
1477                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1478              continue;
1479    
1480            if (include_compiled != NULL &&
1481                pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1482              continue;
1483            }
1484    
1485        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1486        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 1280  skipping was not requested. The scan pro Line 1503  skipping was not requested. The scan pro
1503  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
1504  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1505    
1506  in = fopen(pathname, "r");  pathlen = strlen(pathname);
1507  if (in == NULL)  
1508    /* Open using zlib if it is supported and the file name ends with .gz. */
1509    
1510    #ifdef SUPPORT_LIBZ
1511    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1512      {
1513      ingz = gzopen(pathname, "rb");
1514      if (ingz == NULL)
1515        {
1516        if (!silent)
1517          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1518            strerror(errno));
1519        return 2;
1520        }
1521      handle = (void *)ingz;
1522      frtype = FR_LIBZ;
1523      }
1524    else
1525    #endif
1526    
1527    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1528    
1529    #ifdef SUPPORT_LIBBZ2
1530    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1531      {
1532      inbz2 = BZ2_bzopen(pathname, "rb");
1533      handle = (void *)inbz2;
1534      frtype = FR_LIBBZ2;
1535      }
1536    else
1537    #endif
1538    
1539    /* Otherwise use plain fopen(). The label is so that we can come back here if
1540    an attempt to read a .bz2 file indicates that it really is a plain file. */
1541    
1542    #ifdef SUPPORT_LIBBZ2
1543    PLAIN_FILE:
1544    #endif
1545      {
1546      in = fopen(pathname, "rb");
1547      handle = (void *)in;
1548      frtype = FR_PLAIN;
1549      }
1550    
1551    /* All the opening methods return errno when they fail. */
1552    
1553    if (handle == NULL)
1554    {    {
1555    if (!silent)    if (!silent)
1556      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 1289  if (in == NULL) Line 1558  if (in == NULL)
1558    return 2;    return 2;
1559    }    }
1560    
1561  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1562    
1563    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1564    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1565    
1566    /* Close in an appropriate manner. */
1567    
1568    #ifdef SUPPORT_LIBZ
1569    if (frtype == FR_LIBZ)
1570      gzclose(ingz);
1571    else
1572    #endif
1573    
1574    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1575    read failed. If the error indicates that the file isn't in fact bzipped, try
1576    again as a normal file. */
1577    
1578    #ifdef SUPPORT_LIBBZ2
1579    if (frtype == FR_LIBBZ2)
1580      {
1581      if (rc == 2)
1582        {
1583        int errnum;
1584        const char *err = BZ2_bzerror(inbz2, &errnum);
1585        if (errnum == BZ_DATA_ERROR_MAGIC)
1586          {
1587          BZ2_bzclose(inbz2);
1588          goto PLAIN_FILE;
1589          }
1590        else if (!silent)
1591          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1592            pathname, err);
1593        }
1594      BZ2_bzclose(inbz2);
1595      }
1596    else
1597    #endif
1598    
1599    /* Normal file close */
1600    
1601  fclose(in);  fclose(in);
1602    
1603    /* Pass back the yield from pcregrep(). */
1604    
1605  return rc;  return rc;
1606  }  }
1607    
# Line 1313  for (op = optionlist; op->one_char != 0; Line 1622  for (op = optionlist; op->one_char != 0;
1622    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1623    }    }
1624  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1625  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1626      "options.\n");
1627  return rc;  return rc;
1628  }  }
1629    
# Line 1332  option_item *op; Line 1642  option_item *op;
1642  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1643  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1644  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");
1645  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");
 printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
1646    
1647    #ifdef SUPPORT_LIBZ
1648    printf("Files whose names end in .gz are read using zlib.\n");
1649    #endif
1650    
1651    #ifdef SUPPORT_LIBBZ2
1652    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1653    #endif
1654    
1655    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1656    printf("Other files and the standard input are read as plain files.\n\n");
1657    #else
1658    printf("All files are read as plain files, without any interpretation.\n\n");
1659    #endif
1660    
1661    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1662  printf("Options:\n");  printf("Options:\n");
1663    
1664  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
# Line 1342  for (op = optionlist; op->one_char != 0; Line 1666  for (op = optionlist; op->one_char != 0;
1666    int n;    int n;
1667    char s[4];    char s[4];
1668    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, "   ");
1669    printf("  %s --%s%n", s, op->long_name, &n);    n = 30 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1670    if (n < 1) n = 1;    if (n < 1) n = 1;
1671    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                    ", op->help_text);
1672    }    }
# Line 1368  handle_option(int letter, int options) Line 1691  handle_option(int letter, int options)
1691  {  {
1692  switch(letter)  switch(letter)
1693    {    {
1694      case N_FOFFSETS: file_offsets = TRUE; break;
1695    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1696      case N_LOFFSETS: line_offsets = number = TRUE; break;
1697    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1698    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1699    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1700    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1701    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1702    case 'l': filenames = FN_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1703    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1704    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1705    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
# Line 1559  const char *error; Line 1884  const char *error;
1884    
1885  /* 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;
1886  "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".
1887  */  Note that the return values from pcre_config(), though derived from the ASCII
1888    codes, are the same in EBCDIC environments, so we must use the actual values
1889    rather than escapes such as as '\r'. */
1890    
1891  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
1892  switch(i)  switch(i)
1893    {    {
1894    default:                 newline = (char *)"lf"; break;    default:               newline = (char *)"lf"; break;
1895    case '\r':               newline = (char *)"cr"; break;    case 13:               newline = (char *)"cr"; break;
1896    case ('\r' << 8) | '\n': newline = (char *)"crlf"; break;    case (13 << 8) | 10:   newline = (char *)"crlf"; break;
1897    case -1:                 newline = (char *)"any"; break;    case -1:               newline = (char *)"any"; break;
1898    case -2:                 newline = (char *)"anycrlf"; break;    case -2:               newline = (char *)"anycrlf"; break;
1899    }    }
1900    
1901  /* Process the options */  /* Process the options */
# Line 1610  for (i = 1; i < argc; i++) Line 1937  for (i = 1; i < argc; i++)
1937      Some options have variations in the long name spelling: specifically, we      Some options have variations in the long name spelling: specifically, we
1938      allow "regexp" because GNU grep allows it, though I personally go along      allow "regexp" because GNU grep allows it, though I personally go along
1939      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".      with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
1940      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
1941      these categories, fortunately. */      both these categories. */
1942    
1943      for (op = optionlist; op->one_char != 0; op++)      for (op = optionlist; op->one_char != 0; op++)
1944        {        {
1945        char *opbra = strchr(op->long_name, '(');        char *opbra = strchr(op->long_name, '(');
1946        char *equals = strchr(op->long_name, '=');        char *equals = strchr(op->long_name, '=');
1947        if (opbra == NULL)     /* Not a (p) case */  
1948          /* Handle options with only one spelling of the name */
1949    
1950          if (opbra == NULL)     /* Does not contain '(' */
1951          {          {
1952          if (equals == NULL)  /* Not thing=data case */          if (equals == NULL)  /* Not thing=data case */
1953            {            {
# Line 1639  for (i = 1; i < argc; i++) Line 1969  for (i = 1; i < argc; i++)
1969              }              }
1970            }            }
1971          }          }
1972        else                   /* Special case xxxx(p) */  
1973          /* Handle options with an alternate spelling of the name */
1974    
1975          else
1976          {          {
1977          char buff1[24];          char buff1[24];
1978          char buff2[24];          char buff2[24];
1979    
1980          int baselen = opbra - op->long_name;          int baselen = opbra - op->long_name;
1981            int fulllen = strchr(op->long_name, ')') - op->long_name + 1;
1982            int arglen = (argequals == NULL || equals == NULL)?
1983              (int)strlen(arg) : argequals - arg;
1984    
1985          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
1986          sprintf(buff2, "%s%.*s", buff1,          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
1987            (int)strlen(op->long_name) - baselen - 2, opbra + 1);  
1988          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strncmp(arg, buff1, arglen) == 0 ||
1989               strncmp(arg, buff2, arglen) == 0)
1990              {
1991              if (equals != NULL && argequals != NULL)
1992                {
1993                option_data = argequals;
1994                if (*option_data == '=')
1995                  {
1996                  option_data++;
1997                  longopwasequals = TRUE;
1998                  }
1999                }
2000            break;            break;
2001              }
2002          }          }
2003        }        }
2004    
# Line 1659  for (i = 1; i < argc; i++) Line 2009  for (i = 1; i < argc; i++)
2009        }        }
2010      }      }
2011    
   
2012    /* Jeffrey Friedl's debugging harness uses these additional options which    /* Jeffrey Friedl's debugging harness uses these additional options which
2013    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
2014    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 1805  if (both_context > 0) Line 2154  if (both_context > 0)
2154    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2155    }    }
2156    
2157    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2158    However, the latter two set the only_matching flag. */
2159    
2160    if ((only_matching && (file_offsets || line_offsets)) ||
2161        (file_offsets && line_offsets))
2162      {
2163      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2164        "and/or --line-offsets\n");
2165      exit(usage(2));
2166      }
2167    
2168    if (file_offsets || line_offsets) only_matching = TRUE;
2169    
2170  /* 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
2171  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2172    
# Line 2038  if (include_pattern != NULL) Line 2400  if (include_pattern != NULL)
2400      }      }
2401    }    }
2402    
2403    if (exclude_dir_pattern != NULL)
2404      {
2405      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2406        pcretables);
2407      if (exclude_dir_compiled == NULL)
2408        {
2409        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2410          errptr, error);
2411        goto EXIT2;
2412        }
2413      }
2414    
2415    if (include_dir_pattern != NULL)
2416      {
2417      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2418        pcretables);
2419      if (include_dir_compiled == NULL)
2420        {
2421        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2422          errptr, error);
2423        goto EXIT2;
2424        }
2425      }
2426    
2427  /* 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. */
2428    
2429  if (i >= argc)  if (i >= argc)
2430    {    {
2431    rc = pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2432    goto EXIT;    goto EXIT;
2433    }    }
2434    

Legend:
Removed from v.199  
changed lines
  Added in v.515

  ViewVC Help
Powered by ViewVC 1.1.5