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