/[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 515 by ph10, Tue May 4 09:12:25 2010 UTC revision 561 by ph10, Sat Oct 30 18:37:47 2010 UTC
# Line 104  enum { DEE_READ, DEE_SKIP }; Line 104  enum { DEE_READ, DEE_SKIP };
104    
105  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };  enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };
106    
107  /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some  /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some
108  environments), a warning is issued if the value of fwrite() is ignored.  environments), a warning is issued if the value of fwrite() is ignored.
109  Unfortunately, casting to (void) does not suppress the warning. To get round  Unfortunately, casting to (void) does not suppress the warning. To get round
110  this, we use a macro that compiles a fudge. Oddly, this does not also seem to  this, we use a macro that compiles a fudge. Oddly, this does not also seem to
111  apply to fprintf(). */  apply to fprintf(). */
112    
113  #define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}  #define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}
# Line 165  static int error_count = 0; Line 165  static int error_count = 0;
165  static int filenames = FN_DEFAULT;  static int filenames = FN_DEFAULT;
166  static int process_options = 0;  static int process_options = 0;
167    
168    static unsigned long int match_limit = 0;
169    static unsigned long int match_limit_recursion = 0;
170    
171  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
172  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
173  static BOOL file_offsets = FALSE;  static BOOL file_offsets = FALSE;
174  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
175  static BOOL invert = FALSE;  static BOOL invert = FALSE;
176    static BOOL line_buffered = FALSE;
177  static BOOL line_offsets = FALSE;  static BOOL line_offsets = FALSE;
178  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
179  static BOOL number = FALSE;  static BOOL number = FALSE;
180  static BOOL omit_zero_count = FALSE;  static BOOL omit_zero_count = FALSE;
181  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
182    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;
# Line 206  used to identify them. */ Line 211  used to identify them. */
211  #define N_NULL         (-9)  #define N_NULL         (-9)
212  #define N_LOFFSETS     (-10)  #define N_LOFFSETS     (-10)
213  #define N_FOFFSETS     (-11)  #define N_FOFFSETS     (-11)
214    #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" },
# Line 213  static option_item optionlist[] = { Line 221  static option_item optionlist[] = {
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" },
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" },
   { OP_OP_STRING, N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },  
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)" },
# Line 228  static option_item optionlist[] = { Line 236  static option_item optionlist[] = {
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" },
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" },
243      { OP_NUMBER,    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" },
# Line 339  return (statbuf.st_mode & S_IFMT) == S_I Line 350  return (statbuf.st_mode & S_IFMT) == S_I
350  }  }
351    
352    
353  /************* Test stdout for being a terminal in Unix **********/  /************* Test for a terminal in Unix **********/
354    
355  static BOOL  static BOOL
356  is_stdout_tty(void)  is_stdout_tty(void)
# Line 347  is_stdout_tty(void) Line 358  is_stdout_tty(void)
358  return isatty(fileno(stdout));  return isatty(fileno(stdout));
359  }  }
360    
361    static BOOL
362    is_file_tty(FILE *f)
363    {
364    return isatty(fileno(f));
365    }
366    
367    
368  /************* Directory scanning in Win32 ***********/  /************* Directory scanning in Win32 ***********/
369    
# Line 354  return isatty(fileno(stdout)); Line 371  return isatty(fileno(stdout));
371  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
372  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
373  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.  <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
374  */  The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
375    undefined when it is indeed undefined. */
376    
377  #elif HAVE_WINDOWS_H  #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
378    
379  #ifndef STRICT  #ifndef STRICT
380  # define STRICT  # define STRICT
# Line 400  dir = (directory_type *) malloc(sizeof(* Line 418  dir = (directory_type *) malloc(sizeof(*
418  if ((pattern == NULL) || (dir == NULL))  if ((pattern == NULL) || (dir == NULL))
419    {    {
420    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
421    exit(2);    pcregrep_exit(2);
422    }    }
423  memcpy(pattern, filename, len);  memcpy(pattern, filename, len);
424  memcpy(&(pattern[len]), "\\*", 3);  memcpy(&(pattern[len]), "\\*", 3);
# Line 459  return !isdirectory(filename); Line 477  return !isdirectory(filename);
477  }  }
478    
479    
480  /************* Test stdout for being a terminal in Win32 **********/  /************* Test for a terminal in Win32 **********/
481    
482  /* I don't know how to do this; assume never */  /* I don't know how to do this; assume never */
483    
# Line 469  is_stdout_tty(void) Line 487  is_stdout_tty(void)
487  return FALSE;  return FALSE;
488  }  }
489    
490    static BOOL
491    is_file_tty(FILE *f)
492    {
493    return FALSE;
494    }
495    
496    
497  /************* Directory scanning when we can't do it ***********/  /************* Directory scanning when we can't do it ***********/
498    
# Line 491  void closedirectory(directory_type *dir) Line 515  void closedirectory(directory_type *dir)
515  int isregfile(char *filename) { return 1; }  int isregfile(char *filename) { return 1; }
516    
517    
518  /************* Test stdout for being a terminal when we can't do it **********/  /************* Test for a terminal when we can't do it **********/
519    
520  static BOOL  static BOOL
521  is_stdout_tty(void)  is_stdout_tty(void)
# Line 499  is_stdout_tty(void) Line 523  is_stdout_tty(void)
523  return FALSE;  return FALSE;
524  }  }
525    
526    static BOOL
527    is_file_tty(FILE *f)
528    {
529    return FALSE;
530    }
531    
532  #endif  #endif
533    
# Line 527  return sys_errlist[n]; Line 556  return sys_errlist[n];
556    
557    
558  /*************************************************  /*************************************************
559    *         Exit from the program                  *
560    *************************************************/
561    
562    /* If there has been a resource error, give a suitable message.
563    
564    Argument:  the return code
565    Returns:   does not return
566    */
567    
568    static void
569    pcregrep_exit(int rc)
570    {
571    if (resource_error)
572      {
573      fprintf(stderr, "pcregrep: Error %d or %d means that a resource limit "
574        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT);
575      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
576      }
577    
578    exit(rc);
579    }
580    
581    
582    
583    /*************************************************
584    *            Read one line of input              *
585    *************************************************/
586    
587    /* Normally, input is read using fread() into a large buffer, so many lines may
588    be read at once. However, doing this for tty input means that no output appears
589    until a lot of input has been typed. Instead, tty input is handled line by
590    line. We cannot use fgets() for this, because it does not stop at a binary
591    zero, and therefore there is no way of telling how many characters it has read,
592    because there may be binary zeros embedded in the data.
593    
594    Arguments:
595      buffer     the buffer to read into
596      length     the maximum number of characters to read
597      f          the file
598    
599    Returns:     the number of characters read, zero at end of file
600    */
601    
602    static int
603    read_one_line(char *buffer, int length, FILE *f)
604    {
605    int c;
606    int yield = 0;
607    while ((c = fgetc(f)) != EOF)
608      {
609      buffer[yield++] = c;
610      if (c == '\n' || yield >= length) break;
611      }
612    return yield;
613    }
614    
615    
616    
617    /*************************************************
618  *             Find end of line                   *  *             Find end of line                   *
619  *************************************************/  *************************************************/
620    
# Line 853  static BOOL Line 941  static BOOL
941  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)  match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)
942  {  {
943  int i;  int i;
944    size_t slen = length;
945    const char *msg = "this text:\n\n";
946    if (slen > 200)
947      {
948      slen = 200;
949      msg = "text that starts:\n\n";
950      }
951  for (i = 0; i < pattern_count; i++)  for (i = 0; i < pattern_count; i++)
952    {    {
953    *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0,    *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length, 0,
954      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);      PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
955    if (*mrc >= 0) return TRUE;    if (*mrc >= 0) return TRUE;
956    if (*mrc == PCRE_ERROR_NOMATCH) continue;    if (*mrc == PCRE_ERROR_NOMATCH) continue;
957    fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);    fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
958    if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);    if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
959    fprintf(stderr, "this text:\n");    fprintf(stderr, "%s", msg);
960    FWRITE(matchptr, 1, length, stderr);   /* In case binary zero included */    FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
961    fprintf(stderr, "\n");    fprintf(stderr, "\n\n");
962    if (error_count == 0 &&    if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT)
963        (*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");  
     }  
964    if (error_count++ > 20)    if (error_count++ > 20)
965      {      {
966      fprintf(stderr, "pcregrep: too many errors - abandoned\n");      fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
967      exit(2);      pcregrep_exit(2);
968      }      }
969    return invert;    /* No more matching; don't show the line again */    return invert;    /* No more matching; don't show the line again */
970    }    }
# Line 924  char *ptr = buffer; Line 1014  char *ptr = buffer;
1014  char *endptr;  char *endptr;
1015  size_t bufflength;  size_t bufflength;
1016  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
1017    BOOL input_line_buffered = line_buffered;
1018  FILE *in = NULL;                    /* Ensure initialized */  FILE *in = NULL;                    /* Ensure initialized */
1019    
1020  #ifdef SUPPORT_LIBZ  #ifdef SUPPORT_LIBZ
# Line 961  else Line 1052  else
1052    
1053    {    {
1054    in = (FILE *)handle;    in = (FILE *)handle;
1055    bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);    if (is_file_tty(in)) input_line_buffered = TRUE;
1056      bufflength = input_line_buffered?
1057        read_one_line(buffer, 3*MBUFTHIRD, in) :
1058        fread(buffer, 1, 3*MBUFTHIRD, in);
1059    }    }
1060    
1061  endptr = buffer + bufflength;  endptr = buffer + bufflength;
# Line 1010  while (ptr < endptr) Line 1104  while (ptr < endptr)
1104            ptr = malloc(newlen + 1);            ptr = malloc(newlen + 1);
1105            if (!ptr) {            if (!ptr) {
1106                    printf("out of memory");                    printf("out of memory");
1107                    exit(2);                    pcregrep_exit(2);
1108            }            }
1109            endptr = ptr;            endptr = ptr;
1110            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
# Line 1263  while (ptr < endptr) Line 1357  while (ptr < endptr)
1357            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);            FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1358            fprintf(stdout, "%c[00m", 0x1b);            fprintf(stdout, "%c[00m", 0x1b);
1359            }            }
1360          FWRITE(ptr + last_offset, 1,          FWRITE(ptr + last_offset, 1,
1361            (linelength + endlinelength) - last_offset, stdout);            (linelength + endlinelength) - last_offset, stdout);
1362          }          }
1363    
# Line 1272  while (ptr < endptr) Line 1366  while (ptr < endptr)
1366        else FWRITE(ptr, 1, linelength + endlinelength, stdout);        else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1367        }        }
1368    
1369      /* End of doing what has to be done for a match */      /* End of doing what has to be done for a match. If --line-buffered was
1370        given, flush the output. */
1371    
1372        if (line_buffered) fflush(stdout);
1373      rc = 0;    /* Had some success */      rc = 0;    /* Had some success */
1374    
1375      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
# Line 1305  while (ptr < endptr) Line 1401  while (ptr < endptr)
1401    offset to the current line is maintained in filepos. */    offset to the current line is maintained in filepos. */
1402    
1403    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1404    filepos += linelength + endlinelength;    filepos += (int)(linelength + endlinelength);
1405    linenumber++;    linenumber++;
1406    
1407      /* If input is line buffered, and the buffer is not yet full, read another
1408      line and add it into the buffer. */
1409    
1410      if (input_line_buffered && bufflength < sizeof(buffer))
1411        {
1412        int add = read_one_line(ptr, sizeof(buffer) - (ptr - buffer), in);
1413        bufflength += add;
1414        endptr += add;
1415        }
1416    
1417    /* If we haven't yet reached the end of the file (the buffer is full), and    /* If we haven't yet reached the end of the file (the buffer is full), and
1418    the current point is in the top 1/3 of the buffer, slide the buffer down by    the current point is in the top 1/3 of the buffer, slide the buffer down by
1419    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
# Line 1342  while (ptr < endptr) Line 1448  while (ptr < endptr)
1448      else      else
1449  #endif  #endif
1450    
1451      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD +
1452          (input_line_buffered?
1453           read_one_line(buffer + 2*MBUFTHIRD, MBUFTHIRD, in) :
1454           fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in));
1455      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1456    
1457      /* Adjust any last match point */      /* Adjust any last match point */
# Line 1459  if ((sep = isdirectory(pathname)) != 0) Line 1567  if ((sep = isdirectory(pathname)) != 0)
1567        {        {
1568        int frc, nflen;        int frc, nflen;
1569        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1570        nflen = strlen(nextfile);        nflen = (int)(strlen(nextfile));
1571    
1572        if (isdirectory(buffer))        if (isdirectory(buffer))
1573          {          {
# Line 1503  skipping was not requested. The scan pro Line 1611  skipping was not requested. The scan pro
1611  argument at top level, we don't show the file name, unless we are only showing  argument at top level, we don't show the file name, unless we are only showing
1612  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1613    
1614  pathlen = strlen(pathname);  pathlen = (int)(strlen(pathname));
1615    
1616  /* Open using zlib if it is supported and the file name ends with .gz. */  /* Open using zlib if it is supported and the file name ends with .gz. */
1617    
# Line 1692  handle_option(int letter, int options) Line 1800  handle_option(int letter, int options)
1800  switch(letter)  switch(letter)
1801    {    {
1802    case N_FOFFSETS: file_offsets = TRUE; break;    case N_FOFFSETS: file_offsets = TRUE; break;
1803    case N_HELP: help(); exit(0);    case N_HELP: help(); pcregrep_exit(0);
1804    case N_LOFFSETS: line_offsets = number = TRUE; break;    case N_LOFFSETS: line_offsets = number = TRUE; break;
1805      case N_LBUFFER: line_buffered = TRUE; break;
1806    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1807    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1808    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
# Line 1714  switch(letter) Line 1823  switch(letter)
1823    
1824    case 'V':    case 'V':
1825    fprintf(stderr, "pcregrep version %s\n", pcre_version());    fprintf(stderr, "pcregrep version %s\n", pcre_version());
1826    exit(0);    pcregrep_exit(0);
1827    break;    break;
1828    
1829    default:    default:
1830    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);    fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
1831    exit(usage(2));    pcregrep_exit(usage(2));
1832    }    }
1833    
1834  return options;  return options;
# Line 1915  for (i = 1; i < argc; i++) Line 2024  for (i = 1; i < argc; i++)
2024    if (argv[i][1] == 0)    if (argv[i][1] == 0)
2025      {      {
2026      if (pattern_filename != NULL || pattern_count > 0) break;      if (pattern_filename != NULL || pattern_count > 0) break;
2027        else exit(usage(2));        else pcregrep_exit(usage(2));
2028      }      }
2029    
2030    /* Handle a long name option, or -- to terminate the options */    /* Handle a long name option, or -- to terminate the options */
# Line 1955  for (i = 1; i < argc; i++) Line 2064  for (i = 1; i < argc; i++)
2064            }            }
2065          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
2066            {            {
2067            int oplen = equals - op->long_name;            int oplen = (int)(equals - op->long_name);
2068            int arglen = (argequals == NULL)? (int)strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)?
2069                (int)strlen(arg) : (int)(argequals - arg);
2070            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
2071              {              {
2072              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1977  for (i = 1; i < argc; i++) Line 2087  for (i = 1; i < argc; i++)
2087          char buff1[24];          char buff1[24];
2088          char buff2[24];          char buff2[24];
2089    
2090          int baselen = opbra - op->long_name;          int baselen = (int)(opbra - op->long_name);
2091          int fulllen = strchr(op->long_name, ')') - op->long_name + 1;          int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
2092          int arglen = (argequals == NULL || equals == NULL)?          int arglen = (argequals == NULL || equals == NULL)?
2093            (int)strlen(arg) : argequals - arg;            (int)strlen(arg) : (int)(argequals - arg);
2094    
2095          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
2096          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);          sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
# Line 2005  for (i = 1; i < argc; i++) Line 2115  for (i = 1; i < argc; i++)
2115      if (op->one_char == 0)      if (op->one_char == 0)
2116        {        {
2117        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);        fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
2118        exit(usage(2));        pcregrep_exit(usage(2));
2119        }        }
2120      }      }
2121    
# Line 2047  for (i = 1; i < argc; i++) Line 2157  for (i = 1; i < argc; i++)
2157          {          {
2158          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",          fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2159            *s, argv[i]);            *s, argv[i]);
2160          exit(usage(2));          pcregrep_exit(usage(2));
2161          }          }
2162        if (op->type != OP_NODATA || s[1] == 0)        if (op->type != OP_NODATA || s[1] == 0)
2163          {          {
# Line 2097  for (i = 1; i < argc; i++) Line 2207  for (i = 1; i < argc; i++)
2207      if (i >= argc - 1 || longopwasequals)      if (i >= argc - 1 || longopwasequals)
2208        {        {
2209        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);        fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);
2210        exit(usage(2));        pcregrep_exit(usage(2));
2211        }        }
2212      option_data = argv[++i];      option_data = argv[++i];
2213      }      }
# Line 2122  for (i = 1; i < argc; i++) Line 2232  for (i = 1; i < argc; i++)
2232      {      {
2233      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2234      }      }
2235    
2236      /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2237      only for unpicking arguments, so just keep it simple. */
2238    
2239    else    else
2240      {      {
2241      char *endptr;      unsigned long int n = 0;
2242      int n = strtoul(option_data, &endptr, 10);      char *endptr = option_data;
2243        while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2244        while (isdigit((unsigned char)(*endptr)))
2245          n = n * 10 + (int)(*endptr++ - '0');
2246      if (*endptr != 0)      if (*endptr != 0)
2247        {        {
2248        if (longop)        if (longop)
2249          {          {
2250          char *equals = strchr(op->long_name, '=');          char *equals = strchr(op->long_name, '=');
2251          int nlen = (equals == NULL)? (int)strlen(op->long_name) :          int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2252            equals - op->long_name;            (int)(equals - op->long_name);
2253          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2254            option_data, nlen, op->long_name);            option_data, nlen, op->long_name);
2255          }          }
2256        else        else
2257          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",          fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2258            option_data, op->one_char);            option_data, op->one_char);
2259        exit(usage(2));        pcregrep_exit(usage(2));
2260        }        }
2261      *((int *)op->dataptr) = n;      *((int *)op->dataptr) = n;
2262      }      }
# Line 2162  if ((only_matching && (file_offsets || l Line 2279  if ((only_matching && (file_offsets || l
2279    {    {
2280    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2281      "and/or --line-offsets\n");      "and/or --line-offsets\n");
2282    exit(usage(2));    pcregrep_exit(usage(2));
2283    }    }
2284    
2285  if (file_offsets || line_offsets) only_matching = TRUE;  if (file_offsets || line_offsets) only_matching = TRUE;
# Line 2373  for (j = 0; j < pattern_count; j++) Line 2490  for (j = 0; j < pattern_count; j++)
2490      }      }
2491    hint_count++;    hint_count++;
2492    }    }
2493    
2494    /* If --match-limit or --recursion-limit was set, put the value(s) into the
2495    pcre_extra block for each pattern. */
2496    
2497    if (match_limit > 0 || match_limit_recursion > 0)
2498      {
2499      for (j = 0; j < pattern_count; j++)
2500        {
2501        if (hints_list[j] == NULL)
2502          {
2503          hints_list[j] = malloc(sizeof(pcre_extra));
2504          if (hints_list[j] == NULL)
2505            {
2506            fprintf(stderr, "pcregrep: malloc failed\n");
2507            pcregrep_exit(2);
2508            }
2509          }
2510        if (match_limit > 0)
2511          {
2512          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2513          hints_list[j]->match_limit = match_limit;
2514          }
2515        if (match_limit_recursion > 0)
2516          {
2517          hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2518          hints_list[j]->match_limit_recursion = match_limit_recursion;
2519          }
2520        }
2521      }
2522    
2523  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
2524    
# Line 2455  if (pattern_list != NULL) Line 2601  if (pattern_list != NULL)
2601    }    }
2602  if (hints_list != NULL)  if (hints_list != NULL)
2603    {    {
2604    for (i = 0; i < hint_count; i++) free(hints_list[i]);    for (i = 0; i < hint_count; i++)
2605        {
2606        if (hints_list[i] != NULL) free(hints_list[i]);
2607        }
2608    free(hints_list);    free(hints_list);
2609    }    }
2610  return rc;  pcregrep_exit(rc);
2611    
2612  EXIT2:  EXIT2:
2613  rc = 2;  rc = 2;

Legend:
Removed from v.515  
changed lines
  Added in v.561

  ViewVC Help
Powered by ViewVC 1.1.5