1/*************************************************
2*               pcregrep program                 *
3*************************************************/
4
5/* This is a grep program that uses the PCRE regular expression library to do
6its pattern matching. On a Unix or Win32 system it can recurse into
7directories.
8
9           Copyright (c) 1997-2012 University of Cambridge
10
11-----------------------------------------------------------------------------
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14
15    * Redistributions of source code must retain the above copyright notice,
16      this list of conditions and the following disclaimer.
17
18    * Redistributions in binary form must reproduce the above copyright
19      notice, this list of conditions and the following disclaimer in the
20      documentation and/or other materials provided with the distribution.
21
22    * Neither the name of the University of Cambridge nor the names of its
23      contributors may be used to endorse or promote products derived from
24      this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36POSSIBILITY OF SUCH DAMAGE.
37-----------------------------------------------------------------------------
38*/
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include <ctype.h>
45#include <locale.h>
46#include <stdio.h>
47#include <string.h>
48#include <stdlib.h>
49#include <errno.h>
50
51#include <sys/types.h>
52#include <sys/stat.h>
53
54#ifdef HAVE_UNISTD_H
55#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
66#include "pcre.h"
67
68#define FALSE 0
69#define TRUE 1
70
71typedef int BOOL;
72
73#define MAX_PATTERN_COUNT 100
74#define OFFSET_SIZE 99
75
76#if BUFSIZ > 8192
77#define PATBUFSIZE BUFSIZ
78#else
79#define PATBUFSIZE 8192
80#endif
81
82/* Values for the "filenames" variable, which specifies options for file name
83output. The order is important; it is assumed that a file name is wanted for
84all values greater than FN_DEFAULT. */
85
86enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE };
87
88/* File reading styles */
89
90enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };
91
92/* Actions for the -d and -D options */
93
94enum { dee_READ, dee_SKIP, dee_RECURSE };
95enum { DEE_READ, DEE_SKIP };
96
97/* Actions for special processing options (flag bits) */
98
99#define PO_WORD_MATCH     0x0001
100#define PO_LINE_MATCH     0x0002
101#define PO_FIXED_STRINGS  0x0004
102
103/* Line ending types */
104
105enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };
106
107/* Binary file options */
108
109enum { BIN_BINARY, BIN_NOMATCH, BIN_TEXT };
110
111/* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some
112environments), a warning is issued if the value of fwrite() is ignored.
113Unfortunately, casting to (void) does not suppress the warning. To get round
114this, we use a macro that compiles a fudge. Oddly, this does not also seem to
115apply to fprintf(). */
116
117#define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}
118
119
120
121/*************************************************
122*               Global variables                 *
123*************************************************/
124
125/* Jeffrey Friedl has some debugging requirements that are not part of the
126regular code. */
127
128#ifdef JFRIEDL_DEBUG
129static int S_arg = -1;
130static unsigned int jfriedl_XR = 0; /* repeat regex attempt this many times */
131static unsigned int jfriedl_XT = 0; /* replicate text this many times */
132static const char *jfriedl_prefix = "";
133static const char *jfriedl_postfix = "";
134#endif
135
136static int  endlinetype;
137
138static char *colour_string = (char *)"1;31";
139static char *colour_option = NULL;
140static char *dee_option = NULL;
141static char *DEE_option = NULL;
142static char *main_buffer = NULL;
143static char *newline = NULL;
144static char *pattern_filename = NULL;
145static char *stdin_name = (char *)"(standard input)";
146static char *locale = NULL;
147
148static const unsigned char *pcretables = NULL;
149
150static int  pattern_count = 0;
151static pcre **pattern_list = NULL;
152static pcre_extra **hints_list = NULL;
153
154static char *file_list = NULL;
155static char *include_pattern = NULL;
156static char *exclude_pattern = NULL;
157static char *include_dir_pattern = NULL;
158static char *exclude_dir_pattern = NULL;
159
160static pcre *include_compiled = NULL;
161static pcre *exclude_compiled = NULL;
162static pcre *include_dir_compiled = NULL;
163static pcre *exclude_dir_compiled = NULL;
164
165static int after_context = 0;
166static int before_context = 0;
167static int binary_files = BIN_BINARY;
168static int both_context = 0;
169static int bufthird = PCREGREP_BUFSIZE;
170static int bufsize = 3*PCREGREP_BUFSIZE;
171static int dee_action = dee_READ;
172static int DEE_action = DEE_READ;
173static int error_count = 0;
174static int filenames = FN_DEFAULT;
175static int only_matching = -1;
176static int process_options = 0;
177
178#ifdef SUPPORT_PCREGREP_JIT
179static int study_options = PCRE_STUDY_JIT_COMPILE;
180#else
181static int study_options = 0;
182#endif
183
184static unsigned long int match_limit = 0;
185static unsigned long int match_limit_recursion = 0;
186
187static BOOL count_only = FALSE;
188static BOOL do_colour = FALSE;
189static BOOL file_offsets = FALSE;
190static BOOL hyphenpending = FALSE;
191static BOOL invert = FALSE;
192static BOOL line_buffered = FALSE;
193static BOOL line_offsets = FALSE;
194static BOOL multiline = FALSE;
195static BOOL number = FALSE;
196static BOOL omit_zero_count = FALSE;
197static BOOL resource_error = FALSE;
198static BOOL quiet = FALSE;
199static BOOL silent = FALSE;
200static BOOL utf8 = FALSE;
201
202/* Structure for options and list of them */
203
204enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
205       OP_OP_NUMBER, OP_PATLIST, OP_BINFILES };
206
207typedef struct option_item {
208  int type;
209  int one_char;
210  void *dataptr;
211  const char *long_name;
212  const char *help_text;
213} option_item;
214
215/* Options without a single-letter equivalent get a negative value. This can be
216used to identify them. */
217
218#define N_COLOUR       (-1)
219#define N_EXCLUDE      (-2)
220#define N_EXCLUDE_DIR  (-3)
221#define N_HELP         (-4)
222#define N_INCLUDE      (-5)
223#define N_INCLUDE_DIR  (-6)
224#define N_LABEL        (-7)
225#define N_LOCALE       (-8)
226#define N_NULL         (-9)
227#define N_LOFFSETS     (-10)
228#define N_FOFFSETS     (-11)
229#define N_LBUFFER      (-12)
230#define N_M_LIMIT      (-13)
231#define N_M_LIMIT_REC  (-14)
232#define N_BUFSIZE      (-15)
233#define N_NOJIT        (-16)
234#define N_FILE_LIST    (-17)
235#define N_BINARY_FILES (-18)
236
237static option_item optionlist[] = {
238  { OP_NODATA,     N_NULL,   NULL,              "",              "terminate options" },
239  { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
240  { OP_NUMBER,     'A',      &after_context,    "after-context=number", "set number of following context lines" },
241  { OP_NODATA,     'a',      NULL,              "text",          "treat binary files as text" },
242  { OP_NUMBER,     'B',      &before_context,   "before-context=number", "set number of prior context lines" },
243  { OP_BINFILES,   N_BINARY_FILES, NULL,        "binary-files=word", "set treatment of binary files" },
244  { OP_NUMBER,     N_BUFSIZE,&bufthird,         "buffer-size=number", "set processing buffer size parameter" },
245  { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
246  { OP_OP_STRING,  N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
247  { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
248  { OP_NODATA,     'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
249  { OP_STRING,     'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },
250  { OP_STRING,     'd',      &dee_option,       "directories=action", "how to handle directories" },
251  { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
252  { OP_NODATA,     'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },
253  { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
254  { OP_STRING,     N_FILE_LIST, &file_list,     "file-list=path","read files to search from file" },
255  { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
256  { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
257  { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
258  { OP_NODATA,     'I',      NULL,              "",              "treat binary files as not matching (ignore)" },
259  { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
260#ifdef SUPPORT_PCREGREP_JIT
261  { OP_NODATA,     N_NOJIT,  NULL,              "no-jit",        "do not use just-in-time compiler optimization" },
262#else
263  { OP_NODATA,     N_NOJIT,  NULL,              "no-jit",        "ignored: this pcregrep does not support JIT" },
264#endif
265  { OP_NODATA,     'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
266  { OP_NODATA,     'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
267  { OP_STRING,     N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
268  { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
269  { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
270  { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
271  { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
272  { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
273  { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
274  { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
275  { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
276  { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
277  { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
278  { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
279  { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
280  { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
281  { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
282  { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },
283
284  /* These two were accidentally implemented with underscores instead of
285  hyphens in the option names. As this was not discovered for several releases,
286  the incorrect versions are left in the table for compatibility. However, the
287  --help function misses out any option that has an underscore in its name. */
288
289  { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
290  { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
291
292#ifdef JFRIEDL_DEBUG
293  { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },
294#endif
295  { OP_NODATA,    's',      NULL,              "no-messages",   "suppress error messages" },
296  { OP_NODATA,    'u',      NULL,              "utf-8",         "use UTF-8 mode" },
297  { OP_NODATA,    'V',      NULL,              "version",       "print version information and exit" },
298  { OP_NODATA,    'v',      NULL,              "invert-match",  "select non-matching lines" },
299  { OP_NODATA,    'w',      NULL,              "word-regex(p)", "force patterns to match only as words"  },
300  { OP_NODATA,    'x',      NULL,              "line-regex(p)", "force patterns to match only whole lines" },
301  { OP_NODATA,    0,        NULL,               NULL,            NULL }
302};
303
304/* Tables for prefixing and suffixing patterns, according to the -w, -x, and -F
305options. These set the 1, 2, and 4 bits in process_options, respectively. Note
306that the combination of -w and -x has the same effect as -x on its own, so we
307can treat them as the same. */
308
309static const char *prefix[] = {
310  "", "\\b", "^(?:", "^(?:", "\\Q", "\\b\\Q", "^(?:\\Q", "^(?:\\Q" };
311
312static const char *suffix[] = {
313  "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };
314
315/* UTF-8 tables - used only when the newline setting is "any". */
316
317const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
318
319const char utf8_table4[] = {
320  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
321  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
322  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
323  3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
324
325
326
327/*************************************************
328*         Exit from the program                  *
329*************************************************/
330
331/* If there has been a resource error, give a suitable message.
332
333Argument:  the return code
334Returns:   does not return
335*/
336
337static void
338pcregrep_exit(int rc)
339{
340if (resource_error)
341  {
342  fprintf(stderr, "pcregrep: Error %d, %d or %d means that a resource limit "
343    "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT,
344    PCRE_ERROR_JIT_STACKLIMIT);
345  fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n");
346  }
347
348exit(rc);
349}
350
351
352/*************************************************
353*            OS-specific functions               *
354*************************************************/
355
356/* These functions are defined so that they can be made system specific,
357although at present the only ones are for Unix, Win32, and for "no support". */
358
359
360/************* Directory scanning in Unix ***********/
361
362#if defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H
363#include <sys/types.h>
364#include <sys/stat.h>
365#include <dirent.h>
366
367typedef DIR directory_type;
368
369static int
370isdirectory(char *filename)
371{
372struct stat statbuf;
373if (stat(filename, &statbuf) < 0)
374  return 0;        /* In the expectation that opening as a file will fail */
375return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0;
376}
377
378static directory_type *
379opendirectory(char *filename)
380{
381return opendir(filename);
382}
383
384static char *
385readdirectory(directory_type *dir)
386{
387for (;;)
388  {
389  struct dirent *dent = readdir(dir);
390  if (dent == NULL) return NULL;
391  if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
392    return dent->d_name;
393  }
394/* Control never reaches here */
395}
396
397static void
398closedirectory(directory_type *dir)
399{
400closedir(dir);
401}
402
403
404/************* Test for regular file in Unix **********/
405
406static int
407isregfile(char *filename)
408{
409struct stat statbuf;
410if (stat(filename, &statbuf) < 0)
411  return 1;        /* In the expectation that opening as a file will fail */
412return (statbuf.st_mode & S_IFMT) == S_IFREG;
413}
414
415
416/************* Test for a terminal in Unix **********/
417
418static BOOL
419is_stdout_tty(void)
420{
421return isatty(fileno(stdout));
422}
423
424static BOOL
425is_file_tty(FILE *f)
426{
427return isatty(fileno(f));
428}
429
430
431/************* Directory scanning in Win32 ***********/
432
433/* I (Philip Hazel) have no means of testing this code. It was contributed by
434Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
435when it did not exist. David Byron added a patch that moved the #include of
436<windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
437The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
438undefined when it is indeed undefined. */
439
440#elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
441
442#ifndef STRICT
443# define STRICT
444#endif
445#ifndef WIN32_LEAN_AND_MEAN
446# define WIN32_LEAN_AND_MEAN
447#endif
448
449#include <windows.h>
450
451#ifndef INVALID_FILE_ATTRIBUTES
452#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
453#endif
454
455typedef struct directory_type
456{
457HANDLE handle;
458BOOL first;
459WIN32_FIND_DATA data;
460} directory_type;
461
462int
463isdirectory(char *filename)
464{
465DWORD attr = GetFileAttributes(filename);
466if (attr == INVALID_FILE_ATTRIBUTES)
467  return 0;
468return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) ? '/' : 0;
469}
470
471directory_type *
472opendirectory(char *filename)
473{
474size_t len;
475char *pattern;
476directory_type *dir;
477DWORD err;
478len = strlen(filename);
479pattern = (char *) malloc(len + 3);
480dir = (directory_type *) malloc(sizeof(*dir));
481if ((pattern == NULL) || (dir == NULL))
482  {
483  fprintf(stderr, "pcregrep: malloc failed\n");
484  pcregrep_exit(2);
485  }
486memcpy(pattern, filename, len);
487memcpy(&(pattern[len]), "\\*", 3);
488dir->handle = FindFirstFile(pattern, &(dir->data));
489if (dir->handle != INVALID_HANDLE_VALUE)
490  {
491  free(pattern);
492  dir->first = TRUE;
493  return dir;
494  }
495err = GetLastError();
496free(pattern);
497free(dir);
498errno = (err == ERROR_ACCESS_DENIED) ? EACCES : ENOENT;
499return NULL;
500}
501
502char *
503readdirectory(directory_type *dir)
504{
505for (;;)
506  {
507  if (!dir->first)
508    {
509    if (!FindNextFile(dir->handle, &(dir->data)))
510      return NULL;
511    }
512  else
513    {
514    dir->first = FALSE;
515    }
516  if (strcmp(dir->data.cFileName, ".") != 0 && strcmp(dir->data.cFileName, "..") != 0)
517    return dir->data.cFileName;
518  }
519#ifndef _MSC_VER
520return NULL;   /* Keep compiler happy; never executed */
521#endif
522}
523
524void
525closedirectory(directory_type *dir)
526{
527FindClose(dir->handle);
528free(dir);
529}
530
531
532/************* Test for regular file in Win32 **********/
533
534/* I don't know how to do this, or if it can be done; assume all paths are
535regular if they are not directories. */
536
537int isregfile(char *filename)
538{
539return !isdirectory(filename);
540}
541
542
543/************* Test for a terminal in Win32 **********/
544
545/* I don't know how to do this; assume never */
546
547static BOOL
548is_stdout_tty(void)
549{
550return FALSE;
551}
552
553static BOOL
554is_file_tty(FILE *f)
555{
556return FALSE;
557}
558
559
560/************* Directory scanning when we can't do it ***********/
561
562/* The type is void, and apart from isdirectory(), the functions do nothing. */
563
564#else
565
566typedef void directory_type;
567
568int isdirectory(char *filename) { return 0; }
569directory_type * opendirectory(char *filename) { return (directory_type*)0;}
570char *readdirectory(directory_type *dir) { return (char*)0;}
571void closedirectory(directory_type *dir) {}
572
573
574/************* Test for regular when we can't do it **********/
575
576/* Assume all files are regular. */
577
578int isregfile(char *filename) { return 1; }
579
580
581/************* Test for a terminal when we can't do it **********/
582
583static BOOL
584is_stdout_tty(void)
585{
586return FALSE;
587}
588
589static BOOL
590is_file_tty(FILE *f)
591{
592return FALSE;
593}
594
595#endif
596
597
598
599#ifndef HAVE_STRERROR
600/*************************************************
601*     Provide strerror() for non-ANSI libraries  *
602*************************************************/
603
604/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()
605in their libraries, but can provide the same facility by this simple
606alternative function. */
607
608extern int   sys_nerr;
609extern char *sys_errlist[];
610
611char *
612strerror(int n)
613{
614if (n < 0 || n >= sys_nerr) return "unknown error number";
615return sys_errlist[n];
616}
617#endif /* HAVE_STRERROR */
618
619
620
621/*************************************************
622*            Read one line of input              *
623*************************************************/
624
625/* Normally, input is read using fread() into a large buffer, so many lines may
626be read at once. However, doing this for tty input means that no output appears
627until a lot of input has been typed. Instead, tty input is handled line by
628line. We cannot use fgets() for this, because it does not stop at a binary
629zero, and therefore there is no way of telling how many characters it has read,
630because there may be binary zeros embedded in the data.
631
632Arguments:
633  buffer     the buffer to read into
634  length     the maximum number of characters to read
635  f          the file
636
637Returns:     the number of characters read, zero at end of file
638*/
639
640static unsigned int
641read_one_line(char *buffer, int length, FILE *f)
642{
643int c;
644int yield = 0;
645while ((c = fgetc(f)) != EOF)
646  {
647  buffer[yield++] = c;
648  if (c == '\n' || yield >= length) break;
649  }
650return yield;
651}
652
653
654
655/*************************************************
656*             Find end of line                   *
657*************************************************/
658
659/* The length of the endline sequence that is found is set via lenptr. This may
660be zero at the very end of the file if there is no line-ending sequence there.
661
662Arguments:
663  p         current position in line
664  endptr    end of available data
665  lenptr    where to put the length of the eol sequence
666
667Returns:    pointer after the last byte of the line,
668            including the newline byte(s)
669*/
670
671static char *
672end_of_line(char *p, char *endptr, int *lenptr)
673{
674switch(endlinetype)
675  {
676  default:      /* Just in case */
677  case EL_LF:
678  while (p < endptr && *p != '\n') p++;
679  if (p < endptr)
680    {
681    *lenptr = 1;
682    return p + 1;
683    }
684  *lenptr = 0;
685  return endptr;
686
687  case EL_CR:
688  while (p < endptr && *p != '\r') p++;
689  if (p < endptr)
690    {
691    *lenptr = 1;
692    return p + 1;
693    }
694  *lenptr = 0;
695  return endptr;
696
697  case EL_CRLF:
698  for (;;)
699    {
700    while (p < endptr && *p != '\r') p++;
701    if (++p >= endptr)
702      {
703      *lenptr = 0;
704      return endptr;
705      }
706    if (*p == '\n')
707      {
708      *lenptr = 2;
709      return p + 1;
710      }
711    }
712  break;
713
714  case EL_ANYCRLF:
715  while (p < endptr)
716    {
717    int extra = 0;
718    register int c = *((unsigned char *)p);
719
720    if (utf8 && c >= 0xc0)
721      {
722      int gcii, gcss;
723      extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
724      gcss = 6*extra;
725      c = (c & utf8_table3[extra]) << gcss;
726      for (gcii = 1; gcii <= extra; gcii++)
727        {
728        gcss -= 6;
729        c |= (p[gcii] & 0x3f) << gcss;
730        }
731      }
732
733    p += 1 + extra;
734
735    switch (c)
736      {
737      case 0x0a:    /* LF */
738      *lenptr = 1;
739      return p;
740
741      case 0x0d:    /* CR */
742      if (p < endptr && *p == 0x0a)
743        {
744        *lenptr = 2;
745        p++;
746        }
747      else *lenptr = 1;
748      return p;
749
750      default:
751      break;
752      }
753    }   /* End of loop for ANYCRLF case */
754
755  *lenptr = 0;  /* Must have hit the end */
756  return endptr;
757
758  case EL_ANY:
759  while (p < endptr)
760    {
761    int extra = 0;
762    register int c = *((unsigned char *)p);
763
764    if (utf8 && c >= 0xc0)
765      {
766      int gcii, gcss;
767      extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
768      gcss = 6*extra;
769      c = (c & utf8_table3[extra]) << gcss;
770      for (gcii = 1; gcii <= extra; gcii++)
771        {
772        gcss -= 6;
773        c |= (p[gcii] & 0x3f) << gcss;
774        }
775      }
776
777    p += 1 + extra;
778
779    switch (c)
780      {
781      case 0x0a:    /* LF */
782      case 0x0b:    /* VT */
783      case 0x0c:    /* FF */
784      *lenptr = 1;
785      return p;
786
787      case 0x0d:    /* CR */
788      if (p < endptr && *p == 0x0a)
789        {
790        *lenptr = 2;
791        p++;
792        }
793      else *lenptr = 1;
794      return p;
795
796      case 0x85:    /* NEL */
797      *lenptr = utf8? 2 : 1;
798      return p;
799
800      case 0x2028:  /* LS */
801      case 0x2029:  /* PS */
802      *lenptr = 3;
803      return p;
804
805      default:
806      break;
807      }
808    }   /* End of loop for ANY case */
809
810  *lenptr = 0;  /* Must have hit the end */
811  return endptr;
812  }     /* End of overall switch */
813}
814
815
816
817/*************************************************
818*         Find start of previous line            *
819*************************************************/
820
821/* This is called when looking back for before lines to print.
822
823Arguments:
824  p         start of the subsequent line
825  startptr  start of available data
826
827Returns:    pointer to the start of the previous line
828*/
829
830static char *
831previous_line(char *p, char *startptr)
832{
833switch(endlinetype)
834  {
835  default:      /* Just in case */
836  case EL_LF:
837  p--;
838  while (p > startptr && p[-1] != '\n') p--;
839  return p;
840
841  case EL_CR:
842  p--;
843  while (p > startptr && p[-1] != '\n') p--;
844  return p;
845
846  case EL_CRLF:
847  for (;;)
848    {
849    p -= 2;
850    while (p > startptr && p[-1] != '\n') p--;
851    if (p <= startptr + 1 || p[-2] == '\r') return p;
852    }
853  return p;   /* But control should never get here */
854
855  case EL_ANY:
856  case EL_ANYCRLF:
857  if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;
858  if (utf8) while ((*p & 0xc0) == 0x80) p--;
859
860  while (p > startptr)
861    {
862    register int c;
863    char *pp = p - 1;
864
865    if (utf8)
866      {
867      int extra = 0;
868      while ((*pp & 0xc0) == 0x80) pp--;
869      c = *((unsigned char *)pp);
870      if (c >= 0xc0)
871        {
872        int gcii, gcss;
873        extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
874        gcss = 6*extra;
875        c = (c & utf8_table3[extra]) << gcss;
876        for (gcii = 1; gcii <= extra; gcii++)
877          {
878          gcss -= 6;
879          c |= (pp[gcii] & 0x3f) << gcss;
880          }
881        }
882      }
883    else c = *((unsigned char *)pp);
884
885    if (endlinetype == EL_ANYCRLF) switch (c)
886      {
887      case 0x0a:    /* LF */
888      case 0x0d:    /* CR */
889      return p;
890
891      default:
892      break;
893      }
894
895    else switch (c)
896      {
897      case 0x0a:    /* LF */
898      case 0x0b:    /* VT */
899      case 0x0c:    /* FF */
900      case 0x0d:    /* CR */
901      case 0x85:    /* NEL */
902      case 0x2028:  /* LS */
903      case 0x2029:  /* PS */
904      return p;
905
906      default:
907      break;
908      }
909
910    p = pp;  /* Back one character */
911    }        /* End of loop for ANY case */
912
913  return startptr;  /* Hit start of data */
914  }     /* End of overall switch */
915}
916
917
918
919
920
921/*************************************************
922*       Print the previous "after" lines         *
923*************************************************/
924
925/* This is called if we are about to lose said lines because of buffer filling,
926and at the end of the file. The data in the line is written using fwrite() so
927that a binary zero does not terminate it.
928
929Arguments:
930  lastmatchnumber   the number of the last matching line, plus one
931  lastmatchrestart  where we restarted after the last match
932  endptr            end of available data
933  printname         filename for printing
934
935Returns:            nothing
936*/
937
938static void do_after_lines(int lastmatchnumber, char *lastmatchrestart,
939  char *endptr, char *printname)
940{
941if (after_context > 0 && lastmatchnumber > 0)
942  {
943  int count = 0;
944  while (lastmatchrestart < endptr && count++ < after_context)
945    {
946    int ellength;
947    char *pp = lastmatchrestart;
948    if (printname != NULL) fprintf(stdout, "%s-", printname);
949    if (number) fprintf(stdout, "%d-", lastmatchnumber++);
950    pp = end_of_line(pp, endptr, &ellength);
951    FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
952    lastmatchrestart = pp;
953    }
954  hyphenpending = TRUE;
955  }
956}
957
958
959
960/*************************************************
961*   Apply patterns to subject till one matches   *
962*************************************************/
963
964/* This function is called to run through all patterns, looking for a match. It
965is used multiple times for the same subject when colouring is enabled, in order
966to find all possible matches.
967
968Arguments:
969  matchptr     the start of the subject
970  length       the length of the subject to match
971  startoffset  where to start matching
972  offsets      the offets vector to fill in
973  mrc          address of where to put the result of pcre_exec()
974
975Returns:      TRUE if there was a match
976              FALSE if there was no match
977              invert if there was a non-fatal error
978*/
979
980static BOOL
981match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
982  int *mrc)
983{
984int i;
985size_t slen = length;
986const char *msg = "this text:\n\n";
987if (slen > 200)
988  {
989  slen = 200;
990  msg = "text that starts:\n\n";
991  }
992for (i = 0; i < pattern_count; i++)
993  {
994  *mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, (int)length,
995    startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
996  if (*mrc >= 0) return TRUE;
997  if (*mrc == PCRE_ERROR_NOMATCH) continue;
998  fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc);
999  if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
1000  fprintf(stderr, "%s", msg);
1001  FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
1002  fprintf(stderr, "\n\n");
1003  if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT ||
1004      *mrc == PCRE_ERROR_JIT_STACKLIMIT)
1005    resource_error = TRUE;
1006  if (error_count++ > 20)
1007    {
1008    fprintf(stderr, "pcregrep: Too many errors - abandoned.\n");
1009    pcregrep_exit(2);
1010    }
1011  return invert;    /* No more matching; don't show the line again */
1012  }
1013
1014return FALSE;  /* No match, no errors */
1015}
1016
1017
1018
1019/*************************************************
1020*            Grep an individual file             *
1021*************************************************/
1022
1023/* This is called from grep_or_recurse() below. It uses a buffer that is three
1024times the value of bufthird. The matching point is never allowed to stray into
1025the top third of the buffer, thus keeping more of the file available for
1026context printing or for multiline scanning. For large files, the pointer will
1027be in the middle third most of the time, so the bottom third is available for
1028"before" context printing.
1029
1030Arguments:
1031  handle       the fopened FILE stream for a normal file
1032               the gzFile pointer when reading is via libz
1033               the BZFILE pointer when reading is via libbz2
1034  frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
1035  filename     the file name or NULL (for errors)
1036  printname    the file name if it is to be printed for each match
1037               or NULL if the file name is not to be printed
1038               it cannot be NULL if filenames[_nomatch]_only is set
1039
1040Returns:       0 if there was at least one match
1041               1 otherwise (no matches)
1042               2 if an overlong line is encountered
1043               3 if there is a read error on a .bz2 file
1044*/
1045
1046static int
1047pcregrep(void *handle, int frtype, char *filename, char *printname)
1048{
1049int rc = 1;
1050int linenumber = 1;
1051int lastmatchnumber = 0;
1052int count = 0;
1053int filepos = 0;
1054int offsets[OFFSET_SIZE];
1055char *lastmatchrestart = NULL;
1056char *ptr = main_buffer;
1057char *endptr;
1058size_t bufflength;
1059BOOL binary = FALSE;
1060BOOL endhyphenpending = FALSE;
1061BOOL input_line_buffered = line_buffered;
1062FILE *in = NULL;                    /* Ensure initialized */
1063
1064#ifdef SUPPORT_LIBZ
1065gzFile ingz = NULL;
1066#endif
1067
1068#ifdef SUPPORT_LIBBZ2
1069BZFILE *inbz2 = NULL;
1070#endif
1071
1072
1073/* Do the first read into the start of the buffer and set up the pointer to end
1074of what we have. In the case of libz, a non-zipped .gz file will be read as a
1075plain file. However, if a .bz2 file isn't actually bzipped, the first read will
1076fail. */
1077
1078#ifdef SUPPORT_LIBZ
1079if (frtype == FR_LIBZ)
1080  {
1081  ingz = (gzFile)handle;
1082  bufflength = gzread (ingz, main_buffer, bufsize);
1083  }
1084else
1085#endif
1086
1087#ifdef SUPPORT_LIBBZ2
1088if (frtype == FR_LIBBZ2)
1089  {
1090  inbz2 = (BZFILE *)handle;
1091  bufflength = BZ2_bzread(inbz2, main_buffer, bufsize);
1092  if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
1093  }                                    /* without the cast it is unsigned. */
1094else
1095#endif
1096
1097  {
1098  in = (FILE *)handle;
1099  if (is_file_tty(in)) input_line_buffered = TRUE;
1100  bufflength = input_line_buffered?
1101    read_one_line(main_buffer, bufsize, in) :
1102    fread(main_buffer, 1, bufsize, in);
1103  }
1104
1105endptr = main_buffer + bufflength;
1106
1107/* Unless binary-files=text, see if we have a binary file. This uses the same
1108rule as GNU grep, namely, a search for a binary zero byte near the start of the
1109file. */
1110
1111if (binary_files != BIN_TEXT)
1112  {
1113  binary =
1114    memchr(main_buffer, 0, (bufflength > 1024)? 1024 : bufflength) != NULL;
1115  if (binary && binary_files == BIN_NOMATCH) return 1;
1116  }
1117
1118/* Loop while the current pointer is not at the end of the file. For large
1119files, endptr will be at the end of the buffer when we are in the middle of the
1120file, but ptr will never get there, because as soon as it gets over 2/3 of the
1121way, the buffer is shifted left and re-filled. */
1122
1123while (ptr < endptr)
1124  {
1125  int endlinelength;
1126  int mrc = 0;
1127  int startoffset = 0;
1128  BOOL match;
1129  char *matchptr = ptr;
1130  char *t = ptr;
1131  size_t length, linelength;
1132
1133  /* At this point, ptr is at the start of a line. We need to find the length
1134  of the subject string to pass to pcre_exec(). In multiline mode, it is the
1135  length remainder of the data in the buffer. Otherwise, it is the length of
1136  the next line, excluding the terminating newline. After matching, we always
1137  advance by the length of the next line. In multiline mode the PCRE_FIRSTLINE
1138  option is used for compiling, so that any match is constrained to be in the
1139  first line. */
1140
1141  t = end_of_line(t, endptr, &endlinelength);
1142  linelength = t - ptr - endlinelength;
1143  length = multiline? (size_t)(endptr - ptr) : linelength;
1144
1145  /* Check to see if the line we are looking at extends right to the very end
1146  of the buffer without a line terminator. This means the line is too long to
1147  handle. */
1148
1149  if (endlinelength == 0 && t == main_buffer + bufsize)
1150    {
1151    fprintf(stderr, "pcregrep: line %d%s%s is too long for the internal buffer\n"
1152                    "pcregrep: check the --buffer-size option\n",
1153                    linenumber,
1154                    (filename == NULL)? "" : " of file ",
1155                    (filename == NULL)? "" : filename);
1156    return 2;
1157    }
1158
1159  /* Extra processing for Jeffrey Friedl's debugging. */
1160
1161#ifdef JFRIEDL_DEBUG
1162  if (jfriedl_XT || jfriedl_XR)
1163  {
1164      #include <sys/time.h>
1165      #include <time.h>
1166      struct timeval start_time, end_time;
1167      struct timezone dummy;
1168      int i;
1169
1170      if (jfriedl_XT)
1171      {
1172          unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix);
1173          const char *orig = ptr;
1174          ptr = malloc(newlen + 1);
1175          if (!ptr) {
1176                  printf("out of memory");
1177                  pcregrep_exit(2);
1178          }
1179          endptr = ptr;
1180          strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
1181          for (i = 0; i < jfriedl_XT; i++) {
1182                  strncpy(endptr, orig,  length);
1183                  endptr += length;
1184          }
1185          strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix);
1186          length = newlen;
1187      }
1188
1189      if (gettimeofday(&start_time, &dummy) != 0)
1190              perror("bad gettimeofday");
1191
1192
1193      for (i = 0; i < jfriedl_XR; i++)
1194          match = (pcre_exec(pattern_list[0], hints_list[0], ptr, length, 0,
1195              PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
1196
1197      if (gettimeofday(&end_time, &dummy) != 0)
1198              perror("bad gettimeofday");
1199
1200      double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0))
1201                      -
1202                      (start_time.tv_sec + (start_time.tv_usec / 1000000.0)));
1203
1204      printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta);
1205      return 0;
1206  }
1207#endif
1208
1209  /* We come back here after a match when the -o option (only_matching) is set,
1210  in order to find any further matches in the same line. */
1211
1212  ONLY_MATCHING_RESTART:
1213
1214  /* Run through all the patterns until one matches or there is an error other
1215  than NOMATCH. This code is in a subroutine so that it can be re-used for
1216  finding subsequent matches when colouring matched lines. */
1217
1218  match = match_patterns(matchptr, length, startoffset, offsets, &mrc);
1219
1220  /* If it's a match or a not-match (as required), do what's wanted. */
1221
1222  if (match != invert)
1223    {
1224    BOOL hyphenprinted = FALSE;
1225
1226    /* We've failed if we want a file that doesn't have any matches. */
1227
1228    if (filenames == FN_NOMATCH_ONLY) return 1;
1229
1230    /* Just count if just counting is wanted. */
1231
1232    if (count_only) count++;
1233
1234    /* When handling a binary file and binary-files==binary, the "binary"
1235    variable will be set true (it's false in all other cases). In this
1236    situation we just want to output the file name. No need to scan further. */
1237
1238    else if (binary)
1239      {
1240      fprintf(stdout, "Binary file %s matches\n", filename);
1241      return 0;
1242      }
1243
1244    /* If all we want is a file name, there is no need to scan any more lines
1245    in the file. */
1246
1247    else if (filenames == FN_MATCH_ONLY)
1248      {
1249      fprintf(stdout, "%s\n", printname);
1250      return 0;
1251      }
1252
1253    /* Likewise, if all we want is a yes/no answer. */
1254
1255    else if (quiet) return 0;
1256
1257    /* The --only-matching option prints just the substring that matched, or a
1258    captured portion of it, as long as this string is not empty, and the
1259    --file-offsets and --line-offsets options output offsets for the matching
1260    substring (they both force --only-matching = 0). None of these options
1261    prints any context. Afterwards, adjust the start and then jump back to look
1262    for further matches in the same line. If we are in invert mode, however,
1263    nothing is printed and we do not restart - this could still be useful
1264    because the return code is set. */
1265
1266    else if (only_matching >= 0)
1267      {
1268      if (!invert)
1269        {
1270        if (printname != NULL) fprintf(stdout, "%s:", printname);
1271        if (number) fprintf(stdout, "%d:", linenumber);
1272        if (line_offsets)
1273          fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
1274            offsets[1] - offsets[0]);
1275        else if (file_offsets)
1276          fprintf(stdout, "%d,%d\n",
1277            (int)(filepos + matchptr + offsets[0] - ptr),
1278            offsets[1] - offsets[0]);
1279        else if (only_matching < mrc)
1280          {
1281          int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
1282          if (plen > 0)
1283            {
1284            if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1285            FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
1286            if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
1287            fprintf(stdout, "\n");
1288            }
1289          }
1290        else if (printname != NULL || number) fprintf(stdout, "\n");
1291        match = FALSE;
1292        if (line_buffered) fflush(stdout);
1293        rc = 0;                      /* Had some success */
1294        startoffset = offsets[1];    /* Restart after the match */
1295        goto ONLY_MATCHING_RESTART;
1296        }
1297      }
1298
1299    /* This is the default case when none of the above options is set. We print
1300    the matching lines(s), possibly preceded and/or followed by other lines of
1301    context. */
1302
1303    else
1304      {
1305      /* See if there is a requirement to print some "after" lines from a
1306      previous match. We never print any overlaps. */
1307
1308      if (after_context > 0 && lastmatchnumber > 0)
1309        {
1310        int ellength;
1311        int linecount = 0;
1312        char *p = lastmatchrestart;
1313
1314        while (p < ptr && linecount < after_context)
1315          {
1316          p = end_of_line(p, ptr, &ellength);
1317          linecount++;
1318          }
1319
1320        /* It is important to advance lastmatchrestart during this printing so
1321        that it interacts correctly with any "before" printing below. Print
1322        each line's data using fwrite() in case there are binary zeroes. */
1323
1324        while (lastmatchrestart < p)
1325          {
1326          char *pp = lastmatchrestart;
1327          if (printname != NULL) fprintf(stdout, "%s-", printname);
1328          if (number) fprintf(stdout, "%d-", lastmatchnumber++);
1329          pp = end_of_line(pp, endptr, &ellength);
1330          FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
1331          lastmatchrestart = pp;
1332          }
1333        if (lastmatchrestart != ptr) hyphenpending = TRUE;
1334        }
1335
1336      /* If there were non-contiguous lines printed above, insert hyphens. */
1337
1338      if (hyphenpending)
1339        {
1340        fprintf(stdout, "--\n");
1341        hyphenpending = FALSE;
1342        hyphenprinted = TRUE;
1343        }
1344
1345      /* See if there is a requirement to print some "before" lines for this
1346      match. Again, don't print overlaps. */
1347
1348      if (before_context > 0)
1349        {
1350        int linecount = 0;
1351        char *p = ptr;
1352
1353        while (p > main_buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
1354               linecount < before_context)
1355          {
1356          linecount++;
1357          p = previous_line(p, main_buffer);
1358          }
1359
1360        if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
1361          fprintf(stdout, "--\n");
1362
1363        while (p < ptr)
1364          {
1365          int ellength;
1366          char *pp = p;
1367          if (printname != NULL) fprintf(stdout, "%s-", printname);
1368          if (number) fprintf(stdout, "%d-", linenumber - linecount--);
1369          pp = end_of_line(pp, endptr, &ellength);
1370          FWRITE(p, 1, pp - p, stdout);
1371          p = pp;
1372          }
1373        }
1374
1375      /* Now print the matching line(s); ensure we set hyphenpending at the end
1376      of the file if any context lines are being output. */
1377
1378      if (after_context > 0 || before_context > 0)
1379        endhyphenpending = TRUE;
1380
1381      if (printname != NULL) fprintf(stdout, "%s:", printname);
1382      if (number) fprintf(stdout, "%d:", linenumber);
1383
1384      /* In multiline mode, we want to print to the end of the line in which
1385      the end of the matched string is found, so we adjust linelength and the
1386      line number appropriately, but only when there actually was a match
1387      (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
1388      the match will always be before the first newline sequence. */
1389
1390      if (multiline & !invert)
1391        {
1392        char *endmatch = ptr + offsets[1];
1393        t = ptr;
1394        while (t < endmatch)
1395          {
1396          t = end_of_line(t, endptr, &endlinelength);
1397          if (t < endmatch) linenumber++; else break;
1398          }
1399        linelength = t - ptr - endlinelength;
1400        }
1401
1402      /*** NOTE: Use only fwrite() to output the data line, so that binary
1403      zeroes are treated as just another data character. */
1404
1405      /* This extra option, for Jeffrey Friedl's debugging requirements,
1406      replaces the matched string, or a specific captured string if it exists,
1407      with X. When this happens, colouring is ignored. */
1408
1409#ifdef JFRIEDL_DEBUG
1410      if (S_arg >= 0 && S_arg < mrc)
1411        {
1412        int first = S_arg * 2;
1413        int last  = first + 1;
1414        FWRITE(ptr, 1, offsets[first], stdout);
1415        fprintf(stdout, "X");
1416        FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
1417        }
1418      else
1419#endif
1420
1421      /* We have to split the line(s) up if colouring, and search for further
1422      matches, but not of course if the line is a non-match. */
1423
1424      if (do_colour && !invert)
1425        {
1426        int plength;
1427        FWRITE(ptr, 1, offsets[0], stdout);
1428        fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1429        FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1430        fprintf(stdout, "%c[00m", 0x1b);
1431        for (;;)
1432          {
1433          startoffset = offsets[1];
1434          if (startoffset >= (int)linelength + endlinelength ||
1435              !match_patterns(matchptr, length, startoffset, offsets, &mrc))
1436            break;
1437          FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
1438          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1439          FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1440          fprintf(stdout, "%c[00m", 0x1b);
1441          }
1442
1443        /* In multiline mode, we may have already printed the complete line
1444        and its line-ending characters (if they matched the pattern), so there
1445        may be no more to print. */
1446
1447        plength = (int)((linelength + endlinelength) - startoffset);
1448        if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout);
1449        }
1450
1451      /* Not colouring; no need to search for further matches */
1452
1453      else FWRITE(ptr, 1, linelength + endlinelength, stdout);
1454      }
1455
1456    /* End of doing what has to be done for a match. If --line-buffered was
1457    given, flush the output. */
1458
1459    if (line_buffered) fflush(stdout);
1460    rc = 0;    /* Had some success */
1461
1462    /* Remember where the last match happened for after_context. We remember
1463    where we are about to restart, and that line's number. */
1464
1465    lastmatchrestart = ptr + linelength + endlinelength;
1466    lastmatchnumber = linenumber + 1;
1467    }
1468
1469  /* For a match in multiline inverted mode (which of course did not cause
1470  anything to be printed), we have to move on to the end of the match before
1471  proceeding. */
1472
1473  if (multiline && invert && match)
1474    {
1475    int ellength;
1476    char *endmatch = ptr + offsets[1];
1477    t = ptr;
1478    while (t < endmatch)
1479      {
1480      t = end_of_line(t, endptr, &ellength);
1481      if (t <= endmatch) linenumber++; else break;
1482      }
1483    endmatch = end_of_line(endmatch, endptr, &ellength);
1484    linelength = endmatch - ptr - ellength;
1485    }
1486
1487  /* Advance to after the newline and increment the line number. The file
1488  offset to the current line is maintained in filepos. */
1489
1490  ptr += linelength + endlinelength;
1491  filepos += (int)(linelength + endlinelength);
1492  linenumber++;
1493
1494  /* If input is line buffered, and the buffer is not yet full, read another
1495  line and add it into the buffer. */
1496
1497  if (input_line_buffered && bufflength < (size_t)bufsize)
1498    {
1499    int add = read_one_line(ptr, bufsize - (int)(ptr - main_buffer), in);
1500    bufflength += add;
1501    endptr += add;
1502    }
1503
1504  /* If we haven't yet reached the end of the file (the buffer is full), and
1505  the current point is in the top 1/3 of the buffer, slide the buffer down by
1506  1/3 and refill it. Before we do this, if some unprinted "after" lines are
1507  about to be lost, print them. */
1508
1509  if (bufflength >= (size_t)bufsize && ptr > main_buffer + 2*bufthird)
1510    {
1511    if (after_context > 0 &&
1512        lastmatchnumber > 0 &&
1513        lastmatchrestart < main_buffer + bufthird)
1514      {
1515      do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1516      lastmatchnumber = 0;
1517      }
1518
1519    /* Now do the shuffle */
1520
1521    memmove(main_buffer, main_buffer + bufthird, 2*bufthird);
1522    ptr -= bufthird;
1523
1524#ifdef SUPPORT_LIBZ
1525    if (frtype == FR_LIBZ)
1526      bufflength = 2*bufthird +
1527        gzread (ingz, main_buffer + 2*bufthird, bufthird);
1528    else
1529#endif
1530
1531#ifdef SUPPORT_LIBBZ2
1532    if (frtype == FR_LIBBZ2)
1533      bufflength = 2*bufthird +
1534        BZ2_bzread(inbz2, main_buffer + 2*bufthird, bufthird);
1535    else
1536#endif
1537
1538    bufflength = 2*bufthird +
1539      (input_line_buffered?
1540       read_one_line(main_buffer + 2*bufthird, bufthird, in) :
1541       fread(main_buffer + 2*bufthird, 1, bufthird, in));
1542    endptr = main_buffer + bufflength;
1543
1544    /* Adjust any last match point */
1545
1546    if (lastmatchnumber > 0) lastmatchrestart -= bufthird;
1547    }
1548  }     /* Loop through the whole file */
1549
1550/* End of file; print final "after" lines if wanted; do_after_lines sets
1551hyphenpending if it prints something. */
1552
1553if (only_matching < 0 && !count_only)
1554  {
1555  do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
1556  hyphenpending |= endhyphenpending;
1557  }
1558
1559/* Print the file name if we are looking for those without matches and there
1560were none. If we found a match, we won't have got this far. */
1561
1562if (filenames == FN_NOMATCH_ONLY)
1563  {
1564  fprintf(stdout, "%s\n", printname);
1565  return 0;
1566  }
1567
1568/* Print the match count if wanted */
1569
1570if (count_only)
1571  {
1572  if (count > 0 || !omit_zero_count)
1573    {
1574    if (printname != NULL && filenames != FN_NONE)
1575      fprintf(stdout, "%s:", printname);
1576    fprintf(stdout, "%d\n", count);
1577    }
1578  }
1579
1580return rc;
1581}
1582
1583
1584
1585/*************************************************
1586*     Grep a file or recurse into a directory    *
1587*************************************************/
1588
1589/* Given a path name, if it's a directory, scan all the files if we are
1590recursing; if it's a file, grep it.
1591
1592Arguments:
1593  pathname          the path to investigate
1594  dir_recurse       TRUE if recursing is wanted (-r or -drecurse)
1595  only_one_at_top   TRUE if the path is the only one at toplevel
1596
1597Returns:   0 if there was at least one match
1598           1 if there were no matches
1599           2 there was some kind of error
1600
1601However, file opening failures are suppressed if "silent" is set.
1602*/
1603
1604static int
1605grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top)
1606{
1607int rc = 1;
1608int sep;
1609int frtype;
1610void *handle;
1611FILE *in = NULL;           /* Ensure initialized */
1612
1613#ifdef SUPPORT_LIBZ
1614gzFile ingz = NULL;
1615#endif
1616
1617#ifdef SUPPORT_LIBBZ2
1618BZFILE *inbz2 = NULL;
1619#endif
1620
1621#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1622int pathlen;
1623#endif
1624
1625/* If the file name is "-" we scan stdin */
1626
1627if (strcmp(pathname, "-") == 0)
1628  {
1629  return pcregrep(stdin, FR_PLAIN, stdin_name,
1630    (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
1631      stdin_name : NULL);
1632  }
1633
1634/* If the file is a directory, skip if skipping or if we are recursing, scan
1635each file and directory within it, subject to any include or exclude patterns
1636that were set. The scanning code is localized so it can be made
1637system-specific. */
1638
1639if ((sep = isdirectory(pathname)) != 0)
1640  {
1641  if (dee_action == dee_SKIP) return 1;
1642  if (dee_action == dee_RECURSE)
1643    {
1644    char buffer[1024];
1645    char *nextfile;
1646    directory_type *dir = opendirectory(pathname);
1647
1648    if (dir == NULL)
1649      {
1650      if (!silent)
1651        fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", pathname,
1652          strerror(errno));
1653      return 2;
1654      }
1655
1656    while ((nextfile = readdirectory(dir)) != NULL)
1657      {
1658      int frc, nflen;
1659      sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
1660      nflen = (int)(strlen(nextfile));
1661
1662      if (isdirectory(buffer))
1663        {
1664        if (exclude_dir_compiled != NULL &&
1665            pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1666          continue;
1667
1668        if (include_dir_compiled != NULL &&
1669            pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1670          continue;
1671        }
1672      else
1673        {
1674        if (exclude_compiled != NULL &&
1675            pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
1676          continue;
1677
1678        if (include_compiled != NULL &&
1679            pcre_exec(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
1680          continue;
1681        }
1682
1683      frc = grep_or_recurse(buffer, dir_recurse, FALSE);
1684      if (frc > 1) rc = frc;
1685       else if (frc == 0 && rc == 1) rc = 0;
1686      }
1687
1688    closedirectory(dir);
1689    return rc;
1690    }
1691  }
1692
1693/* If the file is not a directory and not a regular file, skip it if that's
1694been requested. */
1695
1696else if (!isregfile(pathname) && DEE_action == DEE_SKIP) return 1;
1697
1698/* Control reaches here if we have a regular file, or if we have a directory
1699and recursion or skipping was not requested, or if we have anything else and
1700skipping was not requested. The scan proceeds. If this is the first and only
1701argument at top level, we don't show the file name, unless we are only showing
1702the file name, or the filename was forced (-H). */
1703
1704#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1705pathlen = (int)(strlen(pathname));
1706#endif
1707
1708/* Open using zlib if it is supported and the file name ends with .gz. */
1709
1710#ifdef SUPPORT_LIBZ
1711if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
1712  {
1713  ingz = gzopen(pathname, "rb");
1714  if (ingz == NULL)
1715    {
1716    if (!silent)
1717      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1718        strerror(errno));
1719    return 2;
1720    }
1721  handle = (void *)ingz;
1722  frtype = FR_LIBZ;
1723  }
1724else
1725#endif
1726
1727/* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */
1728
1729#ifdef SUPPORT_LIBBZ2
1730if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
1731  {
1732  inbz2 = BZ2_bzopen(pathname, "rb");
1733  handle = (void *)inbz2;
1734  frtype = FR_LIBBZ2;
1735  }
1736else
1737#endif
1738
1739/* Otherwise use plain fopen(). The label is so that we can come back here if
1740an attempt to read a .bz2 file indicates that it really is a plain file. */
1741
1742#ifdef SUPPORT_LIBBZ2
1743PLAIN_FILE:
1744#endif
1745  {
1746  in = fopen(pathname, "rb");
1747  handle = (void *)in;
1748  frtype = FR_PLAIN;
1749  }
1750
1751/* All the opening methods return errno when they fail. */
1752
1753if (handle == NULL)
1754  {
1755  if (!silent)
1756    fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname,
1757      strerror(errno));
1758  return 2;
1759  }
1760
1761/* Now grep the file */
1762
1763rc = pcregrep(handle, frtype, pathname, (filenames > FN_DEFAULT ||
1764  (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);
1765
1766/* Close in an appropriate manner. */
1767
1768#ifdef SUPPORT_LIBZ
1769if (frtype == FR_LIBZ)
1770  gzclose(ingz);
1771else
1772#endif
1773
1774/* If it is a .bz2 file and the result is 3, it means that the first attempt to
1775read failed. If the error indicates that the file isn't in fact bzipped, try
1776again as a normal file. */
1777
1778#ifdef SUPPORT_LIBBZ2
1779if (frtype == FR_LIBBZ2)
1780  {
1781  if (rc == 3)
1782    {
1783    int errnum;
1784    const char *err = BZ2_bzerror(inbz2, &errnum);
1785    if (errnum == BZ_DATA_ERROR_MAGIC)
1786      {
1787      BZ2_bzclose(inbz2);
1788      goto PLAIN_FILE;
1789      }
1790    else if (!silent)
1791      fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n",
1792        pathname, err);
1793    rc = 2;    /* The normal "something went wrong" code */
1794    }
1795  BZ2_bzclose(inbz2);
1796  }
1797else
1798#endif
1799
1800/* Normal file close */
1801
1802fclose(in);
1803
1804/* Pass back the yield from pcregrep(). */
1805
1806return rc;
1807}
1808
1809
1810
1811
1812/*************************************************
1813*                Usage function                  *
1814*************************************************/
1815
1816static int
1817usage(int rc)
1818{
1819option_item *op;
1820fprintf(stderr, "Usage: pcregrep [-");
1821for (op = optionlist; op->one_char != 0; op++)
1822  {
1823  if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1824  }
1825fprintf(stderr, "] [long options] [pattern] [files]\n");
1826fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1827  "options.\n");
1828return rc;
1829}
1830
1831
1832
1833
1834/*************************************************
1835*                Help function                   *
1836*************************************************/
1837
1838static void
1839help(void)
1840{
1841option_item *op;
1842
1843printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
1844printf("Search for PATTERN in each FILE or standard input.\n");
1845printf("PATTERN must be present if neither -e nor -f is used.\n");
1846printf("\"-\" can be used as a file name to mean STDIN.\n");
1847
1848#ifdef SUPPORT_LIBZ
1849printf("Files whose names end in .gz are read using zlib.\n");
1850#endif
1851
1852#ifdef SUPPORT_LIBBZ2
1853printf("Files whose names end in .bz2 are read using bzlib2.\n");
1854#endif
1855
1856#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
1857printf("Other files and the standard input are read as plain files.\n\n");
1858#else
1859printf("All files are read as plain files, without any interpretation.\n\n");
1860#endif
1861
1862printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
1863printf("Options:\n");
1864
1865for (op = optionlist; op->one_char != 0; op++)
1866  {
1867  int n;
1868  char s[4];
1869
1870  /* Two options were accidentally implemented and documented with underscores
1871  instead of hyphens in their names, something that was not noticed for quite a
1872  few releases. When fixing this, I left the underscored versions in the list
1873  in case people were using them. However, we don't want to display them in the
1874  help data. There are no other options that contain underscores, and we do not
1875  expect ever to implement such options. Therefore, just omit any option that
1876  contains an underscore. */
1877
1878  if (strchr(op->long_name, '_') != NULL) continue;
1879
1880  if (op->one_char > 0 && (op->long_name)[0] == 0)
1881    n = 31 - printf("  -%c", op->one_char);
1882  else
1883    {
1884    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);
1885      else strcpy(s, "   ");
1886    n = 31 - printf("  %s --%s", s, op->long_name);
1887    }
1888
1889  if (n < 1) n = 1;
1890  printf("%.*s%s\n", n, "                           ", op->help_text);
1891  }
1892
1893printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n");
1894printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);
1895printf("When reading patterns or file names from a file, trailing white\n");
1896printf("space is removed and blank lines are ignored.\n");
1897printf("There is a maximum of %d patterns, each of maximum size %d bytes.\n",
1898  MAX_PATTERN_COUNT, PATBUFSIZE);
1899
1900printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");
1901printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");
1902}
1903
1904
1905
1906
1907/*************************************************
1908*    Handle a single-letter, no data option      *
1909*************************************************/
1910
1911static int
1912handle_option(int letter, int options)
1913{
1914switch(letter)
1915  {
1916  case N_FOFFSETS: file_offsets = TRUE; break;
1917  case N_HELP: help(); pcregrep_exit(0);
1918  case N_LBUFFER: line_buffered = TRUE; break;
1919  case N_LOFFSETS: line_offsets = number = TRUE; break;
1920  case N_NOJIT: study_options &= ~PCRE_STUDY_JIT_COMPILE; break;
1921  case 'a': binary_files = BIN_TEXT; break;
1922  case 'c': count_only = TRUE; break;
1923  case 'F': process_options |= PO_FIXED_STRINGS; break;
1924  case 'H': filenames = FN_FORCE; break;
1925  case 'I': binary_files = BIN_NOMATCH; break;
1926  case 'h': filenames = FN_NONE; break;
1927  case 'i': options |= PCRE_CASELESS; break;
1928  case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
1929  case 'L': filenames = FN_NOMATCH_ONLY; break;
1930  case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
1931  case 'n': number = TRUE; break;
1932  case 'o': only_matching = 0; break;
1933  case 'q': quiet = TRUE; break;
1934  case 'r': dee_action = dee_RECURSE; break;
1935  case 's': silent = TRUE; break;
1936  case 'u': options |= PCRE_UTF8; utf8 = TRUE; break;
1937  case 'v': invert = TRUE; break;
1938  case 'w': process_options |= PO_WORD_MATCH; break;
1939  case 'x': process_options |= PO_LINE_MATCH; break;
1940
1941  case 'V':
1942  fprintf(stderr, "pcregrep version %s\n", pcre_version());
1943  pcregrep_exit(0);
1944  break;
1945
1946  default:
1947  fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
1948  pcregrep_exit(usage(2));
1949  }
1950
1951return options;
1952}
1953
1954
1955
1956
1957/*************************************************
1958*          Construct printed ordinal             *
1959*************************************************/
1960
1961/* This turns a number into "1st", "3rd", etc. */
1962
1963static char *
1964ordin(int n)
1965{
1966static char buffer[8];
1967char *p = buffer;
1968sprintf(p, "%d", n);
1969while (*p != 0) p++;
1970switch (n%10)
1971  {
1972  case 1: strcpy(p, "st"); break;
1973  case 2: strcpy(p, "nd"); break;
1974  case 3: strcpy(p, "rd"); break;
1975  default: strcpy(p, "th"); break;
1976  }
1977return buffer;
1978}
1979
1980
1981
1982/*************************************************
1983*          Compile a single pattern              *
1984*************************************************/
1985
1986/* When the -F option has been used, this is called for each substring.
1987Otherwise it's called for each supplied pattern.
1988
1989Arguments:
1990  pattern        the pattern string
1991  options        the PCRE options
1992  filename       the file name, or NULL for a command-line pattern
1993  count          0 if this is the only command line pattern, or
1994                 number of the command line pattern, or
1995                 linenumber for a pattern from a file
1996
1997Returns:         TRUE on success, FALSE after an error
1998*/
1999
2000static BOOL
2001compile_single_pattern(char *pattern, int options, char *filename, int count)
2002{
2003char buffer[PATBUFSIZE];
2004const char *error;
2005int errptr;
2006
2007if (pattern_count >= MAX_PATTERN_COUNT)
2008  {
2009  fprintf(stderr, "pcregrep: Too many %spatterns (max %d)\n",
2010    (filename == NULL)? "command-line " : "", MAX_PATTERN_COUNT);
2011  return FALSE;
2012  }
2013
2014sprintf(buffer, "%s%.*s%s", prefix[process_options], bufthird, pattern,
2015  suffix[process_options]);
2016pattern_list[pattern_count] =
2017  pcre_compile(buffer, options, &error, &errptr, pcretables);
2018if (pattern_list[pattern_count] != NULL)
2019  {
2020  pattern_count++;
2021  return TRUE;
2022  }
2023
2024/* Handle compile errors */
2025
2026errptr -= (int)strlen(prefix[process_options]);
2027if (errptr > (int)strlen(pattern)) errptr = (int)strlen(pattern);
2028
2029if (filename == NULL)
2030  {
2031  if (count == 0)
2032    fprintf(stderr, "pcregrep: Error in command-line regex "
2033      "at offset %d: %s\n", errptr, error);
2034  else
2035    fprintf(stderr, "pcregrep: Error in %s command-line regex "
2036      "at offset %d: %s\n", ordin(count), errptr, error);
2037  }
2038else
2039  {
2040  fprintf(stderr, "pcregrep: Error in regex in line %d of %s "
2041    "at offset %d: %s\n", count, filename, errptr, error);
2042  }
2043
2044return FALSE;
2045}
2046
2047
2048
2049/*************************************************
2050*           Compile one supplied pattern         *
2051*************************************************/
2052
2053/* When the -F option has been used, each string may be a list of strings,
2054separated by line breaks. They will be matched literally.
2055
2056Arguments:
2057  pattern        the pattern string
2058  options        the PCRE options
2059  filename       the file name, or NULL for a command-line pattern
2060  count          0 if this is the only command line pattern, or
2061                 number of the command line pattern, or
2062                 linenumber for a pattern from a file
2063
2064Returns:         TRUE on success, FALSE after an error
2065*/
2066
2067static BOOL
2068compile_pattern(char *pattern, int options, char *filename, int count)
2069{
2070if ((process_options & PO_FIXED_STRINGS) != 0)
2071  {
2072  char *eop = pattern + strlen(pattern);
2073  char buffer[PATBUFSIZE];
2074  for(;;)
2075    {
2076    int ellength;
2077    char *p = end_of_line(pattern, eop, &ellength);
2078    if (ellength == 0)
2079      return compile_single_pattern(pattern, options, filename, count);
2080    sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern);
2081    pattern = p;
2082    if (!compile_single_pattern(buffer, options, filename, count))
2083      return FALSE;
2084    }
2085  }
2086else return compile_single_pattern(pattern, options, filename, count);
2087}
2088
2089
2090
2091/*************************************************
2092*                Main program                    *
2093*************************************************/
2094
2095/* Returns 0 if something matched, 1 if nothing matched, 2 after an error. */
2096
2097int
2098main(int argc, char **argv)
2099{
2100int i, j;
2101int rc = 1;
2102int pcre_options = 0;
2103int cmd_pattern_count = 0;
2104int hint_count = 0;
2105int errptr;
2106BOOL only_one_at_top;
2107char *patterns[MAX_PATTERN_COUNT];
2108const char *locale_from = "--locale";
2109const char *error;
2110
2111#ifdef SUPPORT_PCREGREP_JIT
2112pcre_jit_stack *jit_stack = NULL;
2113#endif
2114
2115/* Set the default line ending value from the default in the PCRE library;
2116"lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf".
2117Note that the return values from pcre_config(), though derived from the ASCII
2118codes, are the same in EBCDIC environments, so we must use the actual values
2119rather than escapes such as as '\r'. */
2120
2121(void)pcre_config(PCRE_CONFIG_NEWLINE, &i);
2122switch(i)
2123  {
2124  default:               newline = (char *)"lf"; break;
2125  case 13:               newline = (char *)"cr"; break;
2126  case (13 << 8) | 10:   newline = (char *)"crlf"; break;
2127  case -1:               newline = (char *)"any"; break;
2128  case -2:               newline = (char *)"anycrlf"; break;
2129  }
2130
2131/* Process the options */
2132
2133for (i = 1; i < argc; i++)
2134  {
2135  option_item *op = NULL;
2136  char *option_data = (char *)"";    /* default to keep compiler happy */
2137  BOOL longop;
2138  BOOL longopwasequals = FALSE;
2139
2140  if (argv[i][0] != '-') break;
2141
2142  /* If we hit an argument that is just "-", it may be a reference to STDIN,
2143  but only if we have previously had -e or -f to define the patterns. */
2144
2145  if (argv[i][1] == 0)
2146    {
2147    if (pattern_filename != NULL || pattern_count > 0) break;
2148      else pcregrep_exit(usage(2));
2149    }
2150
2151  /* Handle a long name option, or -- to terminate the options */
2152
2153  if (argv[i][1] == '-')
2154    {
2155    char *arg = argv[i] + 2;
2156    char *argequals = strchr(arg, '=');
2157
2158    if (*arg == 0)    /* -- terminates options */
2159      {
2160      i++;
2161      break;                /* out of the options-handling loop */
2162      }
2163
2164    longop = TRUE;
2165
2166    /* Some long options have data that follows after =, for example file=name.
2167    Some options have variations in the long name spelling: specifically, we
2168    allow "regexp" because GNU grep allows it, though I personally go along
2169    with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
2170    These options are entered in the table as "regex(p)". Options can be in
2171    both these categories. */
2172
2173    for (op = optionlist; op->one_char != 0; op++)
2174      {
2175      char *opbra = strchr(op->long_name, '(');
2176      char *equals = strchr(op->long_name, '=');
2177
2178      /* Handle options with only one spelling of the name */
2179
2180      if (opbra == NULL)     /* Does not contain '(' */
2181        {
2182        if (equals == NULL)  /* Not thing=data case */
2183          {
2184          if (strcmp(arg, op->long_name) == 0) break;
2185          }
2186        else                 /* Special case xxx=data */
2187          {
2188          int oplen = (int)(equals - op->long_name);
2189          int arglen = (argequals == NULL)?
2190            (int)strlen(arg) : (int)(argequals - arg);
2191          if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
2192            {
2193            option_data = arg + arglen;
2194            if (*option_data == '=')
2195              {
2196              option_data++;
2197              longopwasequals = TRUE;
2198              }
2199            break;
2200            }
2201          }
2202        }
2203
2204      /* Handle options with an alternate spelling of the name */
2205
2206      else
2207        {
2208        char buff1[24];
2209        char buff2[24];
2210
2211        int baselen = (int)(opbra - op->long_name);
2212        int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
2213        int arglen = (argequals == NULL || equals == NULL)?
2214          (int)strlen(arg) : (int)(argequals - arg);
2215
2216        sprintf(buff1, "%.*s", baselen, op->long_name);
2217        sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);
2218
2219        if (strncmp(arg, buff1, arglen) == 0 ||
2220           strncmp(arg, buff2, arglen) == 0)
2221          {
2222          if (equals != NULL && argequals != NULL)
2223            {
2224            option_data = argequals;
2225            if (*option_data == '=')
2226              {
2227              option_data++;
2228              longopwasequals = TRUE;
2229              }
2230            }
2231          break;
2232          }
2233        }
2234      }
2235
2236    if (op->one_char == 0)
2237      {
2238      fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
2239      pcregrep_exit(usage(2));
2240      }
2241    }
2242
2243  /* Jeffrey Friedl's debugging harness uses these additional options which
2244  are not in the right form for putting in the option table because they use
2245  only one hyphen, yet are more than one character long. By putting them
2246  separately here, they will not get displayed as part of the help() output,
2247  but I don't think Jeffrey will care about that. */
2248
2249#ifdef JFRIEDL_DEBUG
2250  else if (strcmp(argv[i], "-pre") == 0) {
2251          jfriedl_prefix = argv[++i];
2252          continue;
2253  } else if (strcmp(argv[i], "-post") == 0) {
2254          jfriedl_postfix = argv[++i];
2255          continue;
2256  } else if (strcmp(argv[i], "-XT") == 0) {
2257          sscanf(argv[++i], "%d", &jfriedl_XT);
2258          continue;
2259  } else if (strcmp(argv[i], "-XR") == 0) {
2260          sscanf(argv[++i], "%d", &jfriedl_XR);
2261          continue;
2262  }
2263#endif
2264
2265
2266  /* One-char options; many that have no data may be in a single argument; we
2267  continue till we hit the last one or one that needs data. */
2268
2269  else
2270    {
2271    char *s = argv[i] + 1;
2272    longop = FALSE;
2273    while (*s != 0)
2274      {
2275      for (op = optionlist; op->one_char != 0; op++)
2276        {
2277        if (*s == op->one_char) break;
2278        }
2279      if (op->one_char == 0)
2280        {
2281        fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n",
2282          *s, argv[i]);
2283        pcregrep_exit(usage(2));
2284        }
2285
2286      /* Check for a single-character option that has data: OP_OP_NUMBER
2287      is used for one that either has a numerical number or defaults, i.e. the
2288      data is optional. If a digit follows, there is data; if not, carry on
2289      with other single-character options in the same string. */
2290
2291      option_data = s+1;
2292      if (op->type == OP_OP_NUMBER)
2293        {
2294        if (isdigit((unsigned char)s[1])) break;
2295        }
2296      else   /* Check for end or a dataless option */
2297        {
2298        if (op->type != OP_NODATA || s[1] == 0) break;
2299        }
2300
2301      /* Handle a single-character option with no data, then loop for the
2302      next character in the string. */
2303
2304      pcre_options = handle_option(*s++, pcre_options);
2305      }
2306    }
2307
2308  /* At this point we should have op pointing to a matched option. If the type
2309  is NO_DATA, it means that there is no data, and the option might set
2310  something in the PCRE options. */
2311
2312  if (op->type == OP_NODATA)
2313    {
2314    pcre_options = handle_option(op->one_char, pcre_options);
2315    continue;
2316    }
2317
2318  /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that
2319  either has a value or defaults to something. It cannot have data in a
2320  separate item. At the moment, the only such options are "colo(u)r",
2321  "only-matching", and Jeffrey Friedl's special -S debugging option. */
2322
2323  if (*option_data == 0 &&
2324      (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
2325    {
2326    switch (op->one_char)
2327      {
2328      case N_COLOUR:
2329      colour_option = (char *)"auto";
2330      break;
2331
2332      case 'o':
2333      only_matching = 0;
2334      break;
2335
2336#ifdef JFRIEDL_DEBUG
2337      case 'S':
2338      S_arg = 0;
2339      break;
2340#endif
2341      }
2342    continue;
2343    }
2344
2345  /* Otherwise, find the data string for the option. */
2346
2347  if (*option_data == 0)
2348    {
2349    if (i >= argc - 1 || longopwasequals)
2350      {
2351      fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]);
2352      pcregrep_exit(usage(2));
2353      }
2354    option_data = argv[++i];
2355    }
2356
2357  /* If the option type is OP_PATLIST, it's the -e option, which can be called
2358  multiple times to create a list of patterns. */
2359
2360  if (op->type == OP_PATLIST)
2361    {
2362    if (cmd_pattern_count >= MAX_PATTERN_COUNT)
2363      {
2364      fprintf(stderr, "pcregrep: Too many command-line patterns (max %d)\n",
2365        MAX_PATTERN_COUNT);
2366      return 2;
2367      }
2368    patterns[cmd_pattern_count++] = option_data;
2369    }
2370
2371  /* Handle OP_BINARY_FILES */
2372
2373  else if (op->type == OP_BINFILES)
2374    {
2375    if (strcmp(option_data, "binary") == 0)
2376      binary_files = BIN_BINARY;
2377    else if (strcmp(option_data, "without-match") == 0)
2378      binary_files = BIN_NOMATCH;
2379    else if (strcmp(option_data, "text") == 0)
2380      binary_files = BIN_TEXT;
2381    else
2382      {
2383      fprintf(stderr, "pcregrep: unknown value \"%s\" for binary-files\n",
2384        option_data);
2385      pcregrep_exit(usage(2));
2386      }
2387    }
2388
2389  /* Otherwise, deal with single string or numeric data values. */
2390
2391  else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
2392           op->type != OP_OP_NUMBER)
2393    {
2394    *((char **)op->dataptr) = option_data;
2395    }
2396
2397  /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
2398  only for unpicking arguments, so just keep it simple. */
2399
2400  else
2401    {
2402    unsigned long int n = 0;
2403    char *endptr = option_data;
2404    while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
2405    while (isdigit((unsigned char)(*endptr)))
2406      n = n * 10 + (int)(*endptr++ - '0');
2407    if (toupper(*endptr) == 'K')
2408      {
2409      n *= 1024;
2410      endptr++;
2411      }
2412    else if (toupper(*endptr) == 'M')
2413      {
2414      n *= 1024*1024;
2415      endptr++;
2416      }
2417    if (*endptr != 0)
2418      {
2419      if (longop)
2420        {
2421        char *equals = strchr(op->long_name, '=');
2422        int nlen = (equals == NULL)? (int)strlen(op->long_name) :
2423          (int)(equals - op->long_name);
2424        fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n",
2425          option_data, nlen, op->long_name);
2426        }
2427      else
2428        fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n",
2429          option_data, op->one_char);
2430      pcregrep_exit(usage(2));
2431      }
2432    if (op->type == OP_LONGNUMBER)
2433        *((unsigned long int *)op->dataptr) = n;
2434    else
2435        *((int *)op->dataptr) = n;
2436    }
2437  }
2438
2439/* Options have been decoded. If -C was used, its value is used as a default
2440for -A and -B. */
2441
2442if (both_context > 0)
2443  {
2444  if (after_context == 0) after_context = both_context;
2445  if (before_context == 0) before_context = both_context;
2446  }
2447
2448/* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
2449However, the latter two set only_matching. */
2450
2451if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
2452    (file_offsets && line_offsets))
2453  {
2454  fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
2455    "and/or --line-offsets\n");
2456  pcregrep_exit(usage(2));
2457  }
2458
2459if (file_offsets || line_offsets) only_matching = 0;
2460
2461/* If a locale has not been provided as an option, see if the LC_CTYPE or
2462LC_ALL environment variable is set, and if so, use it. */
2463
2464if (locale == NULL)
2465  {
2466  locale = getenv("LC_ALL");
2467  locale_from = "LCC_ALL";
2468  }
2469
2470if (locale == NULL)
2471  {
2472  locale = getenv("LC_CTYPE");
2473  locale_from = "LC_CTYPE";
2474  }
2475
2476/* If a locale has been provided, set it, and generate the tables the PCRE
2477needs. Otherwise, pcretables==NULL, which causes the use of default tables. */
2478
2479if (locale != NULL)
2480  {
2481  if (setlocale(LC_CTYPE, locale) == NULL)
2482    {
2483    fprintf(stderr, "pcregrep: Failed to set locale %s (obtained from %s)\n",
2484      locale, locale_from);
2485    return 2;
2486    }
2487  pcretables = pcre_maketables();
2488  }
2489
2490/* Sort out colouring */
2491
2492if (colour_option != NULL && strcmp(colour_option, "never") != 0)
2493  {
2494  if (strcmp(colour_option, "always") == 0) do_colour = TRUE;
2495  else if (strcmp(colour_option, "auto") == 0) do_colour = is_stdout_tty();
2496  else
2497    {
2498    fprintf(stderr, "pcregrep: Unknown colour setting \"%s\"\n",
2499      colour_option);
2500    return 2;
2501    }
2502  if (do_colour)
2503    {
2504    char *cs = getenv("PCREGREP_COLOUR");
2505    if (cs == NULL) cs = getenv("PCREGREP_COLOR");
2506    if (cs != NULL) colour_string = cs;
2507    }
2508  }
2509
2510/* Interpret the newline type; the default settings are Unix-like. */
2511
2512if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)
2513  {
2514  pcre_options |= PCRE_NEWLINE_CR;
2515  endlinetype = EL_CR;
2516  }
2517else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)
2518  {
2519  pcre_options |= PCRE_NEWLINE_LF;
2520  endlinetype = EL_LF;
2521  }
2522else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)
2523  {
2524  pcre_options |= PCRE_NEWLINE_CRLF;
2525  endlinetype = EL_CRLF;
2526  }
2527else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0)
2528  {
2529  pcre_options |= PCRE_NEWLINE_ANY;
2530  endlinetype = EL_ANY;
2531  }
2532else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0)
2533  {
2534  pcre_options |= PCRE_NEWLINE_ANYCRLF;
2535  endlinetype = EL_ANYCRLF;
2536  }
2537else
2538  {
2539  fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline);
2540  return 2;
2541  }
2542
2543/* Interpret the text values for -d and -D */
2544
2545if (dee_option != NULL)
2546  {
2547  if (strcmp(dee_option, "read") == 0) dee_action = dee_READ;
2548  else if (strcmp(dee_option, "recurse") == 0) dee_action = dee_RECURSE;
2549  else if (strcmp(dee_option, "skip") == 0) dee_action = dee_SKIP;
2550  else
2551    {
2552    fprintf(stderr, "pcregrep: Invalid value \"%s\" for -d\n", dee_option);
2553    return 2;
2554    }
2555  }
2556
2557if (DEE_option != NULL)
2558  {
2559  if (strcmp(DEE_option, "read") == 0) DEE_action = DEE_READ;
2560  else if (strcmp(DEE_option, "skip") == 0) DEE_action = DEE_SKIP;
2561  else
2562    {
2563    fprintf(stderr, "pcregrep: Invalid value \"%s\" for -D\n", DEE_option);
2564    return 2;
2565    }
2566  }
2567
2568/* Check the values for Jeffrey Friedl's debugging options. */
2569
2570#ifdef JFRIEDL_DEBUG
2571if (S_arg > 9)
2572  {
2573  fprintf(stderr, "pcregrep: bad value for -S option\n");
2574  return 2;
2575  }
2576if (jfriedl_XT != 0 || jfriedl_XR != 0)
2577  {
2578  if (jfriedl_XT == 0) jfriedl_XT = 1;
2579  if (jfriedl_XR == 0) jfriedl_XR = 1;
2580  }
2581#endif
2582
2583/* Get memory for the main buffer, and to store the pattern and hints lists. */
2584
2585bufsize = 3*bufthird;
2586main_buffer = (char *)malloc(bufsize);
2587pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
2588hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));
2589
2590if (main_buffer == NULL || pattern_list == NULL || hints_list == NULL)
2591  {
2592  fprintf(stderr, "pcregrep: malloc failed\n");
2593  goto EXIT2;
2594  }
2595
2596/* If no patterns were provided by -e, and there is no file provided by -f,
2597the first argument is the one and only pattern, and it must exist. */
2598
2599if (cmd_pattern_count == 0 && pattern_filename == NULL)
2600  {
2601  if (i >= argc) return usage(2);
2602  patterns[cmd_pattern_count++] = argv[i++];
2603  }
2604
2605/* Compile the patterns that were provided on the command line, either by
2606multiple uses of -e or as a single unkeyed pattern. */
2607
2608for (j = 0; j < cmd_pattern_count; j++)
2609  {
2610  if (!compile_pattern(patterns[j], pcre_options, NULL,
2611       (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))
2612    goto EXIT2;
2613  }
2614
2615/* Compile the regular expressions that are provided in a file. */
2616
2617if (pattern_filename != NULL)
2618  {
2619  int linenumber = 0;
2620  FILE *f;
2621  char *filename;
2622  char buffer[PATBUFSIZE];
2623
2624  if (strcmp(pattern_filename, "-") == 0)
2625    {
2626    f = stdin;
2627    filename = stdin_name;
2628    }
2629  else
2630    {
2631    f = fopen(pattern_filename, "r");
2632    if (f == NULL)
2633      {
2634      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,
2635        strerror(errno));
2636      goto EXIT2;
2637      }
2638    filename = pattern_filename;
2639    }
2640
2641  while (fgets(buffer, PATBUFSIZE, f) != NULL)
2642    {
2643    char *s = buffer + (int)strlen(buffer);
2644    while (s > buffer && isspace((unsigned char)(s[-1]))) s--;
2645    *s = 0;
2646    linenumber++;
2647    if (buffer[0] == 0) continue;   /* Skip blank lines */
2648    if (!compile_pattern(buffer, pcre_options, filename, linenumber))
2649      goto EXIT2;
2650    }
2651
2652  if (f != stdin) fclose(f);
2653  }
2654
2655/* Study the regular expressions, as we will be running them many times. Unless
2656JIT has been explicitly disabled, arrange a stack for it to use. */
2657
2658#ifdef SUPPORT_PCREGREP_JIT
2659if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0)
2660  jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024);
2661#endif
2662
2663for (j = 0; j < pattern_count; j++)
2664  {
2665  hints_list[j] = pcre_study(pattern_list[j], study_options, &error);
2666  if (error != NULL)
2667    {
2668    char s[16];
2669    if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);
2670    fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
2671    goto EXIT2;
2672    }
2673  hint_count++;
2674#ifdef SUPPORT_PCREGREP_JIT
2675  if (jit_stack != NULL && hints_list[j] != NULL)
2676    pcre_assign_jit_stack(hints_list[j], NULL, jit_stack);
2677#endif
2678  }
2679
2680/* If --match-limit or --recursion-limit was set, put the value(s) into the
2681pcre_extra block for each pattern. */
2682
2683if (match_limit > 0 || match_limit_recursion > 0)
2684  {
2685  for (j = 0; j < pattern_count; j++)
2686    {
2687    if (hints_list[j] == NULL)
2688      {
2689      hints_list[j] = malloc(sizeof(pcre_extra));
2690      if (hints_list[j] == NULL)
2691        {
2692        fprintf(stderr, "pcregrep: malloc failed\n");
2693        pcregrep_exit(2);
2694        }
2695      }
2696    if (match_limit > 0)
2697      {
2698      hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
2699      hints_list[j]->match_limit = match_limit;
2700      }
2701    if (match_limit_recursion > 0)
2702      {
2703      hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2704      hints_list[j]->match_limit_recursion = match_limit_recursion;
2705      }
2706    }
2707  }
2708
2709/* If there are include or exclude patterns, compile them. */
2710
2711if (exclude_pattern != NULL)
2712  {
2713  exclude_compiled = pcre_compile(exclude_pattern, 0, &error, &errptr,
2714    pcretables);
2715  if (exclude_compiled == NULL)
2716    {
2717    fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n",
2718      errptr, error);
2719    goto EXIT2;
2720    }
2721  }
2722
2723if (include_pattern != NULL)
2724  {
2725  include_compiled = pcre_compile(include_pattern, 0, &error, &errptr,
2726    pcretables);
2727  if (include_compiled == NULL)
2728    {
2729    fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n",
2730      errptr, error);
2731    goto EXIT2;
2732    }
2733  }
2734
2735if (exclude_dir_pattern != NULL)
2736  {
2737  exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
2738    pcretables);
2739  if (exclude_dir_compiled == NULL)
2740    {
2741    fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
2742      errptr, error);
2743    goto EXIT2;
2744    }
2745  }
2746
2747if (include_dir_pattern != NULL)
2748  {
2749  include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
2750    pcretables);
2751  if (include_dir_compiled == NULL)
2752    {
2753    fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
2754      errptr, error);
2755    goto EXIT2;
2756    }
2757  }
2758
2759/* If a file that contains a list of files to search has been specified, read
2760it line by line and search the given files. Otherwise, if there are no further
2761arguments, do the business on stdin and exit. */
2762
2763if (file_list != NULL)
2764  {
2765  char buffer[PATBUFSIZE];
2766  FILE *fl;
2767  if (strcmp(file_list, "-") == 0) fl = stdin; else
2768    {
2769    fl = fopen(file_list, "rb");
2770    if (fl == NULL)
2771      {
2772      fprintf(stderr, "pcregrep: Failed to open %s: %s\n", file_list,
2773        strerror(errno));
2774      goto EXIT2;
2775      }
2776    }
2777  while (fgets(buffer, PATBUFSIZE, fl) != NULL)
2778    {
2779    int frc;
2780    char *end = buffer + (int)strlen(buffer);
2781    while (end > buffer && isspace(end[-1])) end--;
2782    *end = 0;
2783    if (*buffer != 0)
2784      {
2785      frc = grep_or_recurse(buffer, dee_action == dee_RECURSE, FALSE);
2786      if (frc > 1) rc = frc;
2787        else if (frc == 0 && rc == 1) rc = 0;
2788      }
2789    }
2790  if (fl != stdin) fclose (fl);
2791  }
2792
2793/* Do this only if there was no file list (and no file arguments). */
2794
2795else if (i >= argc)
2796  {
2797  rc = pcregrep(stdin, FR_PLAIN, stdin_name,
2798    (filenames > FN_DEFAULT)? stdin_name : NULL);
2799  goto EXIT;
2800  }
2801
2802/* After handling file-list or if there are remaining arguments, work through
2803them as files or directories. Pass in the fact that there is only one argument
2804at top level - this suppresses the file name if the argument is not a directory
2805and filenames are not otherwise forced. */
2806
2807only_one_at_top = i == argc - 1 && file_list == NULL;
2808
2809for (; i < argc; i++)
2810  {
2811  int frc = grep_or_recurse(argv[i], dee_action == dee_RECURSE,
2812    only_one_at_top);
2813  if (frc > 1) rc = frc;
2814    else if (frc == 0 && rc == 1) rc = 0;
2815  }
2816
2817EXIT:
2818#ifdef SUPPORT_PCREGREP_JIT
2819if (jit_stack != NULL) pcre_jit_stack_free(jit_stack);
2820#endif
2821if (main_buffer != NULL) free(main_buffer);
2822if (pattern_list != NULL)
2823  {
2824  for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
2825  free(pattern_list);
2826  }
2827if (hints_list != NULL)
2828  {
2829  for (i = 0; i < hint_count; i++)
2830    {
2831    if (hints_list[i] != NULL) pcre_free_study(hints_list[i]);
2832    }
2833  free(hints_list);
2834  }
2835pcregrep_exit(rc);
2836
2837EXIT2:
2838rc = 2;
2839goto EXIT;
2840}
2841
2842/* End of pcregrep */
2843