xref: /netbsd-src/external/gpl2/grep/dist/src/grep.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: grep.c,v 1.2 2016/01/10 22:16:40 christos Exp $	*/
2 
3 /* grep.c - main driver file for grep.
4    Copyright 1992, 1997-1999, 2000 Free Software Foundation, Inc.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20 
21 /* Written July 1992 by Mike Haertel.  */
22 
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #if defined(HAVE_MMAP)
29 # include <sys/mman.h>
30 #endif
31 #if defined(HAVE_SETRLIMIT)
32 # include <sys/time.h>
33 # include <sys/resource.h>
34 #endif
35 #include <stdio.h>
36 #include "system.h"
37 #include "getopt.h"
38 #include "getpagesize.h"
39 #include "grep.h"
40 #include "savedir.h"
41 #include "xstrtol.h"
42 #include "xalloc.h"
43 #include "error.h"
44 #include "exclude.h"
45 #include "closeout.h"
46 
47 #undef MAX
48 #define MAX(A,B) ((A) > (B) ? (A) : (B))
49 
50 struct stats
51 {
52   struct stats const *parent;
53   struct stat stat;
54 };
55 
56 #include <limits.h>
57 #define MAX_OFF_T (sizeof(off_t) == sizeof(char) ? INT_MAX : \
58                    (sizeof(off_t) == sizeof(short) ? SHRT_MAX : \
59                     (sizeof(off_t) == sizeof(int) ? INT_MAX : \
60                      (sizeof(off_t) == sizeof(long) ? LONG_MAX : \
61                       (sizeof(off_t) == sizeof(long long) ? LLONG_MAX : INTMAX_MAX)))))
62 
63 /* base of chain of stat buffers, used to detect directory loops */
64 static struct stats stats_base;
65 
66 /* if non-zero, display usage information and exit */
67 static int show_help;
68 
69 /* If non-zero, print the version on standard output and exit.  */
70 static int show_version;
71 
72 /* If nonzero, suppress diagnostics for nonexistent or unreadable files.  */
73 static int suppress_errors;
74 
75 /* If nonzero, use mmap if possible.  */
76 static int mmap_option;
77 
78 /* If nonzero, use grep_color marker.  */
79 static int color_option;
80 
81 /* If nonzero, show only the part of a line matching the expression. */
82 static int only_matching;
83 
84 /* The color string used.  The user can overwrite it using the environment
85    variable GREP_COLOR.  The default is to print red.  */
86 static const char *grep_color = "01;31";
87 
88 static struct exclude *excluded_patterns;
89 static struct exclude *included_patterns;
90 /* Short options.  */
91 static char const short_options[] =
92 "0123456789A:B:C:D:EFGHIPUVX:abcd:e:f:hiKLlm:noqRrsuvwxyZz";
93 
94 /* Non-boolean long options that have no corresponding short equivalents.  */
95 enum
96 {
97   BINARY_FILES_OPTION = CHAR_MAX + 1,
98   COLOR_OPTION,
99   INCLUDE_OPTION,
100   EXCLUDE_OPTION,
101   EXCLUDE_FROM_OPTION,
102   LINE_BUFFERED_OPTION,
103   LABEL_OPTION
104 };
105 
106 /* Long options equivalences. */
107 static struct option const long_options[] =
108 {
109   {"after-context", required_argument, NULL, 'A'},
110   {"basic-regexp", no_argument, NULL, 'G'},
111   {"before-context", required_argument, NULL, 'B'},
112   {"binary-files", required_argument, NULL, BINARY_FILES_OPTION},
113   {"byte-offset", no_argument, NULL, 'b'},
114   {"context", required_argument, NULL, 'C'},
115   {"color", optional_argument, NULL, COLOR_OPTION},
116   {"colour", optional_argument, NULL, COLOR_OPTION},
117   {"count", no_argument, NULL, 'c'},
118   {"devices", required_argument, NULL, 'D'},
119   {"directories", required_argument, NULL, 'd'},
120   {"extended-regexp", no_argument, NULL, 'E'},
121   {"exclude", required_argument, NULL, EXCLUDE_OPTION},
122   {"exclude-from", required_argument, NULL, EXCLUDE_FROM_OPTION},
123   {"file", required_argument, NULL, 'f'},
124   {"files-with-matches", no_argument, NULL, 'l'},
125   {"files-without-match", no_argument, NULL, 'L'},
126   {"fixed-regexp", no_argument, NULL, 'F'},
127   {"fixed-strings", no_argument, NULL, 'F'},
128   {"help", no_argument, &show_help, 1},
129   {"include", required_argument, NULL, INCLUDE_OPTION},
130   {"ignore-case", no_argument, NULL, 'i'},
131   {"label", required_argument, NULL, LABEL_OPTION},
132   {"line-buffered", no_argument, NULL, LINE_BUFFERED_OPTION},
133   {"line-number", no_argument, NULL, 'n'},
134   {"line-regexp", no_argument, NULL, 'x'},
135   {"max-count", required_argument, NULL, 'm'},
136   {"mmap", no_argument, &mmap_option, 1},
137   {"no-filename", no_argument, NULL, 'h'},
138   {"no-messages", no_argument, NULL, 's'},
139   {"null", no_argument, NULL, 'Z'},
140   {"null-data", no_argument, NULL, 'z'},
141   {"only-matching", no_argument, NULL, 'o'},
142   {"perl-regexp", no_argument, NULL, 'P'},
143   {"quiet", no_argument, NULL, 'q'},
144   {"recursive", no_argument, NULL, 'r'},
145   {"recursive", no_argument, NULL, 'R'},
146   {"regexp", required_argument, NULL, 'e'},
147   {"invert-match", no_argument, NULL, 'v'},
148   {"silent", no_argument, NULL, 'q'},
149   {"text", no_argument, NULL, 'a'},
150   {"binary", no_argument, NULL, 'U'},
151   {"unix-byte-offsets", no_argument, NULL, 'u'},
152   {"version", no_argument, NULL, 'V'},
153   {"with-filename", no_argument, NULL, 'H'},
154   {"word-regexp", no_argument, NULL, 'w'},
155   {0, 0, 0, 0}
156 };
157 
158 /* Define flags declared in grep.h. */
159 int match_icase;
160 int match_words;
161 int match_lines;
162 unsigned char eolbyte;
163 
164 /* For error messages. */
165 /* The name the program was run with, stripped of any leading path. */
166 char *program_name;
167 static char const *filename;
168 static int errseen;
169 
170 /* How to handle directories.  */
171 static enum
172   {
173     READ_DIRECTORIES,
174     RECURSE_DIRECTORIES,
175     SKIP_DIRECTORIES
176   } directories = READ_DIRECTORIES;
177 
178 /* How to handle devices. */
179 static enum
180   {
181     READ_DEVICES,
182     SKIP_DEVICES
183   } devices = READ_DEVICES;
184 
185 static int grepdir PARAMS ((char const *, struct stats const *));
186 #if defined(HAVE_DOS_FILE_CONTENTS)
187 static inline int undossify_input PARAMS ((register char *, size_t));
188 #endif
189 
190 /* Functions we'll use to search. */
191 static void (*compile) PARAMS ((char const *, size_t));
192 static size_t (*execute) PARAMS ((char const *, size_t, size_t *, int));
193 
194 /* Like error, but suppress the diagnostic if requested.  */
195 static void
196 suppressible_error (char const *mesg, int errnum)
197 {
198   if (! suppress_errors)
199     error (0, errnum, "%s", mesg);
200   errseen = 1;
201 }
202 
203 /* Convert STR to a positive integer, storing the result in *OUT.
204    STR must be a valid context length argument; report an error if it
205    isn't.  */
206 static void
207 context_length_arg (char const *str, int *out)
208 {
209   uintmax_t value;
210   if (! (xstrtoumax (str, 0, 10, &value, "") == LONGINT_OK
211 	 && 0 <= (*out = value)
212 	 && *out == value))
213     {
214       error (2, 0, "%s: %s", str, _("invalid context length argument"));
215     }
216 }
217 
218 
219 /* Hairy buffering mechanism for grep.  The intent is to keep
220    all reads aligned on a page boundary and multiples of the
221    page size, unless a read yields a partial page.  */
222 
223 static char *buffer;		/* Base of buffer. */
224 static size_t bufalloc;		/* Allocated buffer size, counting slop. */
225 #define INITIAL_BUFSIZE 32768	/* Initial buffer size, not counting slop. */
226 static int bufdesc;		/* File descriptor. */
227 static char *bufbeg;		/* Beginning of user-visible stuff. */
228 static char *buflim;		/* Limit of user-visible stuff. */
229 static size_t pagesize;		/* alignment of memory pages */
230 static off_t bufoffset;		/* Read offset; defined on regular files.  */
231 static off_t after_last_match;	/* Pointer after last matching line that
232 				   would have been output if we were
233 				   outputting characters. */
234 
235 #if defined(HAVE_MMAP)
236 static int bufmapped;		/* True if buffer is memory-mapped.  */
237 static off_t initial_bufoffset;	/* Initial value of bufoffset. */
238 #else
239 # define bufmapped 0
240 #endif
241 
242 /* Return VAL aligned to the next multiple of ALIGNMENT.  VAL can be
243    an integer or a pointer.  Both args must be free of side effects.  */
244 #define ALIGN_TO(val, alignment) \
245   ((size_t) (val) % (alignment) == 0 \
246    ? (val) \
247    : (val) + ((alignment) - (size_t) (val) % (alignment)))
248 
249 /* Reset the buffer for a new file, returning zero if we should skip it.
250    Initialize on the first time through. */
251 static int
252 reset (int fd, char const *file, struct stats *stats)
253 {
254   if (! pagesize)
255     {
256       pagesize = getpagesize ();
257       if (pagesize == 0 || 2 * pagesize + 1 <= pagesize)
258 	abort ();
259       bufalloc = ALIGN_TO (INITIAL_BUFSIZE, pagesize) + pagesize + 1;
260       buffer = xmalloc (bufalloc);
261     }
262 
263   bufbeg = buflim = ALIGN_TO (buffer + 1, pagesize);
264   bufbeg[-1] = eolbyte;
265   bufdesc = fd;
266 
267   if (fstat (fd, &stats->stat) != 0)
268     {
269       error (0, errno, "fstat");
270       return 0;
271     }
272   if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode))
273     return 0;
274 #ifndef DJGPP
275   if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode) || S_ISSOCK(stats->stat.st_mode)))
276 #else
277   if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode)))
278 #endif
279     return 0;
280   if (S_ISREG (stats->stat.st_mode))
281     {
282       if (file)
283 	bufoffset = 0;
284       else
285 	{
286 	  bufoffset = lseek (fd, 0, SEEK_CUR);
287 	  if (bufoffset < 0)
288 	    {
289 	      error (0, errno, "lseek");
290 	      return 0;
291 	    }
292 	}
293 #if defined(HAVE_MMAP)
294       initial_bufoffset = bufoffset;
295       bufmapped = mmap_option && bufoffset % pagesize == 0;
296 #endif
297     }
298   else
299     {
300 #if defined(HAVE_MMAP)
301       bufmapped = 0;
302 #endif
303     }
304   return 1;
305 }
306 
307 /* Read new stuff into the buffer, saving the specified
308    amount of old stuff.  When we're done, 'bufbeg' points
309    to the beginning of the buffer contents, and 'buflim'
310    points just after the end.  Return zero if there's an error.  */
311 static int
312 fillbuf (size_t save, struct stats const *stats)
313 {
314   size_t fillsize = 0;
315   int cc = 1;
316   char *readbuf;
317   size_t readsize;
318 
319   /* Offset from start of buffer to start of old stuff
320      that we want to save.  */
321   size_t saved_offset = buflim - save - buffer;
322 
323   if (pagesize <= buffer + bufalloc - buflim)
324     {
325       readbuf = buflim;
326       bufbeg = buflim - save;
327     }
328   else
329     {
330       size_t minsize = save + pagesize;
331       size_t newsize;
332       size_t newalloc;
333       char *newbuf;
334 
335       /* Grow newsize until it is at least as great as minsize.  */
336       for (newsize = bufalloc - pagesize - 1; newsize < minsize; newsize *= 2)
337 	if (newsize * 2 < newsize || newsize * 2 + pagesize + 1 < newsize * 2)
338 	  xalloc_die ();
339 
340       /* Try not to allocate more memory than the file size indicates,
341 	 as that might cause unnecessary memory exhaustion if the file
342 	 is large.  However, do not use the original file size as a
343 	 heuristic if we've already read past the file end, as most
344 	 likely the file is growing.  */
345       if (S_ISREG (stats->stat.st_mode))
346 	{
347 	  off_t to_be_read = stats->stat.st_size - bufoffset;
348 	  off_t maxsize_off = save + to_be_read;
349 	  if (0 <= to_be_read && to_be_read <= maxsize_off
350 	      && maxsize_off == (size_t) maxsize_off
351 	      && minsize <= (size_t) maxsize_off
352 	      && (size_t) maxsize_off < newsize)
353 	    newsize = maxsize_off;
354 	}
355 
356       /* Add enough room so that the buffer is aligned and has room
357 	 for byte sentinels fore and aft.  */
358       newalloc = newsize + pagesize + 1;
359 
360       newbuf = bufalloc < newalloc ? xmalloc (bufalloc = newalloc) : buffer;
361       readbuf = ALIGN_TO (newbuf + 1 + save, pagesize);
362       bufbeg = readbuf - save;
363       memmove (bufbeg, buffer + saved_offset, save);
364       bufbeg[-1] = eolbyte;
365       if (newbuf != buffer)
366 	{
367 	  free (buffer);
368 	  buffer = newbuf;
369 	}
370     }
371 
372   readsize = buffer + bufalloc - readbuf;
373   readsize -= readsize % pagesize;
374 
375 #if defined(HAVE_MMAP)
376   if (bufmapped)
377     {
378       size_t mmapsize = readsize;
379 
380       /* Don't mmap past the end of the file; some hosts don't allow this.
381 	 Use `read' on the last page.  */
382       if (stats->stat.st_size - bufoffset < mmapsize)
383 	{
384 	  mmapsize = stats->stat.st_size - bufoffset;
385 	  mmapsize -= mmapsize % pagesize;
386 	}
387 
388       if (mmapsize
389 	  && (mmap ((caddr_t) readbuf, mmapsize,
390 		    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
391 		    bufdesc, bufoffset)
392 	      != (caddr_t) -1))
393 	{
394 	  /* Do not bother to use madvise with MADV_SEQUENTIAL or
395 	     MADV_WILLNEED on the mmapped memory.  One might think it
396 	     would help, but it slows us down about 30% on SunOS 4.1.  */
397 	  fillsize = mmapsize;
398 	}
399       else
400 	{
401 	  /* Stop using mmap on this file.  Synchronize the file
402 	     offset.  Do not warn about mmap failures.  On some hosts
403 	     (e.g. Solaris 2.5) mmap can fail merely because some
404 	     other process has an advisory read lock on the file.
405 	     There's no point alarming the user about this misfeature.  */
406 	  bufmapped = 0;
407 	  if (bufoffset != initial_bufoffset
408 	      && lseek (bufdesc, bufoffset, SEEK_SET) < 0)
409 	    {
410 	      error (0, errno, "lseek");
411 	      cc = 0;
412 	    }
413 	}
414     }
415 #endif /*HAVE_MMAP*/
416 
417   if (! fillsize)
418     {
419       ssize_t bytesread;
420       while ((bytesread = read (bufdesc, readbuf, readsize)) < 0
421 	     && errno == EINTR)
422 	continue;
423       if (bytesread < 0)
424 	cc = 0;
425       else
426 	fillsize = bytesread;
427     }
428 
429   bufoffset += fillsize;
430 #if defined(HAVE_DOS_FILE_CONTENTS)
431   if (fillsize)
432     fillsize = undossify_input (readbuf, fillsize);
433 #endif
434   buflim = readbuf + fillsize;
435   return cc;
436 }
437 
438 /* Flags controlling the style of output. */
439 static enum
440 {
441   BINARY_BINARY_FILES,
442   TEXT_BINARY_FILES,
443   WITHOUT_MATCH_BINARY_FILES
444 } binary_files;		/* How to handle binary files.  */
445 
446 static int filename_mask;	/* If zero, output nulls after filenames.  */
447 static int out_quiet;		/* Suppress all normal output. */
448 static int out_invert;		/* Print nonmatching stuff. */
449 static int out_file;		/* Print filenames. */
450 static int out_line;		/* Print line numbers. */
451 static int out_byte;		/* Print byte offsets. */
452 static int out_before;		/* Lines of leading context. */
453 static int out_after;		/* Lines of trailing context. */
454 static int count_matches;	/* Count matching lines.  */
455 static int list_files;		/* List matching files.  */
456 static int no_filenames;	/* Suppress file names.  */
457 static off_t max_count;		/* Stop after outputting this many
458 				   lines from an input file.  */
459 static int line_buffered;       /* If nonzero, use line buffering, i.e.
460 				   fflush everyline out.  */
461 static char *label = NULL;      /* Fake filename for stdin */
462 
463 
464 /* Internal variables to keep track of byte count, context, etc. */
465 static uintmax_t totalcc;	/* Total character count before bufbeg. */
466 static char const *lastnl;	/* Pointer after last newline counted. */
467 static char const *lastout;	/* Pointer after last character output;
468 				   NULL if no character has been output
469 				   or if it's conceptually before bufbeg. */
470 static uintmax_t totalnl;	/* Total newline count before lastnl. */
471 static off_t outleft;		/* Maximum number of lines to be output.  */
472 static int pending;		/* Pending lines of output.
473 				   Always kept 0 if out_quiet is true.  */
474 static int done_on_match;	/* Stop scanning file on first match.  */
475 static int exit_on_match;	/* Exit on first match.  */
476 
477 #if defined(HAVE_DOS_FILE_CONTENTS)
478 # include "dosbuf.c"
479 #endif
480 
481 /* Add two numbers that count input bytes or lines, and report an
482    error if the addition overflows.  */
483 static uintmax_t
484 add_count (uintmax_t a, uintmax_t b)
485 {
486   uintmax_t sum = a + b;
487   if (sum < a)
488     error (2, 0, _("input is too large to count"));
489   return sum;
490 }
491 
492 static void
493 nlscan (char const *lim)
494 {
495   size_t newlines = 0;
496   char const *beg;
497   for (beg = lastnl; beg != lim; beg = memchr (beg, eolbyte, lim - beg), beg++)
498     newlines++;
499   totalnl = add_count (totalnl, newlines);
500   lastnl = lim;
501 }
502 
503 /* Print a byte offset, followed by a character separator.  */
504 static void
505 print_offset_sep (uintmax_t pos, char sep)
506 {
507   /* Do not rely on printf to print pos, since uintmax_t may be longer
508      than long, and long long is not portable.  */
509 
510   char buf[sizeof pos * CHAR_BIT];
511   char *p = buf + sizeof buf - 1;
512   *p = sep;
513 
514   do
515     *--p = '0' + pos % 10;
516   while ((pos /= 10) != 0);
517 
518   fwrite (p, 1, buf + sizeof buf - p, stdout);
519 }
520 
521 static void
522 prline (char const *beg, char const *lim, int sep)
523 {
524   if (out_file)
525     printf ("%s%c", filename, sep & filename_mask);
526   if (out_line)
527     {
528       nlscan (beg);
529       totalnl = add_count (totalnl, 1);
530       print_offset_sep (totalnl, sep);
531       lastnl = lim;
532     }
533   if (out_byte)
534     {
535       uintmax_t pos = add_count (totalcc, beg - bufbeg);
536 #if defined(HAVE_DOS_FILE_CONTENTS)
537       pos = dossified_pos (pos);
538 #endif
539       print_offset_sep (pos, sep);
540     }
541   if (only_matching)
542     {
543       size_t match_size;
544       size_t match_offset;
545       while ((match_offset = (*execute) (beg, lim - beg, &match_size, 1))
546 	  != (size_t) -1)
547         {
548 	  char const *b = beg + match_offset;
549 	  if (b == lim)
550 	    break;
551 	  if (match_size == 0)
552 	    {
553 	      beg++;
554 	      continue;
555 	    }
556 	  if(color_option)
557 	    printf("\33[%sm", grep_color);
558 	  fwrite(b, sizeof (char), match_size, stdout);
559 	  if(color_option)
560 	    fputs("\33[00m", stdout);
561 	  fputs("\n", stdout);
562 	  beg = b + match_size;
563         }
564       lastout = lim;
565       if(line_buffered)
566 	fflush(stdout);
567       return;
568     }
569   if (color_option)
570     {
571       size_t match_size;
572       size_t match_offset;
573       if(match_icase)
574         {
575 	  /* Yuck, this is tricky */
576           char *buf = (char*) xmalloc (lim - beg);
577 	  char *ibeg = buf;
578 	  char *ilim = ibeg + (lim - beg);
579 	  int i;
580 	  for (i = 0; i < lim - beg; i++)
581 	    ibeg[i] = tolower (beg[i]);
582 	  while ((match_offset = (*execute) (ibeg, ilim-ibeg, &match_size, 1))
583 		 != (size_t) -1)
584 	    {
585 	      char const *b = beg + match_offset;
586 	      if (b == lim)
587 		break;
588 	      fwrite (beg, sizeof (char), match_offset, stdout);
589 	      printf ("\33[%sm", grep_color);
590 	      fwrite (b, sizeof (char), match_size, stdout);
591 	      fputs ("\33[00m", stdout);
592 	      beg = b + match_size;
593 	      ibeg = ibeg + match_offset + match_size;
594 	    }
595 	  fwrite (beg, 1, lim - beg, stdout);
596 	  free (buf);
597 	  lastout = lim;
598 	  return;
599 	}
600       while (lim-beg && (match_offset = (*execute) (beg, lim - beg, &match_size, 1))
601 	     != (size_t) -1)
602 	{
603 	  char const *b = beg + match_offset;
604 	  /* Avoid matching the empty line at the end of the buffer. */
605 	  if (b == lim)
606 	    break;
607 	  /* Avoid hanging on grep --color "" foo */
608 	  if (match_size == 0)
609 	    break;
610 	  fwrite (beg, sizeof (char), match_offset, stdout);
611 	  printf ("\33[%sm", grep_color);
612 	  fwrite (b, sizeof (char), match_size, stdout);
613 	  fputs ("\33[00m", stdout);
614 	  beg = b + match_size;
615 	}
616     }
617   fwrite (beg, 1, lim - beg, stdout);
618   if (ferror (stdout))
619     error (0, errno, _("writing output"));
620   lastout = lim;
621   if (line_buffered)
622     fflush (stdout);
623 }
624 
625 /* Print pending lines of trailing context prior to LIM. Trailing context ends
626    at the next matching line when OUTLEFT is 0.  */
627 static void
628 prpending (char const *lim)
629 {
630   if (!lastout)
631     lastout = bufbeg;
632   while (pending > 0 && lastout < lim)
633     {
634       char const *nl = memchr (lastout, eolbyte, lim - lastout);
635       size_t match_size;
636       --pending;
637       if (outleft
638 	  || (((*execute) (lastout, nl - lastout, &match_size, 0) == (size_t) -1)
639 	      == !out_invert))
640 	prline (lastout, nl + 1, '-');
641       else
642 	pending = 0;
643     }
644 }
645 
646 /* Print the lines between BEG and LIM.  Deal with context crap.
647    If NLINESP is non-null, store a count of lines between BEG and LIM.  */
648 static void
649 prtext (char const *beg, char const *lim, int *nlinesp)
650 {
651   static int used;		/* avoid printing "--" before any output */
652   char const *bp, *p;
653   char eol = eolbyte;
654   int i, n;
655 
656   if (!out_quiet && pending > 0)
657     prpending (beg);
658 
659   p = beg;
660 
661   if (!out_quiet)
662     {
663       /* Deal with leading context crap. */
664 
665       bp = lastout ? lastout : bufbeg;
666       for (i = 0; i < out_before; ++i)
667 	if (p > bp)
668 	  do
669 	    --p;
670 	  while (p[-1] != eol);
671 
672       /* We only print the "--" separator if our output is
673 	 discontiguous from the last output in the file. */
674       if ((out_before || out_after) && used && p != lastout)
675 	puts ("--");
676 
677       while (p < beg)
678 	{
679 	  char const *nl = memchr (p, eol, beg - p);
680 	  nl++;
681 	  prline (p, nl, '-');
682 	  p = nl;
683 	}
684     }
685 
686   if (nlinesp)
687     {
688       /* Caller wants a line count. */
689       for (n = 0; p < lim && n < outleft; n++)
690 	{
691 	  char const *nl = memchr (p, eol, lim - p);
692 	  nl++;
693 	  if (!out_quiet)
694 	    prline (p, nl, ':');
695 	  p = nl;
696 	}
697       *nlinesp = n;
698 
699       /* relying on it that this function is never called when outleft = 0.  */
700       after_last_match = bufoffset - (buflim - p);
701     }
702   else
703     if (!out_quiet)
704       prline (beg, lim, ':');
705 
706   pending = out_quiet ? 0 : out_after;
707   used = 1;
708 }
709 
710 /* Scan the specified portion of the buffer, matching lines (or
711    between matching lines if OUT_INVERT is true).  Return a count of
712    lines printed. */
713 static int
714 grepbuf (char const *beg, char const *lim)
715 {
716   int nlines, n;
717   register char const *p;
718   size_t match_offset;
719   size_t match_size;
720 
721   nlines = 0;
722   p = beg;
723   while ((match_offset = (*execute) (p, lim - p, &match_size, 0)) != (size_t) -1)
724     {
725       char const *b = p + match_offset;
726       char const *endp = b + match_size;
727       /* Avoid matching the empty line at the end of the buffer. */
728       if (b == lim)
729 	break;
730       if (!out_invert)
731 	{
732 	  prtext (b, endp, (int *) 0);
733 	  nlines++;
734           outleft--;
735 	  if (!outleft || done_on_match)
736 	    {
737 	      if (exit_on_match)
738 		exit (0);
739 	      after_last_match = bufoffset - (buflim - endp);
740 	      return nlines;
741 	    }
742 	}
743       else if (p < b)
744 	{
745 	  prtext (p, b, &n);
746 	  nlines += n;
747           outleft -= n;
748 	  if (!outleft)
749 	    return nlines;
750 	}
751       p = endp;
752     }
753   if (out_invert && p < lim)
754     {
755       prtext (p, lim, &n);
756       nlines += n;
757       outleft -= n;
758     }
759   return nlines;
760 }
761 
762 /* Search a given file.  Normally, return a count of lines printed;
763    but if the file is a directory and we search it recursively, then
764    return -2 if there was a match, and -1 otherwise.  */
765 static int
766 grep (int fd, char const *file, struct stats *stats)
767 {
768   int nlines, i;
769   int not_text;
770   size_t residue, save;
771   char oldc;
772   char *beg;
773   char *lim;
774   char eol = eolbyte;
775 
776   if (!reset (fd, file, stats))
777     return 0;
778 
779   if (file && directories == RECURSE_DIRECTORIES
780       && S_ISDIR (stats->stat.st_mode))
781     {
782       /* Close fd now, so that we don't open a lot of file descriptors
783 	 when we recurse deeply.  */
784       if (close (fd) != 0)
785 	error (0, errno, "%s", file);
786       return grepdir (file, stats) - 2;
787     }
788 
789   totalcc = 0;
790   lastout = 0;
791   totalnl = 0;
792   outleft = max_count;
793   after_last_match = 0;
794   pending = 0;
795 
796   nlines = 0;
797   residue = 0;
798   save = 0;
799 
800   if (! fillbuf (save, stats))
801     {
802       if (! is_EISDIR (errno, file))
803 	suppressible_error (filename, errno);
804       return 0;
805     }
806 
807   not_text = (((binary_files == BINARY_BINARY_FILES && !out_quiet)
808 	       || binary_files == WITHOUT_MATCH_BINARY_FILES)
809 	      && memchr (bufbeg, eol ? '\0' : '\200', buflim - bufbeg));
810   if (not_text && binary_files == WITHOUT_MATCH_BINARY_FILES)
811     return 0;
812   done_on_match += not_text;
813   out_quiet += not_text;
814 
815   for (;;)
816     {
817       lastnl = bufbeg;
818       if (lastout)
819 	lastout = bufbeg;
820 
821       beg = bufbeg + save;
822 
823       /* no more data to scan (eof) except for maybe a residue -> break */
824       if (beg == buflim)
825 	break;
826 
827       /* Determine new residue (the length of an incomplete line at the end of
828          the buffer, 0 means there is no incomplete last line).  */
829       oldc = beg[-1];
830       beg[-1] = eol;
831       for (lim = buflim; lim[-1] != eol; lim--)
832 	continue;
833       beg[-1] = oldc;
834       if (lim == beg)
835 	lim = beg - residue;
836       beg -= residue;
837       residue = buflim - lim;
838 
839       if (beg < lim)
840 	{
841 	  if (outleft)
842 	    nlines += grepbuf (beg, lim);
843 	  if (pending)
844 	    prpending (lim);
845 	  if((!outleft && !pending) || (nlines && done_on_match && !out_invert))
846 	    goto finish_grep;
847 	}
848 
849       /* The last OUT_BEFORE lines at the end of the buffer will be needed as
850 	 leading context if there is a matching line at the begin of the
851 	 next data. Make beg point to their begin.  */
852       i = 0;
853       beg = lim;
854       while (i < out_before && beg > bufbeg && beg != lastout)
855 	{
856 	  ++i;
857 	  do
858 	    --beg;
859 	  while (beg[-1] != eol);
860 	}
861 
862       /* detect if leading context is discontinuous from last printed line.  */
863       if (beg != lastout)
864 	lastout = 0;
865 
866       /* Handle some details and read more data to scan.  */
867       save = residue + lim - beg;
868       if (out_byte)
869 	totalcc = add_count (totalcc, buflim - bufbeg - save);
870       if (out_line)
871 	nlscan (beg);
872       if (! fillbuf (save, stats))
873 	{
874 	  if (! is_EISDIR (errno, file))
875 	    suppressible_error (filename, errno);
876 	  goto finish_grep;
877 	}
878     }
879   if (residue)
880     {
881       *buflim++ = eol;
882       if (outleft)
883 	nlines += grepbuf (bufbeg + save - residue, buflim);
884       if (pending)
885         prpending (buflim);
886     }
887 
888  finish_grep:
889   done_on_match -= not_text;
890   out_quiet -= not_text;
891   if ((not_text & ~out_quiet) && nlines != 0)
892     printf (_("Binary file %s matches\n"), filename);
893   return nlines;
894 }
895 
896 static int
897 grepfile (char const *file, struct stats *stats)
898 {
899   int desc;
900   int count;
901   int status;
902 
903   if (! file)
904     {
905       desc = 0;
906       filename = label ? label : _("(standard input)");
907     }
908   else
909     {
910       while ((desc = open (file, O_RDONLY)) < 0 && errno == EINTR)
911 	continue;
912 
913       if (desc < 0)
914 	{
915 	  int e = errno;
916 
917 	  if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES)
918 	    {
919 	      if (stat (file, &stats->stat) != 0)
920 		{
921 		  error (0, errno, "%s", file);
922 		  return 1;
923 		}
924 
925 	      return grepdir (file, stats);
926 	    }
927 
928 	  if (!suppress_errors)
929 	    {
930 	      if (directories == SKIP_DIRECTORIES)
931 		switch (e)
932 		  {
933 #if defined(EISDIR)
934 		  case EISDIR:
935 		    return 1;
936 #endif
937 		  case EACCES:
938 		    /* When skipping directories, don't worry about
939 		       directories that can't be opened.  */
940 		    if (isdir (file))
941 		      return 1;
942 		    break;
943 		  }
944 	    }
945 
946 	  suppressible_error (file, e);
947 	  return 1;
948 	}
949 
950       filename = file;
951     }
952 
953 #if defined(SET_BINARY)
954   /* Set input to binary mode.  Pipes are simulated with files
955      on DOS, so this includes the case of "foo | grep bar".  */
956   if (!isatty (desc))
957     SET_BINARY (desc);
958 #endif
959 
960   count = grep (desc, file, stats);
961   if (count < 0)
962     status = count + 2;
963   else
964     {
965       if (count_matches)
966 	{
967 	  if (out_file)
968 	    printf ("%s%c", filename, ':' & filename_mask);
969 	  printf ("%d\n", count);
970 	}
971 
972       status = !count;
973       if (list_files == 1 - 2 * status)
974 	printf ("%s%c", filename, '\n' & filename_mask);
975 
976       if (! file)
977 	{
978 	  off_t required_offset = outleft ? bufoffset : after_last_match;
979 	  if ((bufmapped || required_offset != bufoffset)
980 	      && lseek (desc, required_offset, SEEK_SET) < 0
981 	      && S_ISREG (stats->stat.st_mode))
982 	    error (0, errno, "%s", filename);
983 	}
984       else
985 	while (close (desc) != 0)
986 	  if (errno != EINTR)
987 	    {
988 	      error (0, errno, "%s", file);
989 	      break;
990 	    }
991     }
992 
993   return status;
994 }
995 
996 static int
997 grepdir (char const *dir, struct stats const *stats)
998 {
999   int status = 1;
1000   struct stats const *ancestor;
1001   char *name_space;
1002 
1003   /* Mingw32 does not support st_ino.  No known working hosts use zero
1004      for st_ino, so assume that the Mingw32 bug applies if it's zero.  */
1005   if (stats->stat.st_ino)
1006     for (ancestor = stats;  (ancestor = ancestor->parent) != 0;  )
1007       if (ancestor->stat.st_ino == stats->stat.st_ino
1008 	  && ancestor->stat.st_dev == stats->stat.st_dev)
1009 	{
1010 	  if (!suppress_errors)
1011 	    error (0, 0, _("warning: %s: %s"), dir,
1012 		   _("recursive directory loop"));
1013 	  return 1;
1014 	}
1015 
1016   name_space = savedir (dir, stats->stat.st_size, included_patterns,
1017 			excluded_patterns);
1018 
1019   if (! name_space)
1020     {
1021       if (errno)
1022 	suppressible_error (dir, errno);
1023       else
1024 	xalloc_die ();
1025     }
1026   else
1027     {
1028       size_t dirlen = strlen (dir);
1029       int needs_slash = ! (dirlen == FILESYSTEM_PREFIX_LEN (dir)
1030 			   || IS_SLASH (dir[dirlen - 1]));
1031       char *file = NULL;
1032       char const *namep = name_space;
1033       struct stats child;
1034       child.parent = stats;
1035       out_file += !no_filenames;
1036       while (*namep)
1037 	{
1038 	  size_t namelen = strlen (namep);
1039 	  file = xrealloc (file, dirlen + 1 + namelen + 1);
1040 	  strcpy (file, dir);
1041 	  file[dirlen] = '/';
1042 	  strcpy (file + dirlen + needs_slash, namep);
1043 	  namep += namelen + 1;
1044 	  status &= grepfile (file, &child);
1045 	}
1046       out_file -= !no_filenames;
1047       if (file)
1048         free (file);
1049       free (name_space);
1050     }
1051 
1052   return status;
1053 }
1054 
1055 static void
1056 usage (int status)
1057 {
1058   if (status != 0)
1059     {
1060       fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"),
1061 	       program_name);
1062       fprintf (stderr, _("Try `%s --help' for more information.\n"),
1063 	       program_name);
1064     }
1065   else
1066     {
1067       printf (_("Usage: %s [OPTION]... PATTERN [FILE] ...\n"), program_name);
1068       printf (_("\
1069 Search for PATTERN in each FILE or standard input.\n\
1070 Example: %s -i 'hello world' menu.h main.c\n\
1071 \n\
1072 Regexp selection and interpretation:\n"), program_name);
1073       printf (_("\
1074   -E, --extended-regexp     PATTERN is an extended regular expression\n\
1075   -F, --fixed-strings       PATTERN is a set of newline-separated strings\n\
1076   -G, --basic-regexp        PATTERN is a basic regular expression\n"));
1077 #if HAVE_LIBPCRE
1078       printf (_("\
1079   -P, --perl-regexp         PATTERN is a Perl regular expression\n"));
1080 #endif
1081       printf (_("\
1082   -e, --regexp=PATTERN      use PATTERN as a regular expression\n\
1083   -f, --file=FILE           obtain PATTERN from FILE\n\
1084   -i, --ignore-case         ignore case distinctions\n\
1085   -w, --word-regexp         force PATTERN to match only whole words\n\
1086   -x, --line-regexp         force PATTERN to match only whole lines\n\
1087   -z, --null-data           a data line ends in 0 byte, not newline\n"));
1088       printf (_("\
1089 \n\
1090 Miscellaneous:\n\
1091   -s, --no-messages         suppress error messages\n\
1092   -v, --invert-match        select non-matching lines\n\
1093   -V, --version             print version information and exit\n\
1094       --help                display this help and exit\n\
1095       --mmap                use memory-mapped input if possible\n"));
1096       printf (_("\
1097 \n\
1098 Output control:\n\
1099   -m, --max-count=NUM       stop after NUM matches\n\
1100   -b, --byte-offset         print the byte offset with output lines\n\
1101   -n, --line-number         print line number with output lines\n\
1102       --line-buffered       flush output on every line\n\
1103   -H, --with-filename       print the filename for each match\n\
1104   -h, --no-filename         suppress the prefixing filename on output\n\
1105       --label=LABEL         print LABEL as filename for standard input\n\
1106   -o, --only-matching       show only the part of a line matching PATTERN\n\
1107   -q, --quiet, --silent     suppress all normal output\n\
1108       --binary-files=TYPE   assume that binary files are TYPE\n\
1109                             TYPE is 'binary', 'text', or 'without-match'\n\
1110   -a, --text                equivalent to --binary-files=text\n\
1111   -I                        equivalent to --binary-files=without-match\n\
1112   -d, --directories=ACTION  how to handle directories\n\
1113                             ACTION is 'read', 'recurse', or 'skip'\n\
1114   -D, --devices=ACTION      how to handle devices, FIFOs and sockets\n\
1115                             ACTION is 'read' or 'skip'\n\
1116   -R, -r, --recursive       equivalent to --directories=recurse\n\
1117       --include=PATTERN     files that match PATTERN will be examined\n\
1118       --exclude=PATTERN     files that match PATTERN will be skipped.\n\
1119       --exclude-from=FILE   files that match PATTERN in FILE will be skipped.\n\
1120   -L, --files-without-match only print FILE names containing no match\n\
1121   -l, --files-with-matches  only print FILE names containing matches\n\
1122   -c, --count               only print a count of matching lines per FILE\n\
1123   -Z, --null                print 0 byte after FILE name\n"));
1124       printf (_("\
1125 \n\
1126 Context control:\n\
1127   -B, --before-context=NUM  print NUM lines of leading context\n\
1128   -A, --after-context=NUM   print NUM lines of trailing context\n\
1129   -C, --context=NUM         print NUM lines of output context\n\
1130   -NUM                      same as --context=NUM\n\
1131       --color[=WHEN],\n\
1132       --colour[=WHEN]       use markers to distinguish the matching string\n\
1133                             WHEN may be `always', `never' or `auto'.\n\
1134   -U, --binary              do not strip CR characters at EOL (MSDOS)\n\
1135   -u, --unix-byte-offsets   report offsets as if CRs were not there (MSDOS)\n\
1136 \n\
1137 `egrep' means `grep -E'.  `fgrep' means `grep -F'.\n\
1138 With no FILE, or when FILE is -, read standard input.  If less than\n\
1139 two FILEs given, assume -h.  Exit status is 0 if match, 1 if no match,\n\
1140 and 2 if trouble.\n"));
1141       printf (_("\nReport bugs to <bug-grep@gnu.org>.\n"));
1142     }
1143   exit (status);
1144 }
1145 
1146 /* Set the matcher to M, reporting any conflicts.  */
1147 static void
1148 setmatcher (char const *m)
1149 {
1150   if (matcher && strcmp (matcher, m) != 0)
1151     error (2, 0, _("conflicting matchers specified"));
1152   matcher = m;
1153 }
1154 
1155 /* Go through the matchers vector and look for the specified matcher.
1156    If we find it, install it in compile and execute, and return 1.  */
1157 static int
1158 install_matcher (char const *name)
1159 {
1160   int i;
1161 #if defined(HAVE_SETRLIMIT)
1162   struct rlimit rlim;
1163 #endif
1164 
1165   for (i = 0; matchers[i].compile; i++)
1166     if (strcmp (name, matchers[i].name) == 0)
1167       {
1168 	compile = matchers[i].compile;
1169 	execute = matchers[i].execute;
1170 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK)
1171 	/* I think every platform needs to do this, so that regex.c
1172 	   doesn't oveflow the stack.  The default value of
1173 	   `re_max_failures' is too large for some platforms: it needs
1174 	   more than 3MB-large stack.
1175 
1176 	   The test for HAVE_SETRLIMIT should go into `configure'.  */
1177 	if (!getrlimit (RLIMIT_STACK, &rlim))
1178 	  {
1179 	    long newlim;
1180 	    extern long int re_max_failures; /* from regex.c */
1181 
1182 	    /* Approximate the amount regex.c needs, plus some more.  */
1183 	    newlim = re_max_failures * 2 * 20 * sizeof (char *);
1184 	    if (newlim > rlim.rlim_max)
1185 	      {
1186 		newlim = rlim.rlim_max;
1187 		re_max_failures = newlim / (2 * 20 * sizeof (char *));
1188 	      }
1189 	    if (rlim.rlim_cur < newlim)
1190 	      {
1191 		rlim.rlim_cur = newlim;
1192 		setrlimit (RLIMIT_STACK, &rlim);
1193 	      }
1194 	  }
1195 #endif
1196 	return 1;
1197       }
1198   return 0;
1199 }
1200 
1201 /* Find the white-space-separated options specified by OPTIONS, and
1202    using BUF to store copies of these options, set ARGV[0], ARGV[1],
1203    etc. to the option copies.  Return the number N of options found.
1204    Do not set ARGV[N] to NULL.  If ARGV is NULL, do not store ARGV[0]
1205    etc.  Backslash can be used to escape whitespace (and backslashes).  */
1206 static int
1207 prepend_args (char const *options, char *buf, char **argv)
1208 {
1209   char const *o = options;
1210   char *b = buf;
1211   int n = 0;
1212 
1213   for (;;)
1214     {
1215       while (ISSPACE ((unsigned char) *o))
1216 	o++;
1217       if (!*o)
1218 	return n;
1219       if (argv)
1220 	argv[n] = b;
1221       n++;
1222 
1223       do
1224 	if ((*b++ = *o++) == '\\' && *o)
1225 	  b[-1] = *o++;
1226       while (*o && ! ISSPACE ((unsigned char) *o));
1227 
1228       *b++ = '\0';
1229     }
1230 }
1231 
1232 /* Prepend the whitespace-separated options in OPTIONS to the argument
1233    vector of a main program with argument count *PARGC and argument
1234    vector *PARGV.  */
1235 static void
1236 prepend_default_options (char const *options, int *pargc, char ***pargv)
1237 {
1238   if (options)
1239     {
1240       char *buf = xmalloc (strlen (options) + 1);
1241       int prepended = prepend_args (options, buf, (char **) NULL);
1242       int argc = *pargc;
1243       char * const *argv = *pargv;
1244       char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
1245       *pargc = prepended + argc;
1246       *pargv = pp;
1247       *pp++ = *argv++;
1248       pp += prepend_args (options, buf, pp);
1249       while ((*pp++ = *argv++))
1250 	continue;
1251     }
1252 }
1253 
1254 /* Get the next non-digit option from ARGC and ARGV.
1255    Return -1 if there are no more options.
1256    Process any digit options that were encountered on the way,
1257    and store the resulting integer into *DEFAULT_CONTEXT.  */
1258 static int
1259 get_nondigit_option (int argc, char *const *argv, int *default_context)
1260 {
1261   int opt;
1262   char buf[sizeof (uintmax_t) * CHAR_BIT + 4];
1263   char *p = buf;
1264 
1265   /* Set buf[0] to anything but '0', for the leading-zero test below.  */
1266   buf[0] = '\0';
1267 
1268   while (opt = getopt_long (argc, argv, short_options, long_options, NULL),
1269 	 '0' <= opt && opt <= '9')
1270     {
1271       /* Suppress trivial leading zeros, to avoid incorrect
1272 	 diagnostic on strings like 00000000000.  */
1273       p -= buf[0] == '0';
1274 
1275       *p++ = opt;
1276       if (p == buf + sizeof buf - 4)
1277 	{
1278 	  /* Too many digits.  Append "..." to make context_length_arg
1279 	     complain about "X...", where X contains the digits seen
1280 	     so far.  */
1281 	  strcpy (p, "...");
1282 	  p += 3;
1283 	  break;
1284 	}
1285     }
1286   if (p != buf)
1287     {
1288       *p = '\0';
1289       context_length_arg (buf, default_context);
1290     }
1291 
1292   return opt;
1293 }
1294 
1295 int
1296 main (int argc, char **argv)
1297 {
1298   char *keys;
1299   size_t cc, keycc, oldcc, keyalloc;
1300   int with_filenames;
1301   int opt, status;
1302   int default_context;
1303   FILE *fp;
1304   extern char *optarg;
1305   extern int optind;
1306 #ifdef __NetBSD__
1307   extern char *__progname;
1308 #endif
1309 
1310   initialize_main (&argc, &argv);
1311   program_name = argv[0];
1312   if (program_name && strrchr (program_name, '/'))
1313     program_name = strrchr (program_name, '/') + 1;
1314 
1315   if (!strcmp(program_name, "egrep"))
1316     setmatcher ("egrep");
1317   if (!strcmp(program_name, "fgrep"))
1318     setmatcher ("fgrep");
1319 
1320 #if defined(__MSDOS__) || defined(_WIN32)
1321   /* DOS and MS-Windows use backslashes as directory separators, and usually
1322      have an .exe suffix.  They also have case-insensitive filesystems.  */
1323   if (program_name)
1324     {
1325       char *p = program_name;
1326       char *bslash = strrchr (argv[0], '\\');
1327 
1328       if (bslash && bslash >= program_name) /* for mixed forward/backslash case */
1329 	program_name = bslash + 1;
1330       else if (program_name == argv[0]
1331 	       && argv[0][0] && argv[0][1] == ':') /* "c:progname" */
1332 	program_name = argv[0] + 2;
1333 
1334       /* Collapse the letter-case, so `strcmp' could be used hence.  */
1335       for ( ; *p; p++)
1336 	if (*p >= 'A' && *p <= 'Z')
1337 	  *p += 'a' - 'A';
1338 
1339       /* Remove the .exe extension, if any.  */
1340       if ((p = strrchr (program_name, '.')) && strcmp (p, ".exe") == 0)
1341 	*p = '\0';
1342     }
1343 #endif
1344 
1345   keys = NULL;
1346   keycc = 0;
1347   with_filenames = 0;
1348   eolbyte = '\n';
1349   filename_mask = ~0;
1350 
1351   max_count = MAX_OFF_T;
1352 
1353   /* The value -1 means to use DEFAULT_CONTEXT. */
1354   out_after = out_before = -1;
1355   /* Default before/after context: chaged by -C/-NUM options */
1356   default_context = 0;
1357   /* Changed by -o option */
1358   only_matching = 0;
1359 
1360   /* Internationalization. */
1361 #if defined(HAVE_SETLOCALE)
1362   setlocale (LC_ALL, "");
1363 #endif
1364 #if defined(ENABLE_NLS)
1365   bindtextdomain (PACKAGE, LOCALEDIR);
1366   textdomain (PACKAGE);
1367 #endif
1368 
1369   atexit (close_stdout);
1370 
1371   prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv);
1372 
1373   while ((opt = get_nondigit_option (argc, argv, &default_context)) != -1)
1374     switch (opt)
1375       {
1376       case 'A':
1377 	context_length_arg (optarg, &out_after);
1378 	break;
1379 
1380       case 'B':
1381 	context_length_arg (optarg, &out_before);
1382 	break;
1383 
1384       case 'C':
1385 	/* Set output match context, but let any explicit leading or
1386 	   trailing amount specified with -A or -B stand. */
1387 	context_length_arg (optarg, &default_context);
1388 	break;
1389 
1390       case 'D':
1391 	if (strcmp (optarg, "read") == 0)
1392 	  devices = READ_DEVICES;
1393 	else if (strcmp (optarg, "skip") == 0)
1394 	  devices = SKIP_DEVICES;
1395 	else
1396 	  error (2, 0, _("unknown devices method"));
1397 	break;
1398 
1399       case 'E':
1400 	setmatcher ("egrep");
1401 	break;
1402 
1403       case 'F':
1404 	setmatcher ("fgrep");
1405 	break;
1406 
1407       case 'P':
1408 	setmatcher ("perl");
1409 	break;
1410 
1411       case 'G':
1412 	setmatcher ("grep");
1413 	break;
1414 
1415       case 'H':
1416 	with_filenames = 1;
1417 	break;
1418 
1419       case 'I':
1420 	binary_files = WITHOUT_MATCH_BINARY_FILES;
1421 	break;
1422 
1423       case 'U':
1424 #if defined(HAVE_DOS_FILE_CONTENTS)
1425 	dos_use_file_type = DOS_BINARY;
1426 #endif
1427 	break;
1428 
1429       case 'u':
1430 #if defined(HAVE_DOS_FILE_CONTENTS)
1431 	dos_report_unix_offset = 1;
1432 #endif
1433 	break;
1434 
1435       case 'V':
1436 	show_version = 1;
1437 	break;
1438 
1439       case 'X':
1440 	setmatcher (optarg);
1441 	break;
1442 
1443       case 'a':
1444 	binary_files = TEXT_BINARY_FILES;
1445 	break;
1446 
1447       case 'b':
1448 	out_byte = 1;
1449 	break;
1450 
1451       case 'c':
1452 	count_matches = 1;
1453 	break;
1454 
1455       case 'd':
1456 	if (strcmp (optarg, "read") == 0)
1457 	  directories = READ_DIRECTORIES;
1458 	else if (strcmp (optarg, "skip") == 0)
1459 	  directories = SKIP_DIRECTORIES;
1460 	else if (strcmp (optarg, "recurse") == 0)
1461 	  directories = RECURSE_DIRECTORIES;
1462 	else
1463 	  error (2, 0, _("unknown directories method"));
1464 	break;
1465 
1466       case 'e':
1467 	cc = strlen (optarg);
1468 	keys = xrealloc (keys, keycc + cc + 1);
1469 	strcpy (&keys[keycc], optarg);
1470 	keycc += cc;
1471 	keys[keycc++] = '\n';
1472 	break;
1473 
1474       case 'f':
1475 	fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin;
1476 	if (!fp)
1477 	  error (2, errno, "%s", optarg);
1478 	for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2)
1479 	  ;
1480 	keys = xrealloc (keys, keyalloc);
1481 	oldcc = keycc;
1482 	while (!feof (fp)
1483 	       && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0)
1484 	  {
1485 	    keycc += cc;
1486 	    if (keycc == keyalloc - 1)
1487 	      keys = xrealloc (keys, keyalloc *= 2);
1488 	  }
1489 	if (fp != stdin)
1490 	  fclose(fp);
1491 	/* Append final newline if file ended in non-newline. */
1492 	if (oldcc != keycc && keys[keycc - 1] != '\n')
1493 	  keys[keycc++] = '\n';
1494 	break;
1495 
1496       case 'h':
1497 	no_filenames = 1;
1498 	break;
1499 
1500       case 'i':
1501       case 'y':			/* For old-timers . . . */
1502 	match_icase = 1;
1503 	break;
1504 
1505       case 'L':
1506 	/* Like -l, except list files that don't contain matches.
1507 	   Inspired by the same option in Hume's gre. */
1508 	list_files = -1;
1509 	break;
1510 
1511       case 'l':
1512 	list_files = 1;
1513 	break;
1514 
1515       case 'm':
1516 	{
1517 	  uintmax_t value;
1518 	  switch (xstrtoumax (optarg, 0, 10, &value, ""))
1519 	    {
1520 	    case LONGINT_OK:
1521 	      max_count = value;
1522 	      if (0 <= max_count && max_count == value)
1523 		break;
1524 	      /* Fall through.  */
1525 	    case LONGINT_OVERFLOW:
1526 	      max_count = MAX_OFF_T;
1527 	      break;
1528 
1529 	    default:
1530 	      error (2, 0, _("invalid max count"));
1531 	    }
1532 	}
1533 	break;
1534 
1535       case 'n':
1536 	out_line = 1;
1537 	break;
1538 
1539       case 'o':
1540 	only_matching = 1;
1541 	break;
1542 
1543       case 'q':
1544 	exit_on_match = 1;
1545 	close_stdout_set_status(0);
1546 	break;
1547 
1548       case 'R':
1549       case 'r':
1550 	directories = RECURSE_DIRECTORIES;
1551 	break;
1552 
1553       case 's':
1554 	suppress_errors = 1;
1555 	break;
1556 
1557       case 'v':
1558 	out_invert = 1;
1559 	break;
1560 
1561       case 'w':
1562 	match_words = 1;
1563 	break;
1564 
1565       case 'x':
1566 	match_lines = 1;
1567 	break;
1568 
1569       case 'Z':
1570 	filename_mask = 0;
1571 	break;
1572 
1573       case 'z':
1574 	eolbyte = '\0';
1575 	break;
1576 
1577       case BINARY_FILES_OPTION:
1578 	if (strcmp (optarg, "binary") == 0)
1579 	  binary_files = BINARY_BINARY_FILES;
1580 	else if (strcmp (optarg, "text") == 0)
1581 	  binary_files = TEXT_BINARY_FILES;
1582 	else if (strcmp (optarg, "without-match") == 0)
1583 	  binary_files = WITHOUT_MATCH_BINARY_FILES;
1584 	else
1585 	  error (2, 0, _("unknown binary-files type"));
1586 	break;
1587 
1588       case COLOR_OPTION:
1589         if(optarg) {
1590           if(!strcasecmp(optarg, "always") || !strcasecmp(optarg, "yes") ||
1591              !strcasecmp(optarg, "force"))
1592             color_option = 1;
1593           else if(!strcasecmp(optarg, "never") || !strcasecmp(optarg, "no") ||
1594                   !strcasecmp(optarg, "none"))
1595             color_option = 0;
1596           else if(!strcasecmp(optarg, "auto") || !strcasecmp(optarg, "tty") ||
1597                   !strcasecmp(optarg, "if-tty"))
1598             color_option = 2;
1599           else
1600             show_help = 1;
1601         } else
1602           color_option = 2;
1603         if(color_option == 2) {
1604           if(isatty(STDOUT_FILENO) && getenv("TERM") &&
1605 	     strcmp(getenv("TERM"), "dumb"))
1606                   color_option = 1;
1607           else
1608             color_option = 0;
1609         }
1610 	break;
1611 
1612       case EXCLUDE_OPTION:
1613 	if (!excluded_patterns)
1614 	  excluded_patterns = new_exclude ();
1615 	add_exclude (excluded_patterns, optarg);
1616 	break;
1617 
1618       case EXCLUDE_FROM_OPTION:
1619 	if (!excluded_patterns)
1620 	  excluded_patterns = new_exclude ();
1621         if (add_exclude_file (add_exclude, excluded_patterns, optarg, '\n')
1622 	    != 0)
1623           {
1624             error (2, errno, "%s", optarg);
1625           }
1626         break;
1627 
1628       case INCLUDE_OPTION:
1629 	if (!included_patterns)
1630 	  included_patterns = new_exclude ();
1631 	add_exclude (included_patterns, optarg);
1632 	break;
1633 
1634       case LINE_BUFFERED_OPTION:
1635 	line_buffered = 1;
1636 	break;
1637 
1638       case LABEL_OPTION:
1639 	label = optarg;
1640 	break;
1641 
1642       case 0:
1643 	/* long options */
1644 	break;
1645 
1646       default:
1647 	usage (2);
1648 	break;
1649 
1650       }
1651 
1652   /* POSIX.2 says that -q overrides -l, which in turn overrides the
1653      other output options.  */
1654   if (exit_on_match)
1655     list_files = 0;
1656   if (exit_on_match | list_files)
1657     {
1658       count_matches = 0;
1659       done_on_match = 1;
1660     }
1661   out_quiet = count_matches | done_on_match;
1662 
1663   if (out_after < 0)
1664     out_after = default_context;
1665   if (out_before < 0)
1666     out_before = default_context;
1667 
1668   if (color_option)
1669     {
1670       char *userval = getenv ("GREP_COLOR");
1671       if (userval != NULL && *userval != '\0')
1672 	grep_color = userval;
1673     }
1674 
1675   if (! matcher)
1676 #ifdef __NetBSD__
1677     matcher = __progname;
1678 #else
1679     matcher = "grep";
1680 #endif
1681 
1682   if (show_version)
1683     {
1684       printf (_("%s (GNU grep) %s\n"), matcher, VERSION);
1685       printf ("\n");
1686       printf (_("\
1687 Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.\n"));
1688       printf (_("\
1689 This is free software; see the source for copying conditions. There is NO\n\
1690 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
1691       printf ("\n");
1692       exit (0);
1693     }
1694 
1695   if (show_help)
1696     usage (0);
1697 
1698   if (keys)
1699     {
1700       if (keycc == 0)
1701 	{
1702 	  /* No keys were specified (e.g. -f /dev/null).  Match nothing.  */
1703 	  out_invert ^= 1;
1704 	  match_lines = match_words = 0;
1705 	}
1706       else
1707 	/* Strip trailing newline. */
1708         --keycc;
1709     }
1710   else
1711     if (optind < argc)
1712       {
1713 	keys = argv[optind++];
1714 	keycc = strlen (keys);
1715       }
1716     else
1717       usage (2);
1718 
1719   if (!install_matcher (matcher) && !install_matcher ("default"))
1720     abort ();
1721 
1722   (*compile)(keys, keycc);
1723 
1724   if ((argc - optind > 1 && !no_filenames) || with_filenames)
1725     out_file = 1;
1726 
1727 #ifdef SET_BINARY
1728   /* Output is set to binary mode because we shouldn't convert
1729      NL to CR-LF pairs, especially when grepping binary files.  */
1730   if (!isatty (1))
1731     SET_BINARY (1);
1732 #endif
1733 
1734   if (max_count == 0)
1735     exit (1);
1736 
1737   if (optind < argc)
1738     {
1739 	status = 1;
1740 	do
1741 	{
1742 	  char *file = argv[optind];
1743 	  if ((included_patterns || excluded_patterns)
1744 	      && !isdir (file))
1745 	    {
1746 	      if (included_patterns &&
1747 		  ! excluded_filename (included_patterns, file, 0))
1748 		continue;
1749 	      if (excluded_patterns &&
1750 		  excluded_filename (excluded_patterns, file, 0))
1751 		continue;
1752 	    }
1753 	  status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
1754 			      &stats_base);
1755 	}
1756 	while ( ++optind < argc);
1757     }
1758   else
1759     {
1760       if (directories == RECURSE_DIRECTORIES) {
1761 	error (0, 0, _("warning: recursive search of stdin"));
1762       }
1763       status = grepfile ((char *) NULL, &stats_base);
1764     }
1765 
1766   /* We register via atexit() to test stdout.  */
1767   exit (errseen ? 2 : status);
1768 }
1769 /* vim:set shiftwidth=2: */
1770