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