1*10898Sroland.mainz@nrubsig.org /***********************************************************************
2*10898Sroland.mainz@nrubsig.org * *
3*10898Sroland.mainz@nrubsig.org * This software is part of the ast package *
4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1995-2009 AT&T Knowledge Ventures *
5*10898Sroland.mainz@nrubsig.org * and is licensed under the *
6*10898Sroland.mainz@nrubsig.org * Common Public License, Version 1.0 *
7*10898Sroland.mainz@nrubsig.org * by AT&T Knowledge Ventures *
8*10898Sroland.mainz@nrubsig.org * *
9*10898Sroland.mainz@nrubsig.org * A copy of the License is available at *
10*10898Sroland.mainz@nrubsig.org * http://www.opensource.org/licenses/cpl1.0.txt *
11*10898Sroland.mainz@nrubsig.org * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12*10898Sroland.mainz@nrubsig.org * *
13*10898Sroland.mainz@nrubsig.org * Information and Software Systems Research *
14*10898Sroland.mainz@nrubsig.org * AT&T Research *
15*10898Sroland.mainz@nrubsig.org * Florham Park NJ *
16*10898Sroland.mainz@nrubsig.org * *
17*10898Sroland.mainz@nrubsig.org * Glenn Fowler <gsf@research.att.com> *
18*10898Sroland.mainz@nrubsig.org * *
19*10898Sroland.mainz@nrubsig.org ***********************************************************************/
20*10898Sroland.mainz@nrubsig.org #pragma prototyped
21*10898Sroland.mainz@nrubsig.org
22*10898Sroland.mainz@nrubsig.org static const char usage[] =
23*10898Sroland.mainz@nrubsig.org "[-?\n@(#)$Id: grep (AT&T Research) 2006-06-14 $\n]"
24*10898Sroland.mainz@nrubsig.org USAGE_LICENSE
25*10898Sroland.mainz@nrubsig.org "[+NAME?grep - search lines in files for matching patterns]"
26*10898Sroland.mainz@nrubsig.org "[+DESCRIPTION?The \bgrep\b commands search the named input files"
27*10898Sroland.mainz@nrubsig.org " for lines containing a match for the given \apatterns\a."
28*10898Sroland.mainz@nrubsig.org " Matching lines are printed by default. The standard input is searched"
29*10898Sroland.mainz@nrubsig.org " if no files are given or when the file \b-\b is specified.]"
30*10898Sroland.mainz@nrubsig.org "[+?There are six variants of \bgrep\b, each one using a different form of"
31*10898Sroland.mainz@nrubsig.org " \apattern\a, controlled either by option or the command path"
32*10898Sroland.mainz@nrubsig.org " base name. Details of each variant may be found in \bregex\b(3).]"
33*10898Sroland.mainz@nrubsig.org " {"
34*10898Sroland.mainz@nrubsig.org " [+grep?The default basic regular expressions (no alternations.)]"
35*10898Sroland.mainz@nrubsig.org " [+egrep?Extended regular expressions (alternations, one or more.)]"
36*10898Sroland.mainz@nrubsig.org " [+pgrep?\bperl\b(1) regular expressions (lenient extended.)]"
37*10898Sroland.mainz@nrubsig.org " [+xgrep?Augmented regular expressions (conjunction, negation.)]"
38*10898Sroland.mainz@nrubsig.org " [+fgrep?Fixed string expressions.]"
39*10898Sroland.mainz@nrubsig.org " [+agrep?Approximate regular expressions (not implemented.)]"
40*10898Sroland.mainz@nrubsig.org " }"
41*10898Sroland.mainz@nrubsig.org "[G:basic-regexp?\bgrep\b mode (default): basic regular expression \apatterns\a.]"
42*10898Sroland.mainz@nrubsig.org "[E:extended-regexp?\begrep\b mode: extended regular expression \apatterns\a.]"
43*10898Sroland.mainz@nrubsig.org "[X:augmented-regexp?\bxgrep\b mode: augmented regular expression \apatterns\a.]"
44*10898Sroland.mainz@nrubsig.org "[P:perl-regexp?\bpgrep\b mode: \bperl\b(1) regular expression \apatterns\a.]"
45*10898Sroland.mainz@nrubsig.org "[F:fixed-string?\bfgrep\b mode: fixed string \apatterns\a.]"
46*10898Sroland.mainz@nrubsig.org "[A:approximate-regexp?\bagrep\b mode: approximate regular expression \apatterns\a (not implemented.)]"
47*10898Sroland.mainz@nrubsig.org
48*10898Sroland.mainz@nrubsig.org "[C:context?Set the matched line context \abefore\a and \aafter\a count."
49*10898Sroland.mainz@nrubsig.org " By default only matched lines are printed.]:?"
50*10898Sroland.mainz@nrubsig.org " [before[,after]]:=2,2]"
51*10898Sroland.mainz@nrubsig.org "[c:count?Only print a matching line count for each file.]"
52*10898Sroland.mainz@nrubsig.org "[e:expression|pattern|regexp?Specify a matching \apattern\a. More than one"
53*10898Sroland.mainz@nrubsig.org " \apattern\a implies alternation. If this option is specified"
54*10898Sroland.mainz@nrubsig.org " then the command line \apattern\a must be omitted.]:"
55*10898Sroland.mainz@nrubsig.org " [pattern]"
56*10898Sroland.mainz@nrubsig.org "[f:file?Each line in \apattern-file\a is a \apattern\a, placed into a single"
57*10898Sroland.mainz@nrubsig.org " alternating expression.]:"
58*10898Sroland.mainz@nrubsig.org " [pattern-file]"
59*10898Sroland.mainz@nrubsig.org "[H:filename|with-filename?Prefix each matched line with the containing file name.]"
60*10898Sroland.mainz@nrubsig.org "[h:no-filename?Suppress containing file name prefix for each matched line.]"
61*10898Sroland.mainz@nrubsig.org "[i:ignore-case?Ignore case when matching.]"
62*10898Sroland.mainz@nrubsig.org "[l:files-with-matches?Only print file names with at least one match.]"
63*10898Sroland.mainz@nrubsig.org "[L:files-without-matches?Only print file names with no matches.]"
64*10898Sroland.mainz@nrubsig.org "[b:highlight?Highlight matches using the ansi terminal bold sequence.]"
65*10898Sroland.mainz@nrubsig.org "[v:invert-match|revert-match?Invert the \apattern\a match sense.]"
66*10898Sroland.mainz@nrubsig.org "[m:label?All patterns must be of the form \alabel\a:\apattern\a. Match and"
67*10898Sroland.mainz@nrubsig.org " count output will be prefixed by the corresponding \alabel\a:.]"
68*10898Sroland.mainz@nrubsig.org "[O:lenient?Enable lenient \apattern\a interpretation. This is the default.]"
69*10898Sroland.mainz@nrubsig.org "[x:line-match|line-regexp?Force \apatterns\a to match complete lines.]"
70*10898Sroland.mainz@nrubsig.org "[n:number|line-number?Prefix each matched line with its line number.]"
71*10898Sroland.mainz@nrubsig.org "[N:name?Set the standard input file name prefix to"
72*10898Sroland.mainz@nrubsig.org " \aname\a.]:[name:=empty]"
73*10898Sroland.mainz@nrubsig.org "[q:quiet|silent?Do not print matching lines.]"
74*10898Sroland.mainz@nrubsig.org "[S:strict?Enable strict \apattern\a interpretation with diagnostics.]"
75*10898Sroland.mainz@nrubsig.org "[s:suppress|no-messages?Suppress error and warning messages.]"
76*10898Sroland.mainz@nrubsig.org "[t:total?Only print a single matching line count for all files.]"
77*10898Sroland.mainz@nrubsig.org "[T:test?Enable implementation specific tests.]:"
78*10898Sroland.mainz@nrubsig.org " [test]"
79*10898Sroland.mainz@nrubsig.org "[w:word-match|word-regexp?Force \apatterns\a to match complete words.]"
80*10898Sroland.mainz@nrubsig.org "[a?Ignored for GNU compatibility.]"
81*10898Sroland.mainz@nrubsig.org "\n"
82*10898Sroland.mainz@nrubsig.org "\n[ pattern ] [ file ... ]\n"
83*10898Sroland.mainz@nrubsig.org "\n"
84*10898Sroland.mainz@nrubsig.org "[+DIAGNOSTICS?Exit status 0 if matches were found, 1 if no matches were found,"
85*10898Sroland.mainz@nrubsig.org " where \b-v\b invertes the exit status. Exit status 2 for other"
86*10898Sroland.mainz@nrubsig.org " errors that are accompanied by a message on the standard error.]"
87*10898Sroland.mainz@nrubsig.org "[+SEE ALSO?\bed\b(1), \bsed\b(1), \bperl\b(1), \bregex\b(3)]"
88*10898Sroland.mainz@nrubsig.org "[+CAVEATS?Some expressions of necessity require exponential space"
89*10898Sroland.mainz@nrubsig.org " and/or time.]"
90*10898Sroland.mainz@nrubsig.org "[+BUGS?Some expressions may use sub-optimal algorithms. For example,"
91*10898Sroland.mainz@nrubsig.org " don't use this implementation to compute primes.]"
92*10898Sroland.mainz@nrubsig.org ;
93*10898Sroland.mainz@nrubsig.org
94*10898Sroland.mainz@nrubsig.org #include <ast.h>
95*10898Sroland.mainz@nrubsig.org #include <ctype.h>
96*10898Sroland.mainz@nrubsig.org #include <ccode.h>
97*10898Sroland.mainz@nrubsig.org #include <error.h>
98*10898Sroland.mainz@nrubsig.org #include <regex.h>
99*10898Sroland.mainz@nrubsig.org
100*10898Sroland.mainz@nrubsig.org #ifndef EISDIR
101*10898Sroland.mainz@nrubsig.org #define EISDIR (-1)
102*10898Sroland.mainz@nrubsig.org #endif
103*10898Sroland.mainz@nrubsig.org
104*10898Sroland.mainz@nrubsig.org /*
105*10898Sroland.mainz@nrubsig.org * snarfed from Doug McElroy's C++ version
106*10898Sroland.mainz@nrubsig.org *
107*10898Sroland.mainz@nrubsig.org * this grep is based on the Posix re package.
108*10898Sroland.mainz@nrubsig.org * unfortunately it has to have a nonstandard interface.
109*10898Sroland.mainz@nrubsig.org * 1. fgrep does not have usual operators. REG_LITERAL
110*10898Sroland.mainz@nrubsig.org * caters for this.
111*10898Sroland.mainz@nrubsig.org * 2. grep allows null expressions, hence REG_NULL.
112*10898Sroland.mainz@nrubsig.org * 3. it may be possible to combine the multiple
113*10898Sroland.mainz@nrubsig.org * patterns of grep into single patterns. important
114*10898Sroland.mainz@nrubsig.org * special cases are handled by regcomb().
115*10898Sroland.mainz@nrubsig.org * 4. anchoring by -x has to be done separately from
116*10898Sroland.mainz@nrubsig.org * compilation (remember that fgrep has no ^ or $ operator),
117*10898Sroland.mainz@nrubsig.org * hence REG_LEFT|REG_RIGHT. (An honest, but slow alternative:
118*10898Sroland.mainz@nrubsig.org * run regexec with REG_NOSUB off and nmatch=1 and check
119*10898Sroland.mainz@nrubsig.org * whether the match is full length)
120*10898Sroland.mainz@nrubsig.org */
121*10898Sroland.mainz@nrubsig.org
122*10898Sroland.mainz@nrubsig.org typedef struct Item_s /* list item - sue me for waste */
123*10898Sroland.mainz@nrubsig.org {
124*10898Sroland.mainz@nrubsig.org struct Item_s* next; /* next in list */
125*10898Sroland.mainz@nrubsig.org regex_t re; /* compiled re */
126*10898Sroland.mainz@nrubsig.org Sfulong_t hits; /* labeled pattern matches */
127*10898Sroland.mainz@nrubsig.org Sfulong_t total; /* total hits */
128*10898Sroland.mainz@nrubsig.org char string[1]; /* string value */
129*10898Sroland.mainz@nrubsig.org } Item_t;
130*10898Sroland.mainz@nrubsig.org
131*10898Sroland.mainz@nrubsig.org typedef struct List_s /* generic list */
132*10898Sroland.mainz@nrubsig.org {
133*10898Sroland.mainz@nrubsig.org Item_t* head; /* list head */
134*10898Sroland.mainz@nrubsig.org Item_t* tail; /* list tail */
135*10898Sroland.mainz@nrubsig.org } List_t;
136*10898Sroland.mainz@nrubsig.org
137*10898Sroland.mainz@nrubsig.org typedef struct State_s /* program state */
138*10898Sroland.mainz@nrubsig.org {
139*10898Sroland.mainz@nrubsig.org struct
140*10898Sroland.mainz@nrubsig.org {
141*10898Sroland.mainz@nrubsig.org char* base; /* sfsetbuf buffer */
142*10898Sroland.mainz@nrubsig.org size_t size; /* sfsetbuf size */
143*10898Sroland.mainz@nrubsig.org int noshare; /* turn off SF_SHARE */
144*10898Sroland.mainz@nrubsig.org } buffer;
145*10898Sroland.mainz@nrubsig.org
146*10898Sroland.mainz@nrubsig.org List_t file; /* pattern file list */
147*10898Sroland.mainz@nrubsig.org List_t pattern; /* pattern list */
148*10898Sroland.mainz@nrubsig.org List_t re; /* re list */
149*10898Sroland.mainz@nrubsig.org
150*10898Sroland.mainz@nrubsig.org regmatch_t posvec[1]; /* match position vector */
151*10898Sroland.mainz@nrubsig.org regmatch_t* pos; /* match position pointer */
152*10898Sroland.mainz@nrubsig.org int posnum; /* number of match positions */
153*10898Sroland.mainz@nrubsig.org
154*10898Sroland.mainz@nrubsig.org int any; /* if any pattern hit */
155*10898Sroland.mainz@nrubsig.org int list; /* list files with hits */
156*10898Sroland.mainz@nrubsig.org int notfound; /* some input file not found */
157*10898Sroland.mainz@nrubsig.org int options; /* regex options */
158*10898Sroland.mainz@nrubsig.org
159*10898Sroland.mainz@nrubsig.org Sfulong_t hits; /* total matched pattern count */
160*10898Sroland.mainz@nrubsig.org
161*10898Sroland.mainz@nrubsig.org unsigned char byline; /* multiple pattern line by line*/
162*10898Sroland.mainz@nrubsig.org unsigned char count; /* count number of hits */
163*10898Sroland.mainz@nrubsig.org unsigned char label; /* all patterns labeled */
164*10898Sroland.mainz@nrubsig.org unsigned char match; /* match sense */
165*10898Sroland.mainz@nrubsig.org unsigned char query; /* return status but no output */
166*10898Sroland.mainz@nrubsig.org unsigned char number; /* line numbers */
167*10898Sroland.mainz@nrubsig.org unsigned char prefix; /* print file prefix */
168*10898Sroland.mainz@nrubsig.org unsigned char suppress; /* no unopenable file messages */
169*10898Sroland.mainz@nrubsig.org unsigned char words; /* word matches only */
170*10898Sroland.mainz@nrubsig.org } State_s;
171*10898Sroland.mainz@nrubsig.org
172*10898Sroland.mainz@nrubsig.org static void
addre(State_s * state,List_t * p,char * s)173*10898Sroland.mainz@nrubsig.org addre(State_s *state, List_t* p, char* s)
174*10898Sroland.mainz@nrubsig.org {
175*10898Sroland.mainz@nrubsig.org int c;
176*10898Sroland.mainz@nrubsig.org char* b;
177*10898Sroland.mainz@nrubsig.org Item_t* x;
178*10898Sroland.mainz@nrubsig.org Sfio_t* t;
179*10898Sroland.mainz@nrubsig.org
180*10898Sroland.mainz@nrubsig.org b = s;
181*10898Sroland.mainz@nrubsig.org if (state->label)
182*10898Sroland.mainz@nrubsig.org {
183*10898Sroland.mainz@nrubsig.org if (!(s = strchr(s, ':')))
184*10898Sroland.mainz@nrubsig.org error(3, "%s: label:pattern expected", b);
185*10898Sroland.mainz@nrubsig.org c = s - b;
186*10898Sroland.mainz@nrubsig.org s++;
187*10898Sroland.mainz@nrubsig.org }
188*10898Sroland.mainz@nrubsig.org else
189*10898Sroland.mainz@nrubsig.org c = 0;
190*10898Sroland.mainz@nrubsig.org if (!(x = newof(0, Item_t, 1, c)))
191*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "out of space (pattern `%s')", b);
192*10898Sroland.mainz@nrubsig.org if (c)
193*10898Sroland.mainz@nrubsig.org memcpy(x->string, b, c);
194*10898Sroland.mainz@nrubsig.org if (state->words)
195*10898Sroland.mainz@nrubsig.org {
196*10898Sroland.mainz@nrubsig.org if (!(t = sfstropen()))
197*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "out of space (word pattern `%s')", s);
198*10898Sroland.mainz@nrubsig.org if (!(state->options & REG_AUGMENTED))
199*10898Sroland.mainz@nrubsig.org sfputc(t, '\\');
200*10898Sroland.mainz@nrubsig.org sfputc(t, '<');
201*10898Sroland.mainz@nrubsig.org sfputr(t, s, -1);
202*10898Sroland.mainz@nrubsig.org if (!(state->options & REG_AUGMENTED))
203*10898Sroland.mainz@nrubsig.org sfputc(t, '\\');
204*10898Sroland.mainz@nrubsig.org sfputc(t, '>');
205*10898Sroland.mainz@nrubsig.org if (!(s = sfstruse(t)))
206*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "out of space");
207*10898Sroland.mainz@nrubsig.org }
208*10898Sroland.mainz@nrubsig.org else
209*10898Sroland.mainz@nrubsig.org t = 0;
210*10898Sroland.mainz@nrubsig.org if (c = regcomp(&x->re, s, state->options|REG_MULTIPLE))
211*10898Sroland.mainz@nrubsig.org regfatal(&x->re, 3, c);
212*10898Sroland.mainz@nrubsig.org if (t)
213*10898Sroland.mainz@nrubsig.org sfstrclose(t);
214*10898Sroland.mainz@nrubsig.org if (!p->head)
215*10898Sroland.mainz@nrubsig.org {
216*10898Sroland.mainz@nrubsig.org p->head = p->tail = x;
217*10898Sroland.mainz@nrubsig.org if (state->number || !regrecord(&x->re))
218*10898Sroland.mainz@nrubsig.org state->byline = 1;
219*10898Sroland.mainz@nrubsig.org }
220*10898Sroland.mainz@nrubsig.org else if (state->label || regcomb(&p->tail->re, &x->re))
221*10898Sroland.mainz@nrubsig.org {
222*10898Sroland.mainz@nrubsig.org p->tail = p->tail->next = x;
223*10898Sroland.mainz@nrubsig.org if (!state->byline && (state->number || !state->label || !regrecord(&x->re)))
224*10898Sroland.mainz@nrubsig.org state->byline = 1;
225*10898Sroland.mainz@nrubsig.org }
226*10898Sroland.mainz@nrubsig.org else
227*10898Sroland.mainz@nrubsig.org free(x);
228*10898Sroland.mainz@nrubsig.org }
229*10898Sroland.mainz@nrubsig.org
230*10898Sroland.mainz@nrubsig.org static void
addstring(State_s * state,List_t * p,char * s)231*10898Sroland.mainz@nrubsig.org addstring(State_s *state, List_t* p, char* s)
232*10898Sroland.mainz@nrubsig.org {
233*10898Sroland.mainz@nrubsig.org Item_t* x;
234*10898Sroland.mainz@nrubsig.org
235*10898Sroland.mainz@nrubsig.org if (!(x = newof(0, Item_t, 1, strlen(s))))
236*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "out of space (string `%s')", s);
237*10898Sroland.mainz@nrubsig.org strcpy(x->string, s);
238*10898Sroland.mainz@nrubsig.org if (p->head)
239*10898Sroland.mainz@nrubsig.org p->tail->next = x;
240*10898Sroland.mainz@nrubsig.org else
241*10898Sroland.mainz@nrubsig.org p->head = x;
242*10898Sroland.mainz@nrubsig.org p->tail = x;
243*10898Sroland.mainz@nrubsig.org }
244*10898Sroland.mainz@nrubsig.org
245*10898Sroland.mainz@nrubsig.org static void
compile(State_s * state)246*10898Sroland.mainz@nrubsig.org compile(State_s *state)
247*10898Sroland.mainz@nrubsig.org {
248*10898Sroland.mainz@nrubsig.org int line;
249*10898Sroland.mainz@nrubsig.org size_t n;
250*10898Sroland.mainz@nrubsig.org char* s;
251*10898Sroland.mainz@nrubsig.org char* t;
252*10898Sroland.mainz@nrubsig.org char* file;
253*10898Sroland.mainz@nrubsig.org Item_t* x;
254*10898Sroland.mainz@nrubsig.org Sfio_t* f;
255*10898Sroland.mainz@nrubsig.org
256*10898Sroland.mainz@nrubsig.org for (x = state->pattern.head; x; x = x->next)
257*10898Sroland.mainz@nrubsig.org addre(state, &state->re, x->string);
258*10898Sroland.mainz@nrubsig.org for (x = state->file.head; x; x = x->next)
259*10898Sroland.mainz@nrubsig.org {
260*10898Sroland.mainz@nrubsig.org s = x->string;
261*10898Sroland.mainz@nrubsig.org if (!(f = sfopen(NiL, s, "r")))
262*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|4, "%s: cannot open", s);
263*10898Sroland.mainz@nrubsig.org else
264*10898Sroland.mainz@nrubsig.org {
265*10898Sroland.mainz@nrubsig.org file = error_info.file;
266*10898Sroland.mainz@nrubsig.org error_info.file = s;
267*10898Sroland.mainz@nrubsig.org line = error_info.line;
268*10898Sroland.mainz@nrubsig.org error_info.line = 0;
269*10898Sroland.mainz@nrubsig.org while (s = (char*)sfreserve(f, SF_UNBOUND, SF_LOCKR))
270*10898Sroland.mainz@nrubsig.org {
271*10898Sroland.mainz@nrubsig.org if (!(n = sfvalue(f)))
272*10898Sroland.mainz@nrubsig.org break;
273*10898Sroland.mainz@nrubsig.org if (s[n - 1] != '\n')
274*10898Sroland.mainz@nrubsig.org {
275*10898Sroland.mainz@nrubsig.org for (t = s + n; t > s && *--t != '\n'; t--);
276*10898Sroland.mainz@nrubsig.org if (t == s)
277*10898Sroland.mainz@nrubsig.org {
278*10898Sroland.mainz@nrubsig.org sfread(f, s, 0);
279*10898Sroland.mainz@nrubsig.org break;
280*10898Sroland.mainz@nrubsig.org }
281*10898Sroland.mainz@nrubsig.org n = t - s + 1;
282*10898Sroland.mainz@nrubsig.org }
283*10898Sroland.mainz@nrubsig.org s[n - 1] = 0;
284*10898Sroland.mainz@nrubsig.org addre(state, &state->re, s);
285*10898Sroland.mainz@nrubsig.org s[n - 1] = '\n';
286*10898Sroland.mainz@nrubsig.org sfread(f, s, n);
287*10898Sroland.mainz@nrubsig.org }
288*10898Sroland.mainz@nrubsig.org while ((s = sfgetr(f, '\n', 1)) || (s = sfgetr(f, '\n', -1)))
289*10898Sroland.mainz@nrubsig.org {
290*10898Sroland.mainz@nrubsig.org error_info.line++;
291*10898Sroland.mainz@nrubsig.org addre(state, &state->re, s);
292*10898Sroland.mainz@nrubsig.org }
293*10898Sroland.mainz@nrubsig.org error_info.file = file;
294*10898Sroland.mainz@nrubsig.org error_info.line = line;
295*10898Sroland.mainz@nrubsig.org sfclose(f);
296*10898Sroland.mainz@nrubsig.org }
297*10898Sroland.mainz@nrubsig.org }
298*10898Sroland.mainz@nrubsig.org if (!state->re.head)
299*10898Sroland.mainz@nrubsig.org error(3, "no pattern");
300*10898Sroland.mainz@nrubsig.org }
301*10898Sroland.mainz@nrubsig.org
302*10898Sroland.mainz@nrubsig.org static void
highlight(Sfio_t * sp,const char * s,int n,int so,int eo)303*10898Sroland.mainz@nrubsig.org highlight(Sfio_t* sp, const char* s, int n, int so, int eo)
304*10898Sroland.mainz@nrubsig.org {
305*10898Sroland.mainz@nrubsig.org static const char bold[] = {CC_esc,'[','1','m'};
306*10898Sroland.mainz@nrubsig.org static const char normal[] = {CC_esc,'[','0','m'};
307*10898Sroland.mainz@nrubsig.org
308*10898Sroland.mainz@nrubsig.org sfwrite(sp, s, so);
309*10898Sroland.mainz@nrubsig.org sfwrite(sp, bold, sizeof(bold));
310*10898Sroland.mainz@nrubsig.org sfwrite(sp, s + so, eo - so);
311*10898Sroland.mainz@nrubsig.org sfwrite(sp, normal, sizeof(normal));
312*10898Sroland.mainz@nrubsig.org sfwrite(sp, s + eo, n - eo);
313*10898Sroland.mainz@nrubsig.org }
314*10898Sroland.mainz@nrubsig.org
315*10898Sroland.mainz@nrubsig.org typedef struct
316*10898Sroland.mainz@nrubsig.org {
317*10898Sroland.mainz@nrubsig.org State_s *state;
318*10898Sroland.mainz@nrubsig.org Item_t *item;
319*10898Sroland.mainz@nrubsig.org } record_handle;
320*10898Sroland.mainz@nrubsig.org
321*10898Sroland.mainz@nrubsig.org static int
record(void * handle,const char * s,size_t len)322*10898Sroland.mainz@nrubsig.org record(void* handle, const char* s, size_t len)
323*10898Sroland.mainz@nrubsig.org {
324*10898Sroland.mainz@nrubsig.org record_handle *r_x = (record_handle *)handle;
325*10898Sroland.mainz@nrubsig.org State_s *state = r_x->state;
326*10898Sroland.mainz@nrubsig.org Item_t *item = r_x->item;
327*10898Sroland.mainz@nrubsig.org
328*10898Sroland.mainz@nrubsig.org item->hits++;
329*10898Sroland.mainz@nrubsig.org if (state->query || state->list)
330*10898Sroland.mainz@nrubsig.org return -1;
331*10898Sroland.mainz@nrubsig.org if (!state->count)
332*10898Sroland.mainz@nrubsig.org {
333*10898Sroland.mainz@nrubsig.org if (state->prefix)
334*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", error_info.file);
335*10898Sroland.mainz@nrubsig.org if (state->label)
336*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", item->string);
337*10898Sroland.mainz@nrubsig.org if (state->pos)
338*10898Sroland.mainz@nrubsig.org highlight(sfstdout, s, len + 1, state->pos[0].rm_so, state->pos[0].rm_eo);
339*10898Sroland.mainz@nrubsig.org else
340*10898Sroland.mainz@nrubsig.org sfwrite(sfstdout, s, len + 1);
341*10898Sroland.mainz@nrubsig.org }
342*10898Sroland.mainz@nrubsig.org return 0;
343*10898Sroland.mainz@nrubsig.org }
344*10898Sroland.mainz@nrubsig.org
345*10898Sroland.mainz@nrubsig.org static void
execute(State_s * state,Sfio_t * input,char * name)346*10898Sroland.mainz@nrubsig.org execute(State_s *state, Sfio_t* input, char* name)
347*10898Sroland.mainz@nrubsig.org {
348*10898Sroland.mainz@nrubsig.org register char* s;
349*10898Sroland.mainz@nrubsig.org char* file;
350*10898Sroland.mainz@nrubsig.org Item_t* x;
351*10898Sroland.mainz@nrubsig.org size_t len;
352*10898Sroland.mainz@nrubsig.org int result;
353*10898Sroland.mainz@nrubsig.org int line;
354*10898Sroland.mainz@nrubsig.org
355*10898Sroland.mainz@nrubsig.org Sfulong_t hits = 0;
356*10898Sroland.mainz@nrubsig.org
357*10898Sroland.mainz@nrubsig.org if (state->buffer.noshare)
358*10898Sroland.mainz@nrubsig.org sfset(input, SF_SHARE, 0);
359*10898Sroland.mainz@nrubsig.org if (state->buffer.size)
360*10898Sroland.mainz@nrubsig.org sfsetbuf(input, state->buffer.base, state->buffer.size);
361*10898Sroland.mainz@nrubsig.org if (!name)
362*10898Sroland.mainz@nrubsig.org name = "/dev/stdin";
363*10898Sroland.mainz@nrubsig.org file = error_info.file;
364*10898Sroland.mainz@nrubsig.org error_info.file = name;
365*10898Sroland.mainz@nrubsig.org line = error_info.line;
366*10898Sroland.mainz@nrubsig.org error_info.line = 0;
367*10898Sroland.mainz@nrubsig.org if (state->byline)
368*10898Sroland.mainz@nrubsig.org {
369*10898Sroland.mainz@nrubsig.org for (;;)
370*10898Sroland.mainz@nrubsig.org {
371*10898Sroland.mainz@nrubsig.org error_info.line++;
372*10898Sroland.mainz@nrubsig.org if (s = sfgetr(input, '\n', 0))
373*10898Sroland.mainz@nrubsig.org len = sfvalue(input) - 1;
374*10898Sroland.mainz@nrubsig.org else if (s = sfgetr(input, '\n', -1))
375*10898Sroland.mainz@nrubsig.org {
376*10898Sroland.mainz@nrubsig.org len = sfvalue(input);
377*10898Sroland.mainz@nrubsig.org s[len] = '\n';
378*10898Sroland.mainz@nrubsig.org #if _you_like_the_noise
379*10898Sroland.mainz@nrubsig.org error(1, "newline appended");
380*10898Sroland.mainz@nrubsig.org #endif
381*10898Sroland.mainz@nrubsig.org }
382*10898Sroland.mainz@nrubsig.org else
383*10898Sroland.mainz@nrubsig.org {
384*10898Sroland.mainz@nrubsig.org if (sferror(input) && errno != EISDIR)
385*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|2, "read error");
386*10898Sroland.mainz@nrubsig.org break;
387*10898Sroland.mainz@nrubsig.org }
388*10898Sroland.mainz@nrubsig.org x = state->re.head;
389*10898Sroland.mainz@nrubsig.org do
390*10898Sroland.mainz@nrubsig.org {
391*10898Sroland.mainz@nrubsig.org if (!(result = regnexec(&x->re, s, len, state->posnum, state->pos, 0)))
392*10898Sroland.mainz@nrubsig.org {
393*10898Sroland.mainz@nrubsig.org if (!state->label)
394*10898Sroland.mainz@nrubsig.org break;
395*10898Sroland.mainz@nrubsig.org x->hits++;
396*10898Sroland.mainz@nrubsig.org if (state->query || state->list)
397*10898Sroland.mainz@nrubsig.org goto done;
398*10898Sroland.mainz@nrubsig.org if (!state->count)
399*10898Sroland.mainz@nrubsig.org {
400*10898Sroland.mainz@nrubsig.org if (state->prefix)
401*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", name);
402*10898Sroland.mainz@nrubsig.org if (state->number)
403*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%d:", error_info.line);
404*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", x->string);
405*10898Sroland.mainz@nrubsig.org if (state->pos)
406*10898Sroland.mainz@nrubsig.org highlight(sfstdout, s, len + 1, state->pos[0].rm_so, state->pos[0].rm_eo);
407*10898Sroland.mainz@nrubsig.org else
408*10898Sroland.mainz@nrubsig.org sfwrite(sfstdout, s, len + 1);
409*10898Sroland.mainz@nrubsig.org }
410*10898Sroland.mainz@nrubsig.org }
411*10898Sroland.mainz@nrubsig.org else if (result != REG_NOMATCH)
412*10898Sroland.mainz@nrubsig.org regfatal(&x->re, 3, result);
413*10898Sroland.mainz@nrubsig.org } while (x = x->next);
414*10898Sroland.mainz@nrubsig.org if (!state->label && (x != 0) == state->match)
415*10898Sroland.mainz@nrubsig.org {
416*10898Sroland.mainz@nrubsig.org hits++;
417*10898Sroland.mainz@nrubsig.org if (state->query || state->list)
418*10898Sroland.mainz@nrubsig.org break;
419*10898Sroland.mainz@nrubsig.org if (!state->count)
420*10898Sroland.mainz@nrubsig.org {
421*10898Sroland.mainz@nrubsig.org if (state->prefix)
422*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", name);
423*10898Sroland.mainz@nrubsig.org if (state->number)
424*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%d:", error_info.line);
425*10898Sroland.mainz@nrubsig.org if (state->pos)
426*10898Sroland.mainz@nrubsig.org highlight(sfstdout, s, len + 1, state->pos[0].rm_so, state->pos[0].rm_eo);
427*10898Sroland.mainz@nrubsig.org else
428*10898Sroland.mainz@nrubsig.org sfwrite(sfstdout, s, len + 1);
429*10898Sroland.mainz@nrubsig.org }
430*10898Sroland.mainz@nrubsig.org }
431*10898Sroland.mainz@nrubsig.org }
432*10898Sroland.mainz@nrubsig.org }
433*10898Sroland.mainz@nrubsig.org else
434*10898Sroland.mainz@nrubsig.org {
435*10898Sroland.mainz@nrubsig.org register char* e;
436*10898Sroland.mainz@nrubsig.org register char* t;
437*10898Sroland.mainz@nrubsig.org char* r;
438*10898Sroland.mainz@nrubsig.org
439*10898Sroland.mainz@nrubsig.org static char* span = 0;
440*10898Sroland.mainz@nrubsig.org static size_t spansize = 0;
441*10898Sroland.mainz@nrubsig.org
442*10898Sroland.mainz@nrubsig.org s = e = 0;
443*10898Sroland.mainz@nrubsig.org for (;;)
444*10898Sroland.mainz@nrubsig.org {
445*10898Sroland.mainz@nrubsig.org if (s < e)
446*10898Sroland.mainz@nrubsig.org {
447*10898Sroland.mainz@nrubsig.org t = span;
448*10898Sroland.mainz@nrubsig.org for (;;)
449*10898Sroland.mainz@nrubsig.org {
450*10898Sroland.mainz@nrubsig.org len = 2 * (e - s) + t - span + 1;
451*10898Sroland.mainz@nrubsig.org len = roundof(len, SF_BUFSIZE);
452*10898Sroland.mainz@nrubsig.org if (spansize < len)
453*10898Sroland.mainz@nrubsig.org {
454*10898Sroland.mainz@nrubsig.org spansize = len;
455*10898Sroland.mainz@nrubsig.org len = t - span;
456*10898Sroland.mainz@nrubsig.org if (!(span = newof(span, char, spansize, 0)))
457*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "%s: line longer than %lu characters", name, len + e - s);
458*10898Sroland.mainz@nrubsig.org t = span + len;
459*10898Sroland.mainz@nrubsig.org }
460*10898Sroland.mainz@nrubsig.org len = e - s;
461*10898Sroland.mainz@nrubsig.org memcpy(t, s, len);
462*10898Sroland.mainz@nrubsig.org t += len;
463*10898Sroland.mainz@nrubsig.org if (!(s = sfreserve(input, SF_UNBOUND, 0)) || (len = sfvalue(input)) <= 0)
464*10898Sroland.mainz@nrubsig.org {
465*10898Sroland.mainz@nrubsig.org if ((sfvalue(input) || sferror(input)) && errno != EISDIR)
466*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|2, "%s: read error", name);
467*10898Sroland.mainz@nrubsig.org break;
468*10898Sroland.mainz@nrubsig.org }
469*10898Sroland.mainz@nrubsig.org else if (!(e = memchr(s, '\n', len)))
470*10898Sroland.mainz@nrubsig.org e = s + len;
471*10898Sroland.mainz@nrubsig.org else
472*10898Sroland.mainz@nrubsig.org {
473*10898Sroland.mainz@nrubsig.org r = s + len;
474*10898Sroland.mainz@nrubsig.org len = (e - s) + t - span;
475*10898Sroland.mainz@nrubsig.org len = roundof(len, SF_BUFSIZE);
476*10898Sroland.mainz@nrubsig.org if (spansize < len)
477*10898Sroland.mainz@nrubsig.org {
478*10898Sroland.mainz@nrubsig.org spansize = len;
479*10898Sroland.mainz@nrubsig.org len = t - span;
480*10898Sroland.mainz@nrubsig.org if (!(span = newof(span, char, spansize, 0)))
481*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "%s: line longer than %lu characters", name, len + e - s);
482*10898Sroland.mainz@nrubsig.org t = span + len;
483*10898Sroland.mainz@nrubsig.org }
484*10898Sroland.mainz@nrubsig.org len = e - s;
485*10898Sroland.mainz@nrubsig.org memcpy(t, s, len);
486*10898Sroland.mainz@nrubsig.org t += len;
487*10898Sroland.mainz@nrubsig.org s += len + 1;
488*10898Sroland.mainz@nrubsig.org e = r;
489*10898Sroland.mainz@nrubsig.org break;
490*10898Sroland.mainz@nrubsig.org }
491*10898Sroland.mainz@nrubsig.org }
492*10898Sroland.mainz@nrubsig.org *t = '\n';
493*10898Sroland.mainz@nrubsig.org x = state->re.head;
494*10898Sroland.mainz@nrubsig.org do
495*10898Sroland.mainz@nrubsig.org {
496*10898Sroland.mainz@nrubsig.org record_handle r_x = { state, x };
497*10898Sroland.mainz@nrubsig.org if ((result = regrexec(&x->re, span, t - span, state->posnum, state->pos, state->options, '\n', (void*)&r_x, record)) < 0)
498*10898Sroland.mainz@nrubsig.org goto done;
499*10898Sroland.mainz@nrubsig.org if (result && result != REG_NOMATCH)
500*10898Sroland.mainz@nrubsig.org regfatal(&x->re, 3, result);
501*10898Sroland.mainz@nrubsig.org } while (x = x->next);
502*10898Sroland.mainz@nrubsig.org if (!s)
503*10898Sroland.mainz@nrubsig.org break;
504*10898Sroland.mainz@nrubsig.org }
505*10898Sroland.mainz@nrubsig.org else
506*10898Sroland.mainz@nrubsig.org {
507*10898Sroland.mainz@nrubsig.org if (!(s = sfreserve(input, SF_UNBOUND, 0)))
508*10898Sroland.mainz@nrubsig.org {
509*10898Sroland.mainz@nrubsig.org if ((sfvalue(input) || sferror(input)) && errno != EISDIR)
510*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|2, "%s: read error", name);
511*10898Sroland.mainz@nrubsig.org break;
512*10898Sroland.mainz@nrubsig.org }
513*10898Sroland.mainz@nrubsig.org if ((len = sfvalue(input)) <= 0)
514*10898Sroland.mainz@nrubsig.org break;
515*10898Sroland.mainz@nrubsig.org e = s + len;
516*10898Sroland.mainz@nrubsig.org }
517*10898Sroland.mainz@nrubsig.org t = e;
518*10898Sroland.mainz@nrubsig.org while (t > s)
519*10898Sroland.mainz@nrubsig.org if (*--t == '\n')
520*10898Sroland.mainz@nrubsig.org {
521*10898Sroland.mainz@nrubsig.org x = state->re.head;
522*10898Sroland.mainz@nrubsig.org do
523*10898Sroland.mainz@nrubsig.org {
524*10898Sroland.mainz@nrubsig.org record_handle r_x = { state, x };
525*10898Sroland.mainz@nrubsig.org if ((result = regrexec(&x->re, s, t - s, state->posnum, state->pos, state->options, '\n', (void*)&r_x, record)) < 0)
526*10898Sroland.mainz@nrubsig.org goto done;
527*10898Sroland.mainz@nrubsig.org if (result && result != REG_NOMATCH)
528*10898Sroland.mainz@nrubsig.org regfatal(&x->re, 3, result);
529*10898Sroland.mainz@nrubsig.org } while (x = x->next);
530*10898Sroland.mainz@nrubsig.org s = t + 1;
531*10898Sroland.mainz@nrubsig.org break;
532*10898Sroland.mainz@nrubsig.org }
533*10898Sroland.mainz@nrubsig.org }
534*10898Sroland.mainz@nrubsig.org }
535*10898Sroland.mainz@nrubsig.org done:
536*10898Sroland.mainz@nrubsig.org error_info.file = file;
537*10898Sroland.mainz@nrubsig.org error_info.line = line;
538*10898Sroland.mainz@nrubsig.org if (state->byline && !state->label)
539*10898Sroland.mainz@nrubsig.org {
540*10898Sroland.mainz@nrubsig.org if (hits && state->list >= 0)
541*10898Sroland.mainz@nrubsig.org state->any = 1;
542*10898Sroland.mainz@nrubsig.org if (!state->query)
543*10898Sroland.mainz@nrubsig.org {
544*10898Sroland.mainz@nrubsig.org if (!state->list)
545*10898Sroland.mainz@nrubsig.org {
546*10898Sroland.mainz@nrubsig.org if (state->count)
547*10898Sroland.mainz@nrubsig.org {
548*10898Sroland.mainz@nrubsig.org if (state->count & 2)
549*10898Sroland.mainz@nrubsig.org state->hits += hits;
550*10898Sroland.mainz@nrubsig.org else
551*10898Sroland.mainz@nrubsig.org {
552*10898Sroland.mainz@nrubsig.org if (state->prefix)
553*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", name);
554*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%I*u\n", sizeof(hits), hits);
555*10898Sroland.mainz@nrubsig.org }
556*10898Sroland.mainz@nrubsig.org }
557*10898Sroland.mainz@nrubsig.org }
558*10898Sroland.mainz@nrubsig.org else if ((hits != 0) == (state->list > 0))
559*10898Sroland.mainz@nrubsig.org {
560*10898Sroland.mainz@nrubsig.org if (state->list < 0)
561*10898Sroland.mainz@nrubsig.org state->any = 1;
562*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s\n", name);
563*10898Sroland.mainz@nrubsig.org }
564*10898Sroland.mainz@nrubsig.org }
565*10898Sroland.mainz@nrubsig.org }
566*10898Sroland.mainz@nrubsig.org else
567*10898Sroland.mainz@nrubsig.org {
568*10898Sroland.mainz@nrubsig.org x = state->re.head;
569*10898Sroland.mainz@nrubsig.org do
570*10898Sroland.mainz@nrubsig.org {
571*10898Sroland.mainz@nrubsig.org if (x->hits && state->list >= 0)
572*10898Sroland.mainz@nrubsig.org {
573*10898Sroland.mainz@nrubsig.org state->any = 1;
574*10898Sroland.mainz@nrubsig.org if (state->query)
575*10898Sroland.mainz@nrubsig.org break;
576*10898Sroland.mainz@nrubsig.org }
577*10898Sroland.mainz@nrubsig.org if (!state->query)
578*10898Sroland.mainz@nrubsig.org {
579*10898Sroland.mainz@nrubsig.org if (!state->list)
580*10898Sroland.mainz@nrubsig.org {
581*10898Sroland.mainz@nrubsig.org if (state->count)
582*10898Sroland.mainz@nrubsig.org {
583*10898Sroland.mainz@nrubsig.org if (state->count & 2)
584*10898Sroland.mainz@nrubsig.org {
585*10898Sroland.mainz@nrubsig.org x->total += x->hits;
586*10898Sroland.mainz@nrubsig.org state->hits += x->hits;
587*10898Sroland.mainz@nrubsig.org }
588*10898Sroland.mainz@nrubsig.org else
589*10898Sroland.mainz@nrubsig.org {
590*10898Sroland.mainz@nrubsig.org if (state->prefix)
591*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", name);
592*10898Sroland.mainz@nrubsig.org if (state->label)
593*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:", x->string);
594*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%I*u\n", sizeof(x->hits), x->hits);
595*10898Sroland.mainz@nrubsig.org }
596*10898Sroland.mainz@nrubsig.org }
597*10898Sroland.mainz@nrubsig.org }
598*10898Sroland.mainz@nrubsig.org else if ((x->hits != 0) == (state->list > 0))
599*10898Sroland.mainz@nrubsig.org {
600*10898Sroland.mainz@nrubsig.org if (state->list < 0)
601*10898Sroland.mainz@nrubsig.org state->any = 1;
602*10898Sroland.mainz@nrubsig.org if (state->label)
603*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:%s\n", name, x->string);
604*10898Sroland.mainz@nrubsig.org else
605*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s\n", name);
606*10898Sroland.mainz@nrubsig.org }
607*10898Sroland.mainz@nrubsig.org }
608*10898Sroland.mainz@nrubsig.org x->hits = 0;
609*10898Sroland.mainz@nrubsig.org } while (x = x->next);
610*10898Sroland.mainz@nrubsig.org }
611*10898Sroland.mainz@nrubsig.org }
612*10898Sroland.mainz@nrubsig.org
613*10898Sroland.mainz@nrubsig.org
614*10898Sroland.mainz@nrubsig.org static
grep_main(int argc,char ** argv,void * context)615*10898Sroland.mainz@nrubsig.org int grep_main(int argc, char** argv, void *context)
616*10898Sroland.mainz@nrubsig.org {
617*10898Sroland.mainz@nrubsig.org int c;
618*10898Sroland.mainz@nrubsig.org char* s;
619*10898Sroland.mainz@nrubsig.org char* h;
620*10898Sroland.mainz@nrubsig.org Sfio_t* f;
621*10898Sroland.mainz@nrubsig.org State_s state;
622*10898Sroland.mainz@nrubsig.org memset(&state, 0, sizeof(state));
623*10898Sroland.mainz@nrubsig.org
624*10898Sroland.mainz@nrubsig.org NoP(argc);
625*10898Sroland.mainz@nrubsig.org state.match = 1;
626*10898Sroland.mainz@nrubsig.org state.options = REG_FIRST|REG_NOSUB|REG_NULL;
627*10898Sroland.mainz@nrubsig.org h = 0;
628*10898Sroland.mainz@nrubsig.org if (strcmp(astconf("CONFORMANCE", NiL, NiL), "standard"))
629*10898Sroland.mainz@nrubsig.org state.options |= REG_LENIENT;
630*10898Sroland.mainz@nrubsig.org if (s = strrchr(argv[0], '/'))
631*10898Sroland.mainz@nrubsig.org s++;
632*10898Sroland.mainz@nrubsig.org else
633*10898Sroland.mainz@nrubsig.org s = argv[0];
634*10898Sroland.mainz@nrubsig.org switch (*s)
635*10898Sroland.mainz@nrubsig.org {
636*10898Sroland.mainz@nrubsig.org case 'e':
637*10898Sroland.mainz@nrubsig.org case 'E':
638*10898Sroland.mainz@nrubsig.org s = "egrep";
639*10898Sroland.mainz@nrubsig.org state.options |= REG_EXTENDED;
640*10898Sroland.mainz@nrubsig.org break;
641*10898Sroland.mainz@nrubsig.org case 'f':
642*10898Sroland.mainz@nrubsig.org case 'F':
643*10898Sroland.mainz@nrubsig.org s = "fgrep";
644*10898Sroland.mainz@nrubsig.org state.options |= REG_LITERAL;
645*10898Sroland.mainz@nrubsig.org break;
646*10898Sroland.mainz@nrubsig.org case 'p':
647*10898Sroland.mainz@nrubsig.org case 'P':
648*10898Sroland.mainz@nrubsig.org s = "pgrep";
649*10898Sroland.mainz@nrubsig.org state.options |= REG_EXTENDED|REG_LENIENT;
650*10898Sroland.mainz@nrubsig.org break;
651*10898Sroland.mainz@nrubsig.org case 'x':
652*10898Sroland.mainz@nrubsig.org case 'X':
653*10898Sroland.mainz@nrubsig.org s = "xgrep";
654*10898Sroland.mainz@nrubsig.org state.options |= REG_AUGMENTED;
655*10898Sroland.mainz@nrubsig.org break;
656*10898Sroland.mainz@nrubsig.org default:
657*10898Sroland.mainz@nrubsig.org s = "grep";
658*10898Sroland.mainz@nrubsig.org break;
659*10898Sroland.mainz@nrubsig.org }
660*10898Sroland.mainz@nrubsig.org error_info.id = s;
661*10898Sroland.mainz@nrubsig.org while (c = optget(argv, usage))
662*10898Sroland.mainz@nrubsig.org switch (c)
663*10898Sroland.mainz@nrubsig.org {
664*10898Sroland.mainz@nrubsig.org case 'E':
665*10898Sroland.mainz@nrubsig.org state.options |= REG_EXTENDED;
666*10898Sroland.mainz@nrubsig.org break;
667*10898Sroland.mainz@nrubsig.org case 'F':
668*10898Sroland.mainz@nrubsig.org state.options |= REG_LITERAL;
669*10898Sroland.mainz@nrubsig.org break;
670*10898Sroland.mainz@nrubsig.org case 'G':
671*10898Sroland.mainz@nrubsig.org state.options &= ~(REG_AUGMENTED|REG_EXTENDED);
672*10898Sroland.mainz@nrubsig.org break;
673*10898Sroland.mainz@nrubsig.org case 'H':
674*10898Sroland.mainz@nrubsig.org state.prefix = opt_info.num;
675*10898Sroland.mainz@nrubsig.org break;
676*10898Sroland.mainz@nrubsig.org case 'L':
677*10898Sroland.mainz@nrubsig.org state.list = -opt_info.num;
678*10898Sroland.mainz@nrubsig.org break;
679*10898Sroland.mainz@nrubsig.org case 'N':
680*10898Sroland.mainz@nrubsig.org h = opt_info.arg;
681*10898Sroland.mainz@nrubsig.org break;
682*10898Sroland.mainz@nrubsig.org case 'O':
683*10898Sroland.mainz@nrubsig.org state.options |= REG_LENIENT;
684*10898Sroland.mainz@nrubsig.org break;
685*10898Sroland.mainz@nrubsig.org case 'P':
686*10898Sroland.mainz@nrubsig.org state.options |= REG_EXTENDED|REG_LENIENT;
687*10898Sroland.mainz@nrubsig.org break;
688*10898Sroland.mainz@nrubsig.org case 'S':
689*10898Sroland.mainz@nrubsig.org state.options &= ~REG_LENIENT;
690*10898Sroland.mainz@nrubsig.org break;
691*10898Sroland.mainz@nrubsig.org case 'T':
692*10898Sroland.mainz@nrubsig.org s = opt_info.arg;
693*10898Sroland.mainz@nrubsig.org switch (*s)
694*10898Sroland.mainz@nrubsig.org {
695*10898Sroland.mainz@nrubsig.org case 'b':
696*10898Sroland.mainz@nrubsig.org case 'm':
697*10898Sroland.mainz@nrubsig.org c = *s++;
698*10898Sroland.mainz@nrubsig.org state.buffer.size = strton(s, &s, NiL, 1);
699*10898Sroland.mainz@nrubsig.org if (c == 'b' && !(state.buffer.base = newof(0, char, state.buffer.size, 0)))
700*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "out of space [test buffer]");
701*10898Sroland.mainz@nrubsig.org if (*s)
702*10898Sroland.mainz@nrubsig.org error(3, "%s: invalid characters after test", s);
703*10898Sroland.mainz@nrubsig.org break;
704*10898Sroland.mainz@nrubsig.org case 'f':
705*10898Sroland.mainz@nrubsig.org state.options |= REG_FIRST;
706*10898Sroland.mainz@nrubsig.org break;
707*10898Sroland.mainz@nrubsig.org case 'l':
708*10898Sroland.mainz@nrubsig.org state.options |= REG_LEFT;
709*10898Sroland.mainz@nrubsig.org break;
710*10898Sroland.mainz@nrubsig.org case 'n':
711*10898Sroland.mainz@nrubsig.org state.buffer.noshare = 1;
712*10898Sroland.mainz@nrubsig.org break;
713*10898Sroland.mainz@nrubsig.org case 'r':
714*10898Sroland.mainz@nrubsig.org state.options |= REG_RIGHT;
715*10898Sroland.mainz@nrubsig.org break;
716*10898Sroland.mainz@nrubsig.org default:
717*10898Sroland.mainz@nrubsig.org error(3, "%s: unknown test", s);
718*10898Sroland.mainz@nrubsig.org break;
719*10898Sroland.mainz@nrubsig.org }
720*10898Sroland.mainz@nrubsig.org break;
721*10898Sroland.mainz@nrubsig.org case 'X':
722*10898Sroland.mainz@nrubsig.org state.options |= REG_AUGMENTED;
723*10898Sroland.mainz@nrubsig.org break;
724*10898Sroland.mainz@nrubsig.org case 'a':
725*10898Sroland.mainz@nrubsig.org break;
726*10898Sroland.mainz@nrubsig.org case 'b':
727*10898Sroland.mainz@nrubsig.org state.options &= ~(REG_FIRST|REG_NOSUB);
728*10898Sroland.mainz@nrubsig.org break;
729*10898Sroland.mainz@nrubsig.org case 'c':
730*10898Sroland.mainz@nrubsig.org state.count |= 1;
731*10898Sroland.mainz@nrubsig.org break;
732*10898Sroland.mainz@nrubsig.org case 'e':
733*10898Sroland.mainz@nrubsig.org addstring(&state, &state.pattern, opt_info.arg);
734*10898Sroland.mainz@nrubsig.org break;
735*10898Sroland.mainz@nrubsig.org case 'f':
736*10898Sroland.mainz@nrubsig.org addstring(&state, &state.file, opt_info.arg);
737*10898Sroland.mainz@nrubsig.org break;
738*10898Sroland.mainz@nrubsig.org case 'h':
739*10898Sroland.mainz@nrubsig.org state.prefix = 2;
740*10898Sroland.mainz@nrubsig.org break;
741*10898Sroland.mainz@nrubsig.org case 'i':
742*10898Sroland.mainz@nrubsig.org state.options |= REG_ICASE;
743*10898Sroland.mainz@nrubsig.org break;
744*10898Sroland.mainz@nrubsig.org case 'l':
745*10898Sroland.mainz@nrubsig.org state.list = opt_info.num;
746*10898Sroland.mainz@nrubsig.org break;
747*10898Sroland.mainz@nrubsig.org case 'm':
748*10898Sroland.mainz@nrubsig.org state.label = 1;
749*10898Sroland.mainz@nrubsig.org break;
750*10898Sroland.mainz@nrubsig.org case 'n':
751*10898Sroland.mainz@nrubsig.org state.number = 1;
752*10898Sroland.mainz@nrubsig.org break;
753*10898Sroland.mainz@nrubsig.org case 'q':
754*10898Sroland.mainz@nrubsig.org state.query = 1;
755*10898Sroland.mainz@nrubsig.org break;
756*10898Sroland.mainz@nrubsig.org case 's':
757*10898Sroland.mainz@nrubsig.org state.suppress = opt_info.num;
758*10898Sroland.mainz@nrubsig.org break;
759*10898Sroland.mainz@nrubsig.org case 't':
760*10898Sroland.mainz@nrubsig.org state.count |= 2;
761*10898Sroland.mainz@nrubsig.org break;
762*10898Sroland.mainz@nrubsig.org case 'v':
763*10898Sroland.mainz@nrubsig.org if (state.match = !opt_info.num)
764*10898Sroland.mainz@nrubsig.org state.options &= ~REG_INVERT;
765*10898Sroland.mainz@nrubsig.org else
766*10898Sroland.mainz@nrubsig.org state.options |= REG_INVERT;
767*10898Sroland.mainz@nrubsig.org break;
768*10898Sroland.mainz@nrubsig.org case 'w':
769*10898Sroland.mainz@nrubsig.org state.words = 1;
770*10898Sroland.mainz@nrubsig.org break;
771*10898Sroland.mainz@nrubsig.org case 'x':
772*10898Sroland.mainz@nrubsig.org state.options |= REG_LEFT|REG_RIGHT;
773*10898Sroland.mainz@nrubsig.org break;
774*10898Sroland.mainz@nrubsig.org case '?':
775*10898Sroland.mainz@nrubsig.org error(ERROR_USAGE|4, "%s", opt_info.arg);
776*10898Sroland.mainz@nrubsig.org break;
777*10898Sroland.mainz@nrubsig.org case ':':
778*10898Sroland.mainz@nrubsig.org error(2, "%s", opt_info.arg);
779*10898Sroland.mainz@nrubsig.org break;
780*10898Sroland.mainz@nrubsig.org default:
781*10898Sroland.mainz@nrubsig.org error(3, "%s: not implemented", opt_info.name);
782*10898Sroland.mainz@nrubsig.org break;
783*10898Sroland.mainz@nrubsig.org }
784*10898Sroland.mainz@nrubsig.org argv += opt_info.index;
785*10898Sroland.mainz@nrubsig.org if ((state.options & REG_LITERAL) && (state.options & (REG_AUGMENTED|REG_EXTENDED)))
786*10898Sroland.mainz@nrubsig.org error(3, "-F and -A or -P or -X are incompatible");
787*10898Sroland.mainz@nrubsig.org if ((state.options & REG_LITERAL) && state.words)
788*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "-F and -w are incompatible");
789*10898Sroland.mainz@nrubsig.org if (!state.file.head && !state.pattern.head)
790*10898Sroland.mainz@nrubsig.org {
791*10898Sroland.mainz@nrubsig.org if (!argv[0])
792*10898Sroland.mainz@nrubsig.org error(3, "no pattern");
793*10898Sroland.mainz@nrubsig.org addstring(&state, &state.pattern, *argv++);
794*10898Sroland.mainz@nrubsig.org }
795*10898Sroland.mainz@nrubsig.org if (!(state.options & (REG_FIRST|REG_NOSUB)))
796*10898Sroland.mainz@nrubsig.org {
797*10898Sroland.mainz@nrubsig.org if (state.count || state.list || state.query || (state.options & REG_INVERT))
798*10898Sroland.mainz@nrubsig.org state.options |= REG_FIRST|REG_NOSUB;
799*10898Sroland.mainz@nrubsig.org else
800*10898Sroland.mainz@nrubsig.org {
801*10898Sroland.mainz@nrubsig.org state.pos = state.posvec;
802*10898Sroland.mainz@nrubsig.org state.posnum = elementsof(state.posvec);
803*10898Sroland.mainz@nrubsig.org }
804*10898Sroland.mainz@nrubsig.org }
805*10898Sroland.mainz@nrubsig.org compile(&state);
806*10898Sroland.mainz@nrubsig.org if (!argv[0])
807*10898Sroland.mainz@nrubsig.org {
808*10898Sroland.mainz@nrubsig.org state.prefix = h ? 1 : 0;
809*10898Sroland.mainz@nrubsig.org execute(&state, sfstdin, h);
810*10898Sroland.mainz@nrubsig.org }
811*10898Sroland.mainz@nrubsig.org else
812*10898Sroland.mainz@nrubsig.org {
813*10898Sroland.mainz@nrubsig.org if (state.prefix > 1)
814*10898Sroland.mainz@nrubsig.org state.prefix = 0;
815*10898Sroland.mainz@nrubsig.org else if (argv[1])
816*10898Sroland.mainz@nrubsig.org state.prefix = 1;
817*10898Sroland.mainz@nrubsig.org while (s = *argv++)
818*10898Sroland.mainz@nrubsig.org {
819*10898Sroland.mainz@nrubsig.org if (f = sfopen(NiL, s, "r"))
820*10898Sroland.mainz@nrubsig.org {
821*10898Sroland.mainz@nrubsig.org execute(&state, f, s);
822*10898Sroland.mainz@nrubsig.org sfclose(f);
823*10898Sroland.mainz@nrubsig.org if (state.query && state.any)
824*10898Sroland.mainz@nrubsig.org break;
825*10898Sroland.mainz@nrubsig.org }
826*10898Sroland.mainz@nrubsig.org else
827*10898Sroland.mainz@nrubsig.org {
828*10898Sroland.mainz@nrubsig.org state.notfound = 1;
829*10898Sroland.mainz@nrubsig.org if (!state.suppress)
830*10898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|2, "%s: cannot open", s);
831*10898Sroland.mainz@nrubsig.org }
832*10898Sroland.mainz@nrubsig.org }
833*10898Sroland.mainz@nrubsig.org }
834*10898Sroland.mainz@nrubsig.org if ((state.count & 2) && !state.query && !state.list)
835*10898Sroland.mainz@nrubsig.org {
836*10898Sroland.mainz@nrubsig.org if (state.label)
837*10898Sroland.mainz@nrubsig.org {
838*10898Sroland.mainz@nrubsig.org Item_t* x;
839*10898Sroland.mainz@nrubsig.org
840*10898Sroland.mainz@nrubsig.org x = state.re.head;
841*10898Sroland.mainz@nrubsig.org do
842*10898Sroland.mainz@nrubsig.org {
843*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%s:%I*u\n", x->string, sizeof(x->total), x->total);
844*10898Sroland.mainz@nrubsig.org } while (x = x->next);
845*10898Sroland.mainz@nrubsig.org }
846*10898Sroland.mainz@nrubsig.org else
847*10898Sroland.mainz@nrubsig.org sfprintf(sfstdout, "%I*u\n", sizeof(state.hits), state.hits);
848*10898Sroland.mainz@nrubsig.org }
849*10898Sroland.mainz@nrubsig.org return (state.notfound && !state.query) ? 2 : !state.any;
850*10898Sroland.mainz@nrubsig.org }
851*10898Sroland.mainz@nrubsig.org
852*10898Sroland.mainz@nrubsig.org
b_egrep(int argc,char ** argv,void * context)853*10898Sroland.mainz@nrubsig.org int b_egrep(int argc, char** argv, void *context)
854*10898Sroland.mainz@nrubsig.org {
855*10898Sroland.mainz@nrubsig.org return grep_main(argc, argv, context);
856*10898Sroland.mainz@nrubsig.org }
857*10898Sroland.mainz@nrubsig.org
b_grep(int argc,char ** argv,void * context)858*10898Sroland.mainz@nrubsig.org int b_grep(int argc, char** argv, void *context)
859*10898Sroland.mainz@nrubsig.org {
860*10898Sroland.mainz@nrubsig.org return grep_main(argc, argv, context);
861*10898Sroland.mainz@nrubsig.org }
862*10898Sroland.mainz@nrubsig.org
b_fgrep(int argc,char ** argv,void * context)863*10898Sroland.mainz@nrubsig.org int b_fgrep(int argc, char** argv, void *context)
864*10898Sroland.mainz@nrubsig.org {
865*10898Sroland.mainz@nrubsig.org return grep_main(argc, argv, context);
866*10898Sroland.mainz@nrubsig.org }
867*10898Sroland.mainz@nrubsig.org
b_pgrep(int argc,char ** argv,void * context)868*10898Sroland.mainz@nrubsig.org int b_pgrep(int argc, char** argv, void *context)
869*10898Sroland.mainz@nrubsig.org {
870*10898Sroland.mainz@nrubsig.org return grep_main(argc, argv, context);
871*10898Sroland.mainz@nrubsig.org }
872*10898Sroland.mainz@nrubsig.org
b_xgrep(int argc,char ** argv,void * context)873*10898Sroland.mainz@nrubsig.org int b_xgrep(int argc, char** argv, void *context)
874*10898Sroland.mainz@nrubsig.org {
875*10898Sroland.mainz@nrubsig.org return grep_main(argc, argv, context);
876*10898Sroland.mainz@nrubsig.org }
877