| tmain.c - plan9port - [fork] Plan 9 from user space | |
| git clone git://src.adamsgaard.dk/plan9port | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| tmain.c (4858B) | |
| --- | |
| 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… | |
| 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(EARGF(usage())); | |
| 35 break; | |
| 36 | |
| 37 case 'f': | |
| 38 flags['f']++; | |
| 39 filename = EARGF(usage()); | |
| 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… | |
| 106 if(flags['i']) | |
| 107 flag |= Iflag; /* fold upper-lower */ | |
| 108 if(flags['l']) | |
| 109 flag |= Llflag; /* print only name of fil… | |
| 110 if(flags['L']) | |
| 111 flag |= LLflag; /* print only name of fil… | |
| 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… | |
| 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) && co… | |
| 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 l… | |
| 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 l… | |
| 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 } |