]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/grep/main.c
ip/ipconfig: default onlink and autoflag to 1
[plan9front.git] / sys / src / cmd / grep / main.c
1 #define EXTERN
2 #include        "grep.h"
3
4 char *validflags = "bchiLlnsv";
5 void
6 usage(void)
7 {
8         fprint(2, "usage: grep [-%s] [-e pattern] [-f patternfile] [file ...]\n", validflags);
9         exits("usage");
10 }
11
12 void
13 main(int argc, char *argv[])
14 {
15         int i, status;
16
17         ARGBEGIN {
18         default:
19                 if(utfrune(validflags, ARGC()) == nil)
20                         usage();
21                 flags[ARGC()]++;
22                 break;
23
24         case 'e':
25                 flags['e']++;
26                 lineno = 0;
27                 str2top(EARGF(usage()));
28                 break;
29
30         case 'f':
31                 flags['f']++;
32                 filename = EARGF(usage());
33                 rein = Bopen(filename, OREAD);
34                 if(rein == 0) {
35                         fprint(2, "grep: can't open %s: %r\n", filename);
36                         exits("open");
37                 }
38                 lineno = 1;
39                 str2top(filename);
40                 break;
41         } ARGEND
42
43         if(flags['f'] == 0 && flags['e'] == 0) {
44                 if(argc <= 0)
45                         usage();
46                 str2top(argv[0]);
47                 argc--;
48                 argv++;
49         }
50
51         follow = mal(maxfollow*sizeof(*follow));
52         state0 = initstate(topre.beg);
53
54         Binit(&bout, 1, OWRITE);
55         switch(argc) {
56         case 0:
57                 status = search(0, 0);
58                 break;
59         case 1:
60                 status = search(argv[0], 0);
61                 break;
62         default:
63                 status = 0;
64                 for(i=0; i<argc; i++)
65                         status |= search(argv[i], Hflag);
66                 break;
67         }
68         if(status)
69                 exits(0);
70         exits("no matches");
71 }
72
73 int
74 search(char *file, int flag)
75 {
76         State *s, *ns;
77         int c, fid, eof, nl, empty;
78         long count, lineno, n;
79         uchar *elp, *lp, *bol;
80
81         if(file == 0) {
82                 file = "stdin";
83                 fid = 0;
84                 flag |= Bflag;
85         } else
86                 fid = open(file, OREAD);
87
88         if(fid < 0) {
89                 fprint(2, "grep: can't open %s: %r\n", file);
90                 return 0;
91         }
92
93         if(flags['b'])
94                 flag ^= Bflag;          /* dont buffer output */
95         if(flags['c'])
96                 flag |= Cflag;          /* count */
97         if(flags['h'])
98                 flag &= ~Hflag;         /* do not print file name in output */
99         if(flags['i'])
100                 flag |= Iflag;          /* fold upper-lower */
101         if(flags['l'])
102                 flag |= Llflag;         /* print only name of file if any match */
103         if(flags['L'])
104                 flag |= LLflag;         /* print only name of file if any non match */
105         if(flags['n'])
106                 flag |= Nflag;          /* count only */
107         if(flags['s'])
108                 flag |= Sflag;          /* status only */
109         if(flags['v'])
110                 flag |= Vflag;          /* inverse match */
111
112         s = state0;
113         lineno = 0;
114         count = 0;
115         eof = 0;
116         empty = 1;
117         nl = 0;
118         lp = u.buf;
119         bol = lp;
120
121 loop0:
122         n = lp-bol;
123         if(n > sizeof(u.pre))
124                 n = sizeof(u.pre);
125         memmove(u.buf-n, bol, n);
126         bol = u.buf-n;
127         n = read(fid, u.buf, sizeof(u.buf));
128         /* if file has no final newline, simulate one to emit matches to last line */
129         if(n > 0) {
130                 empty = 0;
131                 nl = u.buf[n-1]=='\n';
132         } else {
133                 if(n < 0){
134                         fprint(2, "grep: read error on %s: %r\n", file);
135                         return count != 0;
136                 }
137                 if(!eof && !nl && !empty) {
138                         u.buf[0] = '\n';
139                         n = 1;
140                         eof = 1;
141                 }
142         }
143         if(n <= 0) {
144                 close(fid);
145                 if(flag & Cflag) {
146                         if(flag & Hflag)
147                                 Bprint(&bout, "%s:", file);
148                         Bprint(&bout, "%ld\n", count);
149                 }
150                 if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
151                         Bprint(&bout, "%s\n", file);
152                 Bflush(&bout);
153                 return count != 0;
154         }
155         lp = u.buf;
156         elp = lp+n;
157         if(flag & Iflag)
158                 goto loopi;
159
160 /*
161  * normal character loop
162  */
163 loop:
164         c = *lp;
165         ns = s->next[c];
166         if(ns == 0) {
167                 increment(s, c);
168                 goto loop;
169         }
170 //      if(flags['2'])
171 //              if(s->match)
172 //                      print("%d: %.2x**\n", s, c);
173 //              else
174 //                      print("%d: %.2x\n", s, c);
175         lp++;
176         s = ns;
177         if(c == '\n') {
178                 lineno++;
179                 if(!!s->match == !(flag&Vflag)) {
180                         count++;
181                         if(flag & (Cflag|Sflag|Llflag|LLflag))
182                                 goto cont;
183                         if(flag & Hflag)
184                                 Bprint(&bout, "%s:", file);
185                         if(flag & Nflag)
186                                 Bprint(&bout, "%ld: ", lineno);
187                         /* suppress extra newline at EOF unless we are labeling matches with file name */
188                         Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
189                         if(flag & Bflag)
190                                 Bflush(&bout);
191                 }
192                 if((lineno & Flshcnt) == 0)
193                         Bflush(&bout);
194         cont:
195                 bol = lp;
196         }
197         if(lp != elp)
198                 goto loop;
199         goto loop0;
200
201 /*
202  * character loop for -i flag
203  * for speed
204  */
205 loopi:
206         c = *lp;
207         if(c >= 'A' && c <= 'Z')
208                 c += 'a'-'A';
209         ns = s->next[c];
210         if(ns == 0) {
211                 increment(s, c);
212                 goto loopi;
213         }
214         lp++;
215         s = ns;
216         if(c == '\n') {
217                 lineno++;
218                 if(!!s->match == !(flag&Vflag)) {
219                         count++;
220                         if(flag & (Cflag|Sflag|Llflag|LLflag))
221                                 goto conti;
222                         if(flag & Hflag)
223                                 Bprint(&bout, "%s:", file);
224                         if(flag & Nflag)
225                                 Bprint(&bout, "%ld: ", lineno);
226                         /* suppress extra newline at EOF unless we are labeling matches with file name */
227                         Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
228                         if(flag & Bflag)
229                                 Bflush(&bout);
230                 }
231                 if((lineno & Flshcnt) == 0)
232                         Bflush(&bout);
233         conti:
234                 bol = lp;
235         }
236         if(lp != elp)
237                 goto loopi;
238         goto loop0;
239 }
240
241 State*
242 initstate(Re *r)
243 {
244         State *s;
245         int i;
246
247         addcase(r);
248         if(flags['1'])
249                 reprint("r", r);
250         nfollow = 0;
251         gen++;
252         fol1(r, Cbegin);
253         follow[nfollow++] = r;
254         qsort(follow, nfollow, sizeof(*follow), fcmp);
255
256         s = sal(nfollow);
257         for(i=0; i<nfollow; i++)
258                 s->re[i] = follow[i];
259         return s;
260 }