/[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 1033 by ph10, Mon Sep 10 11:02:48 2012 UTC revision 1096 by chpe, Tue Oct 16 15:56:09 2012 UTC
# Line 143  static char *DEE_option = NULL; Line 143  static char *DEE_option = NULL;
143  static char *locale = NULL;  static char *locale = NULL;
144  static char *main_buffer = NULL;  static char *main_buffer = NULL;
145  static char *newline = NULL;  static char *newline = NULL;
146    static char *om_separator = (char *)"";
147  static char *stdin_name = (char *)"(standard input)";  static char *stdin_name = (char *)"(standard input)";
148    
149  static const unsigned char *pcretables = NULL;  static const unsigned char *pcretables = NULL;
# Line 163  static int dee_action = dee_READ; Line 164  static int dee_action = dee_READ;
164  static int DEE_action = DEE_READ;  static int DEE_action = DEE_READ;
165  static int error_count = 0;  static int error_count = 0;
166  static int filenames = FN_DEFAULT;  static int filenames = FN_DEFAULT;
 static int only_matching = -1;  
167  static int pcre_options = 0;  static int pcre_options = 0;
168  static int process_options = 0;  static int process_options = 0;
169    
# Line 188  static BOOL number = FALSE; Line 188  static BOOL number = FALSE;
188  static BOOL omit_zero_count = FALSE;  static BOOL omit_zero_count = FALSE;
189  static BOOL resource_error = FALSE;  static BOOL resource_error = FALSE;
190  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
191    static BOOL show_only_matching = FALSE;
192  static BOOL silent = FALSE;  static BOOL silent = FALSE;
193  static BOOL utf8 = FALSE;  static BOOL utf8 = FALSE;
194    
195    /* Structure for list of --only-matching capturing numbers. */
196    
197    typedef struct omstr {
198      struct omstr *next;
199      int groupnum;
200    } omstr;
201    
202    static omstr *only_matching = NULL;
203    static omstr *only_matching_last = NULL;
204    
205    /* Structure for holding the two variables that describe a number chain. */
206    
207    typedef struct omdatastr {
208      omstr **anchor;
209      omstr **lastptr;
210    } omdatastr;
211    
212    static omdatastr only_matching_data = { &only_matching, &only_matching_last };
213    
214  /* Structure for list of file names (for -f and --{in,ex}clude-from) */  /* Structure for list of file names (for -f and --{in,ex}clude-from) */
215    
216  typedef struct fnstr {  typedef struct fnstr {
# Line 264  static const char *incexname[4] = { "--i Line 284  static const char *incexname[4] = { "--i
284  /* Structure for options and list of them */  /* Structure for options and list of them */
285    
286  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,  enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
287         OP_OP_NUMBER, OP_PATLIST, OP_FILELIST, OP_BINFILES };         OP_OP_NUMBER, OP_OP_NUMBERS, OP_PATLIST, OP_FILELIST, OP_BINFILES };
288    
289  typedef struct option_item {  typedef struct option_item {
290    int type;    int type;
# Line 297  used to identify them. */ Line 317  used to identify them. */
317  #define N_BINARY_FILES (-18)  #define N_BINARY_FILES (-18)
318  #define N_EXCLUDE_FROM (-19)  #define N_EXCLUDE_FROM (-19)
319  #define N_INCLUDE_FROM (-20)  #define N_INCLUDE_FROM (-20)
320    #define N_OM_SEPARATOR (-21)
321    
322  static option_item optionlist[] = {  static option_item optionlist[] = {
323    { OP_NODATA,     N_NULL,   NULL,              "",              "terminate options" },    { OP_NODATA,     N_NULL,   NULL,              "",              "terminate options" },
# Line 337  static option_item optionlist[] = { Line 358  static option_item optionlist[] = {
358    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
359    { 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)" },
360    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
361    { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },    { OP_OP_NUMBERS, 'o',      &only_matching_data, "only-matching=n", "show only the part of the line that matched" },
362      { OP_STRING,     N_OM_SEPARATOR, &om_separator, "om-separator=text", "set separator for multiple -o output" },
363    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
364    { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
365    { OP_PATLIST,    N_EXCLUDE,&exclude_patdata,  "exclude=pattern","exclude matching files when recursing" },    { OP_PATLIST,    N_EXCLUDE,&exclude_patdata,  "exclude=pattern","exclude matching files when recursing" },
# Line 393  const char utf8_table4[] = { Line 415  const char utf8_table4[] = {
415    
416    
417  /*************************************************  /*************************************************
418    *         Exit from the program                  *
419    *************************************************/
420    
421    /* If there has been a resource error, give a suitable message.
422    
423    Argument:  the return code
424    Returns:   does not return
425    */
426    
427    static void
428    pcregrep_exit(int rc)
429    {
430    if (resource_error)
431      {
432      fprintf(stderr, "pcregrep: Error %d, %d or %d means that a resource limit "
433        "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT,
434        PCRE_ERROR_JIT_STACKLIMIT);
435      fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
436      }
437    exit(rc);
438    }
439    
440    
441    /*************************************************
442  *          Add item to chain of patterns         *  *          Add item to chain of patterns         *
443  *************************************************/  *************************************************/
444    
# Line 403  Arguments: Line 449  Arguments:
449    s          pattern string to add    s          pattern string to add
450    after      if not NULL points to item to insert after    after      if not NULL points to item to insert after
451    
452  Returns:     new pattern block, or NULL after malloc failure  Returns:     new pattern block
453  */  */
454    
455  static patstr *  static patstr *
# Line 413  patstr *p = (patstr *)malloc(sizeof(pats Line 459  patstr *p = (patstr *)malloc(sizeof(pats
459  if (p == NULL)  if (p == NULL)
460    {    {
461    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
462    return NULL;    pcregrep_exit(2);
463    }    }
464  if (strlen(s) > MAXPATLEN)  if (strlen(s) > MAXPATLEN)
465    {    {
# Line 481  while (fn != NULL) Line 527  while (fn != NULL)
527    
528    
529  /*************************************************  /*************************************************
 *         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, %d or %d means that a resource limit "  
     "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT,  
     PCRE_ERROR_JIT_STACKLIMIT);  
   fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");  
   }  
   
 exit(rc);  
 }  
   
   
 /*************************************************  
530  *            OS-specific functions               *  *            OS-specific functions               *
531  *************************************************/  *************************************************/
532    
# Line 779  return sys_errlist[n]; Line 800  return sys_errlist[n];
800    
801    
802  /*************************************************  /*************************************************
803    *                Usage function                  *
804    *************************************************/
805    
806    static int
807    usage(int rc)
808    {
809    option_item *op;
810    fprintf(stderr, "Usage: pcregrep [-");
811    for (op = optionlist; op->one_char != 0; op++)
812      {
813      if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
814      }
815    fprintf(stderr, "] [long options] [pattern] [files]\n");
816    fprintf(stderr, "Type `pcregrep --help' for more information and the long "
817      "options.\n");
818    return rc;
819    }
820    
821    
822    
823    /*************************************************
824    *                Help function                   *
825    *************************************************/
826    
827    static void
828    help(void)
829    {
830    option_item *op;
831    
832    printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
833    printf("Search for PATTERN in each FILE or standard input.\n");
834    printf("PATTERN must be present if neither -e nor -f is used.\n");
835    printf("\"-\" can be used as a file name to mean STDIN.\n");
836    
837    #ifdef SUPPORT_LIBZ
838    printf("Files whose names end in .gz are read using zlib.\n");
839    #endif
840    
841    #ifdef SUPPORT_LIBBZ2
842    printf("Files whose names end in .bz2 are read using bzlib2.\n");
843    #endif
844    
845    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
846    printf("Other files and the standard input are read as plain files.\n\n");
847    #else
848    printf("All files are read as plain files, without any interpretation.\n\n");
849    #endif
850    
851    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
852    printf("Options:\n");
853    
854    for (op = optionlist; op->one_char != 0; op++)
855      {
856      int n;
857      char s[4];
858    
859      /* Two options were accidentally implemented and documented with underscores
860      instead of hyphens in their names, something that was not noticed for quite a
861      few releases. When fixing this, I left the underscored versions in the list
862      in case people were using them. However, we don't want to display them in the
863      help data. There are no other options that contain underscores, and we do not
864      expect ever to implement such options. Therefore, just omit any option that
865      contains an underscore. */
866    
867      if (strchr(op->long_name, '_') != NULL) continue;
868    
869      if (op->one_char > 0 && (op->long_name)[0] == 0)
870        n = 31 - printf("  -%c", op->one_char);
871      else
872        {
873        if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);
874          else strcpy(s, "   ");
875        n = 31 - printf("  %s --%s", s, op->long_name);
876        }
877    
878      if (n < 1) n = 1;
879      printf("%.*s%s\n", n, "                           ", op->help_text);
880      }
881    
882    printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n");
883    printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);
884    printf("When reading patterns or file names from a file, trailing white\n");
885    printf("space is removed and blank lines are ignored.\n");
886    printf("The maximum size of any pattern is %d bytes.\n", MAXPATLEN);
887    
888    printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");
889    printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");
890    }
891    
892    
893    
894    /*************************************************
895  *            Test exclude/includes               *  *            Test exclude/includes               *
896  *************************************************/  *************************************************/
897    
# Line 818  return FALSE; Line 931  return FALSE;
931    
932    
933  /*************************************************  /*************************************************
934    *         Decode integer argument value          *
935    *************************************************/
936    
937    /* Integer arguments can be followed by K or M. Avoid the use of strtoul()
938    because SunOS4 doesn't have it. This is used only for unpicking arguments, so
939    just keep it simple.
940    
941    Arguments:
942      option_data   the option data string
943      op            the option item (for error messages)
944      longop        TRUE if option given in long form
945    
946    Returns:        a long integer
947    */
948    
949    static long int
950    decode_number(char *option_data, option_item *op, BOOL longop)
951    {
952    unsigned long int n = 0;
953    char *endptr = option_data;
954    while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
955    while (isdigit((unsigned char)(*endptr)))
956      n = n * 10 + (int)(*endptr++ - '0');
957    if (toupper(*endptr) == 'K')
958      {
959      n *= 1024;
960      endptr++;
961      }
962    else if (toupper(*endptr) == 'M')
963      {
964      n *= 1024*1024;
965      endptr++;
966      }
967    
968    if (*endptr != 0)   /* Error */
969      {
970      if (longop)
971        {
972        char *equals = strchr(op->long_name, '=');
973        int nlen = (equals == NULL)? (int)strlen(op->long_name) :
974          (int)(equals - op->long_name);
975        fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
976          option_data, nlen, op->long_name);
977        }
978      else
979        fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
980          option_data, op->one_char);
981      pcregrep_exit(usage(2));
982      }
983    
984    return n;
985    }
986    
987    
988    
989    /*************************************************
990    *       Add item to a chain of numbers           *
991    *************************************************/
992    
993    /* Used to add an item onto a chain, or just return an unconnected item if the
994    "after" argument is NULL.
995    
996    Arguments:
997      n          the number to add
998      after      if not NULL points to item to insert after
999    
1000    Returns:     new number block
1001    */
1002    
1003    static omstr *
1004    add_number(int n, omstr *after)
1005    {
1006    omstr *om = (omstr *)malloc(sizeof(omstr));
1007    
1008    if (om == NULL)
1009      {
1010      fprintf(stderr, "pcregrep: malloc failed\n");
1011      pcregrep_exit(2);
1012      }
1013    om->next = NULL;
1014    om->groupnum = n;
1015    
1016    if (after != NULL)
1017      {
1018      om->next = after->next;
1019      after->next = om;
1020      }
1021    return om;
1022    }
1023    
1024    
1025    
1026    /*************************************************
1027  *            Read one line of input              *  *            Read one line of input              *
1028  *************************************************/  *************************************************/
1029    
# Line 1001  switch(endlinetype) Line 1207  switch(endlinetype)
1207        case 0x2029:  /* Unicode PS */        case 0x2029:  /* Unicode PS */
1208        *lenptr = 3;        *lenptr = 3;
1209        return p;        return p;
1210  #endif  /* Not EBCDIC */  #endif  /* Not EBCDIC */
1211    
1212        default:        default:
1213        break;        break;
# Line 1060  switch(endlinetype) Line 1266  switch(endlinetype)
1266    
1267    while (p > startptr)    while (p > startptr)
1268      {      {
1269      register int c;      register unsigned int c;
1270      char *pp = p - 1;      char *pp = p - 1;
1271    
1272      if (utf8)      if (utf8)
# Line 1099  switch(endlinetype) Line 1305  switch(endlinetype)
1305        case '\v':    /* VT */        case '\v':    /* VT */
1306        case '\f':    /* FF */        case '\f':    /* FF */
1307        case '\r':    /* CR */        case '\r':    /* CR */
1308  #ifndef EBCDIE  #ifndef EBCDIE
1309        case 0x85:    /* Unicode NEL */        case 0x85:    /* Unicode NEL */
1310        case 0x2028:  /* Unicode LS */        case 0x2028:  /* Unicode LS */
1311        case 0x2029:  /* Unicode PS */        case 0x2029:  /* Unicode PS */
1312  #endif  /* Not EBCDIC */  #endif  /* Not EBCDIC */
1313        return p;        return p;
1314    
1315        default:        default:
# Line 1412  while (ptr < endptr) Line 1618  while (ptr < endptr)
1618    }    }
1619  #endif  #endif
1620    
1621    /* We come back here after a match when the -o option (only_matching) is set,    /* We come back here after a match when show_only_matching is set, in order
1622    in order to find any further matches in the same line. */    to find any further matches in the same line. This applies to
1623      --only-matching, --file-offsets, and --line-offsets. */
1624    
1625    ONLY_MATCHING_RESTART:    ONLY_MATCHING_RESTART:
1626    
# Line 1460  while (ptr < endptr) Line 1667  while (ptr < endptr)
1667    
1668      else if (quiet) return 0;      else if (quiet) return 0;
1669    
1670      /* The --only-matching option prints just the substring that matched, or a      /* The --only-matching option prints just the substring that matched,
1671      captured portion of it, as long as this string is not empty, and the      and/or one or more captured portions of it, as long as these strings are
1672      --file-offsets and --line-offsets options output offsets for the matching      not empty. The --file-offsets and --line-offsets options output offsets for
1673      substring (they both force --only-matching = 0). None of these options      the matching substring (all three set show_only_matching). None of these
1674      prints any context. Afterwards, adjust the start and then jump back to look      mutually exclusive options prints any context. Afterwards, adjust the start
1675      for further matches in the same line. If we are in invert mode, however,      and then jump back to look for further matches in the same line. If we are
1676      nothing is printed and we do not restart - this could still be useful      in invert mode, however, nothing is printed and we do not restart - this
1677      because the return code is set. */      could still be useful because the return code is set. */
1678    
1679      else if (only_matching >= 0)      else if (show_only_matching)
1680        {        {
1681        if (!invert)        if (!invert)
1682          {          {
1683          if (printname != NULL) fprintf(stdout, "%s:", printname);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1684          if (number) fprintf(stdout, "%d:", linenumber);          if (number) fprintf(stdout, "%d:", linenumber);
1685    
1686            /* Handle --line-offsets */
1687    
1688          if (line_offsets)          if (line_offsets)
1689            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),            fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1690              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1691    
1692            /* Handle --file-offsets */
1693    
1694          else if (file_offsets)          else if (file_offsets)
1695            fprintf(stdout, "%d,%d\n",            fprintf(stdout, "%d,%d\n",
1696              (int)(filepos + matchptr + offsets[0] - ptr),              (int)(filepos + matchptr + offsets[0] - ptr),
1697              offsets[1] - offsets[0]);              offsets[1] - offsets[0]);
1698          else if (only_matching < mrc)  
1699            /* Handle --only-matching, which may occur many times */
1700    
1701            else
1702            {            {
1703            int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];            BOOL printed = FALSE;
1704            if (plen > 0)            omstr *om;
1705    
1706              for (om = only_matching; om != NULL; om = om->next)
1707              {              {
1708              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);              int n = om->groupnum;
1709              FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);              if (n < mrc)
1710              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);                {
1711              fprintf(stdout, "\n");                int plen = offsets[2*n + 1] - offsets[2*n];
1712                  if (plen > 0)
1713                    {
1714                    if (printed) fprintf(stdout, "%s", om_separator);
1715                    if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1716                    FWRITE(matchptr + offsets[n*2], 1, plen, stdout);
1717                    if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1718                    printed = TRUE;
1719                    }
1720                  }
1721              }              }
1722    
1723              if (printed || printname != NULL || number) fprintf(stdout, "\n");
1724            }            }
1725          else if (printname != NULL || number) fprintf(stdout, "\n");  
1726            /* Prepare to repeat to find the next match */
1727    
1728          match = FALSE;          match = FALSE;
1729          if (line_buffered) fflush(stdout);          if (line_buffered) fflush(stdout);
1730          rc = 0;                      /* Had some success */          rc = 0;                      /* Had some success */
# Line 1756  while (ptr < endptr) Line 1987  while (ptr < endptr)
1987  /* 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
1988  hyphenpending if it prints something. */  hyphenpending if it prints something. */
1989    
1990  if (only_matching < 0 && !count_only)  if (!show_only_matching && !count_only)
1991    {    {
1992    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);    do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1993    hyphenpending |= endhyphenpending;    hyphenpending |= endhyphenpending;
# Line 2003  return rc; Line 2234  return rc;
2234    
2235    
2236    
   
 /*************************************************  
 *                Usage function                  *  
 *************************************************/  
   
 static int  
 usage(int rc)  
 {  
 option_item *op;  
 fprintf(stderr, "Usage: pcregrep [-");  
 for (op = optionlist; op->one_char != 0; op++)  
   {  
   if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);  
   }  
 fprintf(stderr, "] [long options] [pattern] [files]\n");  
 fprintf(stderr, "Type `pcregrep --help' for more information and the long "  
   "options.\n");  
 return rc;  
 }  
   
   
   
   
 /*************************************************  
 *                Help function                   *  
 *************************************************/  
   
 static void  
 help(void)  
 {  
 option_item *op;  
   
 printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  
 printf("Search for PATTERN in each FILE or standard input.\n");  
 printf("PATTERN must be present if neither -e nor -f is used.\n");  
 printf("\"-\" can be used as a file name to mean STDIN.\n");  
   
 #ifdef SUPPORT_LIBZ  
 printf("Files whose names end in .gz are read using zlib.\n");  
 #endif  
   
 #ifdef SUPPORT_LIBBZ2  
 printf("Files whose names end in .bz2 are read using bzlib2.\n");  
 #endif  
   
 #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2  
 printf("Other files and the standard input are read as plain files.\n\n");  
 #else  
 printf("All files are read as plain files, without any interpretation.\n\n");  
 #endif  
   
 printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
 printf("Options:\n");  
   
 for (op = optionlist; op->one_char != 0; op++)  
   {  
   int n;  
   char s[4];  
   
   /* Two options were accidentally implemented and documented with underscores  
   instead of hyphens in their names, something that was not noticed for quite a  
   few releases. When fixing this, I left the underscored versions in the list  
   in case people were using them. However, we don't want to display them in the  
   help data. There are no other options that contain underscores, and we do not  
   expect ever to implement such options. Therefore, just omit any option that  
   contains an underscore. */  
   
   if (strchr(op->long_name, '_') != NULL) continue;  
   
   if (op->one_char > 0 && (op->long_name)[0] == 0)  
     n = 31 - printf("  -%c", op->one_char);  
   else  
     {  
     if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);  
       else strcpy(s, "   ");  
     n = 31 - printf("  %s --%s", s, op->long_name);  
     }  
   
   if (n < 1) n = 1;  
   printf("%.*s%s\n", n, "                           ", op->help_text);  
   }  
   
 printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n");  
 printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);  
 printf("When reading patterns or file names from a file, trailing white\n");  
 printf("space is removed and blank lines are ignored.\n");  
 printf("The maximum size of any pattern is %d bytes.\n", MAXPATLEN);  
   
 printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");  
 printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");  
 }  
   
   
   
   
2237  /*************************************************  /*************************************************
2238  *    Handle a single-letter, no data option      *  *    Handle a single-letter, no data option      *
2239  *************************************************/  *************************************************/
# Line 2123  switch(letter) Line 2259  switch(letter)
2259    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
2260    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
2261    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
2262    case 'o': only_matching = 0; break;  
2263      case 'o':
2264      only_matching_last = add_number(0, only_matching_last);
2265      if (only_matching == NULL) only_matching = only_matching_last;
2266      break;
2267    
2268    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
2269    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
2270    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
# Line 2509  for (i = 1; i < argc; i++) Line 2650  for (i = 1; i < argc; i++)
2650      {      {
2651      char *s = argv[i] + 1;      char *s = argv[i] + 1;
2652      longop = FALSE;      longop = FALSE;
2653    
2654      while (*s != 0)      while (*s != 0)
2655        {        {
2656        for (op = optionlist; op->one_char != 0; op++)        for (op = optionlist; op->one_char != 0; op++)
# Line 2521  for (i = 1; i < argc; i++) Line 2663  for (i = 1; i < argc; i++)
2663            *s, argv[i]);            *s, argv[i]);
2664          pcregrep_exit(usage(2));          pcregrep_exit(usage(2));
2665          }          }
2666    
2667        /* Check for a single-character option that has data: OP_OP_NUMBER        option_data = s+1;
2668        is used for one that either has a numerical number or defaults, i.e. the  
2669        data is optional. If a digit follows, there is data; if not, carry on        /* Break out if this is the last character in the string; it's handled
2670          below like a single multi-char option. */
2671    
2672          if (*option_data == 0) break;
2673    
2674          /* Check for a single-character option that has data: OP_OP_NUMBER(S)
2675          are used for ones that either have a numerical number or defaults, i.e.
2676          the data is optional. If a digit follows, there is data; if not, carry on
2677        with other single-character options in the same string. */        with other single-character options in the same string. */
2678    
2679        option_data = s+1;        if (op->type == OP_OP_NUMBER || op->type == OP_OP_NUMBERS)
       if (op->type == OP_OP_NUMBER)  
2680          {          {
2681          if (isdigit((unsigned char)s[1])) break;          if (isdigit((unsigned char)s[1])) break;
2682          }          }
2683        else   /* Check for end or a dataless option */        else   /* Check for an option with data */
2684          {          {
2685          if (op->type != OP_NODATA || s[1] == 0) break;          if (op->type != OP_NODATA) break;
2686          }          }
2687    
2688        /* Handle a single-character option with no data, then loop for the        /* Handle a single-character option with no data, then loop for the
2689        next character in the string. */        next character in the string. */
2690    
2691        pcre_options = handle_option(*s++, pcre_options);        pcre_options = handle_option(*s++, pcre_options);
2692        }        }
2693      }      }
2694    
2695    /* At this point we should have op pointing to a matched option. If the type    /* At this point we should have op pointing to a matched option. If the type
2696    is NO_DATA, it means that there is no data, and the option might set    is NO_DATA, it means that there is no data, and the option might set
2697    something in the PCRE options. */    something in the PCRE options. */
# Line 2554  for (i = 1; i < argc; i++) Line 2702  for (i = 1; i < argc; i++)
2702      continue;      continue;
2703      }      }
2704    
2705    /* 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(S), it's an option that
2706    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
2707    separate item. At the moment, the only such options are "colo(u)r",    separate item. At the moment, the only such options are "colo(u)r",
2708    "only-matching", and Jeffrey Friedl's special -S debugging option. */    "only-matching", and Jeffrey Friedl's special -S debugging option. */
2709    
2710    if (*option_data == 0 &&    if (*option_data == 0 &&
2711        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER ||
2712           op->type == OP_OP_NUMBERS))
2713      {      {
2714      switch (op->one_char)      switch (op->one_char)
2715        {        {
# Line 2569  for (i = 1; i < argc; i++) Line 2718  for (i = 1; i < argc; i++)
2718        break;        break;
2719    
2720        case 'o':        case 'o':
2721        only_matching = 0;        only_matching_last = add_number(0, only_matching_last);
2722          if (only_matching == NULL) only_matching = only_matching_last;
2723        break;        break;
2724    
2725  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
# Line 2593  for (i = 1; i < argc; i++) Line 2743  for (i = 1; i < argc; i++)
2743      option_data = argv[++i];      option_data = argv[++i];
2744      }      }
2745    
2746      /* If the option type is OP_OP_NUMBERS, the value is a number that is to be
2747      added to a chain of numbers. */
2748    
2749      if (op->type == OP_OP_NUMBERS)
2750        {
2751        unsigned long int n = decode_number(option_data, op, longop);
2752        omdatastr *omd = (omdatastr *)op->dataptr;
2753        *(omd->lastptr) = add_number((int)n, *(omd->lastptr));
2754        if (*(omd->anchor) == NULL) *(omd->anchor) = *(omd->lastptr);
2755        }
2756    
2757    /* If the option type is OP_PATLIST, it's the -e option, or one of the    /* If the option type is OP_PATLIST, it's the -e option, or one of the
2758    include/exclude options, which can be called multiple times to create lists    include/exclude options, which can be called multiple times to create lists
2759    of patterns. */    of patterns. */
2760    
2761    if (op->type == OP_PATLIST)    else if (op->type == OP_PATLIST)
2762       {      {
2763       patdatastr *pd = (patdatastr *)op->dataptr;      patdatastr *pd = (patdatastr *)op->dataptr;
2764       *(pd->lastptr) = add_pattern(option_data, *(pd->lastptr));      *(pd->lastptr) = add_pattern(option_data, *(pd->lastptr));
2765       if (*(pd->lastptr) == NULL) goto EXIT2;      if (*(pd->lastptr) == NULL) goto EXIT2;
2766       if (*(pd->anchor) == NULL) *(pd->anchor) = *(pd->lastptr);      if (*(pd->anchor) == NULL) *(pd->anchor) = *(pd->lastptr);
2767       }      }
2768    
2769    /* If the option type is OP_FILELIST, it's one of the options that names a    /* If the option type is OP_FILELIST, it's one of the options that names a
2770    file. */    file. */
# Line 2644  for (i = 1; i < argc; i++) Line 2805  for (i = 1; i < argc; i++)
2805        }        }
2806      }      }
2807    
2808    /* Otherwise, deal with single string or numeric data values. */    /* Otherwise, deal with a single string or numeric data value. */
2809    
2810    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&    else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2811             op->type != OP_OP_NUMBER)             op->type != OP_OP_NUMBER)
2812      {      {
2813      *((char **)op->dataptr) = option_data;      *((char **)op->dataptr) = option_data;
2814      }      }
   
   /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used  
   only for unpicking arguments, so just keep it simple. */  
   
2815    else    else
2816      {      {
2817      unsigned long int n = 0;      unsigned long int n = decode_number(option_data, op, longop);
2818      char *endptr = option_data;      if (op->type == OP_LONGNUMBER) *((unsigned long int *)op->dataptr) = n;
2819      while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;        else *((int *)op->dataptr) = n;
     while (isdigit((unsigned char)(*endptr)))  
       n = n * 10 + (int)(*endptr++ - '0');  
     if (toupper(*endptr) == 'K')  
       {  
       n *= 1024;  
       endptr++;  
       }  
     else if (toupper(*endptr) == 'M')  
       {  
       n *= 1024*1024;  
       endptr++;  
       }  
     if (*endptr != 0)  
       {  
       if (longop)  
         {  
         char *equals = strchr(op->long_name, '=');  
         int nlen = (equals == NULL)? (int)strlen(op->long_name) :  
           (int)(equals - op->long_name);  
         fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",  
           option_data, nlen, op->long_name);  
         }  
       else  
         fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",  
           option_data, op->one_char);  
       pcregrep_exit(usage(2));  
       }  
     if (op->type == OP_LONGNUMBER)  
         *((unsigned long int *)op->dataptr) = n;  
     else  
         *((int *)op->dataptr) = n;  
2820      }      }
2821    }    }
2822    
# Line 2704  if (both_context > 0) Line 2830  if (both_context > 0)
2830    }    }
2831    
2832  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.  /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2833  However, the latter two set only_matching. */  However, all three set show_only_matching because they display, each in their
2834    own way, only the data that has matched. */
2835    
2836  if ((only_matching >= 0 && (file_offsets || line_offsets)) ||  if ((only_matching != NULL && (file_offsets || line_offsets)) ||
2837      (file_offsets && line_offsets))      (file_offsets && line_offsets))
2838    {    {
2839    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "    fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
# Line 2714  if ((only_matching >= 0 && (file_offsets Line 2841  if ((only_matching >= 0 && (file_offsets
2841    pcregrep_exit(usage(2));    pcregrep_exit(usage(2));
2842    }    }
2843    
2844  if (file_offsets || line_offsets) only_matching = 0;  if (only_matching != NULL || file_offsets || line_offsets)
2845      show_only_matching = TRUE;
2846    
2847  /* 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
2848  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
# Line 2880  for (fn = pattern_files; fn != NULL; fn Line 3008  for (fn = pattern_files; fn != NULL; fn
3008      goto EXIT2;      goto EXIT2;
3009    }    }
3010    
3011  /* Study the regular expressions, as we will be running them many times. Unless  /* Study the regular expressions, as we will be running them many times. If an
3012  JIT has been explicitly disabled, arrange a stack for it to use. */  extra block is needed for a limit, set PCRE_STUDY_EXTRA_NEEDED so that one is
3013    returned, even if studying produces no data. */
3014    
3015    if (match_limit > 0 || match_limit_recursion > 0)
3016      study_options |= PCRE_STUDY_EXTRA_NEEDED;
3017    
3018    /* Unless JIT has been explicitly disabled, arrange a stack for it to use. */
3019    
3020  #ifdef SUPPORT_PCREGREP_JIT  #ifdef SUPPORT_PCREGREP_JIT
3021  if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0)  if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0)
# Line 2905  for (j = 1, cp = patterns; cp != NULL; j Line 3039  for (j = 1, cp = patterns; cp != NULL; j
3039    }    }
3040    
3041  /* 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
3042  pcre_extra block for each pattern. */  pcre_extra block for each pattern. There will always be an extra block because
3043    of the use of PCRE_STUDY_EXTRA_NEEDED above. */
3044    
3045  if (match_limit > 0 || match_limit_recursion > 0)  for (cp = patterns; cp != NULL; cp = cp->next)
3046    {    {
3047    for (cp = patterns; cp != NULL; cp = cp->next)    if (match_limit > 0)
3048      {      {
3049      if (cp->hint == NULL)      cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT;
3050        {      cp->hint->match_limit = match_limit;
3051        cp->hint = (pcre_extra *)malloc(sizeof(pcre_extra));      }
3052        if (cp->hint == NULL)  
3053          {    if (match_limit_recursion > 0)
3054          fprintf(stderr, "pcregrep: malloc failed\n");      {
3055          pcregrep_exit(2);      cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
3056          }      cp->hint->match_limit_recursion = match_limit_recursion;
       }  
     if (match_limit > 0)  
       {  
       cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT;  
       cp->hint->match_limit = match_limit;  
       }  
     if (match_limit_recursion > 0)  
       {  
       cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;  
       cp->hint->match_limit_recursion = match_limit_recursion;  
       }  
3057      }      }
3058    }    }
3059    
# Line 3037  free_file_chain(include_from); Line 3161  free_file_chain(include_from);
3161  free_file_chain(pattern_files);  free_file_chain(pattern_files);
3162  free_file_chain(file_lists);  free_file_chain(file_lists);
3163    
3164    while (only_matching != NULL)
3165      {
3166      omstr *this = only_matching;
3167      only_matching = this->next;
3168      free(this);
3169      }
3170    
3171  pcregrep_exit(rc);  pcregrep_exit(rc);
3172    
3173  EXIT2:  EXIT2:

Legend:
Removed from v.1033  
changed lines
  Added in v.1096

  ViewVC Help
Powered by ViewVC 1.1.5