/[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 564 by ph10, Sun Oct 31 16:07:24 2010 UTC revision 588 by ph10, Sat Jan 15 11:22: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;  static unsigned long int match_limit = 0;
# Line 178  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;
 static BOOL only_matching = FALSE;  
182  static BOOL resource_error = FALSE;  static BOOL resource_error = FALSE;
183  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
184  static BOOL silent = FALSE;  static BOOL silent = FALSE;
# Line 186  static BOOL utf8 = FALSE; Line 186  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 216  used to identify them. */ Line 216  used to identify them. */
216  #define N_M_LIMIT_REC  (-14)  #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_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },    { OP_OP_STRING,  N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
225    { OP_NUMBER,    'C',      &both_context,     "context=number", "set number of context lines, before & after" },    { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
226    { OP_NODATA,    'c',      NULL,              "count",         "print only a count of matching lines per FILE" },    { 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_NUMBER,    N_M_LIMIT,&match_limit,      "match-limit=number", "set PCRE match limit option" },    { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
243    { OP_NUMBER,    N_M_LIMIT_REC,&match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },    { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
244    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
245    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
246    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
247    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
248    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
249    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
250    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
251    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
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 287  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 556  return sys_errlist[n]; Line 589  return sys_errlist[n];
589    
590    
591  /*************************************************  /*************************************************
 *         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);  
 }  
   
   
   
 /*************************************************  
592  *            Read one line of input              *  *            Read one line of input              *
593  *************************************************/  *************************************************/
594    
# Line 626  Arguments: Line 634  Arguments:
634    endptr    end of available data    endptr    end of available data
635    lenptr    where to put the length of the eol sequence    lenptr    where to put the length of the eol sequence
636    
637  Returns:    pointer to the last byte of the line  Returns:    pointer to the last byte of the line, including the newline byte(s)
638  */  */
639    
640  static char *  static char *
# Line 947  if (slen > 200) Line 955  if (slen > 200)
955    {    {
956    slen = 200;    slen = 200;
957    msg = "text that starts:\n\n";    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,
# Line 1174  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;
# Line 1301  while (ptr < endptr) Line 1316  while (ptr < endptr)
1316        (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
1317        the match will always be before the first newline sequence. */        the match will always be before the first newline sequence. */
1318    
1319        if (multiline)        if (multiline & !invert)
1320          {          {
1321          int ellength;          char *endmatch = ptr + offsets[1];
1322          char *endmatch = ptr;          t = ptr;
1323          if (!invert)          while (t < endmatch)
1324            {            {
1325            endmatch += offsets[1];            t = end_of_line(t, endptr, &endlinelength);
1326            t = ptr;            if (t < endmatch) linenumber++; else break;
           while (t < endmatch)  
             {  
             t = end_of_line(t, endptr, &ellength);  
             if (t <= endmatch) linenumber++; else break;  
             }  
1327            }            }
1328          endmatch = end_of_line(endmatch, endptr, &ellength);          linelength = t - ptr - endlinelength;
         linelength = endmatch - ptr - ellength;  
1329          }          }
1330    
1331        /*** 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 1339  while (ptr < endptr) Line 1348  while (ptr < endptr)
1348  #endif  #endif
1349    
1350        /* 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
1351        matches. */        matches, but not of course if the line is a non-match. */
1352    
1353        if (do_colour)        if (do_colour && !invert)
1354          {          {
1355            int plength;
1356          int last_offset = 0;          int last_offset = 0;
1357          FWRITE(ptr, 1, offsets[0], stdout);          FWRITE(ptr, 1, offsets[0], stdout);
1358          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
# Line 1353  while (ptr < endptr) Line 1363  while (ptr < endptr)
1363            last_offset += offsets[1];            last_offset += offsets[1];
1364            matchptr += offsets[1];            matchptr += offsets[1];
1365            length -= offsets[1];            length -= offsets[1];
1366            if (!match_patterns(matchptr, length, offsets, &mrc)) break;            if (last_offset >= linelength + endlinelength ||
1367                  !match_patterns(matchptr, length, offsets, &mrc)) break;
1368            FWRITE(matchptr, 1, offsets[0], stdout);            FWRITE(matchptr, 1, offsets[0], stdout);
1369            fprintf(stdout, "%c[%sm", 0x1b, colour_string);            fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1370            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1371            fprintf(stdout, "%c[00m", 0x1b);            fprintf(stdout, "%c[00m", 0x1b);
1372            }            }
1373          FWRITE(ptr + last_offset, 1,  
1374            (linelength + endlinelength) - last_offset, stdout);          /* In multiline mode, we may have already printed the complete line
1375            and its line-ending characters (if they matched the pattern), so there
1376            may be no more to print. */
1377    
1378            plength = (linelength + endlinelength) - last_offset;
1379            if (plength > 0)
1380              FWRITE(ptr + last_offset, 1, plength, stdout);
1381          }          }
1382    
1383        /* Not colouring; no need to search for further matches */        /* Not colouring; no need to search for further matches */
# Line 1465  while (ptr < endptr) Line 1482  while (ptr < endptr)
1482  /* 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
1483  hyphenpending if it prints something. */  hyphenpending if it prints something. */
1484    
1485  if (!only_matching && !count_only)  if (only_matching < 0 && !count_only)
1486    {    {
1487    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1488    hyphenpending |= endhyphenpending;    hyphenpending |= endhyphenpending;
# Line 1775  for (op = optionlist; op->one_char != 0; Line 1792  for (op = optionlist; op->one_char != 0;
1792    {    {
1793    int n;    int n;
1794    char s[4];    char s[4];
1795    
1796      /* Two options were accidentally implemented and documented with underscores
1797      instead of hyphens in their names, something that was not noticed for quite a
1798      few releases. When fixing this, I left the underscored versions in the list
1799      in case people were using them. However, we don't want to display them in the
1800      help data. There are no other options that contain underscores, and we do not
1801      expect ever to implement such options. Therefore, just omit any option that
1802      contains an underscore. */
1803    
1804      if (strchr(op->long_name, '_') != NULL) continue;
1805    
1806    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, "   ");
1807    n = 30 - printf("  %s --%s", s, op->long_name);    n = 31 - printf("  %s --%s", s, op->long_name);
1808    if (n < 1) n = 1;    if (n < 1) n = 1;
1809    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                     ", op->help_text);
1810    }    }
1811    
1812  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 1814  switch(letter) Line 1842  switch(letter)
1842    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1843    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1844    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
1845    case 'o': only_matching = TRUE; break;    case 'o': only_matching = 0; break;
1846    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1847    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1848    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
# Line 2154  for (i = 1; i < argc; i++) Line 2182  for (i = 1; i < argc; i++)
2182      while (*s != 0)      while (*s != 0)
2183        {        {
2184        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
2185          { if (*s == op->one_char) break; }          {
2186            if (*s == op->one_char) break;
2187            }
2188        if (op->one_char == 0)        if (op->one_char == 0)
2189          {          {
2190          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2191            *s, argv[i]);            *s, argv[i]);
2192          pcregrep_exit(usage(2));          pcregrep_exit(usage(2));
2193          }          }
2194        if (op->type != OP_NODATA || s[1] == 0)  
2195          /* Check for a single-character option that has data: OP_OP_NUMBER
2196          is used for one that either has a numerical number or defaults, i.e. the
2197          data is optional. If a digit follows, there is data; if not, carry on
2198          with other single-character options in the same string. */
2199    
2200          option_data = s+1;
2201          if (op->type == OP_OP_NUMBER)
2202            {
2203            if (isdigit((unsigned char)s[1])) break;
2204            }
2205          else   /* Check for end or a dataless option */
2206          {          {
2207          option_data = s+1;          if (op->type != OP_NODATA || s[1] == 0) break;
         break;  
2208          }          }
2209    
2210          /* Handle a single-character option with no data, then loop for the
2211          next character in the string. */
2212    
2213        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
2214        }        }
2215      }      }
# Line 2182  for (i = 1; i < argc; i++) Line 2226  for (i = 1; i < argc; i++)
2226    
2227    /* 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
2228    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
2229    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",
2230    Jeffrey Friedl's special -S debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2231    
2232    if (*option_data == 0 &&    if (*option_data == 0 &&
2233        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
# Line 2193  for (i = 1; i < argc; i++) Line 2237  for (i = 1; i < argc; i++)
2237        case N_COLOUR:        case N_COLOUR:
2238        colour_option = (char *)"auto";        colour_option = (char *)"auto";
2239        break;        break;
2240    
2241          case 'o':
2242          only_matching = 0;
2243          break;
2244    
2245  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2246        case 'S':        case 'S':
2247        S_arg = 0;        S_arg = 0;
# Line 2230  for (i = 1; i < argc; i++) Line 2279  for (i = 1; i < argc; i++)
2279    
2280    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with single string or numeric data values. */
2281    
2282    else if (op->type != OP_NUMBER && op->type != OP_OP_NUMBER)    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2283               op->type != OP_OP_NUMBER)
2284      {      {
2285      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2286      }      }
# Line 2260  for (i = 1; i < argc; i++) Line 2310  for (i = 1; i < argc; i++)
2310            option_data, op->one_char);            option_data, op->one_char);
2311        pcregrep_exit(usage(2));        pcregrep_exit(usage(2));
2312        }        }
2313      *((int *)op->dataptr) = n;      if (op->type == OP_LONGNUMBER)
2314            *((unsigned long int *)op->dataptr) = n;
2315        else
2316            *((int *)op->dataptr) = n;
2317      }      }
2318    }    }
2319    
# Line 2274  if (both_context > 0) Line 2327  if (both_context > 0)
2327    }    }
2328    
2329  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2330  However, the latter two set the only_matching flag. */  However, the latter two set only_matching. */
2331    
2332  if ((only_matching && (file_offsets || line_offsets)) ||  if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2333      (file_offsets && line_offsets))      (file_offsets && line_offsets))
2334    {    {
2335    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
# Line 2284  if ((only_matching && (file_offsets || l Line 2337  if ((only_matching && (file_offsets || l
2337    pcregrep_exit(usage(2));    pcregrep_exit(usage(2));
2338    }    }
2339    
2340  if (file_offsets || line_offsets) only_matching = TRUE;  if (file_offsets || line_offsets) only_matching = 0;
2341    
2342  /* 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
2343  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
# Line 2492  for (j = 0; j < pattern_count; j++) Line 2545  for (j = 0; j < pattern_count; j++)
2545      }      }
2546    hint_count++;    hint_count++;
2547    }    }
2548    
2549  /* 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
2550  pcre_extra block for each pattern. */  pcre_extra block for each pattern. */
2551    
# Line 2503  if (match_limit > 0 || match_limit_recur Line 2556  if (match_limit > 0 || match_limit_recur
2556      if (hints_list[j] == NULL)      if (hints_list[j] == NULL)
2557        {        {
2558        hints_list[j] = malloc(sizeof(pcre_extra));        hints_list[j] = malloc(sizeof(pcre_extra));
2559        if (hints_list[j] == NULL)        if (hints_list[j] == NULL)
2560          {          {
2561          fprintf(stderr, "pcregrep: malloc failed\n");          fprintf(stderr, "pcregrep: malloc failed\n");
2562          pcregrep_exit(2);          pcregrep_exit(2);
2563          }          }
2564        }        }
2565      if (match_limit > 0)      if (match_limit > 0)
2566        {        {
2567        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2568        hints_list[j]->match_limit = match_limit;        hints_list[j]->match_limit = match_limit;
2569        }        }
2570      if (match_limit_recursion > 0)      if (match_limit_recursion > 0)
2571        {        {
2572        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;        hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2573        hints_list[j]->match_limit_recursion = match_limit_recursion;        hints_list[j]->match_limit_recursion = match_limit_recursion;
2574        }        }
2575      }      }
2576    }    }
2577    
2578  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2579    
# Line 2603  if (pattern_list != NULL) Line 2656  if (pattern_list != NULL)
2656    }    }
2657  if (hints_list != NULL)  if (hints_list != NULL)
2658    {    {
2659    for (i = 0; i < hint_count; i++)    for (i = 0; i < hint_count; i++)
2660      {      {
2661      if (hints_list[i] != NULL) free(hints_list[i]);      if (hints_list[i] != NULL) free(hints_list[i]);
2662      }      }
2663    free(hints_list);    free(hints_list);
2664    }    }
2665  pcregrep_exit(rc);  pcregrep_exit(rc);

Legend:
Removed from v.564  
changed lines
  Added in v.588

  ViewVC Help
Powered by ViewVC 1.1.5