/[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 565 by ph10, Sun Oct 31 18:18:48 2010 UTC revision 667 by ph10, Mon Aug 22 14:57:32 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;
168  static int filenames = FN_DEFAULT;  static int filenames = FN_DEFAULT;
169  static int only_matching = -1;  static int only_matching = -1;
170  static int process_options = 0;  static int process_options = 0;
171    static int study_options = 0;
172    
173  static unsigned long int match_limit = 0;  static unsigned long int match_limit = 0;
174  static unsigned long int match_limit_recursion = 0;  static unsigned long int match_limit_recursion = 0;
# Line 186  static BOOL utf8 = FALSE; Line 190  static BOOL utf8 = FALSE;
190    
191  /* Structure for options and list of them */  /* Structure for options and list of them */
192    
193  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,
194         OP_PATLIST };         OP_OP_NUMBER, OP_PATLIST };
195    
196  typedef struct option_item {  typedef struct option_item {
197    int type;    int type;
# Line 214  used to identify them. */ Line 218  used to identify them. */
218  #define N_LBUFFER      (-12)  #define N_LBUFFER      (-12)
219  #define N_M_LIMIT      (-13)  #define N_M_LIMIT      (-13)
220  #define N_M_LIMIT_REC  (-14)  #define N_M_LIMIT_REC  (-14)
221    #define N_BUFSIZE      (-15)
222    
223  static option_item optionlist[] = {  static option_item optionlist[] = {
224    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "  terminate options" },
225    { OP_NODATA,    N_HELP,   NULL,              "help",          "display this help and exit" },    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
226    { 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" },
227    { 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" },
228    { 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" },
229    { 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" },
230    { 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" },
231    { 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" },
232    { 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" },
233    { 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" },
234    { 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" },
235    { 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)" },
236    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_NODATA,     'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },
237    { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
238    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
239    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
240    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
241    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },    { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
242    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },    { OP_NODATA,     'j',      NULL,              "jit",           "use JIT compiler if available" },
243    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },    { OP_NODATA,     'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
244    { OP_NODATA,    N_LBUFFER, NULL,             "line-buffered", "use line buffering" },    { OP_NODATA,     'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
245    { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },    { OP_STRING,     N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
246    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
247    { OP_NUMBER,    N_M_LIMIT,&match_limit,      "match-limit=number", "set PCRE match limit option" },    { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
248    { OP_NUMBER,    N_M_LIMIT_REC,&match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },    { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
249    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
250    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
251    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
252    { OP_OP_NUMBER, 'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },    { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
253    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
254    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
255    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
256    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
257      { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
258      { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
259      { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
260      { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },
261    
262      /* These two were accidentally implemented with underscores instead of
263      hyphens in the option names. As this was not discovered for several releases,
264      the incorrect versions are left in the table for compatibility. However, the
265      --help function misses out any option that has an underscore in its name. */
266    
267    { 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" },
268    { 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" },
269    
270  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
271    { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },    { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },
272  #endif  #endif
# Line 287  const char utf8_table4[] = { Line 303  const char utf8_table4[] = {
303    
304    
305  /*************************************************  /*************************************************
306    *         Exit from the program                  *
307    *************************************************/
308    
309    /* If there has been a resource error, give a suitable message.
310    
311    Argument:  the return code
312    Returns:   does not return
313    */
314    
315    static void
316    pcregrep_exit(int rc)
317    {
318    if (resource_error)
319      {
320      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
321        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
322      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
323      }
324    
325    exit(rc);
326    }
327    
328    
329    /*************************************************
330  *            OS-specific functions               *  *            OS-specific functions               *
331  *************************************************/  *************************************************/
332    
# Line 556  return sys_errlist[n]; Line 596  return sys_errlist[n];
596    
597    
598  /*************************************************  /*************************************************
 *         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);  
 }  
   
   
   
 /*************************************************  
599  *            Read one line of input              *  *            Read one line of input              *
600  *************************************************/  *************************************************/
601    
# Line 626  Arguments: Line 641  Arguments:
641    endptr    end of available data    endptr    end of available data
642    lenptr    where to put the length of the eol sequence    lenptr    where to put the length of the eol sequence
643    
644  Returns:    pointer to the last byte of the line  Returns:    pointer after the last byte of the line,
645                including the newline byte(s)
646  */  */
647    
648  static char *  static char *
# Line 927  is used multiple times for the same subj Line 943  is used multiple times for the same subj
943  to find all possible matches.  to find all possible matches.
944    
945  Arguments:  Arguments:
946    matchptr    the start of the subject    matchptr     the start of the subject
947    length      the length of the subject to match    length       the length of the subject to match
948    offsets     the offets vector to fill in    startoffset  where to start matching
949    mrc         address of where to put the result of pcre_exec()    offsets      the offets vector to fill in
950      mrc          address of where to put the result of pcre_exec()
951    
952  Returns:      TRUE if there was a match  Returns:      TRUE if there was a match
953                FALSE if there was no match                FALSE if there was no match
# Line 938  Returns:      TRUE if there was a match Line 955  Returns:      TRUE if there was a match
955  */  */
956    
957  static BOOL  static BOOL
958  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)  match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
959      int *mrc)
960  {  {
961  int i;  int i;
962  size_t slen = length;  size_t slen = length;
# Line 947  if (slen > 200) Line 965  if (slen > 200)
965    {    {
966    slen = 200;    slen = 200;
967    msg = "text that starts:\n\n";    msg = "text that starts:\n\n";
968    }    }
969  for (i = 0; i < pattern_count; i++)  for (i = 0; i < pattern_count; i++)
970    {    {
971    *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,
972      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);      startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
973    if (*mrc >= 0) return TRUE;    if (*mrc >= 0) return TRUE;
974    if (*mrc == PCRE_ERROR_NOMATCH) continue;    if (*mrc == PCRE_ERROR_NOMATCH) continue;
975    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
# Line 979  return FALSE;  /* No match, no errors */ Line 997  return FALSE;  /* No match, no errors */
997  *************************************************/  *************************************************/
998    
999  /* 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
1000  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
1001  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
1002  context printing or for multiline scanning. For large files, the pointer will  context printing or for multiline scanning. For large files, the pointer will
1003  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 990  Arguments: Line 1008  Arguments:
1008                 the gzFile pointer when reading is via libz                 the gzFile pointer when reading is via libz
1009                 the BZFILE pointer when reading is via libbz2                 the BZFILE pointer when reading is via libbz2
1010    frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2    frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
1011      filename     the file name or NULL (for errors)
1012    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
1013                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
1014                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
1015    
1016  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
1017                 1 otherwise (no matches)                 1 otherwise (no matches)
1018                 2 if there is a read error on a .bz2 file                 2 if an overlong line is encountered
1019                   3 if there is a read error on a .bz2 file
1020  */  */
1021    
1022  static int  static int
1023  pcregrep(void *handle, int frtype, char *printname)  pcregrep(void *handle, int frtype, char *filename, char *printname)
1024  {  {
1025  int rc = 1;  int rc = 1;
1026  int linenumber = 1;  int linenumber = 1;
# Line 1009  int count = 0; Line 1029  int count = 0;
1029  int filepos = 0;  int filepos = 0;
1030  int offsets[OFFSET_SIZE];  int offsets[OFFSET_SIZE];
1031  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
1032  char buffer[3*MBUFTHIRD];  char *ptr = main_buffer;
 char *ptr = buffer;  
1033  char *endptr;  char *endptr;
1034  size_t bufflength;  size_t bufflength;
1035  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
# Line 1035  fail. */ Line 1054  fail. */
1054  if (frtype == FR_LIBZ)  if (frtype == FR_LIBZ)
1055    {    {
1056    ingz = (gzFile)handle;    ingz = (gzFile)handle;
1057    bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);    bufflength = gzread (ingz, main_buffer, bufsize);
1058    }    }
1059  else  else
1060  #endif  #endif
# Line 1044  else Line 1063  else
1063  if (frtype == FR_LIBBZ2)  if (frtype == FR_LIBBZ2)
1064    {    {
1065    inbz2 = (BZFILE *)handle;    inbz2 = (BZFILE *)handle;
1066    bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);    bufflength = BZ2_bzread(inbz2, main_buffer, bufsize);
1067    if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */    if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1068    }                                    /* without the cast it is unsigned. */    }                                    /* without the cast it is unsigned. */
1069  else  else
# Line 1054  else Line 1073  else
1073    in = (FILE *)handle;    in = (FILE *)handle;
1074    if (is_file_tty(in)) input_line_buffered = TRUE;    if (is_file_tty(in)) input_line_buffered = TRUE;
1075    bufflength = input_line_buffered?    bufflength = input_line_buffered?
1076      read_one_line(buffer, 3*MBUFTHIRD, in) :      read_one_line(main_buffer, bufsize, in) :
1077      fread(buffer, 1, 3*MBUFTHIRD, in);      fread(main_buffer, 1, bufsize, in);
1078    }    }
1079    
1080  endptr = buffer + bufflength;  endptr = main_buffer + bufflength;
1081    
1082  /* 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
1083  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 1069  while (ptr < endptr) Line 1088  while (ptr < endptr)
1088    {    {
1089    int endlinelength;    int endlinelength;
1090    int mrc = 0;    int mrc = 0;
1091      int startoffset = 0;
1092    BOOL match;    BOOL match;
1093    char *matchptr = ptr;    char *matchptr = ptr;
1094    char *t = ptr;    char *t = ptr;
# Line 1086  while (ptr < endptr) Line 1106  while (ptr < endptr)
1106    linelength = t - ptr - endlinelength;    linelength = t - ptr - endlinelength;
1107    length = multiline? (size_t)(endptr - ptr) : linelength;    length = multiline? (size_t)(endptr - ptr) : linelength;
1108    
1109      /* Check to see if the line we are looking at extends right to the very end
1110      of the buffer without a line terminator. This means the line is too long to
1111      handle. */
1112    
1113      if (endlinelength == 0 && t == main_buffer + bufsize)
1114        {
1115        fprintf(stderr, "pcregrep: line %d%s%s is too long for the internal buffer\n"
1116                        "pcregrep: check the --buffer-size option\n",
1117                        linenumber,
1118                        (filename == NULL)? "" : " of file ",
1119                        (filename == NULL)? "" : filename);
1120        return 2;
1121        }
1122    
1123    /* Extra processing for Jeffrey Friedl's debugging. */    /* Extra processing for Jeffrey Friedl's debugging. */
1124    
1125  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
# Line 1145  while (ptr < endptr) Line 1179  while (ptr < endptr)
1179    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
1180    finding subsequent matches when colouring matched lines. */    finding subsequent matches when colouring matched lines. */
1181    
1182    match = match_patterns(matchptr, length, offsets, &mrc);    match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
1183    
1184    /* 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. */
1185    
# Line 1174  while (ptr < endptr) Line 1208  while (ptr < endptr)
1208    
1209      else if (quiet) return 0;      else if (quiet) return 0;
1210    
1211      /* The --only-matching option prints just the substring that matched, or a      /* The --only-matching option prints just the substring that matched, or a
1212      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
1213      --file-offsets and --line-offsets options output offsets for the matching      --file-offsets and --line-offsets options output offsets for the matching
1214      substring (they both force --only-matching = 0). None of these options      substring (they both force --only-matching = 0). None of these options
1215      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
1216      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,
1217      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
1218      be useful because the return code is set. */      because the return code is set. */
1219    
1220      else if (only_matching >= 0)      else if (only_matching >= 0)
1221        {        {
# Line 1193  while (ptr < endptr) Line 1227  while (ptr < endptr)
1227            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1228              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1229          else if (file_offsets)          else if (file_offsets)
1230            fprintf(stdout, "%d,%d\n",            fprintf(stdout, "%d,%d\n",
1231              (int)(filepos + matchptr + offsets[0] - ptr),              (int)(filepos + matchptr + offsets[0] - ptr),
1232              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1233          else if (only_matching < mrc)          else if (only_matching < mrc)
1234            {            {
1235            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1236            if (plen > 0)            if (plen > 0)
1237              {              {
1238              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1239              FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);              FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1240              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1241              fprintf(stdout, "\n");              fprintf(stdout, "\n");
1242              }              }
1243            }            }
1244          else if (printname != NULL || number) fprintf(stdout, "\n");          else if (printname != NULL || number) fprintf(stdout, "\n");
         matchptr += offsets[1];  
         length -= offsets[1];  
1245          match = FALSE;          match = FALSE;
1246          if (line_buffered) fflush(stdout);          if (line_buffered) fflush(stdout);
1247          rc = 0;    /* Had some success */          rc = 0;                      /* Had some success */
1248            startoffset = offsets[1];    /* Restart after the match */
1249          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1250          }          }
1251        }        }
# Line 1271  while (ptr < endptr) Line 1304  while (ptr < endptr)
1304          int linecount = 0;          int linecount = 0;
1305          char *p = ptr;          char *p = ptr;
1306    
1307          while (p > buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&          while (p > main_buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
1308                 linecount < before_context)                 linecount < before_context)
1309            {            {
1310            linecount++;            linecount++;
1311            p = previous_line(p, buffer);            p = previous_line(p, main_buffer);
1312            }            }
1313    
1314          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 1308  while (ptr < endptr) Line 1341  while (ptr < endptr)
1341        (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
1342        the match will always be before the first newline sequence. */        the match will always be before the first newline sequence. */
1343    
1344        if (multiline)        if (multiline & !invert)
1345          {          {
1346          int ellength;          char *endmatch = ptr + offsets[1];
1347          char *endmatch = ptr;          t = ptr;
1348          if (!invert)          while (t < endmatch)
1349            {            {
1350            endmatch += offsets[1];            t = end_of_line(t, endptr, &endlinelength);
1351            t = ptr;            if (t < endmatch) linenumber++; else break;
           while (t < endmatch)  
             {  
             t = end_of_line(t, endptr, &ellength);  
             if (t <= endmatch) linenumber++; else break;  
             }  
1352            }            }
1353          endmatch = end_of_line(endmatch, endptr, &ellength);          linelength = t - ptr - endlinelength;
         linelength = endmatch - ptr - ellength;  
1354          }          }
1355    
1356        /*** 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 1346  while (ptr < endptr) Line 1373  while (ptr < endptr)
1373  #endif  #endif
1374    
1375        /* 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
1376        matches. */        matches, but not of course if the line is a non-match. */
1377    
1378        if (do_colour)        if (do_colour && !invert)
1379          {          {
1380          int last_offset = 0;          int plength;
1381          FWRITE(ptr, 1, offsets[0], stdout);          FWRITE(ptr, 1, offsets[0], stdout);
1382          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1383          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1384          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1385          for (;;)          for (;;)
1386            {            {
1387            last_offset += offsets[1];            startoffset = offsets[1];
1388            matchptr += offsets[1];            if (startoffset >= linelength + endlinelength ||
1389            length -= offsets[1];                !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1390            if (!match_patterns(matchptr, length, offsets, &mrc)) break;              break;
1391            FWRITE(matchptr, 1, offsets[0], stdout);            FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1392            fprintf(stdout, "%c[%sm", 0x1b, colour_string);            fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1393            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1394            fprintf(stdout, "%c[00m", 0x1b);            fprintf(stdout, "%c[00m", 0x1b);
1395            }            }
1396          FWRITE(ptr + last_offset, 1,  
1397            (linelength + endlinelength) - last_offset, stdout);          /* In multiline mode, we may have already printed the complete line
1398            and its line-ending characters (if they matched the pattern), so there
1399            may be no more to print. */
1400    
1401            plength = (linelength + endlinelength) - startoffset;
1402            if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout);
1403          }          }
1404    
1405        /* Not colouring; no need to search for further matches */        /* Not colouring; no need to search for further matches */
# Line 1416  while (ptr < endptr) Line 1448  while (ptr < endptr)
1448    /* 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
1449    line and add it into the buffer. */    line and add it into the buffer. */
1450    
1451    if (input_line_buffered && bufflength < sizeof(buffer))    if (input_line_buffered && bufflength < bufsize)
1452      {      {
1453      int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);      int add = read_one_line(ptr, bufsize - (ptr - main_buffer), in);
1454      bufflength += add;      bufflength += add;
1455      endptr += add;      endptr += add;
1456      }      }
# Line 1428  while (ptr < endptr) Line 1460  while (ptr < endptr)
1460    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
1461    about to be lost, print them. */    about to be lost, print them. */
1462    
1463    if (bufflength >= sizeof(buffer) && ptr > buffer + 2*MBUFTHIRD)    if (bufflength >= bufsize && ptr > main_buffer + 2*bufthird)
1464      {      {
1465      if (after_context > 0 &&      if (after_context > 0 &&
1466          lastmatchnumber > 0 &&          lastmatchnumber > 0 &&
1467          lastmatchrestart < buffer + MBUFTHIRD)          lastmatchrestart < main_buffer + bufthird)
1468        {        {
1469        do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);        do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1470        lastmatchnumber = 0;        lastmatchnumber = 0;
# Line 1440  while (ptr < endptr) Line 1472  while (ptr < endptr)
1472    
1473      /* Now do the shuffle */      /* Now do the shuffle */
1474    
1475      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(main_buffer, main_buffer + bufthird, 2*bufthird);
1476      ptr -= MBUFTHIRD;      ptr -= bufthird;
1477    
1478  #ifdef SUPPORT_LIBZ  #ifdef SUPPORT_LIBZ
1479      if (frtype == FR_LIBZ)      if (frtype == FR_LIBZ)
1480        bufflength = 2*MBUFTHIRD +        bufflength = 2*bufthird +
1481          gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);          gzread (ingz, main_buffer + 2*bufthird, bufthird);
1482      else      else
1483  #endif  #endif
1484    
1485  #ifdef SUPPORT_LIBBZ2  #ifdef SUPPORT_LIBBZ2
1486      if (frtype == FR_LIBBZ2)      if (frtype == FR_LIBBZ2)
1487        bufflength = 2*MBUFTHIRD +        bufflength = 2*bufthird +
1488          BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);          BZ2_bzread(inbz2, main_buffer + 2*bufthird, bufthird);
1489      else      else
1490  #endif  #endif
1491    
1492      bufflength = 2*MBUFTHIRD +      bufflength = 2*bufthird +
1493        (input_line_buffered?        (input_line_buffered?
1494         read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :         read_one_line(main_buffer + 2*bufthird, bufthird, in) :
1495         fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));         fread(main_buffer + 2*bufthird, 1, bufthird, in));
1496      endptr = buffer + bufflength;      endptr = main_buffer + bufflength;
1497    
1498      /* Adjust any last match point */      /* Adjust any last match point */
1499    
1500      if (lastmatchnumber > 0) lastmatchrestart -= MBUFTHIRD;      if (lastmatchnumber > 0) lastmatchrestart -= bufthird;
1501      }      }
1502    }     /* Loop through the whole file */    }     /* Loop through the whole file */
1503    
# Line 1545  BZFILE *inbz2 = NULL; Line 1577  BZFILE *inbz2 = NULL;
1577    
1578  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1579    {    {
1580    return pcregrep(stdin, FR_PLAIN,    return pcregrep(stdin, FR_PLAIN, stdin_name,
1581      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1582        stdin_name : NULL);        stdin_name : NULL);
1583    }    }
# Line 1677  if (handle == NULL) Line 1709  if (handle == NULL)
1709    
1710  /* Now grep the file */  /* Now grep the file */
1711    
1712  rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||  rc = pcregrep(handle, frtype, pathname, (filenames > FN_DEFAULT ||
1713    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1714    
1715  /* Close in an appropriate manner. */  /* Close in an appropriate manner. */
# Line 1688  if (frtype == FR_LIBZ) Line 1720  if (frtype == FR_LIBZ)
1720  else  else
1721  #endif  #endif
1722    
1723  /* 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
1724  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
1725  again as a normal file. */  again as a normal file. */
1726    
1727  #ifdef SUPPORT_LIBBZ2  #ifdef SUPPORT_LIBBZ2
1728  if (frtype == FR_LIBBZ2)  if (frtype == FR_LIBBZ2)
1729    {    {
1730    if (rc == 2)    if (rc == 3)
1731      {      {
1732      int errnum;      int errnum;
1733      const char *err = BZ2_bzerror(inbz2, &errnum);      const char *err = BZ2_bzerror(inbz2, &errnum);
# Line 1707  if (frtype == FR_LIBBZ2) Line 1739  if (frtype == FR_LIBBZ2)
1739      else if (!silent)      else if (!silent)
1740        fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",        fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1741          pathname, err);          pathname, err);
1742        rc = 2;    /* The normal "something went wrong" code */
1743      }      }
1744    BZ2_bzclose(inbz2);    BZ2_bzclose(inbz2);
1745    }    }
# Line 1782  for (op = optionlist; op->one_char != 0; Line 1815  for (op = optionlist; op->one_char != 0;
1815    {    {
1816    int n;    int n;
1817    char s[4];    char s[4];
1818    
1819      /* Two options were accidentally implemented and documented with underscores
1820      instead of hyphens in their names, something that was not noticed for quite a
1821      few releases. When fixing this, I left the underscored versions in the list
1822      in case people were using them. However, we don't want to display them in the
1823      help data. There are no other options that contain underscores, and we do not
1824      expect ever to implement such options. Therefore, just omit any option that
1825      contains an underscore. */
1826    
1827      if (strchr(op->long_name, '_') != NULL) continue;
1828    
1829    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, "   ");
1830    n = 30 - printf("  %s --%s", s, op->long_name);    n = 31 - printf("  %s --%s", s, op->long_name);
1831    if (n < 1) n = 1;    if (n < 1) n = 1;
1832    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1833    }    }
1834    
1835  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");
1836    printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);
1837    printf("When reading patterns from a file instead of using a command line option,\n");
1838  printf("trailing white space is removed and blank lines are ignored.\n");  printf("trailing white space is removed and blank lines are ignored.\n");
1839  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",
1840      MAX_PATTERN_COUNT, PATBUFSIZE);
1841    
1842  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");
1843  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 1817  switch(letter) Line 1864  switch(letter)
1864    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1865    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1866    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1867      case 'j': study_options |= PCRE_STUDY_JIT_COMPILE; break;
1868    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1869    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1870    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
# Line 1892  Returns:         TRUE on success, FALSE Line 1940  Returns:         TRUE on success, FALSE
1940  static BOOL  static BOOL
1941  compile_single_pattern(char *pattern, int options, char *filename, int count)  compile_single_pattern(char *pattern, int options, char *filename, int count)
1942  {  {
1943  char buffer[MBUFTHIRD + 16];  char buffer[PATBUFSIZE];
1944  const char *error;  const char *error;
1945  int errptr;  int errptr;
1946    
# Line 1903  if (pattern_count >= MAX_PATTERN_COUNT) Line 1951  if (pattern_count >= MAX_PATTERN_COUNT)
1951    return FALSE;    return FALSE;
1952    }    }
1953    
1954  sprintf(buffer, "%s%.*s%s", prefix[process_options], MBUFTHIRD, pattern,  sprintf(buffer, "%s%.*s%s", prefix[process_options], bufthird, pattern,
1955    suffix[process_options]);    suffix[process_options]);
1956  pattern_list[pattern_count] =  pattern_list[pattern_count] =
1957    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
# Line 1962  compile_pattern(char *pattern, int optio Line 2010  compile_pattern(char *pattern, int optio
2010  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
2011    {    {
2012    char *eop = pattern + strlen(pattern);    char *eop = pattern + strlen(pattern);
2013    char buffer[MBUFTHIRD];    char buffer[PATBUFSIZE];
2014    for(;;)    for(;;)
2015      {      {
2016      int ellength;      int ellength;
# Line 2161  for (i = 1; i < argc; i++) Line 2209  for (i = 1; i < argc; i++)
2209      while (*s != 0)      while (*s != 0)
2210        {        {
2211        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2212          {          {
2213          if (*s == op->one_char) break;          if (*s == op->one_char) break;
2214          }          }
2215        if (op->one_char == 0)        if (op->one_char == 0)
2216          {          {
# Line 2170  for (i = 1; i < argc; i++) Line 2218  for (i = 1; i < argc; i++)
2218            *s, argv[i]);            *s, argv[i]);
2219          pcregrep_exit(usage(2));          pcregrep_exit(usage(2));
2220          }          }
2221    
2222        /* Check for a single-character option that has data: OP_OP_NUMBER        /* Check for a single-character option that has data: OP_OP_NUMBER
2223        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
2224        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
2225        with other single-character options in the same string. */        with other single-character options in the same string. */
2226    
2227        option_data = s+1;        option_data = s+1;
2228        if (op->type == OP_OP_NUMBER)        if (op->type == OP_OP_NUMBER)
2229          {          {
2230          if (isdigit((unsigned char)s[1])) break;          if (isdigit((unsigned char)s[1])) break;
2231          }          }
2232        else   /* Check for end or a dataless option */        else   /* Check for end or a dataless option */
2233          {          {
2234          if (op->type != OP_NODATA || s[1] == 0) break;          if (op->type != OP_NODATA || s[1] == 0) break;
2235          }          }
2236    
2237        /* Handle a single-character option with no data, then loop for the        /* Handle a single-character option with no data, then loop for the
2238        next character in the string. */        next character in the string. */
2239    
2240        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
# Line 2205  for (i = 1; i < argc; i++) Line 2253  for (i = 1; i < argc; i++)
2253    
2254    /* 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
2255    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
2256    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",
2257    "only-matching", and Jeffrey Friedl's special -S debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2258    
2259    if (*option_data == 0 &&    if (*option_data == 0 &&
# Line 2216  for (i = 1; i < argc; i++) Line 2264  for (i = 1; i < argc; i++)
2264        case N_COLOUR:        case N_COLOUR:
2265        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2266        break;        break;
2267    
2268        case 'o':        case 'o':
2269        only_matching = 0;        only_matching = 0;
2270        break;        break;
2271    
2272  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2273        case 'S':        case 'S':
2274        S_arg = 0;        S_arg = 0;
# Line 2258  for (i = 1; i < argc; i++) Line 2306  for (i = 1; i < argc; i++)
2306    
2307    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2308    
2309    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2310               op->type != OP_OP_NUMBER)
2311      {      {
2312      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2313      }      }
# Line 2273  for (i = 1; i < argc; i++) Line 2322  for (i = 1; i < argc; i++)
2322      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2323      while (isdigit((unsigned char)(*endptr)))      while (isdigit((unsigned char)(*endptr)))
2324        n = n * 10 + (int)(*endptr++ - '0');        n = n * 10 + (int)(*endptr++ - '0');
2325        if (toupper(*endptr) == 'K')
2326          {
2327          n *= 1024;
2328          endptr++;
2329          }
2330        else if (toupper(*endptr) == 'M')
2331          {
2332          n *= 1024*1024;
2333          endptr++;
2334          }
2335      if (*endptr != 0)      if (*endptr != 0)
2336        {        {
2337        if (longop)        if (longop)
# Line 2288  for (i = 1; i < argc; i++) Line 2347  for (i = 1; i < argc; i++)
2347            option_data, op->one_char);            option_data, op->one_char);
2348        pcregrep_exit(usage(2));        pcregrep_exit(usage(2));
2349        }        }
2350      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2351            *((unsigned long int *)op->dataptr) = n;
2352        else
2353            *((int *)op->dataptr) = n;
2354      }      }
2355    }    }
2356    
# Line 2436  if (jfriedl_XT != 0 || jfriedl_XR != 0) Line 2498  if (jfriedl_XT != 0 || jfriedl_XR != 0)
2498    }    }
2499  #endif  #endif
2500    
2501  /* Get memory to store the pattern and hints lists. */  /* Get memory for the main buffer, and to store the pattern and hints lists. */
2502    
2503    bufsize = 3*bufthird;
2504    main_buffer = (char *)malloc(bufsize);
2505  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
2506  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));
2507    
2508  if (pattern_list == NULL || hints_list == NULL)  if (main_buffer == NULL || pattern_list == NULL || hints_list == NULL)
2509    {    {
2510    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2511    goto EXIT2;    goto EXIT2;
# Line 2473  if (pattern_filename != NULL) Line 2537  if (pattern_filename != NULL)
2537    int linenumber = 0;    int linenumber = 0;
2538    FILE *f;    FILE *f;
2539    char *filename;    char *filename;
2540    char buffer[MBUFTHIRD];    char buffer[PATBUFSIZE];
2541    
2542    if (strcmp(pattern_filename, "-") == 0)    if (strcmp(pattern_filename, "-") == 0)
2543      {      {
# Line 2492  if (pattern_filename != NULL) Line 2556  if (pattern_filename != NULL)
2556      filename = pattern_filename;      filename = pattern_filename;
2557      }      }
2558    
2559    while (fgets(buffer, MBUFTHIRD, f) != NULL)    while (fgets(buffer, PATBUFSIZE, f) != NULL)
2560      {      {
2561      char *s = buffer + (int)strlen(buffer);      char *s = buffer + (int)strlen(buffer);
2562      while (s > buffer && isspace((unsigned char)(s[-1]))) s--;      while (s > buffer && isspace((unsigned char)(s[-1]))) s--;
# Line 2510  if (pattern_filename != NULL) Line 2574  if (pattern_filename != NULL)
2574    
2575  for (j = 0; j < pattern_count; j++)  for (j = 0; j < pattern_count; j++)
2576    {    {
2577    hints_list[j] = pcre_study(pattern_list[j], 0, &error);    hints_list[j] = pcre_study(pattern_list[j], study_options, &error);
2578    if (error != NULL)    if (error != NULL)
2579      {      {
2580      char s[16];      char s[16];
# Line 2520  for (j = 0; j < pattern_count; j++) Line 2584  for (j = 0; j < pattern_count; j++)
2584      }      }
2585    hint_count++;    hint_count++;
2586    }    }
2587    
2588  /* 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
2589  pcre_extra block for each pattern. */  pcre_extra block for each pattern. */
2590    
# Line 2531  if (match_limit > 0 || match_limit_recur Line 2595  if (match_limit > 0 || match_limit_recur
2595      if (hints_list[j] == NULL)      if (hints_list[j] == NULL)
2596        {        {
2597        hints_list[j] = malloc(sizeof(pcre_extra));        hints_list[j] = malloc(sizeof(pcre_extra));
2598        if (hints_list[j] == NULL)        if (hints_list[j] == NULL)
2599          {          {
2600          fprintf(stderr, "pcregrep: malloc failed\n");          fprintf(stderr, "pcregrep: malloc failed\n");
2601          pcregrep_exit(2);          pcregrep_exit(2);
2602          }          }
2603        }        }
2604      if (match_limit > 0)      if (match_limit > 0)
2605        {        {
2606        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2607        hints_list[j]->match_limit = match_limit;        hints_list[j]->match_limit = match_limit;
2608        }        }
2609      if (match_limit_recursion > 0)      if (match_limit_recursion > 0)
2610        {        {
2611        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2612        hints_list[j]->match_limit_recursion = match_limit_recursion;        hints_list[j]->match_limit_recursion = match_limit_recursion;
2613        }        }
2614      }      }
2615    }    }
2616    
2617  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2618    
# Line 2604  if (include_dir_pattern != NULL) Line 2668  if (include_dir_pattern != NULL)
2668    
2669  if (i >= argc)  if (i >= argc)
2670    {    {
2671    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);    rc = pcregrep(stdin, FR_PLAIN, stdin_name,
2672        (filenames > FN_DEFAULT)? stdin_name : NULL);
2673    goto EXIT;    goto EXIT;
2674    }    }
2675    
# Line 2624  for (; i < argc; i++) Line 2689  for (; i < argc; i++)
2689    }    }
2690    
2691  EXIT:  EXIT:
2692    if (main_buffer != NULL) free(main_buffer);
2693  if (pattern_list != NULL)  if (pattern_list != NULL)
2694    {    {
2695    for (i = 0; i < pattern_count; i++) free(pattern_list[i]);    for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
# Line 2631  if (pattern_list != NULL) Line 2697  if (pattern_list != NULL)
2697    }    }
2698  if (hints_list != NULL)  if (hints_list != NULL)
2699    {    {
2700    for (i = 0; i < hint_count; i++)    for (i = 0; i < hint_count; i++)
2701      {      {
2702      if (hints_list[i] != NULL) free(hints_list[i]);      if (hints_list[i] != NULL) pcre_free_study(hints_list[i]);
2703      }      }
2704    free(hints_list);    free(hints_list);
2705    }    }
2706  pcregrep_exit(rc);  pcregrep_exit(rc);

Legend:
Removed from v.565  
changed lines
  Added in v.667

  ViewVC Help
Powered by ViewVC 1.1.5