/[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 91 by nigel, Sat Feb 24 21:41:34 2007 UTC revision 419 by ph10, Wed Aug 12 10:45:33 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.3 01-Jun-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_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    
94  enum { dee_READ, dee_SKIP, dee_RECURSE };  enum { dee_READ, dee_SKIP, dee_RECURSE };
# 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 100  static const char *jfriedl_prefix = ""; Line 121  static const char *jfriedl_prefix = "";
121  static const char *jfriedl_postfix = "";  static const char *jfriedl_postfix = "";
122  #endif  #endif
123    
124  static int  endlinebyte = '\n';     /* Last byte of endline sequence */  static int  endlinetype;
 static int  endlineextra = 0;       /* Extra bytes for endline sequence */  
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;
# Line 115  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 135  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 only_matching = FALSE;  static BOOL only_matching = FALSE;
169  static BOOL quiet = FALSE;  static BOOL quiet = FALSE;
170  static BOOL silent = FALSE;  static BOOL silent = FALSE;
171    static BOOL utf8 = FALSE;
172    
173  /* Structure for options and list of them */  /* Structure for options and list of them */
174    
# Line 159  typedef struct option_item { Line 186  typedef struct option_item {
186  /* 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
187  used to identify them. */  used to identify them. */
188    
189  #define N_COLOUR    (-1)  #define N_COLOUR       (-1)
190  #define N_EXCLUDE   (-2)  #define N_EXCLUDE      (-2)
191  #define N_HELP      (-3)  #define N_EXCLUDE_DIR  (-3)
192  #define N_INCLUDE   (-4)  #define N_HELP         (-4)
193  #define N_LABEL     (-5)  #define N_INCLUDE      (-5)
194  #define N_LOCALE    (-6)  #define N_INCLUDE_DIR  (-6)
195  #define N_NULL      (-7)  #define N_LABEL        (-7)
196    #define N_LOCALE       (-8)
197    #define N_NULL         (-9)
198    #define N_LOFFSETS     (-10)
199    #define N_FOFFSETS     (-11)
200    
201  static option_item optionlist[] = {  static option_item optionlist[] = {
202    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 181  static option_item optionlist[] = { Line 212  static option_item optionlist[] = {
212    { 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)" },
213    { 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" },
214    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
215      { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
216    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
217    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
218    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
219    { 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" },
220    { 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" },
221    { 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" },
222      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
223    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
224    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
225    { OP_STRING,    'N',      &newline,          "newline=type",  "specify newline type (CR, LR, CRLF)" },    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
226    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
227    { 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" },
228    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
229    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },    { OP_NODATA,    'r',      NULL,              "recursive",     "recursively scan sub-directories" },
230    { 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" },
231    { 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" },
232      { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
233      { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
234  #ifdef JFRIEDL_DEBUG  #ifdef JFRIEDL_DEBUG
235    { 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" },
236  #endif  #endif
# Line 219  static const char *prefix[] = { Line 254  static const char *prefix[] = {
254  static const char *suffix[] = {  static const char *suffix[] = {
255    "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };    "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };
256    
257    /* UTF-8 tables - used only when the newline setting is "any". */
258    
259    const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
260    
261    const char utf8_table4[] = {
262      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
263      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
264      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
265      3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
266    
267    
268    
269  /*************************************************  /*************************************************
# Line 231  although at present the only ones are fo Line 276  although at present the only ones are fo
276    
277  /************* Directory scanning in Unix ***********/  /************* Directory scanning in Unix ***********/
278    
279  #if IS_UNIX  #if defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H
280  #include <sys/types.h>  #include <sys/types.h>
281  #include <sys/stat.h>  #include <sys/stat.h>
282  #include <dirent.h>  #include <dirent.h>
# Line 263  for (;;) Line 308  for (;;)
308    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)    if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
309      return dent->d_name;      return dent->d_name;
310    }    }
311  return NULL;   /* Keep compiler happy; never executed */  /* Control never reaches here */
312  }  }
313    
314  static void  static void
# Line 298  return isatty(fileno(stdout)); Line 343  return isatty(fileno(stdout));
343    
344  /* 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
345  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
346  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
347    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
348    */
349    
350  #elif HAVE_WIN32API  #elif HAVE_WINDOWS_H
351    
352  #ifndef STRICT  #ifndef STRICT
353  # define STRICT  # define STRICT
# Line 309  when it did not exist. */ Line 355  when it did not exist. */
355  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
356  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
357  #endif  #endif
358    
359    #include <windows.h>
360    
361  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
362  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
363  #endif  #endif
364    
 #include <windows.h>  
   
365  typedef struct directory_type  typedef struct directory_type
366  {  {
367  HANDLE handle;  HANDLE handle;
# Line 399  regular if they are not directories. */ Line 446  regular if they are not directories. */
446    
447  int isregfile(char *filename)  int isregfile(char *filename)
448  {  {
449  return !isdirectory(filename)  return !isdirectory(filename);
450  }  }
451    
452    
# Line 410  return !isdirectory(filename) Line 457  return !isdirectory(filename)
457  static BOOL  static BOOL
458  is_stdout_tty(void)  is_stdout_tty(void)
459  {  {
460  FALSE;  return FALSE;
461  }  }
462    
463    
# Line 423  FALSE; Line 470  FALSE;
470  typedef void directory_type;  typedef void directory_type;
471    
472  int isdirectory(char *filename) { return 0; }  int isdirectory(char *filename) { return 0; }
473  directory_type * opendirectory(char *filename) {}  directory_type * opendirectory(char *filename) { return (directory_type*)0;}
474  char *readdirectory(directory_type *dir) {}  char *readdirectory(directory_type *dir) { return (char*)0;}
475  void closedirectory(directory_type *dir) {}  void closedirectory(directory_type *dir) {}
476    
477    
# Line 448  return FALSE; Line 495  return FALSE;
495    
496    
497    
498  #if ! HAVE_STRERROR  #ifndef HAVE_STRERROR
499  /*************************************************  /*************************************************
500  *     Provide strerror() for non-ANSI libraries  *  *     Provide strerror() for non-ANSI libraries  *
501  *************************************************/  *************************************************/
# Line 471  return sys_errlist[n]; Line 518  return sys_errlist[n];
518    
519    
520  /*************************************************  /*************************************************
521    *             Find end of line                   *
522    *************************************************/
523    
524    /* The length of the endline sequence that is found is set via lenptr. This may
525    be zero at the very end of the file if there is no line-ending sequence there.
526    
527    Arguments:
528      p         current position in line
529      endptr    end of available data
530      lenptr    where to put the length of the eol sequence
531    
532    Returns:    pointer to the last byte of the line
533    */
534    
535    static char *
536    end_of_line(char *p, char *endptr, int *lenptr)
537    {
538    switch(endlinetype)
539      {
540      default:      /* Just in case */
541      case EL_LF:
542      while (p < endptr && *p != '\n') p++;
543      if (p < endptr)
544        {
545        *lenptr = 1;
546        return p + 1;
547        }
548      *lenptr = 0;
549      return endptr;
550    
551      case EL_CR:
552      while (p < endptr && *p != '\r') p++;
553      if (p < endptr)
554        {
555        *lenptr = 1;
556        return p + 1;
557        }
558      *lenptr = 0;
559      return endptr;
560    
561      case EL_CRLF:
562      for (;;)
563        {
564        while (p < endptr && *p != '\r') p++;
565        if (++p >= endptr)
566          {
567          *lenptr = 0;
568          return endptr;
569          }
570        if (*p == '\n')
571          {
572          *lenptr = 2;
573          return p + 1;
574          }
575        }
576      break;
577    
578      case EL_ANYCRLF:
579      while (p < endptr)
580        {
581        int extra = 0;
582        register int c = *((unsigned char *)p);
583    
584        if (utf8 && c >= 0xc0)
585          {
586          int gcii, gcss;
587          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
588          gcss = 6*extra;
589          c = (c & utf8_table3[extra]) << gcss;
590          for (gcii = 1; gcii <= extra; gcii++)
591            {
592            gcss -= 6;
593            c |= (p[gcii] & 0x3f) << gcss;
594            }
595          }
596    
597        p += 1 + extra;
598    
599        switch (c)
600          {
601          case 0x0a:    /* LF */
602          *lenptr = 1;
603          return p;
604    
605          case 0x0d:    /* CR */
606          if (p < endptr && *p == 0x0a)
607            {
608            *lenptr = 2;
609            p++;
610            }
611          else *lenptr = 1;
612          return p;
613    
614          default:
615          break;
616          }
617        }   /* End of loop for ANYCRLF case */
618    
619      *lenptr = 0;  /* Must have hit the end */
620      return endptr;
621    
622      case EL_ANY:
623      while (p < endptr)
624        {
625        int extra = 0;
626        register int c = *((unsigned char *)p);
627    
628        if (utf8 && c >= 0xc0)
629          {
630          int gcii, gcss;
631          extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
632          gcss = 6*extra;
633          c = (c & utf8_table3[extra]) << gcss;
634          for (gcii = 1; gcii <= extra; gcii++)
635            {
636            gcss -= 6;
637            c |= (p[gcii] & 0x3f) << gcss;
638            }
639          }
640    
641        p += 1 + extra;
642    
643        switch (c)
644          {
645          case 0x0a:    /* LF */
646          case 0x0b:    /* VT */
647          case 0x0c:    /* FF */
648          *lenptr = 1;
649          return p;
650    
651          case 0x0d:    /* CR */
652          if (p < endptr && *p == 0x0a)
653            {
654            *lenptr = 2;
655            p++;
656            }
657          else *lenptr = 1;
658          return p;
659    
660          case 0x85:    /* NEL */
661          *lenptr = utf8? 2 : 1;
662          return p;
663    
664          case 0x2028:  /* LS */
665          case 0x2029:  /* PS */
666          *lenptr = 3;
667          return p;
668    
669          default:
670          break;
671          }
672        }   /* End of loop for ANY case */
673    
674      *lenptr = 0;  /* Must have hit the end */
675      return endptr;
676      }     /* End of overall switch */
677    }
678    
679    
680    
681    /*************************************************
682    *         Find start of previous line            *
683    *************************************************/
684    
685    /* This is called when looking back for before lines to print.
686    
687    Arguments:
688      p         start of the subsequent line
689      startptr  start of available data
690    
691    Returns:    pointer to the start of the previous line
692    */
693    
694    static char *
695    previous_line(char *p, char *startptr)
696    {
697    switch(endlinetype)
698      {
699      default:      /* Just in case */
700      case EL_LF:
701      p--;
702      while (p > startptr && p[-1] != '\n') p--;
703      return p;
704    
705      case EL_CR:
706      p--;
707      while (p > startptr && p[-1] != '\n') p--;
708      return p;
709    
710      case EL_CRLF:
711      for (;;)
712        {
713        p -= 2;
714        while (p > startptr && p[-1] != '\n') p--;
715        if (p <= startptr + 1 || p[-2] == '\r') return p;
716        }
717      return p;   /* But control should never get here */
718    
719      case EL_ANY:
720      case EL_ANYCRLF:
721      if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;
722      if (utf8) while ((*p & 0xc0) == 0x80) p--;
723    
724      while (p > startptr)
725        {
726        register int c;
727        char *pp = p - 1;
728    
729        if (utf8)
730          {
731          int extra = 0;
732          while ((*pp & 0xc0) == 0x80) pp--;
733          c = *((unsigned char *)pp);
734          if (c >= 0xc0)
735            {
736            int gcii, gcss;
737            extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
738            gcss = 6*extra;
739            c = (c & utf8_table3[extra]) << gcss;
740            for (gcii = 1; gcii <= extra; gcii++)
741              {
742              gcss -= 6;
743              c |= (pp[gcii] & 0x3f) << gcss;
744              }
745            }
746          }
747        else c = *((unsigned char *)pp);
748    
749        if (endlinetype == EL_ANYCRLF) switch (c)
750          {
751          case 0x0a:    /* LF */
752          case 0x0d:    /* CR */
753          return p;
754    
755          default:
756          break;
757          }
758    
759        else switch (c)
760          {
761          case 0x0a:    /* LF */
762          case 0x0b:    /* VT */
763          case 0x0c:    /* FF */
764          case 0x0d:    /* CR */
765          case 0x85:    /* NEL */
766          case 0x2028:  /* LS */
767          case 0x2029:  /* PS */
768          return p;
769    
770          default:
771          break;
772          }
773    
774        p = pp;  /* Back one character */
775        }        /* End of loop for ANY case */
776    
777      return startptr;  /* Hit start of data */
778      }     /* End of overall switch */
779    }
780    
781    
782    
783    
784    
785    /*************************************************
786  *       Print the previous "after" lines         *  *       Print the previous "after" lines         *
787  *************************************************/  *************************************************/
788    
# Line 495  if (after_context > 0 && lastmatchnumber Line 807  if (after_context > 0 && lastmatchnumber
807    int count = 0;    int count = 0;
808    while (lastmatchrestart < endptr && count++ < after_context)    while (lastmatchrestart < endptr && count++ < after_context)
809      {      {
810        int ellength;
811      char *pp = lastmatchrestart;      char *pp = lastmatchrestart;
812      if (printname != NULL) fprintf(stdout, "%s-", printname);      if (printname != NULL) fprintf(stdout, "%s-", printname);
813      if (number) fprintf(stdout, "%d-", lastmatchnumber++);      if (number) fprintf(stdout, "%d-", lastmatchnumber++);
814      while (*pp != endlinebyte) pp++;      pp = end_of_line(pp, endptr, &ellength);
815      fwrite(lastmatchrestart, 1, pp - lastmatchrestart + (1 + endlineextra),      fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
816        stdout);      lastmatchrestart = pp;
     lastmatchrestart = pp + 1;  
817      }      }
818    hyphenpending = TRUE;    hyphenpending = TRUE;
819    }    }
# Line 510  if (after_context > 0 && lastmatchnumber Line 822  if (after_context > 0 && lastmatchnumber
822    
823    
824  /*************************************************  /*************************************************
825    *   Apply patterns to subject till one matches   *
826    *************************************************/
827    
828    /* This function is called to run through all patterns, looking for a match. It
829    is used multiple times for the same subject when colouring is enabled, in order
830    to find all possible matches.
831    
832    Arguments:
833      matchptr    the start of the subject
834      length      the length of the subject to match
835      offsets     the offets vector to fill in
836      mrc         address of where to put the result of pcre_exec()
837    
838    Returns:      TRUE if there was a match
839                  FALSE if there was no match
840                  invert if there was a non-fatal error
841    */
842    
843    static BOOL
844    match_patterns(char *matchptr, size_t length, int *offsets, int *mrc)
845    {
846    int i;
847    for (i = 0; i < pattern_count; i++)
848      {
849      *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0,
850        PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
851      if (*mrc >= 0) return TRUE;
852      if (*mrc == PCRE_ERROR_NOMATCH) continue;
853      fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", *mrc);
854      if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
855      fprintf(stderr, "this text:\n");
856      fwrite(matchptr, 1, length, stderr);  /* In case binary zero included */
857      fprintf(stderr, "\n");
858      if (error_count == 0 &&
859          (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT))
860        {
861        fprintf(stderr, "pcregrep: error %d means that a resource limit "
862          "was exceeded\n", *mrc);
863        fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");
864        }
865      if (error_count++ > 20)
866        {
867        fprintf(stderr, "pcregrep: too many errors - abandoned\n");
868        exit(2);
869        }
870      return invert;    /* No more matching; don't show the line again */
871      }
872    
873    return FALSE;  /* No match, no errors */
874    }
875    
876    
877    
878    /*************************************************
879  *            Grep an individual file             *  *            Grep an individual file             *
880  *************************************************/  *************************************************/
881    
# Line 521  be in the middle third most of the time, Line 887  be in the middle third most of the time,
887  "before" context printing.  "before" context printing.
888    
889  Arguments:  Arguments:
890    in           the fopened FILE stream    handle       the fopened FILE stream for a normal file
891                   the gzFile pointer when reading is via libz
892                   the BZFILE pointer when reading is via libbz2
893      frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
894    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
895                 or NULL if the file name is not to be printed                 or NULL if the file name is not to be printed
896                 it cannot be NULL if filenames[_nomatch]_only is set                 it cannot be NULL if filenames[_nomatch]_only is set
897    
898  Returns:       0 if there was at least one match  Returns:       0 if there was at least one match
899                 1 otherwise (no matches)                 1 otherwise (no matches)
900                   2 if there is a read error on a .bz2 file
901  */  */
902    
903  static int  static int
904  pcregrep(FILE *in, char *printname)  pcregrep(void *handle, int frtype, char *printname)
905  {  {
906  int rc = 1;  int rc = 1;
907  int linenumber = 1;  int linenumber = 1;
908  int lastmatchnumber = 0;  int lastmatchnumber = 0;
909  int count = 0;  int count = 0;
910  int offsets[99];  int filepos = 0;
911    int offsets[OFFSET_SIZE];
912  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
913  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
914  char *ptr = buffer;  char *ptr = buffer;
915  char *endptr;  char *endptr;
916  size_t bufflength;  size_t bufflength;
917  BOOL endhyphenpending = FALSE;  BOOL endhyphenpending = FALSE;
918    FILE *in = NULL;                    /* Ensure initialized */
919    
920    #ifdef SUPPORT_LIBZ
921    gzFile ingz = NULL;
922    #endif
923    
924    #ifdef SUPPORT_LIBBZ2
925    BZFILE *inbz2 = NULL;
926    #endif
927    
928    
929    /* Do the first read into the start of the buffer and set up the pointer to end
930    of what we have. In the case of libz, a non-zipped .gz file will be read as a
931    plain file. However, if a .bz2 file isn't actually bzipped, the first read will
932    fail. */
933    
934    #ifdef SUPPORT_LIBZ
935    if (frtype == FR_LIBZ)
936      {
937      ingz = (gzFile)handle;
938      bufflength = gzread (ingz, buffer, 3*MBUFTHIRD);
939      }
940    else
941    #endif
942    
943  /* Do the first read into the start of the buffer and set up the pointer to  #ifdef SUPPORT_LIBBZ2
944  end of what we have. */  if (frtype == FR_LIBBZ2)
945      {
946      inbz2 = (BZFILE *)handle;
947      bufflength = BZ2_bzread(inbz2, buffer, 3*MBUFTHIRD);
948      if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
949      }                                    /* without the cast it is unsigned. */
950    else
951    #endif
952    
953      {
954      in = (FILE *)handle;
955      bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);
956      }
957    
 bufflength = fread(buffer, 1, 3*MBUFTHIRD, in);  
958  endptr = buffer + bufflength;  endptr = buffer + bufflength;
959    
960  /* 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 558  way, the buffer is shifted left and re-f Line 964  way, the buffer is shifted left and re-f
964    
965  while (ptr < endptr)  while (ptr < endptr)
966    {    {
967    int i;    int endlinelength;
968    int mrc = 0;    int mrc = 0;
969    BOOL match = FALSE;    BOOL match;
970      char *matchptr = ptr;
971    char *t = ptr;    char *t = ptr;
972    size_t length, linelength;    size_t length, linelength;
973    
974    /* 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
975    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
976    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
977    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
978    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
979    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
980      first line. */
981    linelength = 0;  
982    while (t < endptr && *t++ != endlinebyte) linelength++;    t = end_of_line(t, endptr, &endlinelength);
983    length = multiline? endptr - ptr : linelength;    linelength = t - ptr - endlinelength;
984      length = multiline? (size_t)(endptr - ptr) : linelength;
985    
986    /* Extra processing for Jeffrey Friedl's debugging. */    /* Extra processing for Jeffrey Friedl's debugging. */
987    
# Line 585  while (ptr < endptr) Line 992  while (ptr < endptr)
992        #include <time.h>        #include <time.h>
993        struct timeval start_time, end_time;        struct timeval start_time, end_time;
994        struct timezone dummy;        struct timezone dummy;
995          int i;
996    
997        if (jfriedl_XT)        if (jfriedl_XT)
998        {        {
# Line 610  while (ptr < endptr) Line 1018  while (ptr < endptr)
1018    
1019    
1020        for (i = 0; i < jfriedl_XR; i++)        for (i = 0; i < jfriedl_XR; i++)
1021            match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0, 0, offsets, 99) >= 0);            match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0,
1022                  PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1023    
1024        if (gettimeofday(&end_time, &dummy) != 0)        if (gettimeofday(&end_time, &dummy) != 0)
1025                perror("bad gettimeofday");                perror("bad gettimeofday");
# Line 624  while (ptr < endptr) Line 1033  while (ptr < endptr)
1033    }    }
1034  #endif  #endif
1035    
1036      /* We come back here after a match when the -o option (only_matching) is set,
1037      in order to find any further matches in the same line. */
1038    
1039    /* Run through all the patterns until one matches. Note that we don't include    ONLY_MATCHING_RESTART:
   the final newline in the subject string. */  
1040    
1041    for (i = 0; i < pattern_count; i++)    /* Run through all the patterns until one matches or there is an error other
1042      {    than NOMATCH. This code is in a subroutine so that it can be re-used for
1043      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,    finding subsequent matches when colouring matched lines. */
1044        offsets, 99);  
1045      if (mrc >= 0) { match = TRUE; break; }    match = match_patterns(matchptr, length, offsets, &mrc);
     if (mrc != PCRE_ERROR_NOMATCH)  
       {  
       fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);  
       if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);  
       fprintf(stderr, "this line:\n");  
       fwrite(ptr, 1, linelength, stderr);   /* In case binary zero included */  
       fprintf(stderr, "\n");  
       if (error_count == 0 &&  
           (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))  
         {  
         fprintf(stderr, "pcregrep: error %d means that a resource limit "  
           "was exceeded\n", mrc);  
         fprintf(stderr, "pcregrep: check your regex for nested unlimited loops\n");  
         }  
       if (error_count++ > 20)  
         {  
         fprintf(stderr, "pcregrep: too many errors - abandoned\n");  
         exit(2);  
         }  
       match = invert;    /* No more matching; don't show the line again */  
       break;  
       }  
     }  
1046    
1047    /* 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. */
1048    
# Line 685  while (ptr < endptr) Line 1072  while (ptr < endptr)
1072      else if (quiet) return 0;      else if (quiet) return 0;
1073    
1074      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
1075      does not pring any context. */      the --file-offsets and --line-offsets options output offsets for the
1076        matching substring (they both force --only-matching). None of these options
1077        prints any context. Afterwards, adjust the start and length, and then jump
1078        back to look for further matches in the same line. If we are in invert
1079        mode, however, nothing is printed - this could be still useful because the
1080        return code is set. */
1081    
1082      else if (only_matching)      else if (only_matching)
1083        {        {
1084        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
1085        if (number) fprintf(stdout, "%d:", linenumber);          {
1086        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
1087        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
1088            if (line_offsets)
1089              fprintf(stdout, "%d,%d", (int)(matchptr + offsets[0] - ptr),
1090                offsets[1] - offsets[0]);
1091            else if (file_offsets)
1092              fprintf(stdout, "%d,%d", (int)(filepos + matchptr + offsets[0] - ptr),
1093                offsets[1] - offsets[0]);
1094            else
1095              {
1096              if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1097              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1098              if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1099              }
1100            fprintf(stdout, "\n");
1101            matchptr += offsets[1];
1102            length -= offsets[1];
1103            match = FALSE;
1104            goto ONLY_MATCHING_RESTART;
1105            }
1106        }        }
1107    
1108      /* 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 706  while (ptr < endptr) Line 1116  while (ptr < endptr)
1116    
1117        if (after_context > 0 && lastmatchnumber > 0)        if (after_context > 0 && lastmatchnumber > 0)
1118          {          {
1119            int ellength;
1120          int linecount = 0;          int linecount = 0;
1121          char *p = lastmatchrestart;          char *p = lastmatchrestart;
1122    
1123          while (p < ptr && linecount < after_context)          while (p < ptr && linecount < after_context)
1124            {            {
1125            while (*p != endlinebyte) p++;            p = end_of_line(p, ptr, &ellength);
           p++;  
1126            linecount++;            linecount++;
1127            }            }
1128    
# Line 725  while (ptr < endptr) Line 1135  while (ptr < endptr)
1135            char *pp = lastmatchrestart;            char *pp = lastmatchrestart;
1136            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1137            if (number) fprintf(stdout, "%d-", lastmatchnumber++);            if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1138            while (*pp != endlinebyte) pp++;            pp = end_of_line(pp, endptr, &ellength);
1139            fwrite(lastmatchrestart, 1, pp - lastmatchrestart +            fwrite(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1140              (1 + endlineextra), stdout);            lastmatchrestart = pp;
           lastmatchrestart = pp + 1;  
1141            }            }
1142          if (lastmatchrestart != ptr) hyphenpending = TRUE;          if (lastmatchrestart != ptr) hyphenpending = TRUE;
1143          }          }
# Line 754  while (ptr < endptr) Line 1163  while (ptr < endptr)
1163                 linecount < before_context)                 linecount < before_context)
1164            {            {
1165            linecount++;            linecount++;
1166            p--;            p = previous_line(p, buffer);
           while (p > buffer && p[-1] != endlinebyte) p--;  
1167            }            }
1168    
1169          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)          if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
# Line 763  while (ptr < endptr) Line 1171  while (ptr < endptr)
1171    
1172          while (p < ptr)          while (p < ptr)
1173            {            {
1174              int ellength;
1175            char *pp = p;            char *pp = p;
1176            if (printname != NULL) fprintf(stdout, "%s-", printname);            if (printname != NULL) fprintf(stdout, "%s-", printname);
1177            if (number) fprintf(stdout, "%d-", linenumber - linecount--);            if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1178            while (*pp != endlinebyte) pp++;            pp = end_of_line(pp, endptr, &ellength);
1179            fwrite(p, 1, pp - p + (1 + endlineextra), stdout);            fwrite(p, 1, pp - p, stdout);
1180            p = pp + 1;            p = pp;
1181            }            }
1182          }          }
1183    
# Line 783  while (ptr < endptr) Line 1192  while (ptr < endptr)
1192    
1193        /* 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
1194        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
1195        line number appropriately. Because the PCRE_FIRSTLINE option is set, the        line number appropriately, but only when there actually was a match
1196        start of the match will always be before the first newline sequence. */        (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1197          the match will always be before the first newline sequence. */
1198    
1199        if (multiline)        if (multiline)
1200          {          {
1201          char *endmatch = ptr + offsets[1];          int ellength;
1202          t = ptr;          char *endmatch = ptr;
1203          while (t < endmatch) { if (*t++ == endlinebyte) linenumber++; }          if (!invert)
1204          while (endmatch < endptr && *endmatch != endlinebyte) endmatch++;            {
1205          linelength = endmatch - ptr;            endmatch += offsets[1];
1206              t = ptr;
1207              while (t < endmatch)
1208                {
1209                t = end_of_line(t, endptr, &ellength);
1210                if (t <= endmatch) linenumber++; else break;
1211                }
1212              }
1213            endmatch = end_of_line(endmatch, endptr, &ellength);
1214            linelength = endmatch - ptr - ellength;
1215          }          }
1216    
1217        /*** 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 814  while (ptr < endptr) Line 1233  while (ptr < endptr)
1233        else        else
1234  #endif  #endif
1235    
1236        /* We have to split the line(s) up if colouring. */        /* We have to split the line(s) up if colouring, and search for further
1237          matches. */
1238    
1239        if (do_colour)        if (do_colour)
1240          {          {
1241            int last_offset = 0;
1242          fwrite(ptr, 1, offsets[0], stdout);          fwrite(ptr, 1, offsets[0], stdout);
1243          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1244          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1245          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1246          fwrite(ptr + offsets[1], 1, linelength - offsets[1], stdout);          for (;;)
1247              {
1248              last_offset += offsets[1];
1249              matchptr += offsets[1];
1250              length -= offsets[1];
1251              if (!match_patterns(matchptr, length, offsets, &mrc)) break;
1252              fwrite(matchptr, 1, offsets[0], stdout);
1253              fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1254              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1255              fprintf(stdout, "%c[00m", 0x1b);
1256              }
1257            fwrite(ptr + last_offset, 1, (linelength + endlinelength) - last_offset,
1258              stdout);
1259          }          }
       else fwrite(ptr, 1, linelength, stdout);  
1260    
1261        fprintf(stdout, "\n");        /* Not colouring; no need to search for further matches */
1262    
1263          else fwrite(ptr, 1, linelength + endlinelength, stdout);
1264        }        }
1265    
1266      /* End of doing what has to be done for a match */      /* End of doing what has to be done for a match */
# Line 836  while (ptr < endptr) Line 1270  while (ptr < endptr)
1270      /* Remember where the last match happened for after_context. We remember      /* Remember where the last match happened for after_context. We remember
1271      where we are about to restart, and that line's number. */      where we are about to restart, and that line's number. */
1272    
1273      lastmatchrestart = ptr + linelength + 1;      lastmatchrestart = ptr + linelength + endlinelength;
1274      lastmatchnumber = linenumber + 1;      lastmatchnumber = linenumber + 1;
1275      }      }
1276    
1277    /* Advance to after the newline and increment the line number. */    /* For a match in multiline inverted mode (which of course did not cause
1278      anything to be printed), we have to move on to the end of the match before
1279      proceeding. */
1280    
1281      if (multiline && invert && match)
1282        {
1283        int ellength;
1284        char *endmatch = ptr + offsets[1];
1285        t = ptr;
1286        while (t < endmatch)
1287          {
1288          t = end_of_line(t, endptr, &ellength);
1289          if (t <= endmatch) linenumber++; else break;
1290          }
1291        endmatch = end_of_line(endmatch, endptr, &ellength);
1292        linelength = endmatch - ptr - ellength;
1293        }
1294    
1295    ptr += linelength + 1;    /* Advance to after the newline and increment the line number. The file
1296      offset to the current line is maintained in filepos. */
1297    
1298      ptr += linelength + endlinelength;
1299      filepos += linelength + endlinelength;
1300    linenumber++;    linenumber++;
1301    
1302    /* 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 864  while (ptr < endptr) Line 1318  while (ptr < endptr)
1318    
1319      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);      memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD);
1320      ptr -= MBUFTHIRD;      ptr -= MBUFTHIRD;
1321    
1322    #ifdef SUPPORT_LIBZ
1323        if (frtype == FR_LIBZ)
1324          bufflength = 2*MBUFTHIRD +
1325            gzread (ingz, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1326        else
1327    #endif
1328    
1329    #ifdef SUPPORT_LIBBZ2
1330        if (frtype == FR_LIBBZ2)
1331          bufflength = 2*MBUFTHIRD +
1332            BZ2_bzread(inbz2, buffer + 2*MBUFTHIRD, MBUFTHIRD);
1333        else
1334    #endif
1335    
1336      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);      bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in);
1337    
1338      endptr = buffer + bufflength;      endptr = buffer + bufflength;
1339    
1340      /* Adjust any last match point */      /* Adjust any last match point */
# Line 928  grep_or_recurse(char *pathname, BOOL dir Line 1398  grep_or_recurse(char *pathname, BOOL dir
1398  {  {
1399  int rc = 1;  int rc = 1;
1400  int sep;  int sep;
1401  FILE *in;  int frtype;
1402    int pathlen;
1403    void *handle;
1404    FILE *in = NULL;           /* Ensure initialized */
1405    
1406    #ifdef SUPPORT_LIBZ
1407    gzFile ingz = NULL;
1408    #endif
1409    
1410    #ifdef SUPPORT_LIBBZ2
1411    BZFILE *inbz2 = NULL;
1412    #endif
1413    
1414  /* If the file name is "-" we scan stdin */  /* If the file name is "-" we scan stdin */
1415    
1416  if (strcmp(pathname, "-") == 0)  if (strcmp(pathname, "-") == 0)
1417    {    {
1418    return pcregrep(stdin,    return pcregrep(stdin, FR_PLAIN,
1419      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?      (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1420        stdin_name : NULL);        stdin_name : NULL);
1421    }    }
1422    
   
1423  /* 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
1424  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
1425  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
1426    system-specific. */
1427    
1428  if ((sep = isdirectory(pathname)) != 0)  if ((sep = isdirectory(pathname)) != 0)
1429    {    {
# Line 963  if ((sep = isdirectory(pathname)) != 0) Line 1444  if ((sep = isdirectory(pathname)) != 0)
1444    
1445      while ((nextfile = readdirectory(dir)) != NULL)      while ((nextfile = readdirectory(dir)) != NULL)
1446        {        {
1447        int frc, blen;        int frc, nflen;
1448        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);        sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1449        blen = strlen(buffer);        nflen = strlen(nextfile);
1450    
1451          if (isdirectory(buffer))
1452            {
1453            if (exclude_dir_compiled != NULL &&
1454                pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1455              continue;
1456    
1457            if (include_dir_compiled != NULL &&
1458                pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1459              continue;
1460            }
1461          else
1462            {
1463            if (exclude_compiled != NULL &&
1464                pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1465              continue;
1466    
1467        if (exclude_compiled != NULL &&          if (include_compiled != NULL &&
1468            pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0)              pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1469          continue;            continue;
1470            }
       if (include_compiled != NULL &&  
           pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0)  
         continue;  
1471    
1472        frc = grep_or_recurse(buffer, dir_recurse, FALSE);        frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1473        if (frc > 1) rc = frc;        if (frc > 1) rc = frc;
# Line 996  skipping was not requested. The scan pro Line 1490  skipping was not requested. The scan pro
1490  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
1491  the file name, or the filename was forced (-H). */  the file name, or the filename was forced (-H). */
1492    
1493  in = fopen(pathname, "r");  pathlen = strlen(pathname);
1494  if (in == NULL)  
1495    /* Open using zlib if it is supported and the file name ends with .gz. */
1496    
1497    #ifdef SUPPORT_LIBZ
1498    if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1499      {
1500      ingz = gzopen(pathname, "rb");
1501      if (ingz == NULL)
1502        {
1503        if (!silent)
1504          fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1505            strerror(errno));
1506        return 2;
1507        }
1508      handle = (void *)ingz;
1509      frtype = FR_LIBZ;
1510      }
1511    else
1512    #endif
1513    
1514    /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1515    
1516    #ifdef SUPPORT_LIBBZ2
1517    if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1518      {
1519      inbz2 = BZ2_bzopen(pathname, "rb");
1520      handle = (void *)inbz2;
1521      frtype = FR_LIBBZ2;
1522      }
1523    else
1524    #endif
1525    
1526    /* Otherwise use plain fopen(). The label is so that we can come back here if
1527    an attempt to read a .bz2 file indicates that it really is a plain file. */
1528    
1529    #ifdef SUPPORT_LIBBZ2
1530    PLAIN_FILE:
1531    #endif
1532      {
1533      in = fopen(pathname, "rb");
1534      handle = (void *)in;
1535      frtype = FR_PLAIN;
1536      }
1537    
1538    /* All the opening methods return errno when they fail. */
1539    
1540    if (handle == NULL)
1541    {    {
1542    if (!silent)    if (!silent)
1543      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
# Line 1005  if (in == NULL) Line 1545  if (in == NULL)
1545    return 2;    return 2;
1546    }    }
1547    
1548  rc = pcregrep(in, (filenames > FN_DEFAULT ||  /* Now grep the file */
1549    
1550    rc = pcregrep(handle, frtype, (filenames > FN_DEFAULT ||
1551    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);    (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1552    
1553    /* Close in an appropriate manner. */
1554    
1555    #ifdef SUPPORT_LIBZ
1556    if (frtype == FR_LIBZ)
1557      gzclose(ingz);
1558    else
1559    #endif
1560    
1561    /* If it is a .bz2 file and the result is 2, it means that the first attempt to
1562    read failed. If the error indicates that the file isn't in fact bzipped, try
1563    again as a normal file. */
1564    
1565    #ifdef SUPPORT_LIBBZ2
1566    if (frtype == FR_LIBBZ2)
1567      {
1568      if (rc == 2)
1569        {
1570        int errnum;
1571        const char *err = BZ2_bzerror(inbz2, &errnum);
1572        if (errnum == BZ_DATA_ERROR_MAGIC)
1573          {
1574          BZ2_bzclose(inbz2);
1575          goto PLAIN_FILE;
1576          }
1577        else if (!silent)
1578          fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1579            pathname, err);
1580        }
1581      BZ2_bzclose(inbz2);
1582      }
1583    else
1584    #endif
1585    
1586    /* Normal file close */
1587    
1588  fclose(in);  fclose(in);
1589    
1590    /* Pass back the yield from pcregrep(). */
1591    
1592  return rc;  return rc;
1593  }  }
1594    
# Line 1029  for (op = optionlist; op->one_char != 0; Line 1609  for (op = optionlist; op->one_char != 0;
1609    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1610    }    }
1611  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1612  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1613      "options.\n");
1614  return rc;  return rc;
1615  }  }
1616    
# Line 1048  option_item *op; Line 1629  option_item *op;
1629  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1630  printf("Search for PATTERN in each FILE or standard input.\n");  printf("Search for PATTERN in each FILE or standard input.\n");
1631  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");
1632  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");  
1633    
1634    #ifdef SUPPORT_LIBZ
1635    printf("Files whose names end in .gz are read using zlib.\n");
1636    #endif
1637    
1638    #ifdef SUPPORT_LIBBZ2
1639    printf("Files whose names end in .bz2 are read using bzlib2.\n");
1640    #endif
1641    
1642    #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1643    printf("Other files and the standard input are read as plain files.\n\n");
1644    #else
1645    printf("All files are read as plain files, without any interpretation.\n\n");
1646    #endif
1647    
1648    printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1649  printf("Options:\n");  printf("Options:\n");
1650    
1651  for (op = optionlist; op->one_char != 0; op++)  for (op = optionlist; op->one_char != 0; op++)
# Line 1058  for (op = optionlist; op->one_char != 0; Line 1653  for (op = optionlist; op->one_char != 0;
1653    int n;    int n;
1654    char s[4];    char s[4];
1655    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, "   ");
1656    printf("  %s --%s%n", s, op->long_name, &n);    n = 30 - printf("  %s --%s", s, op->long_name);
   n = 30 - n;  
1657    if (n < 1) n = 1;    if (n < 1) n = 1;
1658    printf("%.*s%s\n", n, "                    ", op->help_text);    printf("%.*s%s\n", n, "                    ", op->help_text);
1659    }    }
# Line 1084  handle_option(int letter, int options) Line 1678  handle_option(int letter, int options)
1678  {  {
1679  switch(letter)  switch(letter)
1680    {    {
1681      case N_FOFFSETS: file_offsets = TRUE; break;
1682    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1683      case N_LOFFSETS: line_offsets = number = TRUE; break;
1684    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1685    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1686    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
# Line 1098  switch(letter) Line 1694  switch(letter)
1694    case 'q': quiet = TRUE; break;    case 'q': quiet = TRUE; break;
1695    case 'r': dee_action = dee_RECURSE; break;    case 'r': dee_action = dee_RECURSE; break;
1696    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
1697    case 'u': options |= PCRE_UTF8; break;    case 'u': options |= PCRE_UTF8; utf8 = TRUE; break;
1698    case 'v': invert = TRUE; break;    case 'v': invert = TRUE; break;
1699    case 'w': process_options |= PO_WORD_MATCH; break;    case 'w': process_options |= PO_WORD_MATCH; break;
1700    case 'x': process_options |= PO_LINE_MATCH; break;    case 'x': process_options |= PO_LINE_MATCH; break;
1701    
1702    case 'V':    case 'V':
1703    fprintf(stderr, "pcregrep version %s using ", VERSION);    fprintf(stderr, "pcregrep version %s\n", pcre_version());
   fprintf(stderr, "PCRE version %s\n", pcre_version());  
1704    exit(0);    exit(0);
1705    break;    break;
1706    
# Line 1181  sprintf(buffer, "%s%.*s%s", prefix[proce Line 1776  sprintf(buffer, "%s%.*s%s", prefix[proce
1776    suffix[process_options]);    suffix[process_options]);
1777  pattern_list[pattern_count] =  pattern_list[pattern_count] =
1778    pcre_compile(buffer, options, &error, &errptr, pcretables);    pcre_compile(buffer, options, &error, &errptr, pcretables);
1779  if (pattern_list[pattern_count++] != NULL) return TRUE;  if (pattern_list[pattern_count] != NULL)
1780      {
1781      pattern_count++;
1782      return TRUE;
1783      }
1784    
1785  /* Handle compile errors */  /* Handle compile errors */
1786    
# Line 1231  compile_pattern(char *pattern, int optio Line 1830  compile_pattern(char *pattern, int optio
1830  {  {
1831  if ((process_options & PO_FIXED_STRINGS) != 0)  if ((process_options & PO_FIXED_STRINGS) != 0)
1832    {    {
1833      char *eop = pattern + strlen(pattern);
1834    char buffer[MBUFTHIRD];    char buffer[MBUFTHIRD];
1835    for(;;)    for(;;)
1836      {      {
1837      char *p = strchr(pattern, endlinebyte);      int ellength;
1838      if (p == NULL)      char *p = end_of_line(pattern, eop, &ellength);
1839        if (ellength == 0)
1840        return compile_single_pattern(pattern, options, filename, count);        return compile_single_pattern(pattern, options, filename, count);
1841      sprintf(buffer, "%.*s", p - pattern - endlineextra, pattern);      sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern);
1842      pattern = p + 1;      pattern = p;
1843      if (!compile_single_pattern(buffer, options, filename, count))      if (!compile_single_pattern(buffer, options, filename, count))
1844        return FALSE;        return FALSE;
1845      }      }
# Line 1261  int i, j; Line 1862  int i, j;
1862  int rc = 1;  int rc = 1;
1863  int pcre_options = 0;  int pcre_options = 0;
1864  int cmd_pattern_count = 0;  int cmd_pattern_count = 0;
1865    int hint_count = 0;
1866  int errptr;  int errptr;
1867  BOOL only_one_at_top;  BOOL only_one_at_top;
1868  char *patterns[MAX_PATTERN_COUNT];  char *patterns[MAX_PATTERN_COUNT];
1869  const char *locale_from = "--locale";  const char *locale_from = "--locale";
1870  const char *error;  const char *error;
1871    
1872  /* Set the default line ending value from the default in the PCRE library. */  /* Set the default line ending value from the default in the PCRE library;
1873    "lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf".
1874    Note that the return values from pcre_config(), though derived from the ASCII
1875    codes, are the same in EBCDIC environments, so we must use the actual values
1876    rather than escapes such as as '\r'. */
1877    
1878  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);  (void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
1879  switch(i)  switch(i)
1880    {    {
1881    default:                 newline = (char *)"lf"; break;    default:               newline = (char *)"lf"; break;
1882    case '\r':               newline = (char *)"cr"; break;    case 13:               newline = (char *)"cr"; break;
1883    case ('\r' << 8) | '\n': newline = (char *)"crlf"; break;    case (13 << 8) | 10:   newline = (char *)"crlf"; break;
1884      case -1:               newline = (char *)"any"; break;
1885      case -2:               newline = (char *)"anycrlf"; break;
1886    }    }
1887    
1888  /* Process the options */  /* Process the options */
# Line 1332  for (i = 1; i < argc; i++) Line 1940  for (i = 1; i < argc; i++)
1940          else                 /* Special case xxx=data */          else                 /* Special case xxx=data */
1941            {            {
1942            int oplen = equals - op->long_name;            int oplen = equals - op->long_name;
1943            int arglen = (argequals == NULL)? strlen(arg) : argequals - arg;            int arglen = (argequals == NULL)? (int)strlen(arg) : argequals - arg;
1944            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)            if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
1945              {              {
1946              option_data = arg + arglen;              option_data = arg + arglen;
# Line 1351  for (i = 1; i < argc; i++) Line 1959  for (i = 1; i < argc; i++)
1959          char buff2[24];          char buff2[24];
1960          int baselen = opbra - op->long_name;          int baselen = opbra - op->long_name;
1961          sprintf(buff1, "%.*s", baselen, op->long_name);          sprintf(buff1, "%.*s", baselen, op->long_name);
1962          sprintf(buff2, "%s%.*s", buff1, strlen(op->long_name) - baselen - 2,          sprintf(buff2, "%s%.*s", buff1,
1963            opbra + 1);            (int)strlen(op->long_name) - baselen - 2, opbra + 1);
1964          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)          if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0)
1965            break;            break;
1966          }          }
# Line 1511  if (both_context > 0) Line 2119  if (both_context > 0)
2119    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
2120    }    }
2121    
2122    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2123    However, the latter two set the only_matching flag. */
2124    
2125    if ((only_matching && (file_offsets || line_offsets)) ||
2126        (file_offsets && line_offsets))
2127      {
2128      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2129        "and/or --line-offsets\n");
2130      exit(usage(2));
2131      }
2132    
2133    if (file_offsets || line_offsets) only_matching = TRUE;
2134    
2135  /* 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
2136  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */
2137    
# Line 1565  if (colour_option != NULL && strcmp(colo Line 2186  if (colour_option != NULL && strcmp(colo
2186  if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)  if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)
2187    {    {
2188    pcre_options |= PCRE_NEWLINE_CR;    pcre_options |= PCRE_NEWLINE_CR;
2189    endlinebyte = '\r';    endlinetype = EL_CR;
2190    }    }
2191  else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)  else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)
2192    {    {
2193    pcre_options |= PCRE_NEWLINE_LF;    pcre_options |= PCRE_NEWLINE_LF;
2194      endlinetype = EL_LF;
2195    }    }
2196  else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)  else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)
2197    {    {
2198    pcre_options |= PCRE_NEWLINE_CRLF;    pcre_options |= PCRE_NEWLINE_CRLF;
2199    endlineextra = 1;    endlinetype = EL_CRLF;
2200      }
2201    else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0)
2202      {
2203      pcre_options |= PCRE_NEWLINE_ANY;
2204      endlinetype = EL_ANY;
2205      }
2206    else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0)
2207      {
2208      pcre_options |= PCRE_NEWLINE_ANYCRLF;
2209      endlinetype = EL_ANYCRLF;
2210    }    }
2211  else  else
2212    {    {
# Line 1630  hints_list = (pcre_extra **)malloc(MAX_P Line 2262  hints_list = (pcre_extra **)malloc(MAX_P
2262  if (pattern_list == NULL || hints_list == NULL)  if (pattern_list == NULL || hints_list == NULL)
2263    {    {
2264    fprintf(stderr, "pcregrep: malloc failed\n");    fprintf(stderr, "pcregrep: malloc failed\n");
2265    return 2;    goto EXIT2;
2266    }    }
2267    
2268  /* 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 1649  for (j = 0; j < cmd_pattern_count; j++) Line 2281  for (j = 0; j < cmd_pattern_count; j++)
2281    {    {
2282    if (!compile_pattern(patterns[j], pcre_options, NULL,    if (!compile_pattern(patterns[j], pcre_options, NULL,
2283         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))         (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))
2284      return 2;      goto EXIT2;
2285    }    }
2286    
2287  /* Compile the regular expressions that are provided in a file. */  /* Compile the regular expressions that are provided in a file. */
# Line 1673  if (pattern_filename != NULL) Line 2305  if (pattern_filename != NULL)
2305        {        {
2306        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,        fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,
2307          strerror(errno));          strerror(errno));
2308        return 2;        goto EXIT2;
2309        }        }
2310      filename = pattern_filename;      filename = pattern_filename;
2311      }      }
# Line 1686  if (pattern_filename != NULL) Line 2318  if (pattern_filename != NULL)
2318      linenumber++;      linenumber++;
2319      if (buffer[0] == 0) continue;   /* Skip blank lines */      if (buffer[0] == 0) continue;   /* Skip blank lines */
2320      if (!compile_pattern(buffer, pcre_options, filename, linenumber))      if (!compile_pattern(buffer, pcre_options, filename, linenumber))
2321        return 2;        goto EXIT2;
2322      }      }
2323    
2324    if (f != stdin) fclose(f);    if (f != stdin) fclose(f);
# Line 1702  for (j = 0; j < pattern_count; j++) Line 2334  for (j = 0; j < pattern_count; j++)
2334      char s[16];      char s[16];
2335      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);
2336      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);      fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
2337      return 2;      goto EXIT2;
2338      }      }
2339      hint_count++;
2340    }    }
2341    
2342  /* If there are include or exclude patterns, compile them. */  /* If there are include or exclude patterns, compile them. */
# Line 1716  if (exclude_pattern != NULL) Line 2349  if (exclude_pattern != NULL)
2349      {      {
2350      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",
2351        errptr, error);        errptr, error);
2352      return 2;      goto EXIT2;
2353      }      }
2354    }    }
2355    
# Line 1728  if (include_pattern != NULL) Line 2361  if (include_pattern != NULL)
2361      {      {
2362      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",      fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",
2363        errptr, error);        errptr, error);
2364      return 2;      goto EXIT2;
2365        }
2366      }
2367    
2368    if (exclude_dir_pattern != NULL)
2369      {
2370      exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2371        pcretables);
2372      if (exclude_dir_compiled == NULL)
2373        {
2374        fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2375          errptr, error);
2376        goto EXIT2;
2377        }
2378      }
2379    
2380    if (include_dir_pattern != NULL)
2381      {
2382      include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2383        pcretables);
2384      if (include_dir_compiled == NULL)
2385        {
2386        fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2387          errptr, error);
2388        goto EXIT2;
2389      }      }
2390    }    }
2391    
2392  /* 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. */
2393    
2394  if (i >= argc)  if (i >= argc)
2395    return pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL);    {
2396      rc = pcregrep(stdin, FR_PLAIN, (filenames > FN_DEFAULT)? stdin_name : NULL);
2397      goto EXIT;
2398      }
2399    
2400  /* Otherwise, work through the remaining arguments as files or directories.  /* Otherwise, work through the remaining arguments as files or directories.
2401  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 1752  for (; i < argc; i++) Line 2412  for (; i < argc; i++)
2412      else if (frc == 0 && rc == 1) rc = 0;      else if (frc == 0 && rc == 1) rc = 0;
2413    }    }
2414    
2415    EXIT:
2416    if (pattern_list != NULL)
2417      {
2418      for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
2419      free(pattern_list);
2420      }
2421    if (hints_list != NULL)
2422      {
2423      for (i = 0; i < hint_count; i++) free(hints_list[i]);
2424      free(hints_list);
2425      }
2426  return rc;  return rc;
2427    
2428    EXIT2:
2429    rc = 2;
2430    goto EXIT;
2431  }  }
2432    
2433  /* End of pcregrep */  /* End of pcregrep */

Legend:
Removed from v.91  
changed lines
  Added in v.419

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12