tmain.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 ...]\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(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 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 }