1 8ad51794 2004-03-25 devnull #define EXTERN
2 8ad51794 2004-03-25 devnull #include "grep.h"
4 2305af1c 2007-05-03 devnull char *validflags = "bchiLlnsv";
6 8ad51794 2004-03-25 devnull usage(void)
8 8ad51794 2004-03-25 devnull fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags);
9 8ad51794 2004-03-25 devnull exits("usage");
13 8ad51794 2004-03-25 devnull main(int argc, char *argv[])
15 8ad51794 2004-03-25 devnull int i, status;
17 8ad51794 2004-03-25 devnull ARGBEGIN {
19 8ad51794 2004-03-25 devnull if(utfrune(validflags, ARGC()) == nil)
21 8ad51794 2004-03-25 devnull flags[ARGC()]++;
24 29cfa385 2007-05-03 devnull case 'q': /* gnu grep -q means plan 9 grep -s */
25 29cfa385 2007-05-03 devnull flags['s']++;
28 c8b6342d 2005-01-13 devnull case 'E': /* ignore, turns gnu grep into egrep */
31 8ad51794 2004-03-25 devnull case 'e':
32 8ad51794 2004-03-25 devnull flags['e']++;
33 8ad51794 2004-03-25 devnull lineno = 0;
34 8ad51794 2004-03-25 devnull str2top(ARGF());
37 8ad51794 2004-03-25 devnull case 'f':
38 8ad51794 2004-03-25 devnull flags['f']++;
39 8ad51794 2004-03-25 devnull filename = ARGF();
40 8ad51794 2004-03-25 devnull rein = Bopen(filename, OREAD);
41 8ad51794 2004-03-25 devnull if(rein == 0) {
42 8ad51794 2004-03-25 devnull fprint(2, "grep: can't open %s: %r\n", filename);
43 8ad51794 2004-03-25 devnull exits("open");
45 8ad51794 2004-03-25 devnull lineno = 1;
46 8ad51794 2004-03-25 devnull str2top(filename);
50 8ad51794 2004-03-25 devnull if(flags['f'] == 0 && flags['e'] == 0) {
51 8ad51794 2004-03-25 devnull if(argc <= 0)
53 8ad51794 2004-03-25 devnull str2top(argv[0]);
58 8ad51794 2004-03-25 devnull follow = mal(maxfollow*sizeof(*follow));
59 8ad51794 2004-03-25 devnull state0 = initstate(topre.beg);
61 8ad51794 2004-03-25 devnull Binit(&bout, 1, OWRITE);
62 8ad51794 2004-03-25 devnull switch(argc) {
64 8ad51794 2004-03-25 devnull status = search(0, 0);
67 8ad51794 2004-03-25 devnull status = search(argv[0], 0);
70 8ad51794 2004-03-25 devnull status = 0;
71 8ad51794 2004-03-25 devnull for(i=0; i<argc; i++)
72 8ad51794 2004-03-25 devnull status |= search(argv[i], Hflag);
75 8ad51794 2004-03-25 devnull if(status)
76 8ad51794 2004-03-25 devnull exits(0);
77 8ad51794 2004-03-25 devnull exits("no matches");
81 8ad51794 2004-03-25 devnull search(char *file, int flag)
83 8ad51794 2004-03-25 devnull State *s, *ns;
84 8ad51794 2004-03-25 devnull int c, fid, eof, nl, empty;
85 8ad51794 2004-03-25 devnull long count, lineno, n;
86 8ad51794 2004-03-25 devnull uchar *elp, *lp, *bol;
88 8ad51794 2004-03-25 devnull if(file == 0) {
89 8ad51794 2004-03-25 devnull file = "stdin";
91 8ad51794 2004-03-25 devnull flag |= Bflag;
93 8ad51794 2004-03-25 devnull fid = open(file, OREAD);
95 8ad51794 2004-03-25 devnull if(fid < 0) {
96 8ad51794 2004-03-25 devnull fprint(2, "grep: can't open %s: %r\n", file);
97 8ad51794 2004-03-25 devnull return 0;
100 8ad51794 2004-03-25 devnull if(flags['b'])
101 8ad51794 2004-03-25 devnull flag ^= Bflag; /* dont buffer output */
102 8ad51794 2004-03-25 devnull if(flags['c'])
103 8ad51794 2004-03-25 devnull flag |= Cflag; /* count */
104 8ad51794 2004-03-25 devnull if(flags['h'])
105 8ad51794 2004-03-25 devnull flag &= ~Hflag; /* do not print file name in output */
106 8ad51794 2004-03-25 devnull if(flags['i'])
107 8ad51794 2004-03-25 devnull flag |= Iflag; /* fold upper-lower */
108 8ad51794 2004-03-25 devnull if(flags['l'])
109 8ad51794 2004-03-25 devnull flag |= Llflag; /* print only name of file if any match */
110 8ad51794 2004-03-25 devnull if(flags['L'])
111 8ad51794 2004-03-25 devnull flag |= LLflag; /* print only name of file if any non match */
112 8ad51794 2004-03-25 devnull if(flags['n'])
113 8ad51794 2004-03-25 devnull flag |= Nflag; /* count only */
114 8ad51794 2004-03-25 devnull if(flags['s'])
115 8ad51794 2004-03-25 devnull flag |= Sflag; /* status only */
116 8ad51794 2004-03-25 devnull if(flags['v'])
117 8ad51794 2004-03-25 devnull flag |= Vflag; /* inverse match */
119 8ad51794 2004-03-25 devnull s = state0;
120 8ad51794 2004-03-25 devnull lineno = 0;
121 8ad51794 2004-03-25 devnull count = 0;
122 8ad51794 2004-03-25 devnull eof = 0;
123 8ad51794 2004-03-25 devnull empty = 1;
125 1a84af59 2004-03-25 devnull lp = u.u.buf;
126 8ad51794 2004-03-25 devnull bol = lp;
129 8ad51794 2004-03-25 devnull n = lp-bol;
130 1a84af59 2004-03-25 devnull if(n > sizeof(u.u.pre))
131 1a84af59 2004-03-25 devnull n = sizeof(u.u.pre);
132 1a84af59 2004-03-25 devnull memmove(u.u.buf-n, bol, n);
133 1a84af59 2004-03-25 devnull bol = u.u.buf-n;
134 1a84af59 2004-03-25 devnull n = read(fid, u.u.buf, sizeof(u.u.buf));
135 8ad51794 2004-03-25 devnull /* if file has no final newline, simulate one to emit matches to last line */
136 8ad51794 2004-03-25 devnull if(n > 0) {
137 8ad51794 2004-03-25 devnull empty = 0;
138 1a84af59 2004-03-25 devnull nl = u.u.buf[n-1]=='\n';
139 8ad51794 2004-03-25 devnull } else {
140 8ad51794 2004-03-25 devnull if(n < 0){
141 8ad51794 2004-03-25 devnull fprint(2, "grep: read error on %s: %r\n", file);
142 8ad51794 2004-03-25 devnull return count != 0;
144 8ad51794 2004-03-25 devnull if(!eof && !nl && !empty) {
145 1a84af59 2004-03-25 devnull u.u.buf[0] = '\n';
147 8ad51794 2004-03-25 devnull eof = 1;
150 8ad51794 2004-03-25 devnull if(n <= 0) {
151 8ad51794 2004-03-25 devnull close(fid);
152 8ad51794 2004-03-25 devnull if(flag & Cflag) {
153 8ad51794 2004-03-25 devnull if(flag & Hflag)
154 8ad51794 2004-03-25 devnull Bprint(&bout, "%s:", file);
155 8ad51794 2004-03-25 devnull Bprint(&bout, "%ld\n", count);
157 8ad51794 2004-03-25 devnull if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
158 8ad51794 2004-03-25 devnull Bprint(&bout, "%s\n", file);
159 8ad51794 2004-03-25 devnull Bflush(&bout);
160 8ad51794 2004-03-25 devnull return count != 0;
162 1a84af59 2004-03-25 devnull lp = u.u.buf;
163 8ad51794 2004-03-25 devnull elp = lp+n;
164 8ad51794 2004-03-25 devnull if(flag & Iflag)
165 8ad51794 2004-03-25 devnull goto loopi;
168 8ad51794 2004-03-25 devnull * normal character loop
171 8ad51794 2004-03-25 devnull c = *lp;
172 8ad51794 2004-03-25 devnull ns = s->next[c];
173 8ad51794 2004-03-25 devnull if(ns == 0) {
174 8ad51794 2004-03-25 devnull increment(s, c);
175 8ad51794 2004-03-25 devnull goto loop;
177 cbeb0b26 2006-04-01 devnull /* if(flags['2']) */
178 cbeb0b26 2006-04-01 devnull /* if(s->match) */
179 cbeb0b26 2006-04-01 devnull /* print("%d: %.2x**\n", s, c); */
180 cbeb0b26 2006-04-01 devnull /* else */
181 cbeb0b26 2006-04-01 devnull /* print("%d: %.2x\n", s, c); */
184 8ad51794 2004-03-25 devnull if(c == '\n') {
185 8ad51794 2004-03-25 devnull lineno++;
186 8ad51794 2004-03-25 devnull if(!!s->match == !(flag&Vflag)) {
187 8ad51794 2004-03-25 devnull count++;
188 8ad51794 2004-03-25 devnull if(flag & (Cflag|Sflag|Llflag|LLflag))
189 8ad51794 2004-03-25 devnull goto cont;
190 8ad51794 2004-03-25 devnull if(flag & Hflag)
191 8ad51794 2004-03-25 devnull Bprint(&bout, "%s:", file);
192 8ad51794 2004-03-25 devnull if(flag & Nflag)
193 8ad51794 2004-03-25 devnull Bprint(&bout, "%ld: ", lineno);
194 8ad51794 2004-03-25 devnull /* suppress extra newline at EOF unless we are labeling matches with file name */
195 8ad51794 2004-03-25 devnull Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
196 8ad51794 2004-03-25 devnull if(flag & Bflag)
197 8ad51794 2004-03-25 devnull Bflush(&bout);
199 8ad51794 2004-03-25 devnull if((lineno & Flshcnt) == 0)
200 8ad51794 2004-03-25 devnull Bflush(&bout);
202 8ad51794 2004-03-25 devnull bol = lp;
204 8ad51794 2004-03-25 devnull if(lp != elp)
205 8ad51794 2004-03-25 devnull goto loop;
206 8ad51794 2004-03-25 devnull goto loop0;
209 8ad51794 2004-03-25 devnull * character loop for -i flag
210 8ad51794 2004-03-25 devnull * for speed
213 8ad51794 2004-03-25 devnull c = *lp;
214 8ad51794 2004-03-25 devnull if(c >= 'A' && c <= 'Z')
215 8ad51794 2004-03-25 devnull c += 'a'-'A';
216 8ad51794 2004-03-25 devnull ns = s->next[c];
217 8ad51794 2004-03-25 devnull if(ns == 0) {
218 8ad51794 2004-03-25 devnull increment(s, c);
219 8ad51794 2004-03-25 devnull goto loopi;
223 8ad51794 2004-03-25 devnull if(c == '\n') {
224 8ad51794 2004-03-25 devnull lineno++;
225 8ad51794 2004-03-25 devnull if(!!s->match == !(flag&Vflag)) {
226 8ad51794 2004-03-25 devnull count++;
227 8ad51794 2004-03-25 devnull if(flag & (Cflag|Sflag|Llflag|LLflag))
228 8ad51794 2004-03-25 devnull goto conti;
229 8ad51794 2004-03-25 devnull if(flag & Hflag)
230 8ad51794 2004-03-25 devnull Bprint(&bout, "%s:", file);
231 8ad51794 2004-03-25 devnull if(flag & Nflag)
232 8ad51794 2004-03-25 devnull Bprint(&bout, "%ld: ", lineno);
233 8ad51794 2004-03-25 devnull /* suppress extra newline at EOF unless we are labeling matches with file name */
234 8ad51794 2004-03-25 devnull Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
235 8ad51794 2004-03-25 devnull if(flag & Bflag)
236 8ad51794 2004-03-25 devnull Bflush(&bout);
238 8ad51794 2004-03-25 devnull if((lineno & Flshcnt) == 0)
239 8ad51794 2004-03-25 devnull Bflush(&bout);
241 8ad51794 2004-03-25 devnull bol = lp;
243 8ad51794 2004-03-25 devnull if(lp != elp)
244 8ad51794 2004-03-25 devnull goto loopi;
245 8ad51794 2004-03-25 devnull goto loop0;
249 8ad51794 2004-03-25 devnull initstate(Re *r)
251 8ad51794 2004-03-25 devnull State *s;
254 8ad51794 2004-03-25 devnull addcase(r);
255 8ad51794 2004-03-25 devnull if(flags['1'])
256 8ad51794 2004-03-25 devnull reprint("r", r);
257 8ad51794 2004-03-25 devnull nfollow = 0;
259 8ad51794 2004-03-25 devnull fol1(r, Cbegin);
260 8ad51794 2004-03-25 devnull follow[nfollow++] = r;
261 8ad51794 2004-03-25 devnull qsort(follow, nfollow, sizeof(*follow), fcmp);
263 8ad51794 2004-03-25 devnull s = sal(nfollow);
264 8ad51794 2004-03-25 devnull for(i=0; i<nfollow; i++)
265 8ad51794 2004-03-25 devnull s->re[i] = follow[i];
266 8ad51794 2004-03-25 devnull return s;