/[pcre]/code/tags/pcre-8.01/pcregrep.c
ViewVC logotype

Diff of /code/tags/pcre-8.01/pcregrep.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 279 by ph10, Tue Dec 4 20:01:43 2007 UTC revision 345 by ph10, Mon Apr 28 15:10:02 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 55  POSSIBILITY OF SUCH DAMAGE. Line 55  POSSIBILITY OF SUCH DAMAGE.
55  #include <unistd.h>  #include <unistd.h>
56  #endif  #endif
57    
58    #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"  #include "pcre.h"
67    
68  #define FALSE 0  #define FALSE 0
# 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 127  static pcre_extra **hints_list = NULL; Line 139  static pcre_extra **hints_list = NULL;
139    
140  static char *include_pattern = NULL;  static char *include_pattern = NULL;
141  static char *exclude_pattern = NULL;  static char *exclude_pattern = NULL;
142    static char *include_dir_pattern = NULL;
143    static char *exclude_dir_pattern = NULL;
144    
145  static pcre *include_compiled = NULL;  static pcre *include_compiled = NULL;
146  static pcre *exclude_compiled = NULL;  static pcre *exclude_compiled = NULL;
147    static pcre *include_dir_compiled = NULL;
148    static pcre *exclude_dir_compiled = NULL;
149    
150  static int after_context = 0;  static int after_context = 0;
151  static int before_context = 0;  static int before_context = 0;
# Line 142  static int process_options = 0; Line 158  static int process_options = 0;
158    
159  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
160  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
161    static BOOL file_offsets = FALSE;
162  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
163  static BOOL invert = FALSE;  static BOOL invert = FALSE;
164    static BOOL line_offsets = FALSE;
165  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
166  static BOOL number = FALSE;  static BOOL number = FALSE;
167  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
# Line 167  typedef struct option_item { Line 185  typedef struct option_item {
185  /* Options without a single-letter equivalent get a negative value. This can be  /* Options without a single-letter equivalent get a negative value. This can be
186  used to identify them. */  used to identify them. */
187    
188  #define N_COLOUR    (-1)  #define N_COLOUR       (-1)
189  #define N_EXCLUDE   (-2)  #define N_EXCLUDE      (-2)
190  #define N_HELP      (-3)  #define N_EXCLUDE_DIR  (-3)
191  #define N_INCLUDE   (-4)  #define N_HELP         (-4)
192  #define N_LABEL     (-5)  #define N_INCLUDE      (-5)
193  #define N_LOCALE    (-6)  #define N_INCLUDE_DIR  (-6)
194  #define N_NULL      (-7)  #define N_LABEL        (-7)
195    #define N_LOCALE       (-8)
196    #define N_NULL         (-9)
197    #define N_LOFFSETS     (-10)
198    #define N_FOFFSETS     (-11)
199    
200  static option_item optionlist[] = {  static option_item optionlist[] = {
201    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 189  static option_item optionlist[] = { Line 211  static option_item optionlist[] = {
211    { 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)" },
212    { 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" },
213    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
214      { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
215    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
216    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
217    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
218    { 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" },
219    { 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" },
220    { 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" },
221      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
222    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
223    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
224    { 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)" },
225    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
226    { 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" },
227    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
228    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },
229    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },    { OP_STRING,    N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
230    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },    { OP_STRING,    N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
231      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
232      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
233  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
234    { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },    { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },
235  #endif  #endif
# Line 316  return isatty(fileno(stdout)); Line 342  return isatty(fileno(stdout));
342    
343  /* 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
344  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
345  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
346    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
347    */
348    
349  #elif HAVE_WINDOWS_H  #elif HAVE_WINDOWS_H
350    
# Line 327  when it did not exist. */ Line 354  when it did not exist. */
354  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
355  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
356  #endif  #endif
357    
358    #include <windows.h>
359    
360  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
361  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
362  #endif  #endif
363    
 #include <windows.h>  
   
364  typedef struct directory_type  typedef struct directory_type
365  {  {
366  HANDLE handle;  HANDLE handle;
# Line 417  regular if they are not directories. */ Line 445  regular if they are not directories. */
445    
446  int isregfile(char *filename)  int isregfile(char *filename)
447  {  {
448  return !isdirectory(filename)  return !isdirectory(filename);
449  }  }
450    
451    
# Line 428  return !isdirectory(filename) Line 456  return !isdirectory(filename)
456  static BOOL  static BOOL
457  is_stdout_tty(void)  is_stdout_tty(void)
458  {  {
459  FALSE;  return FALSE;
460  }  }
461    
462    
# Line 804  be in the middle third most of the time, Line 832  be in the middle third most of the time,
832  "before" context printing.  "before" context printing.
833    
834  Arguments:  Arguments:
835    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
836                   the gzFile pointer when reading is via libz
837                   the BZFILE pointer when reading is via libbz2
838      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
839    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
840                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
841                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
842    
843  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
844                 1 otherwise (no matches)                 1 otherwise (no matches)
845                   2 if there is a read error on a .bz2 file
846  */  */
847    
848  static int  static int
849  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
850  {  {
851  int rc = 1;  int rc = 1;
852  int linenumber = 1;  int linenumber = 1;
853  int lastmatchnumber = 0;  int lastmatchnumber = 0;
854  int count = 0;  int count = 0;
855    int filepos = 0;
856  int offsets[99];  int offsets[99];
857  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
858  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
# Line 827  char *ptr = buffer; Line 860  char *ptr = buffer;
860  char *endptr;  char *endptr;
861  size_t bufflength;  size_t bufflength;
862  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
863    FILE *in = NULL;                    /* Ensure initialized */
864    
865    #ifdef SUPPORT_LIBZ
866    gzFile ingz = NULL;
867    #endif
868    
869  /* Do the first read into the start of the buffer and set up the pointer to  #ifdef SUPPORT_LIBBZ2
870  end of what we have. */  BZFILE *inbz2 = NULL;
871    #endif
872    
873    
874    /* Do the first read into the start of the buffer and set up the pointer to end
875    of what we have. In the case of libz, a non-zipped .gz file will be read as a
876    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
877    fail. */
878    
879    #ifdef SUPPORT_LIBZ
880    if (frtype == FR_LIBZ)
881      {
882      ingz = (gzFile)handle;
883      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
884      }
885    else
886    #endif
887    
888    #ifdef SUPPORT_LIBBZ2
889    if (frtype == FR_LIBBZ2)
890      {
891      inbz2 = (BZFILE *)handle;
892      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
893      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
894      }                                    /* without the cast it is unsigned. */
895    else
896    #endif
897    
898      {
899      in = (FILE *)handle;
900      bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);
901      }
902    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
903  endptr = buffer + bufflength;  endptr = buffer + bufflength;
904    
905  /* 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 912  while (ptr < endptr)
912    int i, endlinelength;    int i, endlinelength;
913    int mrc = 0;    int mrc = 0;
914    BOOL match = FALSE;    BOOL match = FALSE;
915    char *matchptr = ptr;    char *matchptr = ptr;
916    char *t = ptr;    char *t = ptr;
917    size_t length, linelength;    size_t length, linelength;
918    
# Line 907  while (ptr < endptr) Line 975  while (ptr < endptr)
975    }    }
976  #endif  #endif
977    
978    /* We come back here after a match when the -o option (only_matching) is set,    /* We come back here after a match when the -o option (only_matching) is set,
979    in order to find any further matches in the same line. */    in order to find any further matches in the same line. */
980    
981    ONLY_MATCHING_RESTART:    ONLY_MATCHING_RESTART:
982    
983    /* 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
984    the final newline in the subject string. */    the final newline in the subject string. */
# Line 972  while (ptr < endptr) Line 1040  while (ptr < endptr)
1040      else if (quiet) return 0;      else if (quiet) return 0;
1041    
1042      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
1043      does not print any context. Afterwards, adjust the start and length, and      the --file-offsets and --line-offsets options output offsets for the
1044      then jump back to look for further matches in the same line. If we are in      matching substring (they both force --only-matching). None of these options
1045      invert mode, however, nothing is printed - this could be useful still      prints any context. Afterwards, adjust the start and length, and then jump
1046      because the return code is set. */      back to look for further matches in the same line. If we are in invert
1047        mode, however, nothing is printed - this could be still useful because the
1048        return code is set. */
1049    
1050      else if (only_matching)      else if (only_matching)
1051        {        {
1052        if (!invert)        if (!invert)
1053          {          {
1054          if (printname != NULL) fprintf(stdout, "%s:", printname);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1055          if (number) fprintf(stdout, "%d:", linenumber);          if (number) fprintf(stdout, "%d:", linenumber);
1056          fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (line_offsets)
1057              fprintf(stdout, "%d,%d", matchptr + offsets[0] - ptr,
1058                offsets[1] - offsets[0]);
1059            else if (file_offsets)
1060              fprintf(stdout, "%d,%d", filepos + matchptr + offsets[0] - ptr,
1061                offsets[1] - offsets[0]);
1062            else
1063              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1064          fprintf(stdout, "\n");          fprintf(stdout, "\n");
1065          matchptr += offsets[1];          matchptr += offsets[1];
1066          length -= offsets[1];          length -= offsets[1];
1067          match = FALSE;          match = FALSE;
1068          goto ONLY_MATCHING_RESTART;          goto ONLY_MATCHING_RESTART;
1069          }          }
1070        }        }
1071    
1072      /* 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 1163  while (ptr < endptr) Line 1240  while (ptr < endptr)
1240      linelength = endmatch - ptr - ellength;      linelength = endmatch - ptr - ellength;
1241      }      }
1242    
1243    /* Advance to after the newline and increment the line number. */    /* Advance to after the newline and increment the line number. The file
1244      offset to the current line is maintained in filepos. */
1245    
1246    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1247      filepos += linelength + endlinelength;
1248    linenumber++;    linenumber++;
1249    
1250    /* 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 1187  while (ptr < endptr) Line 1266  while (ptr < endptr)
1266    
1267      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1268      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1269    
1270    #ifdef SUPPORT_LIBZ
1271        if (frtype == FR_LIBZ)
1272          bufflength = 2*MBUFTHIRD +
1273            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1274        else
1275    #endif
1276    
1277    #ifdef SUPPORT_LIBBZ2
1278        if (frtype == FR_LIBBZ2)
1279          bufflength = 2*MBUFTHIRD +
1280            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1281        else
1282    #endif
1283    
1284      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);
1285    
1286      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1287    
1288      /* Adjust any last match point */      /* Adjust any last match point */
# Line 1251  grep_or_recurse(char *pathname, BOOL dir Line 1346  grep_or_recurse(char *pathname, BOOL dir
1346  {  {
1347  int rc = 1;  int rc = 1;
1348  int sep;  int sep;
1349  FILE *in;  int frtype;
1350    int pathlen;
1351    void *handle;
1352    FILE *in = NULL;           /* Ensure initialized */
1353    
1354    #ifdef SUPPORT_LIBZ
1355    gzFile ingz = NULL;
1356    #endif
1357    
1358    #ifdef SUPPORT_LIBBZ2
1359    BZFILE *inbz2 = NULL;
1360    #endif
1361    
1362  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1363    
1364  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1365    {    {
1366    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1367      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1368        stdin_name : NULL);        stdin_name : NULL);
1369    }    }
1370    
   
1371  /* 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
1372  each file within it, subject to any include or exclude patterns that were set.  each file and directory within it, subject to any include or exclude patterns
1373  The scanning code is localized so it can be made system-specific. */  that were set. The scanning code is localized so it can be made
1374    system-specific. */
1375    
1376  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1377    {    {
# Line 1286  if ((sep = isdirectory(pathname)) != 0) Line 1392  if ((sep = isdirectory(pathname)) != 0)
1392    
1393      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1394        {        {
1395        int frc, blen;        int frc, nflen;
1396        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1397        blen = strlen(buffer);        nflen = strlen(nextfile);
1398    
1399          if (isdirectory(buffer))
1400            {
1401            if (exclude_dir_compiled != NULL &&
1402                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1403              continue;
1404    
1405            if (include_dir_compiled != NULL &&
1406                pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1407              continue;
1408            }
1409          else
1410            {
1411            if (exclude_compiled != NULL &&
1412                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1413              continue;
1414    
1415        if (exclude_compiled != NULL &&          if (include_compiled != NULL &&
1416            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)              pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1417          continue;            continue;
1418            }
       if (include_compiled != NULL &&  
           pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
         continue;  
1419    
1420        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1421        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 1319  skipping was not requested. The scan pro Line 1438  skipping was not requested. The scan pro
1438  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
1439  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1440    
1441  in = fopen(pathname, "r");  pathlen = strlen(pathname);
1442  if (in == NULL)  
1443    /* Open using zlib if it is supported and the file name ends with .gz. */
1444    
1445    #ifdef SUPPORT_LIBZ
1446    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1447      {
1448      ingz = gzopen(pathname, "rb");
1449      if (ingz == NULL)
1450        {
1451        if (!silent)
1452          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1453            strerror(errno));
1454        return 2;
1455        }
1456      handle = (void *)ingz;
1457      frtype = FR_LIBZ;
1458      }
1459    else
1460    #endif
1461    
1462    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1463    
1464    #ifdef SUPPORT_LIBBZ2
1465    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1466      {
1467      inbz2 = BZ2_bzopen(pathname, "rb");
1468      handle = (void *)inbz2;
1469      frtype = FR_LIBBZ2;
1470      }
1471    else
1472    #endif
1473    
1474    /* Otherwise use plain fopen(). The label is so that we can come back here if
1475    an attempt to read a .bz2 file indicates that it really is a plain file. */
1476    
1477    #ifdef SUPPORT_LIBBZ2
1478    PLAIN_FILE:
1479    #endif
1480      {
1481      in = fopen(pathname, "r");
1482      handle = (void *)in;
1483      frtype = FR_PLAIN;
1484      }
1485    
1486    /* All the opening methods return errno when they fail. */
1487    
1488    if (handle == NULL)
1489    {    {
1490    if (!silent)    if (!silent)
1491      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 1328  if (in == NULL) Line 1493  if (in == NULL)
1493    return 2;    return 2;
1494    }    }
1495    
1496  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1497    
1498    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1499    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1500    
1501    /* Close in an appropriate manner. */
1502    
1503    #ifdef SUPPORT_LIBZ
1504    if (frtype == FR_LIBZ)
1505      gzclose(ingz);
1506    else
1507    #endif
1508    
1509    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1510    read failed. If the error indicates that the file isn't in fact bzipped, try
1511    again as a normal file. */
1512    
1513    #ifdef SUPPORT_LIBBZ2
1514    if (frtype == FR_LIBBZ2)
1515      {
1516      if (rc == 2)
1517        {
1518        int errnum;
1519        const char *err = BZ2_bzerror(inbz2, &errnum);
1520        if (errnum == BZ_DATA_ERROR_MAGIC)
1521          {
1522          BZ2_bzclose(inbz2);
1523          goto PLAIN_FILE;
1524          }
1525        else if (!silent)
1526          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1527            pathname, err);
1528        }
1529      BZ2_bzclose(inbz2);
1530      }
1531    else
1532    #endif
1533    
1534    /* Normal file close */
1535    
1536  fclose(in);  fclose(in);
1537    
1538    /* Pass back the yield from pcregrep(). */
1539    
1540  return rc;  return rc;
1541  }  }
1542    
# Line 1352  for (op = optionlist; op->one_char != 0; Line 1557  for (op = optionlist; op->one_char != 0;
1557    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1558    }    }
1559  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1560  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1561      "options.\n");
1562  return rc;  return rc;
1563  }  }
1564    
# Line 1371  option_item *op; Line 1577  option_item *op;
1577  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1578  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1579  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");
1580  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");
1581  printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");  
1582    #ifdef SUPPORT_LIBZ
1583    printf("Files whose names end in .gz are read using zlib.\n");
1584    #endif
1585    
1586    #ifdef SUPPORT_LIBBZ2
1587    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1588    #endif
1589    
1590    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1591    printf("Other files and the standard input are read as plain files.\n\n");
1592    #else
1593    printf("All files are read as plain files, without any interpretation.\n\n");
1594    #endif
1595    
1596    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1597  printf("Options:\n");  printf("Options:\n");
1598    
1599  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
# Line 1381  for (op = optionlist; op->one_char != 0; Line 1601  for (op = optionlist; op->one_char != 0;
1601    int n;    int n;
1602    char s[4];    char s[4];
1603    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, "   ");
1604    printf("  %s --%s%n", s, op->long_name, &n);    n = 30 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1605    if (n < 1) n = 1;    if (n < 1) n = 1;
1606    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                    ", op->help_text);
1607    }    }
# Line 1407  handle_option(int letter, int options) Line 1626  handle_option(int letter, int options)
1626  {  {
1627  switch(letter)  switch(letter)
1628    {    {
1629      case N_FOFFSETS: file_offsets = TRUE; break;
1630    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1631      case N_LOFFSETS: line_offsets = number = TRUE; break;
1632    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1633    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1634    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
# Line 1844  if (both_context > 0) Line 2065  if (both_context > 0)
2065    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2066    }    }
2067    
2068    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2069    However, the latter two set the only_matching flag. */
2070    
2071    if ((only_matching && (file_offsets || line_offsets)) ||
2072        (file_offsets && line_offsets))
2073      {
2074      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2075        "and/or --line-offsets\n");
2076      exit(usage(2));
2077      }
2078    
2079    if (file_offsets || line_offsets) only_matching = TRUE;
2080    
2081  /* 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
2082  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2083    
# Line 2077  if (include_pattern != NULL) Line 2311  if (include_pattern != NULL)
2311      }      }
2312    }    }
2313    
2314    if (exclude_dir_pattern != NULL)
2315      {
2316      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2317        pcretables);
2318      if (exclude_dir_compiled == NULL)
2319        {
2320        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2321          errptr, error);
2322        goto EXIT2;
2323        }
2324      }
2325    
2326    if (include_dir_pattern != NULL)
2327      {
2328      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2329        pcretables);
2330      if (include_dir_compiled == NULL)
2331        {
2332        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2333          errptr, error);
2334        goto EXIT2;
2335        }
2336      }
2337    
2338  /* If there are no further arguments, do the business on stdin and exit. */  /* If there are no further arguments, do the business on stdin and exit. */
2339    
2340  if (i >= argc)  if (i >= argc)
2341    {    {
2342    rc = pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2343    goto EXIT;    goto EXIT;
2344    }    }
2345    

Legend:
Removed from v.279  
changed lines
  Added in v.345

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12