/[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 222 by ph10, Fri Aug 17 10:48:51 2007 UTC revision 324 by ph10, Fri Mar 7 19:48:32 2008 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-2007 University of Cambridge             Copyright (c) 1997-2008 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 38  POSSIBILITY OF SUCH DAMAGE. Line 38  POSSIBILITY OF SUCH DAMAGE.
38  */  */
39    
40  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
41  #include <config.h>  #include "config.h"
42  #endif  #endif
43    
44  #include <ctype.h>  #include <ctype.h>
# Line 55  POSSIBILITY OF SUCH DAMAGE. Line 55  POSSIBILITY OF SUCH DAMAGE.
55  #include <unistd.h>  #include <unistd.h>
56  #endif  #endif
57    
58  #include <pcre.h>  #ifdef SUPPORT_LIBZ
59    #include <zlib.h>
60    #endif
61    
62    #ifdef SUPPORT_LIBBZ2
63    #include <bzlib.h>
64    #endif
65    
66    #include "pcre.h"
67    
68  #define FALSE 0  #define FALSE 0
69  #define TRUE 1  #define TRUE 1
# Line 76  all values greater than FN_DEFAULT. */ Line 84  all values greater than FN_DEFAULT. */
84    
85  enum { FN_NONE, FN_DEFAULT, FN_ONLY, FN_NOMATCH_ONLY, FN_FORCE };  enum { FN_NONE, FN_DEFAULT, FN_ONLY, FN_NOMATCH_ONLY, FN_FORCE };
86    
87    /* File reading styles */
88    
89    enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };
90    
91  /* Actions for the -d and -D options */  /* Actions for the -d and -D options */
92    
93  enum { dee_READ, dee_SKIP, dee_RECURSE };  enum { dee_READ, dee_SKIP, dee_RECURSE };
# Line 142  static int process_options = 0; Line 154  static int process_options = 0;
154    
155  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
156  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
157    static BOOL file_offsets = FALSE;
158  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
159  static BOOL invert = FALSE;  static BOOL invert = FALSE;
160    static BOOL line_offsets = FALSE;
161  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
162  static BOOL number = FALSE;  static BOOL number = FALSE;
163  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
# Line 174  used to identify them. */ Line 188  used to identify them. */
188  #define N_LABEL     (-5)  #define N_LABEL     (-5)
189  #define N_LOCALE    (-6)  #define N_LOCALE    (-6)
190  #define N_NULL      (-7)  #define N_NULL      (-7)
191    #define N_LOFFSETS  (-8)
192    #define N_FOFFSETS  (-9)
193    
194  static option_item optionlist[] = {  static option_item optionlist[] = {
195    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 189  static option_item optionlist[] = { Line 205  static option_item optionlist[] = {
205    { OP_PATLIST,   'e',      NULL,              "regex(p)",      "specify pattern (may be used more than once)" },    { OP_PATLIST,   'e',      NULL,              "regex(p)",      "specify pattern (may be used more than once)" },
206    { 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" },
207    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
208      { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
209    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
210    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
211    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
212    { 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" },
213    { 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" },
214    { 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" },
215      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
216    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
217    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
218    { OP_STRING,    'N',      &newline,          "newline=type",  "specify newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
219    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
220    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },
221    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
# Line 316  return isatty(fileno(stdout)); Line 334  return isatty(fileno(stdout));
334    
335  /* I (Philip Hazel) have no means of testing this code. It was contributed by  /* I (Philip Hazel) have no means of testing this code. It was contributed by
336  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
337  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
338    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
339    */
340    
341  #elif HAVE_WINDOWS_H  #elif HAVE_WINDOWS_H
342    
# Line 327  when it did not exist. */ Line 346  when it did not exist. */
346  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
347  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
348  #endif  #endif
349    
350    #include <windows.h>
351    
352  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
353  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
354  #endif  #endif
355    
 #include <windows.h>  
   
356  typedef struct directory_type  typedef struct directory_type
357  {  {
358  HANDLE handle;  HANDLE handle;
# Line 417  regular if they are not directories. */ Line 437  regular if they are not directories. */
437    
438  int isregfile(char *filename)  int isregfile(char *filename)
439  {  {
440  return !isdirectory(filename)  return !isdirectory(filename);
441  }  }
442    
443    
# Line 428  return !isdirectory(filename) Line 448  return !isdirectory(filename)
448  static BOOL  static BOOL
449  is_stdout_tty(void)  is_stdout_tty(void)
450  {  {
451  FALSE;  return FALSE;
452  }  }
453    
454    
# Line 804  be in the middle third most of the time, Line 824  be in the middle third most of the time,
824  "before" context printing.  "before" context printing.
825    
826  Arguments:  Arguments:
827    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
828                   the gzFile pointer when reading is via libz
829                   the BZFILE pointer when reading is via libbz2
830      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
831    printname    the file name if it is to be printed for each match    printname    the file name if it is to be printed for each match
832                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
833                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
834    
835  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
836                 1 otherwise (no matches)                 1 otherwise (no matches)
837                   2 if there is a read error on a .bz2 file
838  */  */
839    
840  static int  static int
841  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
842  {  {
843  int rc = 1;  int rc = 1;
844  int linenumber = 1;  int linenumber = 1;
845  int lastmatchnumber = 0;  int lastmatchnumber = 0;
846  int count = 0;  int count = 0;
847    int filepos = 0;
848  int offsets[99];  int offsets[99];
849  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
850  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
# Line 827  char *ptr = buffer; Line 852  char *ptr = buffer;
852  char *endptr;  char *endptr;
853  size_t bufflength;  size_t bufflength;
854  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
855    FILE *in = NULL;                    /* Ensure initialized */
856    
857    #ifdef SUPPORT_LIBZ
858    gzFile ingz = NULL;
859    #endif
860    
861    #ifdef SUPPORT_LIBBZ2
862    BZFILE *inbz2 = NULL;
863    #endif
864    
865    
866    /* Do the first read into the start of the buffer and set up the pointer to end
867    of what we have. In the case of libz, a non-zipped .gz file will be read as a
868    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
869    fail. */
870    
871    #ifdef SUPPORT_LIBZ
872    if (frtype == FR_LIBZ)
873      {
874      ingz = (gzFile)handle;
875      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
876      }
877    else
878    #endif
879    
880    #ifdef SUPPORT_LIBBZ2
881    if (frtype == FR_LIBBZ2)
882      {
883      inbz2 = (BZFILE *)handle;
884      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
885      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
886      }                                    /* without the cast it is unsigned. */
887    else
888    #endif
889    
890  /* Do the first read into the start of the buffer and set up the pointer to    {
891  end of what we have. */    in = (FILE *)handle;
892      bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);
893      }
894    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
895  endptr = buffer + bufflength;  endptr = buffer + bufflength;
896    
897  /* Loop while the current pointer is not at the end of the file. For large  /* Loop while the current pointer is not at the end of the file. For large
# Line 844  while (ptr < endptr) Line 904  while (ptr < endptr)
904    int i, endlinelength;    int i, endlinelength;
905    int mrc = 0;    int mrc = 0;
906    BOOL match = FALSE;    BOOL match = FALSE;
907      char *matchptr = ptr;
908    char *t = ptr;    char *t = ptr;
909    size_t length, linelength;    size_t length, linelength;
910    
# Line 906  while (ptr < endptr) Line 967  while (ptr < endptr)
967    }    }
968  #endif  #endif
969    
970      /* We come back here after a match when the -o option (only_matching) is set,
971      in order to find any further matches in the same line. */
972    
973      ONLY_MATCHING_RESTART:
974    
975    /* Run through all the patterns until one matches. Note that we don't include    /* Run through all the patterns until one matches. Note that we don't include
976    the final newline in the subject string. */    the final newline in the subject string. */
977    
978    for (i = 0; i < pattern_count; i++)    for (i = 0; i < pattern_count; i++)
979      {      {
980      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,      mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0, 0,
981        offsets, 99);        offsets, 99);
982      if (mrc >= 0) { match = TRUE; break; }      if (mrc >= 0) { match = TRUE; break; }
983      if (mrc != PCRE_ERROR_NOMATCH)      if (mrc != PCRE_ERROR_NOMATCH)
# Line 920  while (ptr < endptr) Line 985  while (ptr < endptr)
985        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);
986        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
987        fprintf(stderr, "this line:\n");        fprintf(stderr, "this line:\n");
988        fwrite(ptr, 1, linelength, stderr);   /* In case binary zero included */        fwrite(matchptr, 1, linelength, stderr);  /* In case binary zero included */
989        fprintf(stderr, "\n");        fprintf(stderr, "\n");
990        if (error_count == 0 &&        if (error_count == 0 &&
991            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))
# Line 967  while (ptr < endptr) Line 1032  while (ptr < endptr)
1032      else if (quiet) return 0;      else if (quiet) return 0;
1033    
1034      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
1035      does not pring any context. */      the --file-offsets and --line-offsets options output offsets for the
1036        matching substring (they both force --only-matching). None of these options
1037        prints any context. Afterwards, adjust the start and length, and then jump
1038        back to look for further matches in the same line. If we are in invert
1039        mode, however, nothing is printed - this could be still useful because the
1040        return code is set. */
1041    
1042      else if (only_matching)      else if (only_matching)
1043        {        {
1044        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
1045        if (number) fprintf(stdout, "%d:", linenumber);          {
1046        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1047        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
1048            if (line_offsets)
1049              fprintf(stdout, "%d,%d", matchptr + offsets[0] - ptr,
1050                offsets[1] - offsets[0]);
1051            else if (file_offsets)
1052              fprintf(stdout, "%d,%d", filepos + matchptr + offsets[0] - ptr,
1053                offsets[1] - offsets[0]);
1054            else
1055              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1056            fprintf(stdout, "\n");
1057            matchptr += offsets[1];
1058            length -= offsets[1];
1059            match = FALSE;
1060            goto ONLY_MATCHING_RESTART;
1061            }
1062        }        }
1063    
1064      /* This is the default case when none of the above options is set. We print      /* This is the default case when none of the above options is set. We print
# Line 1113  while (ptr < endptr) Line 1197  while (ptr < endptr)
1197          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1198          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1199          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1200          fwrite(ptr + offsets[1], 1, linelength - offsets[1], stdout);          fwrite(ptr + offsets[1], 1, (linelength + endlinelength) - offsets[1],
1201              stdout);
1202          }          }
1203        else fwrite(ptr, 1, linelength + endlinelength, stdout);        else fwrite(ptr, 1, linelength + endlinelength, stdout);
1204        }        }
# Line 1147  while (ptr < endptr) Line 1232  while (ptr < endptr)
1232      linelength = endmatch - ptr - ellength;      linelength = endmatch - ptr - ellength;
1233      }      }
1234    
1235    /* Advance to after the newline and increment the line number. */    /* Advance to after the newline and increment the line number. The file
1236      offset to the current line is maintained in filepos. */
1237    
1238    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1239      filepos += linelength + endlinelength;
1240    linenumber++;    linenumber++;
1241    
1242    /* 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
# Line 1171  while (ptr < endptr) Line 1258  while (ptr < endptr)
1258    
1259      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1260      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1261    
1262    #ifdef SUPPORT_LIBZ
1263        if (frtype == FR_LIBZ)
1264          bufflength = 2*MBUFTHIRD +
1265            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1266        else
1267    #endif
1268    
1269    #ifdef SUPPORT_LIBBZ2
1270        if (frtype == FR_LIBBZ2)
1271          bufflength = 2*MBUFTHIRD +
1272            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1273        else
1274    #endif
1275    
1276      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);
1277    
1278      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1279    
1280      /* Adjust any last match point */      /* Adjust any last match point */
# Line 1235  grep_or_recurse(char *pathname, BOOL dir Line 1338  grep_or_recurse(char *pathname, BOOL dir
1338  {  {
1339  int rc = 1;  int rc = 1;
1340  int sep;  int sep;
1341  FILE *in;  int frtype;
1342    int pathlen;
1343    void *handle;
1344    FILE *in = NULL;           /* Ensure initialized */
1345    
1346    #ifdef SUPPORT_LIBZ
1347    gzFile ingz = NULL;
1348    #endif
1349    
1350    #ifdef SUPPORT_LIBBZ2
1351    BZFILE *inbz2 = NULL;
1352    #endif
1353    
1354  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1355    
1356  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1357    {    {
1358    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1359      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1360        stdin_name : NULL);        stdin_name : NULL);
1361    }    }
1362    
   
1363  /* If the file is a directory, skip if skipping or if we are recursing, scan  /* If the file is a directory, skip if skipping or if we are recursing, scan
1364  each file within it, subject to any include or exclude patterns that were set.  each file within it, subject to any include or exclude patterns that were set.
1365  The scanning code is localized so it can be made system-specific. */  The scanning code is localized so it can be made system-specific. */
# Line 1270  if ((sep = isdirectory(pathname)) != 0) Line 1383  if ((sep = isdirectory(pathname)) != 0)
1383    
1384      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1385        {        {
1386        int frc, blen;        int frc, nflen;
1387        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1388        blen = strlen(buffer);        nflen = strlen(nextfile);
1389    
1390        if (exclude_compiled != NULL &&        if (!isdirectory(buffer))
1391            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)          {
1392          continue;          if (exclude_compiled != NULL &&
1393                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1394        if (include_compiled != NULL &&            continue;
1395            pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
1396          continue;          if (include_compiled != NULL &&
1397                pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1398              continue;
1399            }
1400    
1401        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1402        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 1303  skipping was not requested. The scan pro Line 1419  skipping was not requested. The scan pro
1419  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
1420  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1421    
1422  in = fopen(pathname, "r");  pathlen = strlen(pathname);
1423  if (in == NULL)  
1424    /* Open using zlib if it is supported and the file name ends with .gz. */
1425    
1426    #ifdef SUPPORT_LIBZ
1427    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1428      {
1429      ingz = gzopen(pathname, "rb");
1430      if (ingz == NULL)
1431        {
1432        if (!silent)
1433          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1434            strerror(errno));
1435        return 2;
1436        }
1437      handle = (void *)ingz;
1438      frtype = FR_LIBZ;
1439      }
1440    else
1441    #endif
1442    
1443    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1444    
1445    #ifdef SUPPORT_LIBBZ2
1446    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1447      {
1448      inbz2 = BZ2_bzopen(pathname, "rb");
1449      handle = (void *)inbz2;
1450      frtype = FR_LIBBZ2;
1451      }
1452    else
1453    #endif
1454    
1455    /* Otherwise use plain fopen(). The label is so that we can come back here if
1456    an attempt to read a .bz2 file indicates that it really is a plain file. */
1457    
1458    #ifdef SUPPORT_LIBBZ2
1459    PLAIN_FILE:
1460    #endif
1461      {
1462      in = fopen(pathname, "r");
1463      handle = (void *)in;
1464      frtype = FR_PLAIN;
1465      }
1466    
1467    /* All the opening methods return errno when they fail. */
1468    
1469    if (handle == NULL)
1470    {    {
1471    if (!silent)    if (!silent)
1472      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 1312  if (in == NULL) Line 1474  if (in == NULL)
1474    return 2;    return 2;
1475    }    }
1476    
1477  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1478    
1479    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1480    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1481    
1482    /* Close in an appropriate manner. */
1483    
1484    #ifdef SUPPORT_LIBZ
1485    if (frtype == FR_LIBZ)
1486      gzclose(ingz);
1487    else
1488    #endif
1489    
1490    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1491    read failed. If the error indicates that the file isn't in fact bzipped, try
1492    again as a normal file. */
1493    
1494    #ifdef SUPPORT_LIBBZ2
1495    if (frtype == FR_LIBBZ2)
1496      {
1497      if (rc == 2)
1498        {
1499        int errnum;
1500        const char *err = BZ2_bzerror(inbz2, &errnum);
1501        if (errnum == BZ_DATA_ERROR_MAGIC)
1502          {
1503          BZ2_bzclose(inbz2);
1504          goto PLAIN_FILE;
1505          }
1506        else if (!silent)
1507          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1508            pathname, err);
1509        }
1510      BZ2_bzclose(inbz2);
1511      }
1512    else
1513    #endif
1514    
1515    /* Normal file close */
1516    
1517  fclose(in);  fclose(in);
1518    
1519    /* Pass back the yield from pcregrep(). */
1520    
1521  return rc;  return rc;
1522  }  }
1523    
# Line 1336  for (op = optionlist; op->one_char != 0; Line 1538  for (op = optionlist; op->one_char != 0;
1538    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1539    }    }
1540  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1541  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1542      "options.\n");
1543  return rc;  return rc;
1544  }  }
1545    
# Line 1355  option_item *op; Line 1558  option_item *op;
1558  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1559  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1560  printf("PATTERN must be present if neither -e nor -f is used.\n");  printf("PATTERN must be present if neither -e nor -f is used.\n");
1561  printf("\"-\" can be used as a file name to mean STDIN.\n\n");  printf("\"-\" can be used as a file name to mean STDIN.\n");
 printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
1562    
1563    #ifdef SUPPORT_LIBZ
1564    printf("Files whose names end in .gz are read using zlib.\n");
1565    #endif
1566    
1567    #ifdef SUPPORT_LIBBZ2
1568    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1569    #endif
1570    
1571    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1572    printf("Other files and the standard input are read as plain files.\n\n");
1573    #else
1574    printf("All files are read as plain files, without any interpretation.\n\n");
1575    #endif
1576    
1577    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1578  printf("Options:\n");  printf("Options:\n");
1579    
1580  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
# Line 1365  for (op = optionlist; op->one_char != 0; Line 1582  for (op = optionlist; op->one_char != 0;
1582    int n;    int n;
1583    char s[4];    char s[4];
1584    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, "   ");
1585    printf("  %s --%s%n", s, op->long_name, &n);    n = 30 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1586    if (n < 1) n = 1;    if (n < 1) n = 1;
1587    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                    ", op->help_text);
1588    }    }
# Line 1391  handle_option(int letter, int options) Line 1607  handle_option(int letter, int options)
1607  {  {
1608  switch(letter)  switch(letter)
1609    {    {
1610      case N_FOFFSETS: file_offsets = TRUE; break;
1611    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1612      case N_LOFFSETS: line_offsets = number = TRUE; break;
1613    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1614    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1615    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
# Line 1828  if (both_context > 0) Line 2046  if (both_context > 0)
2046    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2047    }    }
2048    
2049    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2050    However, the latter two set the only_matching flag. */
2051    
2052    if ((only_matching && (file_offsets || line_offsets)) ||
2053        (file_offsets && line_offsets))
2054      {
2055      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2056        "and/or --line-offsets\n");
2057      exit(usage(2));
2058      }
2059    
2060    if (file_offsets || line_offsets) only_matching = TRUE;
2061    
2062  /* 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
2063  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2064    
# Line 2065  if (include_pattern != NULL) Line 2296  if (include_pattern != NULL)
2296    
2297  if (i >= argc)  if (i >= argc)
2298    {    {
2299    rc = pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2300    goto EXIT;    goto EXIT;
2301    }    }
2302    

Legend:
Removed from v.222  
changed lines
  Added in v.324

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12