home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / grep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-02-26  |  6.7 KB  |  479 lines

  1. /*
  2.  * grep -- print lines matching (or not matching) a pattern
  3.  *
  4.  *    status returns:
  5.  *        0 - ok, and some matches
  6.  *        1 - ok, but no matches
  7.  *        2 - some error
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <sys/param.h>
  13.  
  14. #define    CBRA    1
  15. #define    CCHR    2
  16. #define    CDOT    4
  17. #define    CCL    6
  18. #define    NCCL    8
  19. #define    CDOL    10
  20. #define    CEOF    11
  21. #define    CKET    12
  22. #define    CBACK    18
  23.  
  24. #define    STAR    01
  25.  
  26. #define    LBSIZE    512
  27. #define    ESIZE    256
  28. #define    NBRA    9
  29.  
  30. char    expbuf[ESIZE];
  31. long    lnum;
  32. char    linebuf[LBSIZE+1];
  33. char    ybuf[ESIZE];
  34. int    bflag;
  35. int    lflag;
  36. int    nflag;
  37. int    cflag;
  38. int    vflag;
  39. int    nfile;
  40. int    hflag    = 1;
  41. int    sflag;
  42. int    yflag;
  43. int    circf;
  44. long    tln;
  45. int    nsucc;
  46. char    *braslist[NBRA];
  47. char    *braelist[NBRA];
  48. char    bittab[] = {
  49.     1,
  50.     2,
  51.     4,
  52.     8,
  53.     16,
  54.     32,
  55.     64,
  56.     128
  57. };
  58.  
  59. main(argc, argv)
  60. char **argv;
  61. {
  62.     while (--argc > 0 && (++argv)[0][0]=='-')
  63.         switch (argv[0][1]) {
  64.  
  65.         case 'y':
  66.             yflag++;
  67.             continue;
  68.  
  69.         case 'h':
  70.             hflag = 0;
  71.             continue;
  72.  
  73.         case 's':
  74.             sflag++;
  75.             continue;
  76.  
  77.         case 'v':
  78.             vflag++;
  79.             continue;
  80.  
  81.         case 'b':
  82.             bflag++;
  83.             continue;
  84.  
  85.         case 'l':
  86.             lflag++;
  87.             continue;
  88.  
  89.         case 'c':
  90.             cflag++;
  91.             continue;
  92.  
  93.         case 'n':
  94.             nflag++;
  95.             continue;
  96.  
  97.         case 'e':
  98.             --argc;
  99.             ++argv;
  100.             goto out;
  101.  
  102.         default:
  103.             errexit("grep: unknown flag\n", (char *)NULL);
  104.             continue;
  105.         }
  106. out:
  107.     if (argc<=0)
  108.         exit(2);
  109.     if (yflag) {
  110.         register char *p, *s;
  111.         for (s = ybuf, p = *argv; *p; ) {
  112.             if (*p == '\\') {
  113.                 *s++ = *p++;
  114.                 if (*p)
  115.                     *s++ = *p++;
  116.             } else if (*p == '[') {
  117.                 while (*p != '\0' && *p != ']')
  118.                     *s++ = *p++;
  119.             } else if (islower(*p)) {
  120.                 *s++ = '[';
  121.                 *s++ = toupper(*p);
  122.                 *s++ = *p++;
  123.                 *s++ = ']';
  124.             } else
  125.                 *s++ = *p++;
  126.             if (s >= ybuf+ESIZE-5)
  127.                 errexit("grep: argument too long\n", (char *)NULL);
  128.         }
  129.         *s = '\0';
  130.         *argv = ybuf;
  131.     }
  132.     compile(*argv);
  133.     nfile = --argc;
  134.     if (argc<=0) {
  135.         if (lflag)
  136.             exit(1);
  137.         execute((char *)NULL);
  138.     } else while (--argc >= 0) {
  139.         argv++;
  140.         execute(*argv);
  141.     }
  142.     exit(nsucc == 0);
  143. }
  144.  
  145. compile(astr)
  146. char *astr;
  147. {
  148.     register c;
  149.     register char *ep, *sp;
  150.     char *cstart;
  151.     char *lastep;
  152.     int cclcnt;
  153.     char bracket[NBRA], *bracketp;
  154.     int closed;
  155.     char numbra;
  156.     char neg;
  157.  
  158.     ep = expbuf;
  159.     sp = astr;
  160.     lastep = 0;
  161.     bracketp = bracket;
  162.     closed = numbra = 0;
  163.     if (*sp == '^') {
  164.         circf++;
  165.         sp++;
  166.     }
  167.     for (;;) {
  168.         if (ep >= &expbuf[ESIZE])
  169.             goto cerror;
  170.         if ((c = *sp++) != '*')
  171.             lastep = ep;
  172.         switch (c) {
  173.  
  174.         case '\0':
  175.             *ep++ = CEOF;
  176.             return;
  177.  
  178.         case '.':
  179.             *ep++ = CDOT;
  180.             continue;
  181.  
  182.         case '*':
  183.             if (lastep==0 || *lastep==CBRA || *lastep==CKET)
  184.                 goto defchar;
  185.             *lastep |= STAR;
  186.             continue;
  187.  
  188.         case '$':
  189.             if (*sp != '\0')
  190.                 goto defchar;
  191.             *ep++ = CDOL;
  192.             continue;
  193.  
  194.         case '[':
  195.             if(&ep[17] >= &expbuf[ESIZE])
  196.                 goto cerror;
  197.             *ep++ = CCL;
  198.             neg = 0;
  199.             if((c = *sp++) == '^') {
  200.                 neg = 1;
  201.                 c = *sp++;
  202.             }
  203.             cstart = sp;
  204.             do {
  205.                 if (c=='\0')
  206.                     goto cerror;
  207.                 if (c=='-' && sp>cstart && *sp!=']') {
  208.                     for (c = sp[-2]; c<*sp; c++)
  209.                         ep[c>>3] |= bittab[c&07];
  210.                     sp++;
  211.                 }
  212.                 ep[c>>3] |= bittab[c&07];
  213.             } while((c = *sp++) != ']');
  214.             if(neg) {
  215.                 for(cclcnt = 0; cclcnt < 16; cclcnt++)
  216.                     ep[cclcnt] ^= -1;
  217.                 ep[0] &= 0376;
  218.             }
  219.  
  220.             ep += 16;
  221.  
  222.             continue;
  223.  
  224.         case '\\':
  225.             if((c = *sp++) == '(') {
  226.                 if(numbra >= NBRA) {
  227.                     goto cerror;
  228.                 }
  229.                 *bracketp++ = numbra;
  230.                 *ep++ = CBRA;
  231.                 *ep++ = numbra++;
  232.                 continue;
  233.             }
  234.             if(c == ')') {
  235.                 if(bracketp <= bracket) {
  236.                     goto cerror;
  237.                 }
  238.                 *ep++ = CKET;
  239.                 *ep++ = *--bracketp;
  240.                 closed++;
  241.                 continue;
  242.             }
  243.  
  244.             if(c >= '1' && c <= '9') {
  245.                 if((c -= '1') >= closed)
  246.                     goto cerror;
  247.                 *ep++ = CBACK;
  248.                 *ep++ = c;
  249.                 continue;
  250.             }
  251.  
  252.         defchar:
  253.         default:
  254.             *ep++ = CCHR;
  255.             *ep++ = c;
  256.         }
  257.     }
  258.     cerror:
  259.     errexit("grep: RE error\n", (char *)NULL);
  260. }
  261.  
  262. execute(file)
  263. char *file;
  264. {
  265.     register char *p1, *p2;
  266.     register c;
  267.  
  268.     if (file) {
  269.         if (freopen(file, "r", stdin) == NULL)
  270.             errexit("grep: can't open %s\n", file);
  271.     }
  272.     lnum = 0;
  273.     tln = 0;
  274.     for (;;) {
  275.         lnum++;
  276.         p1 = linebuf;
  277.         while ((c = getchar()) != '\n') {
  278.             if (c == EOF) {
  279.                 if (cflag) {
  280.                     if (nfile>1)
  281.                         printf("%s:", file);
  282.                     printf("%D\n", tln);
  283.                 }
  284.                 return;
  285.             }
  286.             *p1++ = c;
  287.             if (p1 >= &linebuf[LBSIZE-1])
  288.                 break;
  289.         }
  290.         *p1++ = '\0';
  291.         p1 = linebuf;
  292.         p2 = expbuf;
  293.         if (circf) {
  294.             if (advance(p1, p2))
  295.                 goto found;
  296.             goto nfound;
  297.         }
  298.         /* fast check for first character */
  299.         if (*p2==CCHR) {
  300.             c = p2[1];
  301.             do {
  302.                 if (*p1!=c)
  303.                     continue;
  304.                 if (advance(p1, p2))
  305.                     goto found;
  306.             } while (*p1++);
  307.             goto nfound;
  308.         }
  309.         /* regular algorithm */
  310.         do {
  311.             if (advance(p1, p2))
  312.                 goto found;
  313.         } while (*p1++);
  314.     nfound:
  315.         if (vflag)
  316.             succeed(file);
  317.         continue;
  318.     found:
  319.         if (vflag==0)
  320.             succeed(file);
  321.     }
  322. }
  323.  
  324. advance(lp, ep)
  325. register char *lp, *ep;
  326. {
  327.     register char *curlp;
  328.     char c;
  329.     char *bbeg;
  330.     int ct;
  331.  
  332.     for (;;) switch (*ep++) {
  333.  
  334.     case CCHR:
  335.         if (*ep++ == *lp++)
  336.             continue;
  337.         return(0);
  338.  
  339.     case CDOT:
  340.         if (*lp++)
  341.             continue;
  342.         return(0);
  343.  
  344.     case CDOL:
  345.         if (*lp==0)
  346.             continue;
  347.         return(0);
  348.  
  349.     case CEOF:
  350.         return(1);
  351.  
  352.     case CCL:
  353.         c = *lp++ & 0177;
  354.         if(ep[c>>3] & bittab[c & 07]) {
  355.             ep += 16;
  356.             continue;
  357.         }
  358.         return(0);
  359.     case CBRA:
  360.         braslist[*ep++] = lp;
  361.         continue;
  362.  
  363.     case CKET:
  364.         braelist[*ep++] = lp;
  365.         continue;
  366.  
  367.     case CBACK:
  368.         bbeg = braslist[*ep];
  369.         if (braelist[*ep]==0)
  370.             return(0);
  371.         ct = braelist[*ep++] - bbeg;
  372.         if(ecmp(bbeg, lp, ct)) {
  373.             lp += ct;
  374.             continue;
  375.         }
  376.         return(0);
  377.  
  378.     case CBACK|STAR:
  379.         bbeg = braslist[*ep];
  380.         if (braelist[*ep]==0)
  381.             return(0);
  382.         ct = braelist[*ep++] - bbeg;
  383.         curlp = lp;
  384.         while(ecmp(bbeg, lp, ct))
  385.             lp += ct;
  386.         while(lp >= curlp) {
  387.             if(advance(lp, ep))    return(1);
  388.             lp -= ct;
  389.         }
  390.         return(0);
  391.  
  392.  
  393.     case CDOT|STAR:
  394.         curlp = lp;
  395.         while (*lp++);
  396.         goto star;
  397.  
  398.     case CCHR|STAR:
  399.         curlp = lp;
  400.         while (*lp++ == *ep);
  401.         ep++;
  402.         goto star;
  403.  
  404.     case CCL|STAR:
  405.         curlp = lp;
  406.         do {
  407.             c = *lp++ & 0177;
  408.         } while(ep[c>>3] & bittab[c & 07]);
  409.         ep += 16;
  410.         goto star;
  411.  
  412.     star:
  413.         if(--lp == curlp) {
  414.             continue;
  415.         }
  416.  
  417.         if(*ep == CCHR) {
  418.             c = ep[1];
  419.             do {
  420.                 if(*lp != c)
  421.                     continue;
  422.                 if(advance(lp, ep))
  423.                     return(1);
  424.             } while(lp-- > curlp);
  425.             return(0);
  426.         }
  427.  
  428.         do {
  429.             if (advance(lp, ep))
  430.                 return(1);
  431.         } while (lp-- > curlp);
  432.         return(0);
  433.  
  434.     default:
  435.         errexit("grep RE botch\n", (char *)NULL);
  436.     }
  437. }
  438.  
  439. succeed(f)
  440. char *f;
  441. {
  442.     long ftell();
  443.     nsucc = 1;
  444.     if (sflag)
  445.         return;
  446.     if (cflag) {
  447.         tln++;
  448.         return;
  449.     }
  450.     if (lflag) {
  451.         printf("%s\n", f);
  452.         fseek(stdin, 0l, 2);
  453.         return;
  454.     }
  455.     if (nfile > 1 && hflag)
  456.         printf("%s:", f);
  457.     if (bflag)
  458.         printf("%ld:", (ftell(stdin)-1)/BSIZE);
  459.     if (nflag)
  460.         printf("%ld:", lnum);
  461.     printf("%s\n", linebuf);
  462. }
  463.  
  464. ecmp(a, b, count)
  465. char    *a, *b;
  466. {
  467.     register cc = count;
  468.     while(cc--)
  469.         if(*a++ != *b++)    return(0);
  470.     return(1);
  471. }
  472.  
  473. errexit(s, f)
  474. char *s, *f;
  475. {
  476.     fprintf(stderr, s, f);
  477.     exit(2);
  478. }
  479.