/[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 571 by ph10, Tue Nov 16 17:51:37 2010 UTC revision 646 by ph10, Mon Aug 1 09:54:26 2011 UTC
# Line 6  Line 6 
6  its pattern matching. On a Unix or Win32 system it can recurse into  its pattern matching. On a Unix or Win32 system it can recurse into
7  directories.  directories.
8    
9             Copyright (c) 1997-2010 University of Cambridge             Copyright (c) 1997-2011 University of Cambridge
10    
11  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
12  Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
# Line 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 135  static char *colour_string = (char *)"1; Line 135  static char *colour_string = (char *)"1;
135  static char *colour_option = NULL;  static char *colour_option = NULL;
136  static char *dee_option = NULL;  static char *dee_option = NULL;
137  static char *DEE_option = NULL;  static char *DEE_option = NULL;
138    static char *main_buffer = NULL;
139  static char *newline = NULL;  static char *newline = NULL;
140  static char *pattern_filename = NULL;  static char *pattern_filename = NULL;
141  static char *stdin_name = (char *)"(standard input)";  static char *stdin_name = (char *)"(standard input)";
# Line 159  static pcre *exclude_dir_compiled = NULL Line 160  static pcre *exclude_dir_compiled = NULL
160  static int after_context = 0;  static int after_context = 0;
161  static int before_context = 0;  static int before_context = 0;
162  static int both_context = 0;  static int both_context = 0;
163    static int bufthird = PCREGREP_BUFSIZE;
164    static int bufsize = 3*PCREGREP_BUFSIZE;
165  static int dee_action = dee_READ;  static int dee_action = dee_READ;
166  static int DEE_action = DEE_READ;  static int DEE_action = DEE_READ;
167  static int error_count = 0;  static int error_count = 0;
# Line 186  static BOOL utf8 = FALSE; Line 189  static BOOL utf8 = FALSE;
189    
190  /* Structure for options and list of them */  /* Structure for options and list of them */
191    
192  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_OP_NUMBER,  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
193         OP_PATLIST };         OP_OP_NUMBER, OP_PATLIST };
194    
195  typedef struct option_item {  typedef struct option_item {
196    int type;    int type;
# Line 214  used to identify them. */ Line 217  used to identify them. */
217  #define N_LBUFFER      (-12)  #define N_LBUFFER      (-12)
218  #define N_M_LIMIT      (-13)  #define N_M_LIMIT      (-13)
219  #define N_M_LIMIT_REC  (-14)  #define N_M_LIMIT_REC  (-14)
220    #define N_BUFSIZE      (-15)
221    
222  static option_item optionlist[] = {  static option_item optionlist[] = {
223    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "  terminate options" },
224    { OP_NODATA,    N_HELP,   NULL,              "help",          "display this help and exit" },    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
225    { 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" },
226    { 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" },
227    { OP_OP_STRING, N_COLOUR, &colour_option,    "color=option",  "matched text color option" },    { OP_NUMBER,     N_BUFSIZE,&bufthird,         "buffer-size=number", "set processing buffer size parameter" },
228    { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
229    { OP_NUMBER,    'C',      &both_context,     "context=number", "set number of context lines, before & after" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
230    { OP_NODATA,    'c',      NULL,              "count",         "print only a count of matching lines per FILE" },    { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
231    { OP_STRING,    'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },    { OP_NODATA,     'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
232    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },    { OP_STRING,     'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },
233    { OP_PATLIST,   'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },    { OP_STRING,     'd',      &dee_option,       "directories=action", "how to handle directories" },
234    { OP_NODATA,    'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },    { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
235    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_NODATA,     'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },
236    { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
237    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
238    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
239    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
240    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },    { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
241    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },    { OP_NODATA,     'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
242    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },    { OP_NODATA,     'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
243    { OP_NODATA,    N_LBUFFER, NULL,             "line-buffered", "use line buffering" },    { OP_STRING,     N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
244    { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },    { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
245    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
246    { OP_NUMBER,    N_M_LIMIT,&match_limit,      "match-limit=number", "set PCRE match limit option" },    { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
247    { OP_NUMBER,    N_M_LIMIT_REC,&match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },    { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
248    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
249    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
250    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
251    { OP_OP_NUMBER, 'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
252    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
253    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
254    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
255    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
256    { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },    { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
257    { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },    { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
258      { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },
259    
260    /* These two were accidentally implemented with underscores instead of    /* These two were accidentally implemented with underscores instead of
261    hyphens in the option names. As this was not discovered for several releases,    hyphens in the option names. As this was not discovered for several releases,
262    the incorrect versions are left in the table for compatibility. However, the    the incorrect versions are left in the table for compatibility. However, the
263    --help function misses out any option that has an underscore in its name. */    --help function misses out any option that has an underscore in its name. */
264    
265    { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },    { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
266    { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },    { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
267    
# Line 296  const char utf8_table4[] = { Line 301  const char utf8_table4[] = {
301    
302    
303  /*************************************************  /*************************************************
304    *         Exit from the program                  *
305    *************************************************/
306    
307    /* If there has been a resource error, give a suitable message.
308    
309    Argument:  the return code
310    Returns:   does not return
311    */
312    
313    static void
314    pcregrep_exit(int rc)
315    {
316    if (resource_error)
317      {
318      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
319        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
320      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
321      }
322    
323    exit(rc);
324    }
325    
326    
327    /*************************************************
328  *            OS-specific functions               *  *            OS-specific functions               *
329  *************************************************/  *************************************************/
330    
# Line 565  return sys_errlist[n]; Line 594  return sys_errlist[n];
594    
595    
596  /*************************************************  /*************************************************
 *         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);  
 }  
   
   
   
 /*************************************************  
597  *            Read one line of input              *  *            Read one line of input              *
598  *************************************************/  *************************************************/
599    
# Line 635  Arguments: Line 639  Arguments:
639    endptr    end of available data    endptr    end of available data
640    lenptr    where to put the length of the eol sequence    lenptr    where to put the length of the eol sequence
641    
642  Returns:    pointer to the last byte of the line  Returns:    pointer after the last byte of the line,
643                including the newline byte(s)
644  */  */
645    
646  static char *  static char *
# Line 936  is used multiple times for the same subj Line 941  is used multiple times for the same subj
941  to find all possible matches.  to find all possible matches.
942    
943  Arguments:  Arguments:
944    matchptr    the start of the subject    matchptr     the start of the subject
945    length      the length of the subject to match    length       the length of the subject to match
946    offsets     the offets vector to fill in    startoffset  where to start matching
947    mrc         address of where to put the result of pcre_exec()    offsets      the offets vector to fill in
948      mrc          address of where to put the result of pcre_exec()
949    
950  Returns:      TRUE if there was a match  Returns:      TRUE if there was a match
951                FALSE if there was no match                FALSE if there was no match
# Line 947  Returns:      TRUE if there was a match Line 953  Returns:      TRUE if there was a match
953  */  */
954    
955  static BOOL  static BOOL
956  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)  match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
957      int *mrc)
958  {  {
959  int i;  int i;
960  size_t slen = length;  size_t slen = length;
# Line 956  if (slen > 200) Line 963  if (slen > 200)
963    {    {
964    slen = 200;    slen = 200;
965    msg = "text that starts:\n\n";    msg = "text that starts:\n\n";
966    }    }
967  for (i = 0; i < pattern_count; i++)  for (i = 0; i < pattern_count; i++)
968    {    {
969    *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,
970      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);      startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
971    if (*mrc >= 0) return TRUE;    if (*mrc >= 0) return TRUE;
972    if (*mrc == PCRE_ERROR_NOMATCH) continue;    if (*mrc == PCRE_ERROR_NOMATCH) continue;
973    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
# Line 988  return FALSE;  /* No match, no errors */ Line 995  return FALSE;  /* No match, no errors */
995  *************************************************/  *************************************************/
996    
997  /* 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
998  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
999  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
1000  context printing or for multiline scanning. For large files, the pointer will  context printing or for multiline scanning. For large files, the pointer will
1001  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 1006  Arguments:
1006                 the gzFile pointer when reading is via libz                 the gzFile pointer when reading is via libz
1007                 the BZFILE pointer when reading is via libbz2                 the BZFILE pointer when reading is via libbz2
1008    frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2    frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
1009      filename     the file name or NULL (for errors)
1010    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
1011                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
1012                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
1013    
1014  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
1015                 1 otherwise (no matches)                 1 otherwise (no matches)
1016                 2 if there is a read error on a .bz2 file                 2 if an overlong line is encountered
1017                   3 if there is a read error on a .bz2 file
1018  */  */
1019    
1020  static int  static int
1021  pcregrep(void *handle, int frtype, char *printname)  pcregrep(void *handle, int frtype, char *filename, char *printname)
1022  {  {
1023  int rc = 1;  int rc = 1;
1024  int linenumber = 1;  int linenumber = 1;
# Line 1018  int count = 0; Line 1027  int count = 0;
1027  int filepos = 0;  int filepos = 0;
1028  int offsets[OFFSET_SIZE];  int offsets[OFFSET_SIZE];
1029  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
1030  char buffer[3*MBUFTHIRD];  char *ptr = main_buffer;
 char *ptr = buffer;  
1031  char *endptr;  char *endptr;
1032  size_t bufflength;  size_t bufflength;
1033  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
# Line 1044  fail. */ Line 1052  fail. */
1052  if (frtype == FR_LIBZ)  if (frtype == FR_LIBZ)
1053    {    {
1054    ingz = (gzFile)handle;    ingz = (gzFile)handle;
1055    bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);    bufflength = gzread (ingz, main_buffer, bufsize);
1056    }    }
1057  else  else
1058  #endif  #endif
# Line 1053  else Line 1061  else
1061  if (frtype == FR_LIBBZ2)  if (frtype == FR_LIBBZ2)
1062    {    {
1063    inbz2 = (BZFILE *)handle;    inbz2 = (BZFILE *)handle;
1064    bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);    bufflength = BZ2_bzread(inbz2, main_buffer, bufsize);
1065    if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */    if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1066    }                                    /* without the cast it is unsigned. */    }                                    /* without the cast it is unsigned. */
1067  else  else
# Line 1063  else Line 1071  else
1071    in = (FILE *)handle;    in = (FILE *)handle;
1072    if (is_file_tty(in)) input_line_buffered = TRUE;    if (is_file_tty(in)) input_line_buffered = TRUE;
1073    bufflength = input_line_buffered?    bufflength = input_line_buffered?
1074      read_one_line(buffer, 3*MBUFTHIRD, in) :      read_one_line(main_buffer, bufsize, in) :
1075      fread(buffer, 1, 3*MBUFTHIRD, in);      fread(main_buffer, 1, bufsize, in);
1076    }    }
1077    
1078  endptr = buffer + bufflength;  endptr = main_buffer + bufflength;
1079    
1080  /* 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
1081  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 1086  while (ptr < endptr)
1086    {    {
1087    int endlinelength;    int endlinelength;
1088    int mrc = 0;    int mrc = 0;
1089      int startoffset = 0;
1090    BOOL match;    BOOL match;
1091    char *matchptr = ptr;    char *matchptr = ptr;
1092    char *t = ptr;    char *t = ptr;
# Line 1094  while (ptr < endptr) Line 1103  while (ptr < endptr)
1103    t = end_of_line(t, endptr, &endlinelength);    t = end_of_line(t, endptr, &endlinelength);
1104    linelength = t - ptr - endlinelength;    linelength = t - ptr - endlinelength;
1105    length = multiline? (size_t)(endptr - ptr) : linelength;    length = multiline? (size_t)(endptr - ptr) : linelength;
1106    
1107      /* Check to see if the line we are looking at extends right to the very end
1108      of the buffer without a line terminator. This means the line is too long to
1109      handle. */
1110    
1111      if (endlinelength == 0 && t == main_buffer + bufsize)
1112        {
1113        fprintf(stderr, "pcregrep: line %d%s%s is too long for the internal buffer\n"
1114                        "pcregrep: check the --buffer-size option\n",
1115                        linenumber,
1116                        (filename == NULL)? "" : " of file ",
1117                        (filename == NULL)? "" : filename);
1118        return 2;
1119        }
1120    
1121    /* Extra processing for Jeffrey Friedl's debugging. */    /* Extra processing for Jeffrey Friedl's debugging. */
1122    
# Line 1154  while (ptr < endptr) Line 1177  while (ptr < endptr)
1177    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
1178    finding subsequent matches when colouring matched lines. */    finding subsequent matches when colouring matched lines. */
1179    
1180    match = match_patterns(matchptr, length, offsets, &mrc);    match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
1181    
1182    /* 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. */
1183    
# Line 1183  while (ptr < endptr) Line 1206  while (ptr < endptr)
1206    
1207      else if (quiet) return 0;      else if (quiet) return 0;
1208    
1209      /* The --only-matching option prints just the substring that matched, or a      /* The --only-matching option prints just the substring that matched, or a
1210      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
1211      --file-offsets and --line-offsets options output offsets for the matching      --file-offsets and --line-offsets options output offsets for the matching
1212      substring (they both force --only-matching = 0). None of these options      substring (they both force --only-matching = 0). None of these options
1213      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
1214      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,
1215      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
1216      be useful because the return code is set. */      because the return code is set. */
1217    
1218      else if (only_matching >= 0)      else if (only_matching >= 0)
1219        {        {
# Line 1202  while (ptr < endptr) Line 1225  while (ptr < endptr)
1225            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1226              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1227          else if (file_offsets)          else if (file_offsets)
1228            fprintf(stdout, "%d,%d\n",            fprintf(stdout, "%d,%d\n",
1229              (int)(filepos + matchptr + offsets[0] - ptr),              (int)(filepos + matchptr + offsets[0] - ptr),
1230              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1231          else if (only_matching < mrc)          else if (only_matching < mrc)
1232            {            {
1233            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1234            if (plen > 0)            if (plen > 0)
1235              {              {
1236              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1237              FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);              FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1238              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1239              fprintf(stdout, "\n");              fprintf(stdout, "\n");
1240              }              }
1241            }            }
1242          else if (printname != NULL || number) fprintf(stdout, "\n");          else if (printname != NULL || number) fprintf(stdout, "\n");
         matchptr += offsets[1];  
         length -= offsets[1];  
1243          match = FALSE;          match = FALSE;
1244          if (line_buffered) fflush(stdout);          if (line_buffered) fflush(stdout);
1245          rc = 0;    /* Had some success */          rc = 0;                      /* Had some success */
1246            startoffset = offsets[1];    /* Restart after the match */
1247          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1248          }          }
1249        }        }
# Line 1280  while (ptr < endptr) Line 1302  while (ptr < endptr)
1302          int linecount = 0;          int linecount = 0;
1303          char *p = ptr;          char *p = ptr;
1304    
1305          while (p > buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&          while (p > main_buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
1306                 linecount < before_context)                 linecount < before_context)
1307            {            {
1308            linecount++;            linecount++;
1309            p = previous_line(p, buffer);            p = previous_line(p, main_buffer);
1310            }            }
1311    
1312          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 1317  while (ptr < endptr) Line 1339  while (ptr < endptr)
1339        (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
1340        the match will always be before the first newline sequence. */        the match will always be before the first newline sequence. */
1341    
1342        if (multiline)        if (multiline & !invert)
1343          {          {
1344          int ellength;          char *endmatch = ptr + offsets[1];
1345          char *endmatch = ptr;          t = ptr;
1346          if (!invert)          while (t < endmatch)
1347            {            {
1348            endmatch += offsets[1];            t = end_of_line(t, endptr, &endlinelength);
1349            t = ptr;            if (t < endmatch) linenumber++; else break;
           while (t < endmatch)  
             {  
             t = end_of_line(t, endptr, &ellength);  
             if (t <= endmatch) linenumber++; else break;  
             }  
1350            }            }
1351          endmatch = end_of_line(endmatch, endptr, &ellength);          linelength = t - ptr - endlinelength;
         linelength = endmatch - ptr - ellength;  
1352          }          }
1353    
1354        /*** 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 1355  while (ptr < endptr) Line 1371  while (ptr < endptr)
1371  #endif  #endif
1372    
1373        /* We have to split the line(s) up if colouring, and search for further        /* We have to split the line(s) up if colouring, and search for further
1374        matches. */        matches, but not of course if the line is a non-match. */
1375    
1376        if (do_colour)        if (do_colour && !invert)
1377          {          {
1378          int last_offset = 0;          int plength;
1379          FWRITE(ptr, 1, offsets[0], stdout);          FWRITE(ptr, 1, offsets[0], stdout);
1380          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1381          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1382          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1383          for (;;)          for (;;)
1384            {            {
1385            last_offset += offsets[1];            startoffset = offsets[1];
1386            matchptr += offsets[1];            if (startoffset >= linelength + endlinelength ||
1387            length -= offsets[1];                !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1388            if (!match_patterns(matchptr, length, offsets, &mrc)) break;              break;
1389            FWRITE(matchptr, 1, offsets[0], stdout);            FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1390            fprintf(stdout, "%c[%sm", 0x1b, colour_string);            fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1391            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1392            fprintf(stdout, "%c[00m", 0x1b);            fprintf(stdout, "%c[00m", 0x1b);
1393            }            }
1394          FWRITE(ptr + last_offset, 1,  
1395            (linelength + endlinelength) - last_offset, stdout);          /* In multiline mode, we may have already printed the complete line
1396            and its line-ending characters (if they matched the pattern), so there
1397            may be no more to print. */
1398    
1399            plength = (linelength + endlinelength) - startoffset;
1400            if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout);
1401          }          }
1402    
1403        /* Not colouring; no need to search for further matches */        /* Not colouring; no need to search for further matches */
# Line 1425  while (ptr < endptr) Line 1446  while (ptr < endptr)
1446    /* 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
1447    line and add it into the buffer. */    line and add it into the buffer. */
1448    
1449    if (input_line_buffered && bufflength < sizeof(buffer))    if (input_line_buffered && bufflength < bufsize)
1450      {      {
1451      int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);      int add = read_one_line(ptr, bufsize - (ptr - main_buffer), in);
1452      bufflength += add;      bufflength += add;
1453      endptr += add;      endptr += add;
1454      }      }
# Line 1437  while (ptr < endptr) Line 1458  while (ptr < endptr)
1458    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
1459    about to be lost, print them. */    about to be lost, print them. */
1460    
1461    if (bufflength >= sizeof(buffer) && ptr > buffer + 2*MBUFTHIRD)    if (bufflength >= bufsize && ptr > main_buffer + 2*bufthird)
1462      {      {
1463      if (after_context > 0 &&      if (after_context > 0 &&
1464          lastmatchnumber > 0 &&          lastmatchnumber > 0 &&
1465          lastmatchrestart < buffer + MBUFTHIRD)          lastmatchrestart < main_buffer + bufthird)
1466        {        {
1467        do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);        do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1468        lastmatchnumber = 0;        lastmatchnumber = 0;
# Line 1449  while (ptr < endptr) Line 1470  while (ptr < endptr)
1470    
1471      /* Now do the shuffle */      /* Now do the shuffle */
1472    
1473      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(main_buffer, main_buffer + bufthird, 2*bufthird);
1474      ptr -= MBUFTHIRD;      ptr -= bufthird;
1475    
1476  #ifdef SUPPORT_LIBZ  #ifdef SUPPORT_LIBZ
1477      if (frtype == FR_LIBZ)      if (frtype == FR_LIBZ)
1478        bufflength = 2*MBUFTHIRD +        bufflength = 2*bufthird +
1479          gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);          gzread (ingz, main_buffer + 2*bufthird, bufthird);
1480      else      else
1481  #endif  #endif
1482    
1483  #ifdef SUPPORT_LIBBZ2  #ifdef SUPPORT_LIBBZ2
1484      if (frtype == FR_LIBBZ2)      if (frtype == FR_LIBBZ2)
1485        bufflength = 2*MBUFTHIRD +        bufflength = 2*bufthird +
1486          BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);          BZ2_bzread(inbz2, main_buffer + 2*bufthird, bufthird);
1487      else      else
1488  #endif  #endif
1489    
1490      bufflength = 2*MBUFTHIRD +      bufflength = 2*bufthird +
1491        (input_line_buffered?        (input_line_buffered?
1492         read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :         read_one_line(main_buffer + 2*bufthird, bufthird, in) :
1493         fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));         fread(main_buffer + 2*bufthird, 1, bufthird, in));
1494      endptr = buffer + bufflength;      endptr = main_buffer + bufflength;
1495    
1496      /* Adjust any last match point */      /* Adjust any last match point */
1497    
1498      if (lastmatchnumber > 0) lastmatchrestart -= MBUFTHIRD;      if (lastmatchnumber > 0) lastmatchrestart -= bufthird;
1499      }      }
1500    }     /* Loop through the whole file */    }     /* Loop through the whole file */
1501    
# Line 1554  BZFILE *inbz2 = NULL; Line 1575  BZFILE *inbz2 = NULL;
1575    
1576  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1577    {    {
1578    return pcregrep(stdin, FR_PLAIN,    return pcregrep(stdin, FR_PLAIN, stdin_name,
1579      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1580        stdin_name : NULL);        stdin_name : NULL);
1581    }    }
# Line 1686  if (handle == NULL) Line 1707  if (handle == NULL)
1707    
1708  /* Now grep the file */  /* Now grep the file */
1709    
1710  rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||  rc = pcregrep(handle, frtype, pathname, (filenames > FN_DEFAULT ||
1711    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1712    
1713  /* Close in an appropriate manner. */  /* Close in an appropriate manner. */
# Line 1697  if (frtype == FR_LIBZ) Line 1718  if (frtype == FR_LIBZ)
1718  else  else
1719  #endif  #endif
1720    
1721  /* 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
1722  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
1723  again as a normal file. */  again as a normal file. */
1724    
1725  #ifdef SUPPORT_LIBBZ2  #ifdef SUPPORT_LIBBZ2
1726  if (frtype == FR_LIBBZ2)  if (frtype == FR_LIBBZ2)
1727    {    {
1728    if (rc == 2)    if (rc == 3)
1729      {      {
1730      int errnum;      int errnum;
1731      const char *err = BZ2_bzerror(inbz2, &errnum);      const char *err = BZ2_bzerror(inbz2, &errnum);
# Line 1716  if (frtype == FR_LIBBZ2) Line 1737  if (frtype == FR_LIBBZ2)
1737      else if (!silent)      else if (!silent)
1738        fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",        fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1739          pathname, err);          pathname, err);
1740        rc = 2;    /* The normal "something went wrong" code */
1741      }      }
1742    BZ2_bzclose(inbz2);    BZ2_bzclose(inbz2);
1743    }    }
# Line 1791  for (op = optionlist; op->one_char != 0; Line 1813  for (op = optionlist; op->one_char != 0;
1813    {    {
1814    int n;    int n;
1815    char s[4];    char s[4];
1816    
1817    /* Two options were accidentally implemented and documented with underscores    /* Two options were accidentally implemented and documented with underscores
1818    instead of hyphens in their names, something that was not noticed for quite a    instead of hyphens in their names, something that was not noticed for quite a
1819    few releases. When fixing this, I left the underscored versions in the list    few releases. When fixing this, I left the underscored versions in the list
1820    in case people were using them. However, we don't want to display them in the    in case people were using them. However, we don't want to display them in the
1821    help data. There are no other options that contain underscores, and we do not    help data. There are no other options that contain underscores, and we do not
1822    expect ever to implement such options. Therefore, just omit any option that    expect ever to implement such options. Therefore, just omit any option that
1823    contains an underscore. */    contains an underscore. */
1824    
1825    if (strchr(op->long_name, '_') != NULL) continue;    if (strchr(op->long_name, '_') != NULL) continue;
1826    
1827    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, "   ");
1828    n = 31 - printf("  %s --%s", s, op->long_name);    n = 31 - printf("  %s --%s", s, op->long_name);
1829    if (n < 1) n = 1;    if (n < 1) n = 1;
1830    printf("%.*s%s\n", n, "                     ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1831    }    }
1832    
1833  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");
1834    printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);
1835    printf("When reading patterns from a file instead of using a command line option,\n");
1836  printf("trailing white space is removed and blank lines are ignored.\n");  printf("trailing white space is removed and blank lines are ignored.\n");
1837  printf("There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT);  printf("There is a maximum of %d patterns, each of maximum size %d bytes.\n",
1838      MAX_PATTERN_COUNT, PATBUFSIZE);
1839    
1840  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");
1841  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 1912  Returns:         TRUE on success, FALSE Line 1937  Returns:         TRUE on success, FALSE
1937  static BOOL  static BOOL
1938  compile_single_pattern(char *pattern, int options, char *filename, int count)  compile_single_pattern(char *pattern, int options, char *filename, int count)
1939  {  {
1940  char buffer[MBUFTHIRD + 16];  char buffer[PATBUFSIZE];
1941  const char *error;  const char *error;
1942  int errptr;  int errptr;
1943    
# Line 1923  if (pattern_count >= MAX_PATTERN_COUNT) Line 1948  if (pattern_count >= MAX_PATTERN_COUNT)
1948    return FALSE;    return FALSE;
1949    }    }
1950    
1951  sprintf(buffer, "%s%.*s%s", prefix[process_options], MBUFTHIRD, pattern,  sprintf(buffer, "%s%.*s%s", prefix[process_options], bufthird, pattern,
1952    suffix[process_options]);    suffix[process_options]);
1953  pattern_list[pattern_count] =  pattern_list[pattern_count] =
1954    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
# Line 1982  compile_pattern(char *pattern, int optio Line 2007  compile_pattern(char *pattern, int optio
2007  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
2008    {    {
2009    char *eop = pattern + strlen(pattern);    char *eop = pattern + strlen(pattern);
2010    char buffer[MBUFTHIRD];    char buffer[PATBUFSIZE];
2011    for(;;)    for(;;)
2012      {      {
2013      int ellength;      int ellength;
# Line 2181  for (i = 1; i < argc; i++) Line 2206  for (i = 1; i < argc; i++)
2206      while (*s != 0)      while (*s != 0)
2207        {        {
2208        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2209          {          {
2210          if (*s == op->one_char) break;          if (*s == op->one_char) break;
2211          }          }
2212        if (op->one_char == 0)        if (op->one_char == 0)
2213          {          {
# Line 2190  for (i = 1; i < argc; i++) Line 2215  for (i = 1; i < argc; i++)
2215            *s, argv[i]);            *s, argv[i]);
2216          pcregrep_exit(usage(2));          pcregrep_exit(usage(2));
2217          }          }
2218    
2219        /* Check for a single-character option that has data: OP_OP_NUMBER        /* Check for a single-character option that has data: OP_OP_NUMBER
2220        is used for one that either has a numerical number or defaults, i.e. the        is used for one that either has a numerical number or defaults, i.e. the
2221        data is optional. If a digit follows, there is data; if not, carry on        data is optional. If a digit follows, there is data; if not, carry on
2222        with other single-character options in the same string. */        with other single-character options in the same string. */
2223    
2224        option_data = s+1;        option_data = s+1;
2225        if (op->type == OP_OP_NUMBER)        if (op->type == OP_OP_NUMBER)
2226          {          {
2227          if (isdigit((unsigned char)s[1])) break;          if (isdigit((unsigned char)s[1])) break;
2228          }          }
2229        else   /* Check for end or a dataless option */        else   /* Check for end or a dataless option */
2230          {          {
2231          if (op->type != OP_NODATA || s[1] == 0) break;          if (op->type != OP_NODATA || s[1] == 0) break;
2232          }          }
2233    
2234        /* Handle a single-character option with no data, then loop for the        /* Handle a single-character option with no data, then loop for the
2235        next character in the string. */        next character in the string. */
2236    
2237        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
# Line 2225  for (i = 1; i < argc; i++) Line 2250  for (i = 1; i < argc; i++)
2250    
2251    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that
2252    either has a value or defaults to something. It cannot have data in a    either has a value or defaults to something. It cannot have data in a
2253    separate item. At the moment, the only such options are "colo(u)r",    separate item. At the moment, the only such options are "colo(u)r",
2254    "only-matching", and Jeffrey Friedl's special -S debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2255    
2256    if (*option_data == 0 &&    if (*option_data == 0 &&
# Line 2236  for (i = 1; i < argc; i++) Line 2261  for (i = 1; i < argc; i++)
2261        case N_COLOUR:        case N_COLOUR:
2262        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2263        break;        break;
2264    
2265        case 'o':        case 'o':
2266        only_matching = 0;        only_matching = 0;
2267        break;        break;
2268    
2269  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2270        case 'S':        case 'S':
2271        S_arg = 0;        S_arg = 0;
# Line 2278  for (i = 1; i < argc; i++) Line 2303  for (i = 1; i < argc; i++)
2303    
2304    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2305    
2306    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2307               op->type != OP_OP_NUMBER)
2308      {      {
2309      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2310      }      }
# Line 2293  for (i = 1; i < argc; i++) Line 2319  for (i = 1; i < argc; i++)
2319      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2320      while (isdigit((unsigned char)(*endptr)))      while (isdigit((unsigned char)(*endptr)))
2321        n = n * 10 + (int)(*endptr++ - '0');        n = n * 10 + (int)(*endptr++ - '0');
2322        if (toupper(*endptr) == 'K')
2323          {
2324          n *= 1024;
2325          endptr++;
2326          }
2327        else if (toupper(*endptr) == 'M')
2328          {
2329          n *= 1024*1024;
2330          endptr++;
2331          }
2332      if (*endptr != 0)      if (*endptr != 0)
2333        {        {
2334        if (longop)        if (longop)
# Line 2308  for (i = 1; i < argc; i++) Line 2344  for (i = 1; i < argc; i++)
2344            option_data, op->one_char);            option_data, op->one_char);
2345        pcregrep_exit(usage(2));        pcregrep_exit(usage(2));
2346        }        }
2347      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2348            *((unsigned long int *)op->dataptr) = n;
2349        else
2350            *((int *)op->dataptr) = n;
2351      }      }
2352    }    }
2353    
# Line 2456  if (jfriedl_XT != 0 || jfriedl_XR != 0) Line 2495  if (jfriedl_XT != 0 || jfriedl_XR != 0)
2495    }    }
2496  #endif  #endif
2497    
2498  /* Get memory to store the pattern and hints lists. */  /* Get memory for the main buffer, and to store the pattern and hints lists. */
2499    
2500    bufsize = 3*bufthird;
2501    main_buffer = (char *)malloc(bufsize);
2502  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
2503  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));
2504    
2505  if (pattern_list == NULL || hints_list == NULL)  if (main_buffer == NULL || pattern_list == NULL || hints_list == NULL)
2506    {    {
2507    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2508    goto EXIT2;    goto EXIT2;
# Line 2493  if (pattern_filename != NULL) Line 2534  if (pattern_filename != NULL)
2534    int linenumber = 0;    int linenumber = 0;
2535    FILE *f;    FILE *f;
2536    char *filename;    char *filename;
2537    char buffer[MBUFTHIRD];    char buffer[PATBUFSIZE];
2538    
2539    if (strcmp(pattern_filename, "-") == 0)    if (strcmp(pattern_filename, "-") == 0)
2540      {      {
# Line 2512  if (pattern_filename != NULL) Line 2553  if (pattern_filename != NULL)
2553      filename = pattern_filename;      filename = pattern_filename;
2554      }      }
2555    
2556    while (fgets(buffer, MBUFTHIRD, f) != NULL)    while (fgets(buffer, PATBUFSIZE, f) != NULL)
2557      {      {
2558      char *s = buffer + (int)strlen(buffer);      char *s = buffer + (int)strlen(buffer);
2559      while (s > buffer && isspace((unsigned char)(s[-1]))) s--;      while (s > buffer && isspace((unsigned char)(s[-1]))) s--;
# Line 2540  for (j = 0; j < pattern_count; j++) Line 2581  for (j = 0; j < pattern_count; j++)
2581      }      }
2582    hint_count++;    hint_count++;
2583    }    }
2584    
2585  /* 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
2586  pcre_extra block for each pattern. */  pcre_extra block for each pattern. */
2587    
# Line 2551  if (match_limit > 0 || match_limit_recur Line 2592  if (match_limit > 0 || match_limit_recur
2592      if (hints_list[j] == NULL)      if (hints_list[j] == NULL)
2593        {        {
2594        hints_list[j] = malloc(sizeof(pcre_extra));        hints_list[j] = malloc(sizeof(pcre_extra));
2595        if (hints_list[j] == NULL)        if (hints_list[j] == NULL)
2596          {          {
2597          fprintf(stderr, "pcregrep: malloc failed\n");          fprintf(stderr, "pcregrep: malloc failed\n");
2598          pcregrep_exit(2);          pcregrep_exit(2);
2599          }          }
2600        }        }
2601      if (match_limit > 0)      if (match_limit > 0)
2602        {        {
2603        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2604        hints_list[j]->match_limit = match_limit;        hints_list[j]->match_limit = match_limit;
2605        }        }
2606      if (match_limit_recursion > 0)      if (match_limit_recursion > 0)
2607        {        {
2608        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2609        hints_list[j]->match_limit_recursion = match_limit_recursion;        hints_list[j]->match_limit_recursion = match_limit_recursion;
2610        }        }
2611      }      }
2612    }    }
2613    
2614  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2615    
# Line 2624  if (include_dir_pattern != NULL) Line 2665  if (include_dir_pattern != NULL)
2665    
2666  if (i >= argc)  if (i >= argc)
2667    {    {
2668    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);    rc = pcregrep(stdin, FR_PLAIN, stdin_name,
2669        (filenames > FN_DEFAULT)? stdin_name : NULL);
2670    goto EXIT;    goto EXIT;
2671    }    }
2672    
# Line 2644  for (; i < argc; i++) Line 2686  for (; i < argc; i++)
2686    }    }
2687    
2688  EXIT:  EXIT:
2689    if (main_buffer != NULL) free(main_buffer);
2690  if (pattern_list != NULL)  if (pattern_list != NULL)
2691    {    {
2692    for (i = 0; i < pattern_count; i++) free(pattern_list[i]);    for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
# Line 2651  if (pattern_list != NULL) Line 2694  if (pattern_list != NULL)
2694    }    }
2695  if (hints_list != NULL)  if (hints_list != NULL)
2696    {    {
2697    for (i = 0; i < hint_count; i++)    for (i = 0; i < hint_count; i++)
2698      {      {
2699      if (hints_list[i] != NULL) free(hints_list[i]);      if (hints_list[i] != NULL) free(hints_list[i]);
2700      }      }
2701    free(hints_list);    free(hints_list);
2702    }    }
2703  pcregrep_exit(rc);  pcregrep_exit(rc);

Legend:
Removed from v.571  
changed lines
  Added in v.646

  ViewVC Help
Powered by ViewVC 1.1.5