/[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 535 by ph10, Thu Jun 3 19:18:24 2010 UTC revision 586 by ph10, Wed Jan 12 17:36:47 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 163  static int dee_action = dee_READ; Line 163  static int dee_action = dee_READ;
163  static int DEE_action = DEE_READ;  static int DEE_action = DEE_READ;
164  static int error_count = 0;  static int error_count = 0;
165  static int filenames = FN_DEFAULT;  static int filenames = FN_DEFAULT;
166    static int only_matching = -1;
167  static int process_options = 0;  static int process_options = 0;
168    
169    static unsigned long int match_limit = 0;
170    static unsigned long int match_limit_recursion = 0;
171    
172  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
173  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
174  static BOOL file_offsets = FALSE;  static BOOL file_offsets = FALSE;
# Line 175  static BOOL line_offsets = FALSE; Line 179  static BOOL line_offsets = FALSE;
179  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
180  static BOOL number = FALSE;  static BOOL number = FALSE;
181  static BOOL omit_zero_count = FALSE;  static BOOL omit_zero_count = FALSE;
182  static BOOL only_matching = FALSE;  static BOOL resource_error = FALSE;
183  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
184  static BOOL silent = FALSE;  static BOOL silent = FALSE;
185  static BOOL utf8 = FALSE;  static BOOL utf8 = FALSE;
186    
187  /* Structure for options and list of them */  /* Structure for options and list of them */
188    
189  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,
190         OP_PATLIST };         OP_OP_NUMBER, OP_PATLIST };
191    
192  typedef struct option_item {  typedef struct option_item {
193    int type;    int type;
# Line 208  used to identify them. */ Line 212  used to identify them. */
212  #define N_LOFFSETS     (-10)  #define N_LOFFSETS     (-10)
213  #define N_FOFFSETS     (-11)  #define N_FOFFSETS     (-11)
214  #define N_LBUFFER      (-12)  #define N_LBUFFER      (-12)
215    #define N_M_LIMIT      (-13)
216    #define N_M_LIMIT_REC  (-14)
217    
218  static option_item optionlist[] = {  static option_item optionlist[] = {
219    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "  terminate options" },
220    { OP_NODATA,    N_HELP,   NULL,              "help",          "display this help and exit" },    { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
221    { 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" },
222    { 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" },
223    { OP_OP_STRING, N_COLOUR, &colour_option,    "color=option",  "matched text color option" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
224    { 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" },
225    { 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" },
226    { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },    { OP_NODATA,     'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
227    { OP_STRING,    'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },    { OP_STRING,     'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },
228    { OP_STRING,    'd',      &dee_option,       "directories=action", "how to handle directories" },    { OP_STRING,     'd',      &dee_option,       "directories=action", "how to handle directories" },
229    { OP_PATLIST,   'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },    { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
230    { OP_NODATA,    'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },    { OP_NODATA,     'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },
231    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
232    { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },    { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
233    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
234    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
235    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
236    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },    { OP_NODATA,     'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
237    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },    { OP_NODATA,     'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
238    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },    { OP_STRING,     N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
239    { OP_NODATA,    N_LBUFFER, NULL,             "line-buffered", "use line buffering" },    { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
240    { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },    { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
241    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
242    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
243    { 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" },
244    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
245    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
246    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
247    { 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" },
248    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
249    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
250      { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
251      { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
252      { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
253      { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },
254    
255      /* These two were accidentally implemented with underscores instead of
256      hyphens in the option names. As this was not discovered for several releases,
257      the incorrect versions are left in the table for compatibility. However, the
258      --help function misses out any option that has an underscore in its name. */
259    
260    { 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" },
261    { 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" },
262    
263  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
264    { 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" },
265  #endif  #endif
# Line 279  const char utf8_table4[] = { Line 296  const char utf8_table4[] = {
296    
297    
298  /*************************************************  /*************************************************
299    *         Exit from the program                  *
300    *************************************************/
301    
302    /* If there has been a resource error, give a suitable message.
303    
304    Argument:  the return code
305    Returns:   does not return
306    */
307    
308    static void
309    pcregrep_exit(int rc)
310    {
311    if (resource_error)
312      {
313      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
314        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
315      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
316      }
317    
318    exit(rc);
319    }
320    
321    
322    /*************************************************
323  *            OS-specific functions               *  *            OS-specific functions               *
324  *************************************************/  *************************************************/
325    
# Line 363  return isatty(fileno(f)); Line 404  return isatty(fileno(f));
404  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
405  when it did not exist. David Byron added a patch that moved the #include of  when it did not exist. David Byron added a patch that moved the #include of
406  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
407  */  The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
408    undefined when it is indeed undefined. */
409    
410  #elif HAVE_WINDOWS_H  #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
411    
412  #ifndef STRICT  #ifndef STRICT
413  # define STRICT  # define STRICT
# Line 409  dir = (directory_type *) malloc(sizeof(* Line 451  dir = (directory_type *) malloc(sizeof(*
451  if ((pattern == NULL) || (dir == NULL))  if ((pattern == NULL) || (dir == NULL))
452    {    {
453    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
454    exit(2);    pcregrep_exit(2);
455    }    }
456  memcpy(pattern, filename, len);  memcpy(pattern, filename, len);
457  memcpy(&(pattern[len]), "\\*", 3);  memcpy(&(pattern[len]), "\\*", 3);
# Line 907  static BOOL Line 949  static BOOL
949  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)
950  {  {
951  int i;  int i;
952    size_t slen = length;
953    const char *msg = "this text:\n\n";
954    if (slen > 200)
955      {
956      slen = 200;
957      msg = "text that starts:\n\n";
958      }
959  for (i = 0; i < pattern_count; i++)  for (i = 0; i < pattern_count; i++)
960    {    {
961    *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, 0,
962      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
963    if (*mrc >= 0) return TRUE;    if (*mrc >= 0) return TRUE;
964    if (*mrc == PCRE_ERROR_NOMATCH) continue;    if (*mrc == PCRE_ERROR_NOMATCH) continue;
965    fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
966    if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);    if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
967    fprintf(stderr, "this text:\n");    fprintf(stderr, "%s", msg);
968    FWRITE(matchptr, 1, length, stderr);   /* In case binary zero included */    FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
969    fprintf(stderr, "\n");    fprintf(stderr, "\n\n");
970    if (error_count == 0 &&    if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)
971        (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT))      resource_error = TRUE;
     {  
     fprintf(stderr, "pcregrep: error %d means that a resource limit "  
       "was exceeded\n", *mrc);  
     fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");  
     }  
972    if (error_count++ > 20)    if (error_count++ > 20)
973      {      {
974      fprintf(stderr, "pcregrep: too many errors - abandoned\n");      fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
975      exit(2);      pcregrep_exit(2);
976      }      }
977    return invert;    /* No more matching; don't show the line again */    return invert;    /* No more matching; don't show the line again */
978    }    }
# Line 1068  while (ptr < endptr) Line 1112  while (ptr < endptr)
1112            ptr = malloc(newlen + 1);            ptr = malloc(newlen + 1);
1113            if (!ptr) {            if (!ptr) {
1114                    printf("out of memory");                    printf("out of memory");
1115                    exit(2);                    pcregrep_exit(2);
1116            }            }
1117            endptr = ptr;            endptr = ptr;
1118            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
# Line 1138  while (ptr < endptr) Line 1182  while (ptr < endptr)
1182    
1183      else if (quiet) return 0;      else if (quiet) return 0;
1184    
1185      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, or a
1186      the --file-offsets and --line-offsets options output offsets for the      captured portion of it, as long as this string is not empty, and the
1187      matching substring (they both force --only-matching). None of these options      --file-offsets and --line-offsets options output offsets for the matching
1188        substring (they both force --only-matching = 0). None of these options
1189      prints any context. Afterwards, adjust the start and length, and then jump      prints any context. Afterwards, adjust the start and length, and then jump
1190      back to look for further matches in the same line. If we are in invert      back to look for further matches in the same line. If we are in invert
1191      mode, however, nothing is printed - this could be still useful because the      mode, however, nothing is printed and we do not restart - this could still
1192      return code is set. */      be useful because the return code is set. */
1193    
1194      else if (only_matching)      else if (only_matching >= 0)
1195        {        {
1196        if (!invert)        if (!invert)
1197          {          {
1198          if (printname != NULL) fprintf(stdout, "%s:", printname);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1199          if (number) fprintf(stdout, "%d:", linenumber);          if (number) fprintf(stdout, "%d:", linenumber);
1200          if (line_offsets)          if (line_offsets)
1201            fprintf(stdout, "%d,%d", (int)(matchptr + offsets[0] - ptr),            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1202              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1203          else if (file_offsets)          else if (file_offsets)
1204            fprintf(stdout, "%d,%d", (int)(filepos + matchptr + offsets[0] - ptr),            fprintf(stdout, "%d,%d\n",
1205                (int)(filepos + matchptr + offsets[0] - ptr),
1206              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1207          else          else if (only_matching < mrc)
1208            {            {
1209            if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1210            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            if (plen > 0)
1211            if (do_colour) fprintf(stdout, "%c[00m", 0x1b);              {
1212                if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1213                FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1214                if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1215                fprintf(stdout, "\n");
1216                }
1217            }            }
1218          fprintf(stdout, "\n");          else if (printname != NULL || number) fprintf(stdout, "\n");
1219          matchptr += offsets[1];          matchptr += offsets[1];
1220          length -= offsets[1];          length -= offsets[1];
1221          match = FALSE;          match = FALSE;
1222            if (line_buffered) fflush(stdout);
1223            rc = 0;    /* Had some success */
1224          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1225          }          }
1226        }        }
# Line 1301  while (ptr < endptr) Line 1354  while (ptr < endptr)
1354  #endif  #endif
1355    
1356        /* 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
1357        matches. */        matches, but not of course if the line is a non-match. */
1358    
1359        if (do_colour)        if (do_colour && !invert)
1360          {          {
1361          int last_offset = 0;          int last_offset = 0;
1362          FWRITE(ptr, 1, offsets[0], stdout);          FWRITE(ptr, 1, offsets[0], stdout);
# Line 1427  while (ptr < endptr) Line 1480  while (ptr < endptr)
1480  /* End of file; print final "after" lines if wanted; do_after_lines sets  /* End of file; print final "after" lines if wanted; do_after_lines sets
1481  hyphenpending if it prints something. */  hyphenpending if it prints something. */
1482    
1483  if (!only_matching && !count_only)  if (only_matching < 0 && !count_only)
1484    {    {
1485    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1486    hyphenpending |= endhyphenpending;    hyphenpending |= endhyphenpending;
# Line 1737  for (op = optionlist; op->one_char != 0; Line 1790  for (op = optionlist; op->one_char != 0;
1790    {    {
1791    int n;    int n;
1792    char s[4];    char s[4];
1793    
1794      /* Two options were accidentally implemented and documented with underscores
1795      instead of hyphens in their names, something that was not noticed for quite a
1796      few releases. When fixing this, I left the underscored versions in the list
1797      in case people were using them. However, we don't want to display them in the
1798      help data. There are no other options that contain underscores, and we do not
1799      expect ever to implement such options. Therefore, just omit any option that
1800      contains an underscore. */
1801    
1802      if (strchr(op->long_name, '_') != NULL) continue;
1803    
1804    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, "   ");
1805    n = 30 - printf("  %s --%s", s, op->long_name);    n = 31 - printf("  %s --%s", s, op->long_name);
1806    if (n < 1) n = 1;    if (n < 1) n = 1;
1807    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1808    }    }
1809    
1810  printf("\nWhen reading patterns from a file instead of using a command line option,\n");  printf("\nWhen reading patterns from a file instead of using a command line option,\n");
# Line 1764  handle_option(int letter, int options) Line 1828  handle_option(int letter, int options)
1828  switch(letter)  switch(letter)
1829    {    {
1830    case N_FOFFSETS: file_offsets = TRUE; break;    case N_FOFFSETS: file_offsets = TRUE; break;
1831    case N_HELP: help(); exit(0);    case N_HELP: help(); pcregrep_exit(0);
1832    case N_LOFFSETS: line_offsets = number = TRUE; break;    case N_LOFFSETS: line_offsets = number = TRUE; break;
1833    case N_LBUFFER: line_buffered = TRUE; break;    case N_LBUFFER: line_buffered = TRUE; break;
1834    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
# Line 1776  switch(letter) Line 1840  switch(letter)
1840    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1841    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1842    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
1843    case 'o': only_matching = TRUE; break;    case 'o': only_matching = 0; break;
1844    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1845    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1846    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
# Line 1787  switch(letter) Line 1851  switch(letter)
1851    
1852    case 'V':    case 'V':
1853    fprintf(stderr, "pcregrep version %s\n", pcre_version());    fprintf(stderr, "pcregrep version %s\n", pcre_version());
1854    exit(0);    pcregrep_exit(0);
1855    break;    break;
1856    
1857    default:    default:
1858    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
1859    exit(usage(2));    pcregrep_exit(usage(2));
1860    }    }
1861    
1862  return options;  return options;
# Line 1988  for (i = 1; i < argc; i++) Line 2052  for (i = 1; i < argc; i++)
2052    if (argv[i][1] == 0)    if (argv[i][1] == 0)
2053      {      {
2054      if (pattern_filename != NULL || pattern_count > 0) break;      if (pattern_filename != NULL || pattern_count > 0) break;
2055        else exit(usage(2));        else pcregrep_exit(usage(2));
2056      }      }
2057    
2058    /* Handle a long name option, or -- to terminate the options */    /* Handle a long name option, or -- to terminate the options */
# Line 2079  for (i = 1; i < argc; i++) Line 2143  for (i = 1; i < argc; i++)
2143      if (op->one_char == 0)      if (op->one_char == 0)
2144        {        {
2145        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
2146        exit(usage(2));        pcregrep_exit(usage(2));
2147        }        }
2148      }      }
2149    
# Line 2116  for (i = 1; i < argc; i++) Line 2180  for (i = 1; i < argc; i++)
2180      while (*s != 0)      while (*s != 0)
2181        {        {
2182        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2183          { if (*s == op->one_char) break; }          {
2184            if (*s == op->one_char) break;
2185            }
2186        if (op->one_char == 0)        if (op->one_char == 0)
2187          {          {
2188          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2189            *s, argv[i]);            *s, argv[i]);
2190          exit(usage(2));          pcregrep_exit(usage(2));
2191          }          }
2192        if (op->type != OP_NODATA || s[1] == 0)  
2193          /* Check for a single-character option that has data: OP_OP_NUMBER
2194          is used for one that either has a numerical number or defaults, i.e. the
2195          data is optional. If a digit follows, there is data; if not, carry on
2196          with other single-character options in the same string. */
2197    
2198          option_data = s+1;
2199          if (op->type == OP_OP_NUMBER)
2200            {
2201            if (isdigit((unsigned char)s[1])) break;
2202            }
2203          else   /* Check for end or a dataless option */
2204          {          {
2205          option_data = s+1;          if (op->type != OP_NODATA || s[1] == 0) break;
         break;  
2206          }          }
2207    
2208          /* Handle a single-character option with no data, then loop for the
2209          next character in the string. */
2210    
2211        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
2212        }        }
2213      }      }
# Line 2144  for (i = 1; i < argc; i++) Line 2224  for (i = 1; i < argc; i++)
2224    
2225    /* 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
2226    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
2227    separate item. At the moment, the only such options are "colo(u)r" and    separate item. At the moment, the only such options are "colo(u)r",
2228    Jeffrey Friedl's special -S debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2229    
2230    if (*option_data == 0 &&    if (*option_data == 0 &&
2231        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
# Line 2155  for (i = 1; i < argc; i++) Line 2235  for (i = 1; i < argc; i++)
2235        case N_COLOUR:        case N_COLOUR:
2236        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2237        break;        break;
2238    
2239          case 'o':
2240          only_matching = 0;
2241          break;
2242    
2243  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2244        case 'S':        case 'S':
2245        S_arg = 0;        S_arg = 0;
# Line 2171  for (i = 1; i < argc; i++) Line 2256  for (i = 1; i < argc; i++)
2256      if (i >= argc - 1 || longopwasequals)      if (i >= argc - 1 || longopwasequals)
2257        {        {
2258        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);
2259        exit(usage(2));        pcregrep_exit(usage(2));
2260        }        }
2261      option_data = argv[++i];      option_data = argv[++i];
2262      }      }
# Line 2192  for (i = 1; i < argc; i++) Line 2277  for (i = 1; i < argc; i++)
2277    
2278    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2279    
2280    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2281               op->type != OP_OP_NUMBER)
2282      {      {
2283      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2284      }      }
2285    
2286      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2287      only for unpicking arguments, so just keep it simple. */
2288    
2289    else    else
2290      {      {
2291      char *endptr;      unsigned long int n = 0;
2292      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2293        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2294        while (isdigit((unsigned char)(*endptr)))
2295          n = n * 10 + (int)(*endptr++ - '0');
2296      if (*endptr != 0)      if (*endptr != 0)
2297        {        {
2298        if (longop)        if (longop)
# Line 2213  for (i = 1; i < argc; i++) Line 2306  for (i = 1; i < argc; i++)
2306        else        else
2307          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2308            option_data, op->one_char);            option_data, op->one_char);
2309        exit(usage(2));        pcregrep_exit(usage(2));
2310        }        }
2311      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2312            *((unsigned long int *)op->dataptr) = n;
2313        else
2314            *((int *)op->dataptr) = n;
2315      }      }
2316    }    }
2317    
# Line 2229  if (both_context > 0) Line 2325  if (both_context > 0)
2325    }    }
2326    
2327  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2328  However, the latter two set the only_matching flag. */  However, the latter two set only_matching. */
2329    
2330  if ((only_matching && (file_offsets || line_offsets)) ||  if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2331      (file_offsets && line_offsets))      (file_offsets && line_offsets))
2332    {    {
2333    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2334      "and/or --line-offsets\n");      "and/or --line-offsets\n");
2335    exit(usage(2));    pcregrep_exit(usage(2));
2336    }    }
2337    
2338  if (file_offsets || line_offsets) only_matching = TRUE;  if (file_offsets || line_offsets) only_matching = 0;
2339    
2340  /* If a locale has not been provided as an option, see if the LC_CTYPE or  /* If a locale has not been provided as an option, see if the LC_CTYPE or
2341  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
# Line 2448  for (j = 0; j < pattern_count; j++) Line 2544  for (j = 0; j < pattern_count; j++)
2544    hint_count++;    hint_count++;
2545    }    }
2546    
2547    /* If --match-limit or --recursion-limit was set, put the value(s) into the
2548    pcre_extra block for each pattern. */
2549    
2550    if (match_limit > 0 || match_limit_recursion > 0)
2551      {
2552      for (j = 0; j < pattern_count; j++)
2553        {
2554        if (hints_list[j] == NULL)
2555          {
2556          hints_list[j] = malloc(sizeof(pcre_extra));
2557          if (hints_list[j] == NULL)
2558            {
2559            fprintf(stderr, "pcregrep: malloc failed\n");
2560            pcregrep_exit(2);
2561            }
2562          }
2563        if (match_limit > 0)
2564          {
2565          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2566          hints_list[j]->match_limit = match_limit;
2567          }
2568        if (match_limit_recursion > 0)
2569          {
2570          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2571          hints_list[j]->match_limit_recursion = match_limit_recursion;
2572          }
2573        }
2574      }
2575    
2576  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2577    
2578  if (exclude_pattern != NULL)  if (exclude_pattern != NULL)
# Line 2529  if (pattern_list != NULL) Line 2654  if (pattern_list != NULL)
2654    }    }
2655  if (hints_list != NULL)  if (hints_list != NULL)
2656    {    {
2657    for (i = 0; i < hint_count; i++) free(hints_list[i]);    for (i = 0; i < hint_count; i++)
2658        {
2659        if (hints_list[i] != NULL) free(hints_list[i]);
2660        }
2661    free(hints_list);    free(hints_list);
2662    }    }
2663  return rc;  pcregrep_exit(rc);
2664    
2665  EXIT2:  EXIT2:
2666  rc = 2;  rc = 2;

Legend:
Removed from v.535  
changed lines
  Added in v.586

  ViewVC Help
Powered by ViewVC 1.1.5