/[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 286 by ph10, Mon Dec 17 14:46:11 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 71  POSSIBILITY OF SUCH DAMAGE. Line 71  POSSIBILITY OF SUCH DAMAGE.
71  typedef int BOOL;  typedef int BOOL;
72    
73  #define MAX_PATTERN_COUNT 100  #define MAX_PATTERN_COUNT 100
74    #define OFFSET_SIZE 99
75    
76  #if BUFSIZ > 8192  #if BUFSIZ > 8192
77  #define MBUFTHIRD BUFSIZ  #define MBUFTHIRD BUFSIZ
# Line 82  typedef int BOOL; Line 83  typedef int BOOL;
83  output. The order is important; it is assumed that a file name is wanted for  output. The order is important; it is assumed that a file name is wanted for
84  all values greater than FN_DEFAULT. */  all values greater than FN_DEFAULT. */
85    
86  enum { FN_NONE, FN_DEFAULT, FN_ONLY, FN_NOMATCH_ONLY, FN_FORCE };  enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE };
87    
88  /* File reading styles */  /* File reading styles */
89    
# Line 103  enum { DEE_READ, DEE_SKIP }; Line 104  enum { DEE_READ, DEE_SKIP };
104    
105  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };
106    
107    /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some
108    environments), a warning is issued if the value of fwrite() is ignored.
109    Unfortunately, casting to (void) does not suppress the warning. To get round
110    this, we use a macro that compiles a fudge. Oddly, this does not also seem to
111    apply to fprintf(). */
112    
113    #define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}
114    
115    
116    
117  /*************************************************  /*************************************************
# Line 139  static pcre_extra **hints_list = NULL; Line 148  static pcre_extra **hints_list = NULL;
148    
149  static char *include_pattern = NULL;  static char *include_pattern = NULL;
150  static char *exclude_pattern = NULL;  static char *exclude_pattern = NULL;
151    static char *include_dir_pattern = NULL;
152    static char *exclude_dir_pattern = NULL;
153    
154  static pcre *include_compiled = NULL;  static pcre *include_compiled = NULL;
155  static pcre *exclude_compiled = NULL;  static pcre *exclude_compiled = NULL;
156    static pcre *include_dir_compiled = NULL;
157    static pcre *exclude_dir_compiled = NULL;
158    
159  static int after_context = 0;  static int after_context = 0;
160  static int before_context = 0;  static int before_context = 0;
# Line 160  static BOOL invert = FALSE; Line 173  static BOOL invert = FALSE;
173  static BOOL line_offsets = FALSE;  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 181  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_LOFFSETS  (-8)  #define N_LOCALE       (-8)
206  #define N_FOFFSETS  (-9)  #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 202  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" },    { 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" },
# Line 222  static option_item optionlist[] = { Line 238  static option_item optionlist[] = {
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 803  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 813  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 845  int linenumber = 1; Line 917  int linenumber = 1;
917  int lastmatchnumber = 0;  int lastmatchnumber = 0;
918  int count = 0;  int count = 0;
919  int filepos = 0;  int filepos = 0;
920  int offsets[99];  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;
# Line 901  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;    char *matchptr = ptr;
980    char *t = ptr;    char *t = ptr;
981    size_t length, linelength;    size_t length, linelength;
# Line 911  while (ptr < endptr) Line 983  while (ptr < endptr)
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 928  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 953  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 972  while (ptr < endptr) Line 1047  while (ptr < endptr)
1047    
1048    ONLY_MATCHING_RESTART:    ONLY_MATCHING_RESTART:
1049    
1050    /* Run through all the patterns until one matches. Note that we don't include    /* Run through all the patterns until one matches or there is an error other
1051    the final newline in the subject string. */    than NOMATCH. This code is in a subroutine so that it can be re-used for
1052      finding subsequent matches when colouring matched lines. */
1053    
1054    for (i = 0; i < pattern_count; i++)    match = match_patterns(matchptr, length, offsets, &mrc);
     {  
     mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0, 0,  
       offsets, 99);  
     if (mrc >= 0) { match = TRUE; break; }  
     if (mrc != PCRE_ERROR_NOMATCH)  
       {  
       fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);  
       if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);  
       fprintf(stderr, "this line:\n");  
       fwrite(matchptr, 1, linelength, stderr);  /* In case binary zero included */  
       fprintf(stderr, "\n");  
       if (error_count == 0 &&  
           (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))  
         {  
         fprintf(stderr, "pcregrep: error %d means that a resource limit "  
           "was exceeded\n", mrc);  
         fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");  
         }  
       if (error_count++ > 20)  
         {  
         fprintf(stderr, "pcregrep: too many errors - abandoned\n");  
         exit(2);  
         }  
       match = invert;    /* No more matching; don't show the line again */  
       break;  
       }  
     }  
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 1021  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 1046  while (ptr < endptr) Line 1095  while (ptr < endptr)
1095          if (printname != NULL) fprintf(stdout, "%s:", printname);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1096          if (number) fprintf(stdout, "%d:", linenumber);          if (number) fprintf(stdout, "%d:", linenumber);
1097          if (line_offsets)          if (line_offsets)
1098            fprintf(stdout, "%d,%d", matchptr + offsets[0] - ptr,            fprintf(stdout, "%d,%d", (int)(matchptr + offsets[0] - ptr),
1099              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1100          else if (file_offsets)          else if (file_offsets)
1101            fprintf(stdout, "%d,%d", filepos + matchptr + offsets[0] - ptr,            fprintf(stdout, "%d,%d", (int)(filepos + matchptr + offsets[0] - ptr),
1102              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1103          else          else
1104            fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            {
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");          fprintf(stdout, "\n");
1110          matchptr += offsets[1];          matchptr += offsets[1];
1111          length -= offsets[1];          length -= offsets[1];
# Line 1092  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 1132  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 1182  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 + endlinelength) - offsets[1],          for (;;)
1256            stdout);            {
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 1305  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 1361  if (strcmp(pathname, "-") == 0) Line 1434  if (strcmp(pathname, "-") == 0)
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 1383  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 (include_dir_compiled != NULL &&
1471                pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1472              continue;
1473            }
1474          else
1475            {
1476            if (exclude_compiled != NULL &&
1477                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1478              continue;
1479    
1480        if (exclude_compiled != NULL &&          if (include_compiled != NULL &&
1481            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)              pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1482          continue;            continue;
1483            }
       if (include_compiled != NULL &&  
           pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
         continue;  
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 1456  an attempt to read a .bz2 file indicates Line 1543  an attempt to read a .bz2 file indicates
1543  PLAIN_FILE:  PLAIN_FILE:
1544  #endif  #endif
1545    {    {
1546    in = fopen(pathname, "r");    in = fopen(pathname, "rb");
1547    handle = (void *)in;    handle = (void *)in;
1548    frtype = FR_PLAIN;    frtype = FR_PLAIN;
1549    }    }
# Line 1579  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 1613  switch(letter) Line 1699  switch(letter)
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 1798  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 1849  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 1878  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 1898  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 2288  if (include_pattern != NULL) Line 2398  if (include_pattern != NULL)
2398        errptr, error);        errptr, error);
2399      goto EXIT2;      goto EXIT2;
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. */

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

  ViewVC Help
Powered by ViewVC 1.1.5