/[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 87 by nigel, Sat Feb 24 21:41:21 2007 UTC revision 420 by ph10, Wed Aug 12 17:32:27 2009 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-2006 University of Cambridge             Copyright (c) 1997-2009 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 37  POSSIBILITY OF SUCH DAMAGE. Line 37  POSSIBILITY OF SUCH DAMAGE.
37  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
38  */  */
39    
40    #ifdef HAVE_CONFIG_H
41    #include "config.h"
42    #endif
43    
44  #include <ctype.h>  #include <ctype.h>
45  #include <locale.h>  #include <locale.h>
46  #include <stdio.h>  #include <stdio.h>
# Line 46  POSSIBILITY OF SUCH DAMAGE. Line 50  POSSIBILITY OF SUCH DAMAGE.
50    
51  #include <sys/types.h>  #include <sys/types.h>
52  #include <sys/stat.h>  #include <sys/stat.h>
53    
54    #ifdef HAVE_UNISTD_H
55  #include <unistd.h>  #include <unistd.h>
56    #endif
57    
58    #ifdef SUPPORT_LIBZ
59    #include <zlib.h>
60    #endif
61    
62    #ifdef SUPPORT_LIBBZ2
63    #include <bzlib.h>
64    #endif
65    
 #include "config.h"  
66  #include "pcre.h"  #include "pcre.h"
67    
68  #define FALSE 0  #define FALSE 0
# Line 56  POSSIBILITY OF SUCH DAMAGE. Line 70  POSSIBILITY OF SUCH DAMAGE.
70    
71  typedef int BOOL;  typedef int BOOL;
72    
 #define VERSION "4.2 09-Jan-2006"  
73  #define MAX_PATTERN_COUNT 100  #define MAX_PATTERN_COUNT 100
74    #define OFFSET_SIZE 99
75    
76  #if BUFSIZ > 8192  #if BUFSIZ > 8192
77  #define MBUFTHIRD BUFSIZ  #define MBUFTHIRD BUFSIZ
# Line 65  typedef int BOOL; Line 79  typedef int BOOL;
79  #define MBUFTHIRD 8192  #define MBUFTHIRD 8192
80  #endif  #endif
81    
   
82  /* Values for the "filenames" variable, which specifies options for file name  /* Values for the "filenames" variable, which specifies options for file name
83  output. The order is important; it is assumed that a file name is wanted for  output. The order is important; it is assumed that a file name is wanted for
84  all values greater than FN_DEFAULT. */  all values greater than FN_DEFAULT. */
85    
86  enum { FN_NONE, FN_DEFAULT, FN_ONLY, FN_NOMATCH_ONLY, FN_FORCE };  enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE };
87    
88    /* File reading styles */
89    
90    enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };
91    
92  /* Actions for the -d and -D options */  /* Actions for the -d and -D options */
93    
# Line 83  enum { DEE_READ, DEE_SKIP }; Line 100  enum { DEE_READ, DEE_SKIP };
100  #define PO_LINE_MATCH     0x0002  #define PO_LINE_MATCH     0x0002
101  #define PO_FIXED_STRINGS  0x0004  #define PO_FIXED_STRINGS  0x0004
102    
103    /* Line ending types */
104    
105    enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };
106    
107    
108    
109  /*************************************************  /*************************************************
# Line 94  regular code. */ Line 115  regular code. */
115    
116  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
117  static int S_arg = -1;  static int S_arg = -1;
118    static unsigned int jfriedl_XR = 0; /* repeat regex attempt this many times */
119    static unsigned int jfriedl_XT = 0; /* replicate text this many times */
120    static const char *jfriedl_prefix = "";
121    static const char *jfriedl_postfix = "";
122  #endif  #endif
123    
124    static int  endlinetype;
125    
126  static char *colour_string = (char *)"1;31";  static char *colour_string = (char *)"1;31";
127  static char *colour_option = NULL;  static char *colour_option = NULL;
128  static char *dee_option = NULL;  static char *dee_option = NULL;
129  static char *DEE_option = NULL;  static char *DEE_option = NULL;
130    static char *newline = NULL;
131  static char *pattern_filename = NULL;  static char *pattern_filename = NULL;
132  static char *stdin_name = (char *)"(standard input)";  static char *stdin_name = (char *)"(standard input)";
133  static char *locale = NULL;  static char *locale = NULL;
# Line 107  static char *locale = NULL; Line 135  static char *locale = NULL;
135  static const unsigned char *pcretables = NULL;  static const unsigned char *pcretables = NULL;
136    
137  static int  pattern_count = 0;  static int  pattern_count = 0;
138  static pcre **pattern_list;  static pcre **pattern_list = NULL;
139  static pcre_extra **hints_list;  static pcre_extra **hints_list = NULL;
140    
141  static char *include_pattern = NULL;  static char *include_pattern = NULL;
142  static char *exclude_pattern = NULL;  static char *exclude_pattern = NULL;
143    static char *include_dir_pattern = NULL;
144    static char *exclude_dir_pattern = NULL;
145    
146  static pcre *include_compiled = NULL;  static pcre *include_compiled = NULL;
147  static pcre *exclude_compiled = NULL;  static pcre *exclude_compiled = NULL;
148    static pcre *include_dir_compiled = NULL;
149    static pcre *exclude_dir_compiled = NULL;
150    
151  static int after_context = 0;  static int after_context = 0;
152  static int before_context = 0;  static int before_context = 0;
# Line 127  static int process_options = 0; Line 159  static int process_options = 0;
159    
160  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
161  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
162    static BOOL file_offsets = FALSE;
163  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
164  static BOOL invert = FALSE;  static BOOL invert = FALSE;
165    static BOOL line_offsets = FALSE;
166  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
167  static BOOL number = FALSE;  static BOOL number = FALSE;
168    static BOOL omit_zero_count = FALSE;
169  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
170  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
171  static BOOL silent = FALSE;  static BOOL silent = FALSE;
172    static BOOL utf8 = FALSE;
173    
174  /* Structure for options and list of them */  /* Structure for options and list of them */
175    
# Line 151  typedef struct option_item { Line 187  typedef struct option_item {
187  /* 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
188  used to identify them. */  used to identify them. */
189    
190  #define N_COLOUR    (-1)  #define N_COLOUR       (-1)
191  #define N_EXCLUDE   (-2)  #define N_EXCLUDE      (-2)
192  #define N_HELP      (-3)  #define N_EXCLUDE_DIR  (-3)
193  #define N_INCLUDE   (-4)  #define N_HELP         (-4)
194  #define N_LABEL     (-5)  #define N_INCLUDE      (-5)
195  #define N_LOCALE    (-6)  #define N_INCLUDE_DIR  (-6)
196  #define N_NULL      (-7)  #define N_LABEL        (-7)
197    #define N_LOCALE       (-8)
198    #define N_NULL         (-9)
199    #define N_LOFFSETS     (-10)
200    #define N_FOFFSETS     (-11)
201    
202  static option_item optionlist[] = {  static option_item optionlist[] = {
203    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 173  static option_item optionlist[] = { Line 213  static option_item optionlist[] = {
213    { 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)" },
214    { 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" },
215    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
216      { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
217    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
218    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
219    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
220    { 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" },
221    { 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" },
222    { 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" },
223      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
224    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
225    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
226      { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
227    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
228    { 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" },
229    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
230    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },
231    { 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" },
232    { 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" },
233      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
234      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
235  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
236    { 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" },
237  #endif  #endif
# Line 210  static const char *prefix[] = { Line 255  static const char *prefix[] = {
255  static const char *suffix[] = {  static const char *suffix[] = {
256    "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };    "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };
257    
258    /* UTF-8 tables - used only when the newline setting is "any". */
259    
260    const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
261    
262    const char utf8_table4[] = {
263      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
264      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
265      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
266      3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
267    
268    
269    
270  /*************************************************  /*************************************************
# Line 222  although at present the only ones are fo Line 277  although at present the only ones are fo
277    
278  /************* Directory scanning in Unix ***********/  /************* Directory scanning in Unix ***********/
279    
280  #if IS_UNIX  #if defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H
281  #include <sys/types.h>  #include <sys/types.h>
282  #include <sys/stat.h>  #include <sys/stat.h>
283  #include <dirent.h>  #include <dirent.h>
# Line 254  for (;;) Line 309  for (;;)
309    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
310      return dent->d_name;      return dent->d_name;
311    }    }
312  return NULL;   /* Keep compiler happy; never executed */  /* Control never reaches here */
313  }  }
314    
315  static void  static void
# Line 289  return isatty(fileno(stdout)); Line 344  return isatty(fileno(stdout));
344    
345  /* 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
346  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
347  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
348    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
349    */
350    
351  #elif HAVE_WIN32API  #elif HAVE_WINDOWS_H
352    
353  #ifndef STRICT  #ifndef STRICT
354  # define STRICT  # define STRICT
# Line 300  when it did not exist. */ Line 356  when it did not exist. */
356  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
357  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
358  #endif  #endif
359    
360    #include <windows.h>
361    
362  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
363  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
364  #endif  #endif
365    
 #include <windows.h>  
   
366  typedef struct directory_type  typedef struct directory_type
367  {  {
368  HANDLE handle;  HANDLE handle;
# Line 390  regular if they are not directories. */ Line 447  regular if they are not directories. */
447    
448  int isregfile(char *filename)  int isregfile(char *filename)
449  {  {
450  return !isdirectory(filename)  return !isdirectory(filename);
451  }  }
452    
453    
# Line 401  return !isdirectory(filename) Line 458  return !isdirectory(filename)
458  static BOOL  static BOOL
459  is_stdout_tty(void)  is_stdout_tty(void)
460  {  {
461  FALSE;  return FALSE;
462  }  }
463    
464    
# Line 414  FALSE; Line 471  FALSE;
471  typedef void directory_type;  typedef void directory_type;
472    
473  int isdirectory(char *filename) { return 0; }  int isdirectory(char *filename) { return 0; }
474  directory_type * opendirectory(char *filename) {}  directory_type * opendirectory(char *filename) { return (directory_type*)0;}
475  char *readdirectory(directory_type *dir) {}  char *readdirectory(directory_type *dir) { return (char*)0;}
476  void closedirectory(directory_type *dir) {}  void closedirectory(directory_type *dir) {}
477    
478    
# Line 439  return FALSE; Line 496  return FALSE;
496    
497    
498    
499  #if ! HAVE_STRERROR  #ifndef HAVE_STRERROR
500  /*************************************************  /*************************************************
501  *     Provide strerror() for non-ANSI libraries  *  *     Provide strerror() for non-ANSI libraries  *
502  *************************************************/  *************************************************/
# Line 462  return sys_errlist[n]; Line 519  return sys_errlist[n];
519    
520    
521  /*************************************************  /*************************************************
522    *             Find end of line                   *
523    *************************************************/
524    
525    /* The length of the endline sequence that is found is set via lenptr. This may
526    be zero at the very end of the file if there is no line-ending sequence there.
527    
528    Arguments:
529      p         current position in line
530      endptr    end of available data
531      lenptr    where to put the length of the eol sequence
532    
533    Returns:    pointer to the last byte of the line
534    */
535    
536    static char *
537    end_of_line(char *p, char *endptr, int *lenptr)
538    {
539    switch(endlinetype)
540      {
541      default:      /* Just in case */
542      case EL_LF:
543      while (p < endptr && *p != '\n') p++;
544      if (p < endptr)
545        {
546        *lenptr = 1;
547        return p + 1;
548        }
549      *lenptr = 0;
550      return endptr;
551    
552      case EL_CR:
553      while (p < endptr && *p != '\r') p++;
554      if (p < endptr)
555        {
556        *lenptr = 1;
557        return p + 1;
558        }
559      *lenptr = 0;
560      return endptr;
561    
562      case EL_CRLF:
563      for (;;)
564        {
565        while (p < endptr && *p != '\r') p++;
566        if (++p >= endptr)
567          {
568          *lenptr = 0;
569          return endptr;
570          }
571        if (*p == '\n')
572          {
573          *lenptr = 2;
574          return p + 1;
575          }
576        }
577      break;
578    
579      case EL_ANYCRLF:
580      while (p < endptr)
581        {
582        int extra = 0;
583        register int c = *((unsigned char *)p);
584    
585        if (utf8 && c >= 0xc0)
586          {
587          int gcii, gcss;
588          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
589          gcss = 6*extra;
590          c = (c & utf8_table3[extra]) << gcss;
591          for (gcii = 1; gcii <= extra; gcii++)
592            {
593            gcss -= 6;
594            c |= (p[gcii] & 0x3f) << gcss;
595            }
596          }
597    
598        p += 1 + extra;
599    
600        switch (c)
601          {
602          case 0x0a:    /* LF */
603          *lenptr = 1;
604          return p;
605    
606          case 0x0d:    /* CR */
607          if (p < endptr && *p == 0x0a)
608            {
609            *lenptr = 2;
610            p++;
611            }
612          else *lenptr = 1;
613          return p;
614    
615          default:
616          break;
617          }
618        }   /* End of loop for ANYCRLF case */
619    
620      *lenptr = 0;  /* Must have hit the end */
621      return endptr;
622    
623      case EL_ANY:
624      while (p < endptr)
625        {
626        int extra = 0;
627        register int c = *((unsigned char *)p);
628    
629        if (utf8 && c >= 0xc0)
630          {
631          int gcii, gcss;
632          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
633          gcss = 6*extra;
634          c = (c & utf8_table3[extra]) << gcss;
635          for (gcii = 1; gcii <= extra; gcii++)
636            {
637            gcss -= 6;
638            c |= (p[gcii] & 0x3f) << gcss;
639            }
640          }
641    
642        p += 1 + extra;
643    
644        switch (c)
645          {
646          case 0x0a:    /* LF */
647          case 0x0b:    /* VT */
648          case 0x0c:    /* FF */
649          *lenptr = 1;
650          return p;
651    
652          case 0x0d:    /* CR */
653          if (p < endptr && *p == 0x0a)
654            {
655            *lenptr = 2;
656            p++;
657            }
658          else *lenptr = 1;
659          return p;
660    
661          case 0x85:    /* NEL */
662          *lenptr = utf8? 2 : 1;
663          return p;
664    
665          case 0x2028:  /* LS */
666          case 0x2029:  /* PS */
667          *lenptr = 3;
668          return p;
669    
670          default:
671          break;
672          }
673        }   /* End of loop for ANY case */
674    
675      *lenptr = 0;  /* Must have hit the end */
676      return endptr;
677      }     /* End of overall switch */
678    }
679    
680    
681    
682    /*************************************************
683    *         Find start of previous line            *
684    *************************************************/
685    
686    /* This is called when looking back for before lines to print.
687    
688    Arguments:
689      p         start of the subsequent line
690      startptr  start of available data
691    
692    Returns:    pointer to the start of the previous line
693    */
694    
695    static char *
696    previous_line(char *p, char *startptr)
697    {
698    switch(endlinetype)
699      {
700      default:      /* Just in case */
701      case EL_LF:
702      p--;
703      while (p > startptr && p[-1] != '\n') p--;
704      return p;
705    
706      case EL_CR:
707      p--;
708      while (p > startptr && p[-1] != '\n') p--;
709      return p;
710    
711      case EL_CRLF:
712      for (;;)
713        {
714        p -= 2;
715        while (p > startptr && p[-1] != '\n') p--;
716        if (p <= startptr + 1 || p[-2] == '\r') return p;
717        }
718      return p;   /* But control should never get here */
719    
720      case EL_ANY:
721      case EL_ANYCRLF:
722      if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;
723      if (utf8) while ((*p & 0xc0) == 0x80) p--;
724    
725      while (p > startptr)
726        {
727        register int c;
728        char *pp = p - 1;
729    
730        if (utf8)
731          {
732          int extra = 0;
733          while ((*pp & 0xc0) == 0x80) pp--;
734          c = *((unsigned char *)pp);
735          if (c >= 0xc0)
736            {
737            int gcii, gcss;
738            extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
739            gcss = 6*extra;
740            c = (c & utf8_table3[extra]) << gcss;
741            for (gcii = 1; gcii <= extra; gcii++)
742              {
743              gcss -= 6;
744              c |= (pp[gcii] & 0x3f) << gcss;
745              }
746            }
747          }
748        else c = *((unsigned char *)pp);
749    
750        if (endlinetype == EL_ANYCRLF) switch (c)
751          {
752          case 0x0a:    /* LF */
753          case 0x0d:    /* CR */
754          return p;
755    
756          default:
757          break;
758          }
759    
760        else switch (c)
761          {
762          case 0x0a:    /* LF */
763          case 0x0b:    /* VT */
764          case 0x0c:    /* FF */
765          case 0x0d:    /* CR */
766          case 0x85:    /* NEL */
767          case 0x2028:  /* LS */
768          case 0x2029:  /* PS */
769          return p;
770    
771          default:
772          break;
773          }
774    
775        p = pp;  /* Back one character */
776        }        /* End of loop for ANY case */
777    
778      return startptr;  /* Hit start of data */
779      }     /* End of overall switch */
780    }
781    
782    
783    
784    
785    
786    /*************************************************
787  *       Print the previous "after" lines         *  *       Print the previous "after" lines         *
788  *************************************************/  *************************************************/
789    
# Line 486  if (after_context > 0 && lastmatchnumber Line 808  if (after_context > 0 && lastmatchnumber
808    int count = 0;    int count = 0;
809    while (lastmatchrestart < endptr && count++ < after_context)    while (lastmatchrestart < endptr && count++ < after_context)
810      {      {
811        int ellength;
812      char *pp = lastmatchrestart;      char *pp = lastmatchrestart;
813      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
814      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
815      while (*pp != '\n') pp++;      pp = end_of_line(pp, endptr, &ellength);
816      fwrite(lastmatchrestart, 1, pp - lastmatchrestart + 1, stdout);      fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
817      lastmatchrestart = pp + 1;      lastmatchrestart = pp;
818      }      }
819    hyphenpending = TRUE;    hyphenpending = TRUE;
820    }    }
# Line 500  if (after_context > 0 && lastmatchnumber Line 823  if (after_context > 0 && lastmatchnumber
823    
824    
825  /*************************************************  /*************************************************
826    *   Apply patterns to subject till one matches   *
827    *************************************************/
828    
829    /* This function is called to run through all patterns, looking for a match. It
830    is used multiple times for the same subject when colouring is enabled, in order
831    to find all possible matches.
832    
833    Arguments:
834      matchptr    the start of the subject
835      length      the length of the subject to match
836      offsets     the offets vector to fill in
837      mrc         address of where to put the result of pcre_exec()
838    
839    Returns:      TRUE if there was a match
840                  FALSE if there was no match
841                  invert if there was a non-fatal error
842    */
843    
844    static BOOL
845    match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)
846    {
847    int i;
848    for (i = 0; i < pattern_count; i++)
849      {
850      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0,
851        PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
852      if (*mrc >= 0) return TRUE;
853      if (*mrc == PCRE_ERROR_NOMATCH) continue;
854      fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);
855      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
856      fprintf(stderr, "this text:\n");
857      fwrite(matchptr, 1, length, stderr);  /* In case binary zero included */
858      fprintf(stderr, "\n");
859      if (error_count == 0 &&
860          (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT))
861        {
862        fprintf(stderr, "pcregrep: error %d means that a resource limit "
863          "was exceeded\n", *mrc);
864        fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");
865        }
866      if (error_count++ > 20)
867        {
868        fprintf(stderr, "pcregrep: too many errors - abandoned\n");
869        exit(2);
870        }
871      return invert;    /* No more matching; don't show the line again */
872      }
873    
874    return FALSE;  /* No match, no errors */
875    }
876    
877    
878    
879    /*************************************************
880  *            Grep an individual file             *  *            Grep an individual file             *
881  *************************************************/  *************************************************/
882    
# Line 511  be in the middle third most of the time, Line 888  be in the middle third most of the time,
888  "before" context printing.  "before" context printing.
889    
890  Arguments:  Arguments:
891    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
892                   the gzFile pointer when reading is via libz
893                   the BZFILE pointer when reading is via libbz2
894      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
895    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
896                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
897                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
898    
899  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
900                 1 otherwise (no matches)                 1 otherwise (no matches)
901                   2 if there is a read error on a .bz2 file
902  */  */
903    
904  static int  static int
905  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
906  {  {
907  int rc = 1;  int rc = 1;
908  int linenumber = 1;  int linenumber = 1;
909  int lastmatchnumber = 0;  int lastmatchnumber = 0;
910  int count = 0;  int count = 0;
911  int offsets[99];  int filepos = 0;
912    int offsets[OFFSET_SIZE];
913  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
914  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
915  char *ptr = buffer;  char *ptr = buffer;
916  char *endptr;  char *endptr;
917  size_t bufflength;  size_t bufflength;
918  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
919    FILE *in = NULL;                    /* Ensure initialized */
920    
921  /* Do the first read into the start of the buffer and set up the pointer to  #ifdef SUPPORT_LIBZ
922  end of what we have. */  gzFile ingz = NULL;
923    #endif
924    
925    #ifdef SUPPORT_LIBBZ2
926    BZFILE *inbz2 = NULL;
927    #endif
928    
929    
930    /* Do the first read into the start of the buffer and set up the pointer to end
931    of what we have. In the case of libz, a non-zipped .gz file will be read as a
932    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
933    fail. */
934    
935    #ifdef SUPPORT_LIBZ
936    if (frtype == FR_LIBZ)
937      {
938      ingz = (gzFile)handle;
939      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
940      }
941    else
942    #endif
943    
944    #ifdef SUPPORT_LIBBZ2
945    if (frtype == FR_LIBBZ2)
946      {
947      inbz2 = (BZFILE *)handle;
948      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
949      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
950      }                                    /* without the cast it is unsigned. */
951    else
952    #endif
953    
954      {
955      in = (FILE *)handle;
956      bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);
957      }
958    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
959  endptr = buffer + bufflength;  endptr = buffer + bufflength;
960    
961  /* 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 548  way, the buffer is shifted left and re-f Line 965  way, the buffer is shifted left and re-f
965    
966  while (ptr < endptr)  while (ptr < endptr)
967    {    {
968    int i;    int endlinelength;
969    int mrc = 0;    int mrc = 0;
970    BOOL match = FALSE;    BOOL match;
971      char *matchptr = ptr;
972    char *t = ptr;    char *t = ptr;
973    size_t length, linelength;    size_t length, linelength;
974    
975    /* At this point, ptr is at the start of a line. We need to find the length    /* At this point, ptr is at the start of a line. We need to find the length
976    of the subject string to pass to pcre_exec(). In multiline mode, it is the    of the subject string to pass to pcre_exec(). In multiline mode, it is the
977    length remainder of the data in the buffer. Otherwise, it is the length of    length remainder of the data in the buffer. Otherwise, it is the length of
978    the next line. After matching, we always advance by the length of the next    the next line, excluding the terminating newline. After matching, we always
979    line. In multiline mode the PCRE_FIRSTLINE option is used for compiling, so    advance by the length of the next line. In multiline mode the PCRE_FIRSTLINE
980    that any match is constrained to be in the first line. */    option is used for compiling, so that any match is constrained to be in the
981      first line. */
982    linelength = 0;  
983    while (t < endptr && *t++ != '\n') linelength++;    t = end_of_line(t, endptr, &endlinelength);
984    length = multiline? endptr - ptr : linelength;    linelength = t - ptr - endlinelength;
985      length = multiline? (size_t)(endptr - ptr) : linelength;
986    /* Run through all the patterns until one matches. Note that we don't include  
987    the final newline in the subject string. */    /* Extra processing for Jeffrey Friedl's debugging. */
988    
989    for (i = 0; i < pattern_count; i++)  #ifdef JFRIEDL_DEBUG
990      {    if (jfriedl_XT || jfriedl_XR)
991      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,    {
992        offsets, 99);        #include <sys/time.h>
993      if (mrc >= 0) { match = TRUE; break; }        #include <time.h>
994      if (mrc != PCRE_ERROR_NOMATCH)        struct timeval start_time, end_time;
995        {        struct timezone dummy;
996        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);        int i;
997        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);  
998        fprintf(stderr, "this line:\n");        if (jfriedl_XT)
999        fwrite(ptr, 1, linelength, stderr);   /* In case binary zero included */        {
1000        fprintf(stderr, "\n");            unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix);
1001        if (error_count == 0 &&            const char *orig = ptr;
1002            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))            ptr = malloc(newlen + 1);
1003          {            if (!ptr) {
1004          fprintf(stderr, "pcregrep: error %d means that a resource limit "                    printf("out of memory");
1005            "was exceeded\n", mrc);                    exit(2);
1006          fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");            }
1007          }            endptr = ptr;
1008        if (error_count++ > 20)            strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
1009          {            for (i = 0; i < jfriedl_XT; i++) {
1010          fprintf(stderr, "pcregrep: too many errors - abandoned\n");                    strncpy(endptr, orig,  length);
1011          exit(2);                    endptr += length;
1012          }            }
1013        match = invert;    /* No more matching; don't show the line again */            strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix);
1014        break;            length = newlen;
1015        }        }
1016      }  
1017          if (gettimeofday(&start_time, &dummy) != 0)
1018                  perror("bad gettimeofday");
1019    
1020    
1021          for (i = 0; i < jfriedl_XR; i++)
1022              match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0,
1023                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1024    
1025          if (gettimeofday(&end_time, &dummy) != 0)
1026                  perror("bad gettimeofday");
1027    
1028          double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0))
1029                          -
1030                          (start_time.tv_sec + (start_time.tv_usec / 1000000.0)));
1031    
1032          printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta);
1033          return 0;
1034      }
1035    #endif
1036    
1037      /* We come back here after a match when the -o option (only_matching) is set,
1038      in order to find any further matches in the same line. */
1039    
1040      ONLY_MATCHING_RESTART:
1041    
1042      /* Run through all the patterns until one matches or there is an error other
1043      than NOMATCH. This code is in a subroutine so that it can be re-used for
1044      finding subsequent matches when colouring matched lines. */
1045    
1046      match = match_patterns(matchptr, length, offsets, &mrc);
1047    
1048    /* If it's a match or a not-match (as required), do what's wanted. */    /* If it's a match or a not-match (as required), do what's wanted. */
1049    
# Line 614  while (ptr < endptr) Line 1062  while (ptr < endptr)
1062      /* If all we want is a file name, there is no need to scan any more lines      /* If all we want is a file name, there is no need to scan any more lines
1063      in the file. */      in the file. */
1064    
1065      else if (filenames == FN_ONLY)      else if (filenames == FN_MATCH_ONLY)
1066        {        {
1067        fprintf(stdout, "%s\n", printname);        fprintf(stdout, "%s\n", printname);
1068        return 0;        return 0;
# Line 625  while (ptr < endptr) Line 1073  while (ptr < endptr)
1073      else if (quiet) return 0;      else if (quiet) return 0;
1074    
1075      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
1076      does not pring any context. */      the --file-offsets and --line-offsets options output offsets for the
1077        matching substring (they both force --only-matching). None of these options
1078        prints any context. Afterwards, adjust the start and length, and then jump
1079        back to look for further matches in the same line. If we are in invert
1080        mode, however, nothing is printed - this could be still useful because the
1081        return code is set. */
1082    
1083      else if (only_matching)      else if (only_matching)
1084        {        {
1085        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
1086        if (number) fprintf(stdout, "%d:", linenumber);          {
1087        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1088        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
1089            if (line_offsets)
1090              fprintf(stdout, "%d,%d", (int)(matchptr + offsets[0] - ptr),
1091                offsets[1] - offsets[0]);
1092            else if (file_offsets)
1093              fprintf(stdout, "%d,%d", (int)(filepos + matchptr + offsets[0] - ptr),
1094                offsets[1] - offsets[0]);
1095            else
1096              {
1097              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1098              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1099              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1100              }
1101            fprintf(stdout, "\n");
1102            matchptr += offsets[1];
1103            length -= offsets[1];
1104            match = FALSE;
1105            goto ONLY_MATCHING_RESTART;
1106            }
1107        }        }
1108    
1109      /* 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 646  while (ptr < endptr) Line 1117  while (ptr < endptr)
1117    
1118        if (after_context > 0 && lastmatchnumber > 0)        if (after_context > 0 && lastmatchnumber > 0)
1119          {          {
1120            int ellength;
1121          int linecount = 0;          int linecount = 0;
1122          char *p = lastmatchrestart;          char *p = lastmatchrestart;
1123    
1124          while (p < ptr && linecount < after_context)          while (p < ptr && linecount < after_context)
1125            {            {
1126            while (*p != '\n') p++;            p = end_of_line(p, ptr, &ellength);
           p++;  
1127            linecount++;            linecount++;
1128            }            }
1129    
# Line 665  while (ptr < endptr) Line 1136  while (ptr < endptr)
1136            char *pp = lastmatchrestart;            char *pp = lastmatchrestart;
1137            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1138            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1139            while (*pp != '\n') pp++;            pp = end_of_line(pp, endptr, &ellength);
1140            fwrite(lastmatchrestart, 1, pp - lastmatchrestart + 1, stdout);            fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1141            lastmatchrestart = pp + 1;            lastmatchrestart = pp;
1142            }            }
1143          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
1144          }          }
# Line 693  while (ptr < endptr) Line 1164  while (ptr < endptr)
1164                 linecount < before_context)                 linecount < before_context)
1165            {            {
1166            linecount++;            linecount++;
1167            p--;            p = previous_line(p, buffer);
           while (p > buffer && p[-1] != '\n') p--;  
1168            }            }
1169    
1170          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 702  while (ptr < endptr) Line 1172  while (ptr < endptr)
1172    
1173          while (p < ptr)          while (p < ptr)
1174            {            {
1175              int ellength;
1176            char *pp = p;            char *pp = p;
1177            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1178            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1179            while (*pp != '\n') pp++;            pp = end_of_line(pp, endptr, &ellength);
1180            fwrite(p, 1, pp - p + 1, stdout);   /* In case binary zero */            fwrite(p, 1, pp - p, stdout);
1181            p = pp + 1;            p = pp;
1182            }            }
1183          }          }
1184    
# Line 722  while (ptr < endptr) Line 1193  while (ptr < endptr)
1193    
1194        /* In multiline mode, we want to print to the end of the line in which        /* In multiline mode, we want to print to the end of the line in which
1195        the end of the matched string is found, so we adjust linelength and the        the end of the matched string is found, so we adjust linelength and the
1196        line number appropriately. Because the PCRE_FIRSTLINE option is set, the        line number appropriately, but only when there actually was a match
1197        start of the match will always be before the first \n character. */        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1198          the match will always be before the first newline sequence. */
1199    
1200        if (multiline)        if (multiline)
1201          {          {
1202          char *endmatch = ptr + offsets[1];          int ellength;
1203          t = ptr;          char *endmatch = ptr;
1204          while (t < endmatch) { if (*t++ == '\n') linenumber++; }          if (!invert)
1205          while (endmatch < endptr && *endmatch != '\n') endmatch++;            {
1206          linelength = endmatch - ptr;            endmatch += offsets[1];
1207              t = ptr;
1208              while (t < endmatch)
1209                {
1210                t = end_of_line(t, endptr, &ellength);
1211                if (t <= endmatch) linenumber++; else break;
1212                }
1213              }
1214            endmatch = end_of_line(endmatch, endptr, &ellength);
1215            linelength = endmatch - ptr - ellength;
1216          }          }
1217    
1218        /*** NOTE: Use only fwrite() to output the data line, so that binary        /*** NOTE: Use only fwrite() to output the data line, so that binary
# Line 753  while (ptr < endptr) Line 1234  while (ptr < endptr)
1234        else        else
1235  #endif  #endif
1236    
1237        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1238          matches. */
1239    
1240        if (do_colour)        if (do_colour)
1241          {          {
1242            int last_offset = 0;
1243          fwrite(ptr, 1, offsets[0], stdout);          fwrite(ptr, 1, offsets[0], stdout);
1244          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1245          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1246          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1247          fwrite(ptr + offsets[1], 1, linelength - offsets[1], stdout);          for (;;)
1248              {
1249              last_offset += offsets[1];
1250              matchptr += offsets[1];
1251              length -= offsets[1];
1252              if (!match_patterns(matchptr, length, offsets, &mrc)) break;
1253              fwrite(matchptr, 1, offsets[0], stdout);
1254              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1255              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1256              fprintf(stdout, "%c[00m", 0x1b);
1257              }
1258            fwrite(ptr + last_offset, 1, (linelength + endlinelength) - last_offset,
1259              stdout);
1260          }          }
       else fwrite(ptr, 1, linelength, stdout);  
1261    
1262        fprintf(stdout, "\n");        /* Not colouring; no need to search for further matches */
1263    
1264          else fwrite(ptr, 1, linelength + endlinelength, stdout);
1265        }        }
1266    
1267      /* End of doing what has to be done for a match */      /* End of doing what has to be done for a match */
# Line 775  while (ptr < endptr) Line 1271  while (ptr < endptr)
1271      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
1272      where we are about to restart, and that line's number. */      where we are about to restart, and that line's number. */
1273    
1274      lastmatchrestart = ptr + linelength + 1;      lastmatchrestart = ptr + linelength + endlinelength;
1275      lastmatchnumber = linenumber + 1;      lastmatchnumber = linenumber + 1;
1276      }      }
1277    
1278    /* Advance to after the newline and increment the line number. */    /* For a match in multiline inverted mode (which of course did not cause
1279      anything to be printed), we have to move on to the end of the match before
1280      proceeding. */
1281    
1282      if (multiline && invert && match)
1283        {
1284        int ellength;
1285        char *endmatch = ptr + offsets[1];
1286        t = ptr;
1287        while (t < endmatch)
1288          {
1289          t = end_of_line(t, endptr, &ellength);
1290          if (t <= endmatch) linenumber++; else break;
1291          }
1292        endmatch = end_of_line(endmatch, endptr, &ellength);
1293        linelength = endmatch - ptr - ellength;
1294        }
1295    
1296      /* Advance to after the newline and increment the line number. The file
1297      offset to the current line is maintained in filepos. */
1298    
1299    ptr += linelength + 1;    ptr += linelength + endlinelength;
1300      filepos += linelength + endlinelength;
1301    linenumber++;    linenumber++;
1302    
1303    /* 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 803  while (ptr < endptr) Line 1319  while (ptr < endptr)
1319    
1320      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1321      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1322    
1323    #ifdef SUPPORT_LIBZ
1324        if (frtype == FR_LIBZ)
1325          bufflength = 2*MBUFTHIRD +
1326            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1327        else
1328    #endif
1329    
1330    #ifdef SUPPORT_LIBBZ2
1331        if (frtype == FR_LIBBZ2)
1332          bufflength = 2*MBUFTHIRD +
1333            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1334        else
1335    #endif
1336    
1337      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);
1338    
1339      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1340    
1341      /* Adjust any last match point */      /* Adjust any last match point */
# Line 834  if (filenames == FN_NOMATCH_ONLY) Line 1366  if (filenames == FN_NOMATCH_ONLY)
1366    
1367  if (count_only)  if (count_only)
1368    {    {
1369    if (printname != NULL) fprintf(stdout, "%s:", printname);    if (count > 0 || !omit_zero_count)
1370    fprintf(stdout, "%d\n", count);      {
1371        if (printname != NULL && filenames != FN_NONE)
1372          fprintf(stdout, "%s:", printname);
1373        fprintf(stdout, "%d\n", count);
1374        }
1375    }    }
1376    
1377  return rc;  return rc;
# Line 867  grep_or_recurse(char *pathname, BOOL dir Line 1403  grep_or_recurse(char *pathname, BOOL dir
1403  {  {
1404  int rc = 1;  int rc = 1;
1405  int sep;  int sep;
1406  FILE *in;  int frtype;
1407    int pathlen;
1408    void *handle;
1409    FILE *in = NULL;           /* Ensure initialized */
1410    
1411    #ifdef SUPPORT_LIBZ
1412    gzFile ingz = NULL;
1413    #endif
1414    
1415    #ifdef SUPPORT_LIBBZ2
1416    BZFILE *inbz2 = NULL;
1417    #endif
1418    
1419  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1420    
1421  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1422    {    {
1423    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1424      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1425        stdin_name : NULL);        stdin_name : NULL);
1426    }    }
1427    
   
1428  /* 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
1429  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
1430  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
1431    system-specific. */
1432    
1433  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1434    {    {
# Line 902  if ((sep = isdirectory(pathname)) != 0) Line 1449  if ((sep = isdirectory(pathname)) != 0)
1449    
1450      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1451        {        {
1452        int frc, blen;        int frc, nflen;
1453        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1454        blen = strlen(buffer);        nflen = strlen(nextfile);
1455    
1456        if (exclude_compiled != NULL &&        if (isdirectory(buffer))
1457            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)          {
1458          continue;          if (exclude_dir_compiled != NULL &&
1459                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1460        if (include_compiled != NULL &&            continue;
1461            pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
1462          continue;          if (include_dir_compiled != NULL &&
1463                pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1464              continue;
1465            }
1466          else
1467            {
1468            if (exclude_compiled != NULL &&
1469                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1470              continue;
1471    
1472            if (include_compiled != NULL &&
1473                pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1474              continue;
1475            }
1476    
1477        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1478        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 935  skipping was not requested. The scan pro Line 1495  skipping was not requested. The scan pro
1495  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
1496  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1497    
1498  in = fopen(pathname, "r");  pathlen = strlen(pathname);
1499  if (in == NULL)  
1500    /* Open using zlib if it is supported and the file name ends with .gz. */
1501    
1502    #ifdef SUPPORT_LIBZ
1503    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1504      {
1505      ingz = gzopen(pathname, "rb");
1506      if (ingz == NULL)
1507        {
1508        if (!silent)
1509          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1510            strerror(errno));
1511        return 2;
1512        }
1513      handle = (void *)ingz;
1514      frtype = FR_LIBZ;
1515      }
1516    else
1517    #endif
1518    
1519    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1520    
1521    #ifdef SUPPORT_LIBBZ2
1522    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1523      {
1524      inbz2 = BZ2_bzopen(pathname, "rb");
1525      handle = (void *)inbz2;
1526      frtype = FR_LIBBZ2;
1527      }
1528    else
1529    #endif
1530    
1531    /* Otherwise use plain fopen(). The label is so that we can come back here if
1532    an attempt to read a .bz2 file indicates that it really is a plain file. */
1533    
1534    #ifdef SUPPORT_LIBBZ2
1535    PLAIN_FILE:
1536    #endif
1537      {
1538      in = fopen(pathname, "rb");
1539      handle = (void *)in;
1540      frtype = FR_PLAIN;
1541      }
1542    
1543    /* All the opening methods return errno when they fail. */
1544    
1545    if (handle == NULL)
1546    {    {
1547    if (!silent)    if (!silent)
1548      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 944  if (in == NULL) Line 1550  if (in == NULL)
1550    return 2;    return 2;
1551    }    }
1552    
1553  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1554    
1555    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1556    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1557    
1558    /* Close in an appropriate manner. */
1559    
1560    #ifdef SUPPORT_LIBZ
1561    if (frtype == FR_LIBZ)
1562      gzclose(ingz);
1563    else
1564    #endif
1565    
1566    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1567    read failed. If the error indicates that the file isn't in fact bzipped, try
1568    again as a normal file. */
1569    
1570    #ifdef SUPPORT_LIBBZ2
1571    if (frtype == FR_LIBBZ2)
1572      {
1573      if (rc == 2)
1574        {
1575        int errnum;
1576        const char *err = BZ2_bzerror(inbz2, &errnum);
1577        if (errnum == BZ_DATA_ERROR_MAGIC)
1578          {
1579          BZ2_bzclose(inbz2);
1580          goto PLAIN_FILE;
1581          }
1582        else if (!silent)
1583          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1584            pathname, err);
1585        }
1586      BZ2_bzclose(inbz2);
1587      }
1588    else
1589    #endif
1590    
1591    /* Normal file close */
1592    
1593  fclose(in);  fclose(in);
1594    
1595    /* Pass back the yield from pcregrep(). */
1596    
1597  return rc;  return rc;
1598  }  }
1599    
# Line 968  for (op = optionlist; op->one_char != 0; Line 1614  for (op = optionlist; op->one_char != 0;
1614    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1615    }    }
1616  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1617  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1618      "options.\n");
1619  return rc;  return rc;
1620  }  }
1621    
# Line 987  option_item *op; Line 1634  option_item *op;
1634  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1635  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1636  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");
1637  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");  
1638    
1639    #ifdef SUPPORT_LIBZ
1640    printf("Files whose names end in .gz are read using zlib.\n");
1641    #endif
1642    
1643    #ifdef SUPPORT_LIBBZ2
1644    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1645    #endif
1646    
1647    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1648    printf("Other files and the standard input are read as plain files.\n\n");
1649    #else
1650    printf("All files are read as plain files, without any interpretation.\n\n");
1651    #endif
1652    
1653    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1654  printf("Options:\n");  printf("Options:\n");
1655    
1656  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
# Line 997  for (op = optionlist; op->one_char != 0; Line 1658  for (op = optionlist; op->one_char != 0;
1658    int n;    int n;
1659    char s[4];    char s[4];
1660    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, "   ");
1661    printf("  %s --%s%n", s, op->long_name, &n);    n = 30 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1662    if (n < 1) n = 1;    if (n < 1) n = 1;
1663    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                    ", op->help_text);
1664    }    }
# Line 1023  handle_option(int letter, int options) Line 1683  handle_option(int letter, int options)
1683  {  {
1684  switch(letter)  switch(letter)
1685    {    {
1686      case N_FOFFSETS: file_offsets = TRUE; break;
1687    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1688      case N_LOFFSETS: line_offsets = number = TRUE; break;
1689    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1690    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1691    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
1692    case 'h': filenames = FN_NONE; break;    case 'h': filenames = FN_NONE; break;
1693    case 'i': options |= PCRE_CASELESS; break;    case 'i': options |= PCRE_CASELESS; break;
1694    case 'l': filenames = FN_ONLY; break;    case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1695    case 'L': filenames = FN_NOMATCH_ONLY; break;    case 'L': filenames = FN_NOMATCH_ONLY; break;
1696    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;    case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1697    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
# Line 1037  switch(letter) Line 1699  switch(letter)
1699    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1700    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1701    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
1702    case 'u': options |= PCRE_UTF8; break;    case 'u': options |= PCRE_UTF8; utf8 = TRUE; break;
1703    case 'v': invert = TRUE; break;    case 'v': invert = TRUE; break;
1704    case 'w': process_options |= PO_WORD_MATCH; break;    case 'w': process_options |= PO_WORD_MATCH; break;
1705    case 'x': process_options |= PO_LINE_MATCH; break;    case 'x': process_options |= PO_LINE_MATCH; break;
1706    
1707    case 'V':    case 'V':
1708    fprintf(stderr, "pcregrep version %s using ", VERSION);    fprintf(stderr, "pcregrep version %s\n", pcre_version());
   fprintf(stderr, "PCRE version %s\n", pcre_version());  
1709    exit(0);    exit(0);
1710    break;    break;
1711    
# Line 1120  sprintf(buffer, "%s%.*s%s", prefix[proce Line 1781  sprintf(buffer, "%s%.*s%s", prefix[proce
1781    suffix[process_options]);    suffix[process_options]);
1782  pattern_list[pattern_count] =  pattern_list[pattern_count] =
1783    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
1784  if (pattern_list[pattern_count++] != NULL) return TRUE;  if (pattern_list[pattern_count] != NULL)
1785      {
1786      pattern_count++;
1787      return TRUE;
1788      }
1789    
1790  /* Handle compile errors */  /* Handle compile errors */
1791    
# Line 1152  return FALSE; Line 1817  return FALSE;
1817  *************************************************/  *************************************************/
1818    
1819  /* When the -F option has been used, each string may be a list of strings,  /* When the -F option has been used, each string may be a list of strings,
1820  separated by newlines. They will be matched literally.  separated by line breaks. They will be matched literally.
1821    
1822  Arguments:  Arguments:
1823    pattern        the pattern string    pattern        the pattern string
# Line 1170  compile_pattern(char *pattern, int optio Line 1835  compile_pattern(char *pattern, int optio
1835  {  {
1836  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
1837    {    {
1838      char *eop = pattern + strlen(pattern);
1839    char buffer[MBUFTHIRD];    char buffer[MBUFTHIRD];
1840    for(;;)    for(;;)
1841      {      {
1842      char *p = strchr(pattern, '\n');      int ellength;
1843      if (p == NULL)      char *p = end_of_line(pattern, eop, &ellength);
1844        if (ellength == 0)
1845        return compile_single_pattern(pattern, options, filename, count);        return compile_single_pattern(pattern, options, filename, count);
1846      sprintf(buffer, "%.*s", p - pattern, pattern);      sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern);
1847      pattern = p + 1;      pattern = p;
1848      if (!compile_single_pattern(buffer, options, filename, count))      if (!compile_single_pattern(buffer, options, filename, count))
1849        return FALSE;        return FALSE;
1850      }      }
# Line 1200  int i, j; Line 1867  int i, j;
1867  int rc = 1;  int rc = 1;
1868  int pcre_options = 0;  int pcre_options = 0;
1869  int cmd_pattern_count = 0;  int cmd_pattern_count = 0;
1870    int hint_count = 0;
1871  int errptr;  int errptr;
1872  BOOL only_one_at_top;  BOOL only_one_at_top;
1873  char *patterns[MAX_PATTERN_COUNT];  char *patterns[MAX_PATTERN_COUNT];
1874  const char *locale_from = "--locale";  const char *locale_from = "--locale";
1875  const char *error;  const char *error;
1876    
1877    /* Set the default line ending value from the default in the PCRE library;
1878    "lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf".
1879    Note that the return values from pcre_config(), though derived from the ASCII
1880    codes, are the same in EBCDIC environments, so we must use the actual values
1881    rather than escapes such as as '\r'. */
1882    
1883    (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
1884    switch(i)
1885      {
1886      default:               newline = (char *)"lf"; break;
1887      case 13:               newline = (char *)"cr"; break;
1888      case (13 << 8) | 10:   newline = (char *)"crlf"; break;
1889      case -1:               newline = (char *)"any"; break;
1890      case -2:               newline = (char *)"anycrlf"; break;
1891      }
1892    
1893  /* Process the options */  /* Process the options */
1894    
1895  for (i = 1; i < argc; i++)  for (i = 1; i < argc; i++)
# Line 1261  for (i = 1; i < argc; i++) Line 1945  for (i = 1; i < argc; i++)
1945          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
1946            {            {
1947            int oplen = equals - op->long_name;            int oplen = equals - op->long_name;
1948            int arglen = (argequals == NULL)? strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)? (int)strlen(arg) : argequals - arg;
1949            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
1950              {              {
1951              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1280  for (i = 1; i < argc; i++) Line 1964  for (i = 1; i < argc; i++)
1964          char buff2[24];          char buff2[24];
1965          int baselen = opbra - op->long_name;          int baselen = opbra - op->long_name;
1966          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
1967          sprintf(buff2, "%s%.*s", buff1, strlen(op->long_name) - baselen - 2,          sprintf(buff2, "%s%.*s", buff1,
1968            opbra + 1);            (int)strlen(op->long_name) - baselen - 2, opbra + 1);
1969          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)
1970            break;            break;
1971          }          }
# Line 1294  for (i = 1; i < argc; i++) Line 1978  for (i = 1; i < argc; i++)
1978        }        }
1979      }      }
1980    
1981    
1982      /* Jeffrey Friedl's debugging harness uses these additional options which
1983      are not in the right form for putting in the option table because they use
1984      only one hyphen, yet are more than one character long. By putting them
1985      separately here, they will not get displayed as part of the help() output,
1986      but I don't think Jeffrey will care about that. */
1987    
1988    #ifdef JFRIEDL_DEBUG
1989      else if (strcmp(argv[i], "-pre") == 0) {
1990              jfriedl_prefix = argv[++i];
1991              continue;
1992      } else if (strcmp(argv[i], "-post") == 0) {
1993              jfriedl_postfix = argv[++i];
1994              continue;
1995      } else if (strcmp(argv[i], "-XT") == 0) {
1996              sscanf(argv[++i], "%d", &jfriedl_XT);
1997              continue;
1998      } else if (strcmp(argv[i], "-XR") == 0) {
1999              sscanf(argv[++i], "%d", &jfriedl_XR);
2000              continue;
2001      }
2002    #endif
2003    
2004    
2005    /* One-char options; many that have no data may be in a single argument; we    /* One-char options; many that have no data may be in a single argument; we
2006    continue till we hit the last one or one that needs data. */    continue till we hit the last one or one that needs data. */
2007    
# Line 1333  for (i = 1; i < argc; i++) Line 2041  for (i = 1; i < argc; i++)
2041    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that    /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that
2042    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
2043    separate item. At the moment, the only such options are "colo(u)r" and    separate item. At the moment, the only such options are "colo(u)r" and
2044    Jeffrey Friedl's special debugging option. */    Jeffrey Friedl's special -S debugging option. */
2045    
2046    if (*option_data == 0 &&    if (*option_data == 0 &&
2047        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))        (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
# Line 1416  if (both_context > 0) Line 2124  if (both_context > 0)
2124    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2125    }    }
2126    
2127    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2128    However, the latter two set the only_matching flag. */
2129    
2130    if ((only_matching && (file_offsets || line_offsets)) ||
2131        (file_offsets && line_offsets))
2132      {
2133      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2134        "and/or --line-offsets\n");
2135      exit(usage(2));
2136      }
2137    
2138    if (file_offsets || line_offsets) only_matching = TRUE;
2139    
2140  /* 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
2141  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2142    
# Line 1465  if (colour_option != NULL && strcmp(colo Line 2186  if (colour_option != NULL && strcmp(colo
2186      }      }
2187    }    }
2188    
2189    /* Interpret the newline type; the default settings are Unix-like. */
2190    
2191    if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)
2192      {
2193      pcre_options |= PCRE_NEWLINE_CR;
2194      endlinetype = EL_CR;
2195      }
2196    else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)
2197      {
2198      pcre_options |= PCRE_NEWLINE_LF;
2199      endlinetype = EL_LF;
2200      }
2201    else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)
2202      {
2203      pcre_options |= PCRE_NEWLINE_CRLF;
2204      endlinetype = EL_CRLF;
2205      }
2206    else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0)
2207      {
2208      pcre_options |= PCRE_NEWLINE_ANY;
2209      endlinetype = EL_ANY;
2210      }
2211    else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0)
2212      {
2213      pcre_options |= PCRE_NEWLINE_ANYCRLF;
2214      endlinetype = EL_ANYCRLF;
2215      }
2216    else
2217      {
2218      fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline);
2219      return 2;
2220      }
2221    
2222  /* Interpret the text values for -d and -D */  /* Interpret the text values for -d and -D */
2223    
2224  if (dee_option != NULL)  if (dee_option != NULL)
# Line 1490  if (DEE_option != NULL) Line 2244  if (DEE_option != NULL)
2244      }      }
2245    }    }
2246    
2247  /* Check the value for Jeff Friedl's debugging option. */  /* Check the values for Jeffrey Friedl's debugging options. */
2248    
2249  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
2250  if (S_arg > 9)  if (S_arg > 9)
# Line 1498  if (S_arg > 9) Line 2252  if (S_arg > 9)
2252    fprintf(stderr, "pcregrep: bad value for -S option\n");    fprintf(stderr, "pcregrep: bad value for -S option\n");
2253    return 2;    return 2;
2254    }    }
2255    if (jfriedl_XT != 0 || jfriedl_XR != 0)
2256      {
2257      if (jfriedl_XT == 0) jfriedl_XT = 1;
2258      if (jfriedl_XR == 0) jfriedl_XR = 1;
2259      }
2260  #endif  #endif
2261    
2262  /* Get memory to store the pattern and hints lists. */  /* Get memory to store the pattern and hints lists. */
# Line 1508  hints_list = (pcre_extra **)malloc(MAX_P Line 2267  hints_list = (pcre_extra **)malloc(MAX_P
2267  if (pattern_list == NULL || hints_list == NULL)  if (pattern_list == NULL || hints_list == NULL)
2268    {    {
2269    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2270    return 2;    goto EXIT2;
2271    }    }
2272    
2273  /* If no patterns were provided by -e, and there is no file provided by -f,  /* If no patterns were provided by -e, and there is no file provided by -f,
# Line 1527  for (j = 0; j < cmd_pattern_count; j++) Line 2286  for (j = 0; j < cmd_pattern_count; j++)
2286    {    {
2287    if (!compile_pattern(patterns[j], pcre_options, NULL,    if (!compile_pattern(patterns[j], pcre_options, NULL,
2288         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))
2289      return 2;      goto EXIT2;
2290    }    }
2291    
2292  /* Compile the regular expressions that are provided in a file. */  /* Compile the regular expressions that are provided in a file. */
# Line 1551  if (pattern_filename != NULL) Line 2310  if (pattern_filename != NULL)
2310        {        {
2311        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,
2312          strerror(errno));          strerror(errno));
2313        return 2;        goto EXIT2;
2314        }        }
2315      filename = pattern_filename;      filename = pattern_filename;
2316      }      }
# Line 1564  if (pattern_filename != NULL) Line 2323  if (pattern_filename != NULL)
2323      linenumber++;      linenumber++;
2324      if (buffer[0] == 0) continue;   /* Skip blank lines */      if (buffer[0] == 0) continue;   /* Skip blank lines */
2325      if (!compile_pattern(buffer, pcre_options, filename, linenumber))      if (!compile_pattern(buffer, pcre_options, filename, linenumber))
2326        return 2;        goto EXIT2;
2327      }      }
2328    
2329    if (f != stdin) fclose(f);    if (f != stdin) fclose(f);
# Line 1580  for (j = 0; j < pattern_count; j++) Line 2339  for (j = 0; j < pattern_count; j++)
2339      char s[16];      char s[16];
2340      if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);      if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);
2341      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
2342      return 2;      goto EXIT2;
2343      }      }
2344      hint_count++;
2345    }    }
2346    
2347  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
# Line 1594  if (exclude_pattern != NULL) Line 2354  if (exclude_pattern != NULL)
2354      {      {
2355      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",
2356        errptr, error);        errptr, error);
2357      return 2;      goto EXIT2;
2358      }      }
2359    }    }
2360    
# Line 1606  if (include_pattern != NULL) Line 2366  if (include_pattern != NULL)
2366      {      {
2367      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",
2368        errptr, error);        errptr, error);
2369      return 2;      goto EXIT2;
2370        }
2371      }
2372    
2373    if (exclude_dir_pattern != NULL)
2374      {
2375      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2376        pcretables);
2377      if (exclude_dir_compiled == NULL)
2378        {
2379        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2380          errptr, error);
2381        goto EXIT2;
2382        }
2383      }
2384    
2385    if (include_dir_pattern != NULL)
2386      {
2387      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2388        pcretables);
2389      if (include_dir_compiled == NULL)
2390        {
2391        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2392          errptr, error);
2393        goto EXIT2;
2394      }      }
2395    }    }
2396    
2397  /* 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. */
2398    
2399  if (i >= argc)  if (i >= argc)
2400    return pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    {
2401      rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2402      goto EXIT;
2403      }
2404    
2405  /* Otherwise, work through the remaining arguments as files or directories.  /* Otherwise, work through the remaining arguments as files or directories.
2406  Pass in the fact that there is only one argument at top level - this suppresses  Pass in the fact that there is only one argument at top level - this suppresses
# Line 1630  for (; i < argc; i++) Line 2417  for (; i < argc; i++)
2417      else if (frc == 0 && rc == 1) rc = 0;      else if (frc == 0 && rc == 1) rc = 0;
2418    }    }
2419    
2420    EXIT:
2421    if (pattern_list != NULL)
2422      {
2423      for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
2424      free(pattern_list);
2425      }
2426    if (hints_list != NULL)
2427      {
2428      for (i = 0; i < hint_count; i++) free(hints_list[i]);
2429      free(hints_list);
2430      }
2431  return rc;  return rc;
2432    
2433    EXIT2:
2434    rc = 2;
2435    goto EXIT;
2436  }  }
2437    
2438  /* End of pcregrep */  /* End of pcregrep */

Legend:
Removed from v.87  
changed lines
  Added in v.420

  ViewVC Help
Powered by ViewVC 1.1.5