/[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 585 by ph10, Wed Jan 12 17:21:11 2011 UTC revision 975 by ph10, Sat Jun 2 11:03:06 2012 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-2011 University of Cambridge             Copyright (c) 1997-2012 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 74  typedef int BOOL; Line 74  typedef int BOOL;
74  #define OFFSET_SIZE 99  #define OFFSET_SIZE 99
75    
76  #if BUFSIZ > 8192  #if BUFSIZ > 8192
77  #define MBUFTHIRD BUFSIZ  #define PATBUFSIZE BUFSIZ
78  #else  #else
79  #define MBUFTHIRD 8192  #define PATBUFSIZE 8192
80  #endif  #endif
81    
82  /* Values for the "filenames" variable, which specifies options for file name  /* Values for the "filenames" variable, which specifies options for file name
# Line 104  enum { DEE_READ, DEE_SKIP }; Line 104  enum { DEE_READ, DEE_SKIP };
104    
105  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };
106    
107    /* Binary file options */
108    
109    enum { BIN_BINARY, BIN_NOMATCH, BIN_TEXT };
110    
111  /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some  /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some
112  environments), a warning is issued if the value of fwrite() is ignored.  environments), a warning is issued if the value of fwrite() is ignored.
113  Unfortunately, casting to (void) does not suppress the warning. To get round  Unfortunately, casting to (void) does not suppress the warning. To get round
# Line 135  static char *colour_string = (char *)"1; Line 139  static char *colour_string = (char *)"1;
139  static char *colour_option = NULL;  static char *colour_option = NULL;
140  static char *dee_option = NULL;  static char *dee_option = NULL;
141  static char *DEE_option = NULL;  static char *DEE_option = NULL;
142    static char *main_buffer = NULL;
143  static char *newline = NULL;  static char *newline = NULL;
144  static char *pattern_filename = NULL;  static char *pattern_filename = NULL;
145  static char *stdin_name = (char *)"(standard input)";  static char *stdin_name = (char *)"(standard input)";
# Line 146  static int  pattern_count = 0; Line 151  static int  pattern_count = 0;
151  static pcre **pattern_list = NULL;  static pcre **pattern_list = NULL;
152  static pcre_extra **hints_list = NULL;  static pcre_extra **hints_list = NULL;
153    
154    static char *file_list = NULL;
155  static char *include_pattern = NULL;  static char *include_pattern = NULL;
156  static char *exclude_pattern = NULL;  static char *exclude_pattern = NULL;
157  static char *include_dir_pattern = NULL;  static char *include_dir_pattern = NULL;
# Line 158  static pcre *exclude_dir_compiled = NULL Line 164  static pcre *exclude_dir_compiled = NULL
164    
165  static int after_context = 0;  static int after_context = 0;
166  static int before_context = 0;  static int before_context = 0;
167    static int binary_files = BIN_BINARY;
168  static int both_context = 0;  static int both_context = 0;
169    static int bufthird = PCREGREP_BUFSIZE;
170    static int bufsize = 3*PCREGREP_BUFSIZE;
171  static int dee_action = dee_READ;  static int dee_action = dee_READ;
172  static int DEE_action = DEE_READ;  static int DEE_action = DEE_READ;
173  static int error_count = 0;  static int error_count = 0;
# Line 166  static int filenames = FN_DEFAULT; Line 175  static int filenames = FN_DEFAULT;
175  static int only_matching = -1;  static int only_matching = -1;
176  static int process_options = 0;  static int process_options = 0;
177    
178    #ifdef SUPPORT_PCREGREP_JIT
179    static int study_options = PCRE_STUDY_JIT_COMPILE;
180    #else
181    static int study_options = 0;
182    #endif
183    
184  static unsigned long int match_limit = 0;  static unsigned long int match_limit = 0;
185  static unsigned long int match_limit_recursion = 0;  static unsigned long int match_limit_recursion = 0;
186    
# Line 187  static BOOL utf8 = FALSE; Line 202  static BOOL utf8 = FALSE;
202  /* Structure for options and list of them */  /* Structure for options and list of them */
203    
204  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
205         OP_OP_NUMBER, OP_PATLIST };         OP_OP_NUMBER, OP_PATLIST, OP_BINFILES };
206    
207  typedef struct option_item {  typedef struct option_item {
208    int type;    int type;
# Line 214  used to identify them. */ Line 229  used to identify them. */
229  #define N_LBUFFER      (-12)  #define N_LBUFFER      (-12)
230  #define N_M_LIMIT      (-13)  #define N_M_LIMIT      (-13)
231  #define N_M_LIMIT_REC  (-14)  #define N_M_LIMIT_REC  (-14)
232    #define N_BUFSIZE      (-15)
233    #define N_NOJIT        (-16)
234    #define N_FILE_LIST    (-17)
235    #define N_BINARY_FILES (-18)
236    
237  static option_item optionlist[] = {  static option_item optionlist[] = {
238    { OP_NODATA,     N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "terminate options" },
239    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
240    { OP_NUMBER,     'A',      &after_context,    "after-context=number", "set number of following context lines" },    { OP_NUMBER,     'A',      &after_context,    "after-context=number", "set number of following context lines" },
241      { OP_NODATA,     'a',      NULL,              "text",          "treat binary files as text" },
242    { OP_NUMBER,     'B',      &before_context,   "before-context=number", "set number of prior context lines" },    { OP_NUMBER,     'B',      &before_context,   "before-context=number", "set number of prior context lines" },
243      { OP_BINFILES,   N_BINARY_FILES, NULL,        "binary-files=word", "set treatment of binary files" },
244      { OP_NUMBER,     N_BUFSIZE,&bufthird,         "buffer-size=number", "set processing buffer size parameter" },
245    { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
246    { 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" },
247    { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },    { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
# Line 229  static option_item optionlist[] = { Line 251  static option_item optionlist[] = {
251    { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },    { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
252    { 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" },
253    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
254      { OP_STRING,     N_FILE_LIST, &file_list,     "file-list=path","read files to search from file" },
255    { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },    { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
256    { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
257    { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
258      { OP_NODATA,     'I',      NULL,              "",              "treat binary files as not matching (ignore)" },
259    { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
260    #ifdef SUPPORT_PCREGREP_JIT
261      { OP_NODATA,     N_NOJIT,  NULL,              "no-jit",        "do not use just-in-time compiler optimization" },
262    #else
263      { OP_NODATA,     N_NOJIT,  NULL,              "no-jit",        "ignored: this pcregrep does not support JIT" },
264    #endif
265    { 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" },
266    { 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" },
267    { 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" },
# Line 296  const char utf8_table4[] = { Line 325  const char utf8_table4[] = {
325    
326    
327  /*************************************************  /*************************************************
328    *         Exit from the program                  *
329    *************************************************/
330    
331    /* If there has been a resource error, give a suitable message.
332    
333    Argument:  the return code
334    Returns:   does not return
335    */
336    
337    static void
338    pcregrep_exit(int rc)
339    {
340    if (resource_error)
341      {
342      fprintf(stderr, "pcregrep: Error %d, %d or %d means that a resource limit "
343        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT,
344        PCRE_ERROR_JIT_STACKLIMIT);
345      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
346      }
347    
348    exit(rc);
349    }
350    
351    
352    /*************************************************
353  *            OS-specific functions               *  *            OS-specific functions               *
354  *************************************************/  *************************************************/
355    
# Line 565  return sys_errlist[n]; Line 619  return sys_errlist[n];
619    
620    
621  /*************************************************  /*************************************************
 *         Exit from the program                  *  
 *************************************************/  
   
 /* If there has been a resource error, give a suitable message.  
   
 Argument:  the return code  
 Returns:   does not return  
 */  
   
 static void  
 pcregrep_exit(int rc)  
 {  
 if (resource_error)  
   {  
   fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "  
     "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);  
   fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");  
   }  
   
 exit(rc);  
 }  
   
   
   
 /*************************************************  
622  *            Read one line of input              *  *            Read one line of input              *
623  *************************************************/  *************************************************/
624    
# Line 608  Arguments: Line 637  Arguments:
637  Returns:     the number of characters read, zero at end of file  Returns:     the number of characters read, zero at end of file
638  */  */
639    
640  static int  static unsigned int
641  read_one_line(char *buffer, int length, FILE *f)  read_one_line(char *buffer, int length, FILE *f)
642  {  {
643  int c;  int c;
# Line 635  Arguments: Line 664  Arguments:
664    endptr    end of available data    endptr    end of available data
665    lenptr    where to put the length of the eol sequence    lenptr    where to put the length of the eol sequence
666    
667  Returns:    pointer to the last byte of the line  Returns:    pointer after the last byte of the line,
668                including the newline byte(s)
669  */  */
670    
671  static char *  static char *
# Line 936  is used multiple times for the same subj Line 966  is used multiple times for the same subj
966  to find all possible matches.  to find all possible matches.
967    
968  Arguments:  Arguments:
969    matchptr    the start of the subject    matchptr     the start of the subject
970    length      the length of the subject to match    length       the length of the subject to match
971    offsets     the offets vector to fill in    startoffset  where to start matching
972    mrc         address of where to put the result of pcre_exec()    offsets      the offets vector to fill in
973      mrc          address of where to put the result of pcre_exec()
974    
975  Returns:      TRUE if there was a match  Returns:      TRUE if there was a match
976                FALSE if there was no match                FALSE if there was no match
# Line 947  Returns:      TRUE if there was a match Line 978  Returns:      TRUE if there was a match
978  */  */
979    
980  static BOOL  static BOOL
981  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)  match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
982      int *mrc)
983  {  {
984  int i;  int i;
985  size_t slen = length;  size_t slen = length;
# Line 959  if (slen > 200) Line 991  if (slen > 200)
991    }    }
992  for (i = 0; i < pattern_count; i++)  for (i = 0; i < pattern_count; i++)
993    {    {
994    *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length, 0,    *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length,
995      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);      startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
996    if (*mrc >= 0) return TRUE;    if (*mrc >= 0) return TRUE;
997    if (*mrc == PCRE_ERROR_NOMATCH) continue;    if (*mrc == PCRE_ERROR_NOMATCH) continue;
998    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
# Line 968  for (i = 0; i < pattern_count; i++) Line 1000  for (i = 0; i < pattern_count; i++)
1000    fprintf(stderr, "%s", msg);    fprintf(stderr, "%s", msg);
1001    FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */    FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
1002    fprintf(stderr, "\n\n");    fprintf(stderr, "\n\n");
1003    if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)    if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT ||
1004          *mrc == PCRE_ERROR_JIT_STACKLIMIT)
1005      resource_error = TRUE;      resource_error = TRUE;
1006    if (error_count++ > 20)    if (error_count++ > 20)
1007      {      {
# Line 988  return FALSE;  /* No match, no errors */ Line 1021  return FALSE;  /* No match, no errors */
1021  *************************************************/  *************************************************/
1022    
1023  /* This is called from grep_or_recurse() below. It uses a buffer that is three  /* This is called from grep_or_recurse() below. It uses a buffer that is three
1024  times the value of MBUFTHIRD. The matching point is never allowed to stray into  times the value of bufthird. The matching point is never allowed to stray into
1025  the top third of the buffer, thus keeping more of the file available for  the top third of the buffer, thus keeping more of the file available for
1026  context printing or for multiline scanning. For large files, the pointer will  context printing or for multiline scanning. For large files, the pointer will
1027  be in the middle third most of the time, so the bottom third is available for  be in the middle third most of the time, so the bottom third is available for
# Line 999  Arguments: Line 1032  Arguments:
1032                 the gzFile pointer when reading is via libz                 the gzFile pointer when reading is via libz
1033                 the BZFILE pointer when reading is via libbz2                 the BZFILE pointer when reading is via libbz2
1034    frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2    frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
1035      filename     the file name or NULL (for errors)
1036    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
1037                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
1038                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
1039    
1040  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
1041                 1 otherwise (no matches)                 1 otherwise (no matches)
1042                 2 if there is a read error on a .bz2 file                 2 if an overlong line is encountered
1043                   3 if there is a read error on a .bz2 file
1044  */  */
1045    
1046  static int  static int
1047  pcregrep(void *handle, int frtype, char *printname)  pcregrep(void *handle, int frtype, char *filename, char *printname)
1048  {  {
1049  int rc = 1;  int rc = 1;
1050  int linenumber = 1;  int linenumber = 1;
# Line 1018  int count = 0; Line 1053  int count = 0;
1053  int filepos = 0;  int filepos = 0;
1054  int offsets[OFFSET_SIZE];  int offsets[OFFSET_SIZE];
1055  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
1056  char buffer[3*MBUFTHIRD];  char *ptr = main_buffer;
 char *ptr = buffer;  
1057  char *endptr;  char *endptr;
1058  size_t bufflength;  size_t bufflength;
1059    BOOL binary = FALSE;
1060  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
1061  BOOL input_line_buffered = line_buffered;  BOOL input_line_buffered = line_buffered;
1062  FILE *in = NULL;                    /* Ensure initialized */  FILE *in = NULL;                    /* Ensure initialized */
# Line 1044  fail. */ Line 1079  fail. */
1079  if (frtype == FR_LIBZ)  if (frtype == FR_LIBZ)
1080    {    {
1081    ingz = (gzFile)handle;    ingz = (gzFile)handle;
1082    bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);    bufflength = gzread (ingz, main_buffer, bufsize);
1083    }    }
1084  else  else
1085  #endif  #endif
# Line 1053  else Line 1088  else
1088  if (frtype == FR_LIBBZ2)  if (frtype == FR_LIBBZ2)
1089    {    {
1090    inbz2 = (BZFILE *)handle;    inbz2 = (BZFILE *)handle;
1091    bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);    bufflength = BZ2_bzread(inbz2, main_buffer, bufsize);
1092    if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */    if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1093    }                                    /* without the cast it is unsigned. */    }                                    /* without the cast it is unsigned. */
1094  else  else
# Line 1063  else Line 1098  else
1098    in = (FILE *)handle;    in = (FILE *)handle;
1099    if (is_file_tty(in)) input_line_buffered = TRUE;    if (is_file_tty(in)) input_line_buffered = TRUE;
1100    bufflength = input_line_buffered?    bufflength = input_line_buffered?
1101      read_one_line(buffer, 3*MBUFTHIRD, in) :      read_one_line(main_buffer, bufsize, in) :
1102      fread(buffer, 1, 3*MBUFTHIRD, in);      fread(main_buffer, 1, bufsize, in);
1103    }    }
1104    
1105  endptr = buffer + bufflength;  endptr = main_buffer + bufflength;
1106    
1107    /* Unless binary-files=text, see if we have a binary file. This uses the same
1108    rule as GNU grep, namely, a search for a binary zero byte near the start of the
1109    file. */
1110    
1111    if (binary_files != BIN_TEXT)
1112      {
1113      binary =
1114        memchr(main_buffer, 0, (bufflength > 1024)? 1024 : bufflength) != NULL;
1115      if (binary && binary_files == BIN_NOMATCH) return 1;
1116      }
1117    
1118  /* 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
1119  files, endptr will be at the end of the buffer when we are in the middle of the  files, endptr will be at the end of the buffer when we are in the middle of the
# Line 1078  while (ptr < endptr) Line 1124  while (ptr < endptr)
1124    {    {
1125    int endlinelength;    int endlinelength;
1126    int mrc = 0;    int mrc = 0;
1127      int startoffset = 0;
1128    BOOL match;    BOOL match;
1129    char *matchptr = ptr;    char *matchptr = ptr;
1130    char *t = ptr;    char *t = ptr;
# Line 1095  while (ptr < endptr) Line 1142  while (ptr < endptr)
1142    linelength = t - ptr - endlinelength;    linelength = t - ptr - endlinelength;
1143    length = multiline? (size_t)(endptr - ptr) : linelength;    length = multiline? (size_t)(endptr - ptr) : linelength;
1144    
1145      /* Check to see if the line we are looking at extends right to the very end
1146      of the buffer without a line terminator. This means the line is too long to
1147      handle. */
1148    
1149      if (endlinelength == 0 && t == main_buffer + bufsize)
1150        {
1151        fprintf(stderr, "pcregrep: line %d%s%s is too long for the internal buffer\n"
1152                        "pcregrep: check the --buffer-size option\n",
1153                        linenumber,
1154                        (filename == NULL)? "" : " of file ",
1155                        (filename == NULL)? "" : filename);
1156        return 2;
1157        }
1158    
1159    /* Extra processing for Jeffrey Friedl's debugging. */    /* Extra processing for Jeffrey Friedl's debugging. */
1160    
1161  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
# Line 1154  while (ptr < endptr) Line 1215  while (ptr < endptr)
1215    than NOMATCH. This code is in a subroutine so that it can be re-used for    than NOMATCH. This code is in a subroutine so that it can be re-used for
1216    finding subsequent matches when colouring matched lines. */    finding subsequent matches when colouring matched lines. */
1217    
1218    match = match_patterns(matchptr, length, offsets, &mrc);    match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
1219    
1220    /* 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. */
1221    
# Line 1170  while (ptr < endptr) Line 1231  while (ptr < endptr)
1231    
1232      if (count_only) count++;      if (count_only) count++;
1233    
1234        /* When handling a binary file and binary-files==binary, the "binary"
1235        variable will be set true (it's false in all other cases). In this
1236        situation we just want to output the file name. No need to scan further. */
1237    
1238        else if (binary)
1239          {
1240          fprintf(stdout, "Binary file %s matches\n", filename);
1241          return 0;
1242          }
1243    
1244      /* 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
1245      in the file. */      in the file. */
1246    
# Line 1187  while (ptr < endptr) Line 1258  while (ptr < endptr)
1258      captured portion of it, as long as this string is not empty, and the      captured portion of it, as long as this string is not empty, and the
1259      --file-offsets and --line-offsets options output offsets for the matching      --file-offsets and --line-offsets options output offsets for the matching
1260      substring (they both force --only-matching = 0). None of these options      substring (they both force --only-matching = 0). None of these options
1261      prints any context. Afterwards, adjust the start and length, and then jump      prints any context. Afterwards, adjust the start and then jump back to look
1262      back to look for further matches in the same line. If we are in invert      for further matches in the same line. If we are in invert mode, however,
1263      mode, however, nothing is printed and we do not restart - this could still      nothing is printed and we do not restart - this could still be useful
1264      be useful because the return code is set. */      because the return code is set. */
1265    
1266      else if (only_matching >= 0)      else if (only_matching >= 0)
1267        {        {
# Line 1217  while (ptr < endptr) Line 1288  while (ptr < endptr)
1288              }              }
1289            }            }
1290          else if (printname != NULL || number) fprintf(stdout, "\n");          else if (printname != NULL || number) fprintf(stdout, "\n");
         matchptr += offsets[1];  
         length -= offsets[1];  
1291          match = FALSE;          match = FALSE;
1292          if (line_buffered) fflush(stdout);          if (line_buffered) fflush(stdout);
1293          rc = 0;    /* Had some success */          rc = 0;                      /* Had some success */
1294            startoffset = offsets[1];    /* Restart after the match */
1295          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1296          }          }
1297        }        }
# Line 1280  while (ptr < endptr) Line 1350  while (ptr < endptr)
1350          int linecount = 0;          int linecount = 0;
1351          char *p = ptr;          char *p = ptr;
1352    
1353          while (p > buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&          while (p > main_buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
1354                 linecount < before_context)                 linecount < before_context)
1355            {            {
1356            linecount++;            linecount++;
1357            p = previous_line(p, buffer);            p = previous_line(p, main_buffer);
1358            }            }
1359    
1360          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 1317  while (ptr < endptr) Line 1387  while (ptr < endptr)
1387        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1388        the match will always be before the first newline sequence. */        the match will always be before the first newline sequence. */
1389    
1390        if (multiline)        if (multiline & !invert)
1391          {          {
1392          int ellength;          char *endmatch = ptr + offsets[1];
1393          char *endmatch = ptr;          t = ptr;
1394          if (!invert)          while (t < endmatch)
1395            {            {
1396            endmatch += offsets[1];            t = end_of_line(t, endptr, &endlinelength);
1397            t = ptr;            if (t < endmatch) linenumber++; else break;
           while (t < endmatch)  
             {  
             t = end_of_line(t, endptr, &ellength);  
             if (t <= endmatch) linenumber++; else break;  
             }  
1398            }            }
1399          endmatch = end_of_line(endmatch, endptr, &ellength);          linelength = t - ptr - endlinelength;
         linelength = endmatch - ptr - ellength;  
1400          }          }
1401    
1402        /*** NOTE: Use only fwrite() to output the data line, so that binary        /*** NOTE: Use only fwrite() to output the data line, so that binary
# Line 1359  while (ptr < endptr) Line 1423  while (ptr < endptr)
1423    
1424        if (do_colour && !invert)        if (do_colour && !invert)
1425          {          {
1426          int last_offset = 0;          int plength;
1427          FWRITE(ptr, 1, offsets[0], stdout);          FWRITE(ptr, 1, offsets[0], stdout);
1428          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1429          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1430          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1431          for (;;)          for (;;)
1432            {            {
1433            last_offset += offsets[1];            startoffset = offsets[1];
1434            matchptr += offsets[1];            if (startoffset >= (int)linelength + endlinelength ||
1435            length -= offsets[1];                !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1436            if (!match_patterns(matchptr, length, offsets, &mrc)) break;              break;
1437            FWRITE(matchptr, 1, offsets[0], stdout);            FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1438            fprintf(stdout, "%c[%sm", 0x1b, colour_string);            fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1439            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1440            fprintf(stdout, "%c[00m", 0x1b);            fprintf(stdout, "%c[00m", 0x1b);
1441            }            }
1442          FWRITE(ptr + last_offset, 1,  
1443            (linelength + endlinelength) - last_offset, stdout);          /* In multiline mode, we may have already printed the complete line
1444            and its line-ending characters (if they matched the pattern), so there
1445            may be no more to print. */
1446    
1447            plength = (int)((linelength + endlinelength) - startoffset);
1448            if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout);
1449          }          }
1450    
1451        /* Not colouring; no need to search for further matches */        /* Not colouring; no need to search for further matches */
# Line 1425  while (ptr < endptr) Line 1494  while (ptr < endptr)
1494    /* If input is line buffered, and the buffer is not yet full, read another    /* If input is line buffered, and the buffer is not yet full, read another
1495    line and add it into the buffer. */    line and add it into the buffer. */
1496    
1497    if (input_line_buffered && bufflength < sizeof(buffer))    if (input_line_buffered && bufflength < (size_t)bufsize)
1498      {      {
1499      int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);      int add = read_one_line(ptr, bufsize - (int)(ptr - main_buffer), in);
1500      bufflength += add;      bufflength += add;
1501      endptr += add;      endptr += add;
1502      }      }
# Line 1437  while (ptr < endptr) Line 1506  while (ptr < endptr)
1506    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
1507    about to be lost, print them. */    about to be lost, print them. */
1508    
1509    if (bufflength >= sizeof(buffer) && ptr > buffer + 2*MBUFTHIRD)    if (bufflength >= (size_t)bufsize && ptr > main_buffer + 2*bufthird)
1510      {      {
1511      if (after_context > 0 &&      if (after_context > 0 &&
1512          lastmatchnumber > 0 &&          lastmatchnumber > 0 &&
1513          lastmatchrestart < buffer + MBUFTHIRD)          lastmatchrestart < main_buffer + bufthird)
1514        {        {
1515        do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);        do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1516        lastmatchnumber = 0;        lastmatchnumber = 0;
# Line 1449  while (ptr < endptr) Line 1518  while (ptr < endptr)
1518    
1519      /* Now do the shuffle */      /* Now do the shuffle */
1520    
1521      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(main_buffer, main_buffer + bufthird, 2*bufthird);
1522      ptr -= MBUFTHIRD;      ptr -= bufthird;
1523    
1524  #ifdef SUPPORT_LIBZ  #ifdef SUPPORT_LIBZ
1525      if (frtype == FR_LIBZ)      if (frtype == FR_LIBZ)
1526        bufflength = 2*MBUFTHIRD +        bufflength = 2*bufthird +
1527          gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);          gzread (ingz, main_buffer + 2*bufthird, bufthird);
1528      else      else
1529  #endif  #endif
1530    
1531  #ifdef SUPPORT_LIBBZ2  #ifdef SUPPORT_LIBBZ2
1532      if (frtype == FR_LIBBZ2)      if (frtype == FR_LIBBZ2)
1533        bufflength = 2*MBUFTHIRD +        bufflength = 2*bufthird +
1534          BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);          BZ2_bzread(inbz2, main_buffer + 2*bufthird, bufthird);
1535      else      else
1536  #endif  #endif
1537    
1538      bufflength = 2*MBUFTHIRD +      bufflength = 2*bufthird +
1539        (input_line_buffered?        (input_line_buffered?
1540         read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :         read_one_line(main_buffer + 2*bufthird, bufthird, in) :
1541         fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));         fread(main_buffer + 2*bufthird, 1, bufthird, in));
1542      endptr = buffer + bufflength;      endptr = main_buffer + bufflength;
1543    
1544      /* Adjust any last match point */      /* Adjust any last match point */
1545    
1546      if (lastmatchnumber > 0) lastmatchrestart -= MBUFTHIRD;      if (lastmatchnumber > 0) lastmatchrestart -= bufthird;
1547      }      }
1548    }     /* Loop through the whole file */    }     /* Loop through the whole file */
1549    
# Line 1538  grep_or_recurse(char *pathname, BOOL dir Line 1607  grep_or_recurse(char *pathname, BOOL dir
1607  int rc = 1;  int rc = 1;
1608  int sep;  int sep;
1609  int frtype;  int frtype;
 int pathlen;  
1610  void *handle;  void *handle;
1611  FILE *in = NULL;           /* Ensure initialized */  FILE *in = NULL;           /* Ensure initialized */
1612    
# Line 1550  gzFile ingz = NULL; Line 1618  gzFile ingz = NULL;
1618  BZFILE *inbz2 = NULL;  BZFILE *inbz2 = NULL;
1619  #endif  #endif
1620    
1621    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1622    int pathlen;
1623    #endif
1624    
1625  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1626    
1627  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1628    {    {
1629    return pcregrep(stdin, FR_PLAIN,    return pcregrep(stdin, FR_PLAIN, stdin_name,
1630      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1631        stdin_name : NULL);        stdin_name : NULL);
1632    }    }
# Line 1629  skipping was not requested. The scan pro Line 1701  skipping was not requested. The scan pro
1701  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
1702  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1703    
1704    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1705  pathlen = (int)(strlen(pathname));  pathlen = (int)(strlen(pathname));
1706    #endif
1707    
1708  /* Open using zlib if it is supported and the file name ends with .gz. */  /* Open using zlib if it is supported and the file name ends with .gz. */
1709    
# Line 1686  if (handle == NULL) Line 1760  if (handle == NULL)
1760    
1761  /* Now grep the file */  /* Now grep the file */
1762    
1763  rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||  rc = pcregrep(handle, frtype, pathname, (filenames > FN_DEFAULT ||
1764    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1765    
1766  /* Close in an appropriate manner. */  /* Close in an appropriate manner. */
# Line 1697  if (frtype == FR_LIBZ) Line 1771  if (frtype == FR_LIBZ)
1771  else  else
1772  #endif  #endif
1773    
1774  /* If it is a .bz2 file and the result is 2, it means that the first attempt to  /* If it is a .bz2 file and the result is 3, it means that the first attempt to
1775  read failed. If the error indicates that the file isn't in fact bzipped, try  read failed. If the error indicates that the file isn't in fact bzipped, try
1776  again as a normal file. */  again as a normal file. */
1777    
1778  #ifdef SUPPORT_LIBBZ2  #ifdef SUPPORT_LIBBZ2
1779  if (frtype == FR_LIBBZ2)  if (frtype == FR_LIBBZ2)
1780    {    {
1781    if (rc == 2)    if (rc == 3)
1782      {      {
1783      int errnum;      int errnum;
1784      const char *err = BZ2_bzerror(inbz2, &errnum);      const char *err = BZ2_bzerror(inbz2, &errnum);
# Line 1716  if (frtype == FR_LIBBZ2) Line 1790  if (frtype == FR_LIBBZ2)
1790      else if (!silent)      else if (!silent)
1791        fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",        fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1792          pathname, err);          pathname, err);
1793        rc = 2;    /* The normal "something went wrong" code */
1794      }      }
1795    BZ2_bzclose(inbz2);    BZ2_bzclose(inbz2);
1796    }    }
# Line 1802  for (op = optionlist; op->one_char != 0; Line 1877  for (op = optionlist; op->one_char != 0;
1877    
1878    if (strchr(op->long_name, '_') != NULL) continue;    if (strchr(op->long_name, '_') != NULL) continue;
1879    
1880    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");    if (op->one_char > 0 && (op->long_name)[0] == 0)
1881    n = 31 - printf("  %s --%s", s, op->long_name);      n = 31 - printf("  -%c", op->one_char);
1882      else
1883        {
1884        if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);
1885          else strcpy(s, "   ");
1886        n = 31 - printf("  %s --%s", s, op->long_name);
1887        }
1888    
1889    if (n < 1) n = 1;    if (n < 1) n = 1;
1890    printf("%.*s%s\n", n, "                     ", op->help_text);    printf("%.*s%s\n", n, "                           ", op->help_text);
1891    }    }
1892    
1893  printf("\nWhen reading patterns from a file instead of using a command line option,\n");  printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n");
1894  printf("trailing white space is removed and blank lines are ignored.\n");  printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);
1895  printf("There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT);  printf("When reading patterns or file names from a file, trailing white\n");
1896    printf("space is removed and blank lines are ignored.\n");
1897    printf("There is a maximum of %d patterns, each of maximum size %d bytes.\n",
1898      MAX_PATTERN_COUNT, PATBUFSIZE);
1899    
1900  printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");  printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");
1901  printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");  printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");
# Line 1830  switch(letter) Line 1915  switch(letter)
1915    {    {
1916    case N_FOFFSETS: file_offsets = TRUE; break;    case N_FOFFSETS: file_offsets = TRUE; break;
1917    case N_HELP: help(); pcregrep_exit(0);    case N_HELP: help(); pcregrep_exit(0);
   case N_LOFFSETS: line_offsets = number = TRUE; break;  
1918    case N_LBUFFER: line_buffered = TRUE; break;    case N_LBUFFER: line_buffered = TRUE; break;
1919      case N_LOFFSETS: line_offsets = number = TRUE; break;
1920      case N_NOJIT: study_options &= ~PCRE_STUDY_JIT_COMPILE; break;
1921      case 'a': binary_files = BIN_TEXT; break;
1922    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1923    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1924    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1925      case 'I': binary_files = BIN_NOMATCH; break;
1926    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1927    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1928    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
# Line 1912  Returns:         TRUE on success, FALSE Line 2000  Returns:         TRUE on success, FALSE
2000  static BOOL  static BOOL
2001  compile_single_pattern(char *pattern, int options, char *filename, int count)  compile_single_pattern(char *pattern, int options, char *filename, int count)
2002  {  {
2003  char buffer[MBUFTHIRD + 16];  char buffer[PATBUFSIZE];
2004  const char *error;  const char *error;
2005  int errptr;  int errptr;
2006    
# Line 1923  if (pattern_count >= MAX_PATTERN_COUNT) Line 2011  if (pattern_count >= MAX_PATTERN_COUNT)
2011    return FALSE;    return FALSE;
2012    }    }
2013    
2014  sprintf(buffer, "%s%.*s%s", prefix[process_options], MBUFTHIRD, pattern,  sprintf(buffer, "%s%.*s%s", prefix[process_options], bufthird, pattern,
2015    suffix[process_options]);    suffix[process_options]);
2016  pattern_list[pattern_count] =  pattern_list[pattern_count] =
2017    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
# Line 1982  compile_pattern(char *pattern, int optio Line 2070  compile_pattern(char *pattern, int optio
2070  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
2071    {    {
2072    char *eop = pattern + strlen(pattern);    char *eop = pattern + strlen(pattern);
2073    char buffer[MBUFTHIRD];    char buffer[PATBUFSIZE];
2074    for(;;)    for(;;)
2075      {      {
2076      int ellength;      int ellength;
# Line 2020  char *patterns[MAX_PATTERN_COUNT]; Line 2108  char *patterns[MAX_PATTERN_COUNT];
2108  const char *locale_from = "--locale";  const char *locale_from = "--locale";
2109  const char *error;  const char *error;
2110    
2111    #ifdef SUPPORT_PCREGREP_JIT
2112    pcre_jit_stack *jit_stack = NULL;
2113    #endif
2114    
2115  /* 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;
2116  "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".
2117  Note that the return values from pcre_config(), though derived from the ASCII  Note that the return values from pcre_config(), though derived from the ASCII
# Line 2276  for (i = 1; i < argc; i++) Line 2368  for (i = 1; i < argc; i++)
2368      patterns[cmd_pattern_count++] = option_data;      patterns[cmd_pattern_count++] = option_data;
2369      }      }
2370    
2371      /* Handle OP_BINARY_FILES */
2372    
2373      else if (op->type == OP_BINFILES)
2374        {
2375        if (strcmp(option_data, "binary") == 0)
2376          binary_files = BIN_BINARY;
2377        else if (strcmp(option_data, "without-match") == 0)
2378          binary_files = BIN_NOMATCH;
2379        else if (strcmp(option_data, "text") == 0)
2380          binary_files = BIN_TEXT;
2381        else
2382          {
2383          fprintf(stderr, "pcregrep: unknown value \"%s\" for binary-files\n",
2384            option_data);
2385          pcregrep_exit(usage(2));
2386          }
2387        }
2388    
2389    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2390    
2391    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
# Line 2294  for (i = 1; i < argc; i++) Line 2404  for (i = 1; i < argc; i++)
2404      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2405      while (isdigit((unsigned char)(*endptr)))      while (isdigit((unsigned char)(*endptr)))
2406        n = n * 10 + (int)(*endptr++ - '0');        n = n * 10 + (int)(*endptr++ - '0');
2407        if (toupper(*endptr) == 'K')
2408          {
2409          n *= 1024;
2410          endptr++;
2411          }
2412        else if (toupper(*endptr) == 'M')
2413          {
2414          n *= 1024*1024;
2415          endptr++;
2416          }
2417      if (*endptr != 0)      if (*endptr != 0)
2418        {        {
2419        if (longop)        if (longop)
# Line 2460  if (jfriedl_XT != 0 || jfriedl_XR != 0) Line 2580  if (jfriedl_XT != 0 || jfriedl_XR != 0)
2580    }    }
2581  #endif  #endif
2582    
2583  /* Get memory to store the pattern and hints lists. */  /* Get memory for the main buffer, and to store the pattern and hints lists. */
2584    
2585    bufsize = 3*bufthird;
2586    main_buffer = (char *)malloc(bufsize);
2587  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
2588  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));
2589    
2590  if (pattern_list == NULL || hints_list == NULL)  if (main_buffer == NULL || pattern_list == NULL || hints_list == NULL)
2591    {    {
2592    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2593    goto EXIT2;    goto EXIT2;
# Line 2497  if (pattern_filename != NULL) Line 2619  if (pattern_filename != NULL)
2619    int linenumber = 0;    int linenumber = 0;
2620    FILE *f;    FILE *f;
2621    char *filename;    char *filename;
2622    char buffer[MBUFTHIRD];    char buffer[PATBUFSIZE];
2623    
2624    if (strcmp(pattern_filename, "-") == 0)    if (strcmp(pattern_filename, "-") == 0)
2625      {      {
# Line 2516  if (pattern_filename != NULL) Line 2638  if (pattern_filename != NULL)
2638      filename = pattern_filename;      filename = pattern_filename;
2639      }      }
2640    
2641    while (fgets(buffer, MBUFTHIRD, f) != NULL)    while (fgets(buffer, PATBUFSIZE, f) != NULL)
2642      {      {
2643      char *s = buffer + (int)strlen(buffer);      char *s = buffer + (int)strlen(buffer);
2644      while (s > buffer && isspace((unsigned char)(s[-1]))) s--;      while (s > buffer && isspace((unsigned char)(s[-1]))) s--;
# Line 2530  if (pattern_filename != NULL) Line 2652  if (pattern_filename != NULL)
2652    if (f != stdin) fclose(f);    if (f != stdin) fclose(f);
2653    }    }
2654    
2655  /* Study the regular expressions, as we will be running them many times */  /* Study the regular expressions, as we will be running them many times. Unless
2656    JIT has been explicitly disabled, arrange a stack for it to use. */
2657    
2658    #ifdef SUPPORT_PCREGREP_JIT
2659    if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0)
2660      jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024);
2661    #endif
2662    
2663  for (j = 0; j < pattern_count; j++)  for (j = 0; j < pattern_count; j++)
2664    {    {
2665    hints_list[j] = pcre_study(pattern_list[j], 0, &error);    hints_list[j] = pcre_study(pattern_list[j], study_options, &error);
2666    if (error != NULL)    if (error != NULL)
2667      {      {
2668      char s[16];      char s[16];
# Line 2543  for (j = 0; j < pattern_count; j++) Line 2671  for (j = 0; j < pattern_count; j++)
2671      goto EXIT2;      goto EXIT2;
2672      }      }
2673    hint_count++;    hint_count++;
2674    #ifdef SUPPORT_PCREGREP_JIT
2675      if (jit_stack != NULL && hints_list[j] != NULL)
2676        pcre_assign_jit_stack(hints_list[j], NULL, jit_stack);
2677    #endif
2678    }    }
2679    
2680  /* If --match-limit or --recursion-limit was set, put the value(s) into the  /* If --match-limit or --recursion-limit was set, put the value(s) into the
# Line 2624  if (include_dir_pattern != NULL) Line 2756  if (include_dir_pattern != NULL)
2756      }      }
2757    }    }
2758    
2759  /* If there are no further arguments, do the business on stdin and exit. */  /* If a file that contains a list of files to search has been specified, read
2760    it line by line and search the given files. Otherwise, if there are no further
2761    arguments, do the business on stdin and exit. */
2762    
2763  if (i >= argc)  if (file_list != NULL)
2764    {    {
2765    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);    char buffer[PATBUFSIZE];
2766      FILE *fl;
2767      if (strcmp(file_list, "-") == 0) fl = stdin; else
2768        {
2769        fl = fopen(file_list, "rb");
2770        if (fl == NULL)
2771          {
2772          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", file_list,
2773            strerror(errno));
2774          goto EXIT2;
2775          }
2776        }
2777      while (fgets(buffer, PATBUFSIZE, fl) != NULL)
2778        {
2779        int frc;
2780        char *end = buffer + (int)strlen(buffer);
2781        while (end > buffer && isspace(end[-1])) end--;
2782        *end = 0;
2783        if (*buffer != 0)
2784          {
2785          frc = grep_or_recurse(buffer, dee_action == dee_RECURSE, FALSE);
2786          if (frc > 1) rc = frc;
2787            else if (frc == 0 && rc == 1) rc = 0;
2788          }
2789        }
2790      if (fl != stdin) fclose (fl);
2791      }
2792    
2793    /* Do this only if there was no file list (and no file arguments). */
2794    
2795    else if (i >= argc)
2796      {
2797      rc = pcregrep(stdin, FR_PLAIN, stdin_name,
2798        (filenames > FN_DEFAULT)? stdin_name : NULL);
2799    goto EXIT;    goto EXIT;
2800    }    }
2801    
2802  /* Otherwise, work through the remaining arguments as files or directories.  /* After handling file-list or if there are remaining arguments, work through
2803  Pass in the fact that there is only one argument at top level - this suppresses  them as files or directories. Pass in the fact that there is only one argument
2804  the file name if the argument is not a directory and filenames are not  at top level - this suppresses the file name if the argument is not a directory
2805  otherwise forced. */  and filenames are not otherwise forced. */
2806    
2807  only_one_at_top = i == argc - 1;   /* Catch initial value of i */  only_one_at_top = i == argc - 1 && file_list == NULL;
2808    
2809  for (; i < argc; i++)  for (; i < argc; i++)
2810    {    {
# Line 2648  for (; i < argc; i++) Line 2815  for (; i < argc; i++)
2815    }    }
2816    
2817  EXIT:  EXIT:
2818    #ifdef SUPPORT_PCREGREP_JIT
2819    if (jit_stack != NULL) pcre_jit_stack_free(jit_stack);
2820    #endif
2821    if (main_buffer != NULL) free(main_buffer);
2822  if (pattern_list != NULL)  if (pattern_list != NULL)
2823    {    {
2824    for (i = 0; i < pattern_count; i++) free(pattern_list[i]);    for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
# Line 2657  if (hints_list != NULL) Line 2828  if (hints_list != NULL)
2828    {    {
2829    for (i = 0; i < hint_count; i++)    for (i = 0; i < hint_count; i++)
2830      {      {
2831      if (hints_list[i] != NULL) free(hints_list[i]);      if (hints_list[i] != NULL) pcre_free_study(hints_list[i]);
2832      }      }
2833    free(hints_list);    free(hints_list);
2834    }    }

Legend:
Removed from v.585  
changed lines
  Added in v.975

  ViewVC Help
Powered by ViewVC 1.1.5