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 } 261