home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / grep.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  6KB  |  407 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include <stdio.h>
  3. /*
  4.  * grep -- print lines matching (or not matching) a pattern
  5.  */
  6.  
  7. #define    CCHR    2
  8. #define    CDOT    4
  9. #define    CCL    6
  10. #define    NCCL    8
  11. #define    CDOL    10
  12. #define    CEOF    11
  13.  
  14. #define    CBRC    14
  15. #define    CLET    15
  16. #define    STAR    01
  17.  
  18. #define    LBSIZE    256
  19. #define    ESIZE    256
  20.  
  21. char    expbuf[ESIZE];
  22. long    lnum;
  23. char    linebuf[LBSIZE+1];
  24. int    bflag;
  25. int    nflag;
  26. int    cflag;
  27. int    vflag;
  28. int    nfile;
  29. int    iflag;
  30. int    lflag;
  31. int    wflag;
  32. int    circf;
  33. int    blkno;
  34. char    ibuf[512];
  35. long    tln;
  36.  
  37. main(argc, argv)
  38. char **argv;
  39. {
  40.     char obuf[BUFSIZ];
  41.  
  42.     setbuf(stdout, obuf);
  43.     while (--argc > 0 && (++argv)[0][0]=='-') {
  44.         char *cp = argv[0] + 1;
  45.         while (*cp) switch (*cp++) {
  46.  
  47.         case 'v':
  48.             vflag++;
  49.             continue;
  50.  
  51.         case 'b':
  52.             bflag++;
  53.             continue;
  54.  
  55.         case 'i':
  56.             iflag++;
  57.             continue;
  58.  
  59.         case 'l':
  60.             lflag++;
  61.         case 'c':
  62.             cflag++;
  63.             continue;
  64.  
  65.         case 'w':
  66.             wflag++;
  67.             continue;
  68.  
  69.         case 'n':
  70.             nflag++;
  71.             continue;
  72.  
  73.         default:
  74.             fprintf(stderr, "Unknown flag\n");
  75.             continue;
  76.         }
  77.     }
  78.     if (argc<=0)
  79.         exit(2);
  80.     compile(*argv);
  81.     nfile = --argc;
  82.     if (argc<=0)
  83.         execute(0);
  84.     else while (--argc >= 0) {
  85.         argv++;
  86.         execute(*argv);
  87.     }
  88.     exit(0);
  89. }
  90.  
  91. compile(astr)
  92. char *astr;
  93. {
  94.     register c;
  95.     register char *ep, *sp;
  96.     char *lastep;
  97.     int cclcnt;
  98.  
  99.     ep = expbuf;
  100.     sp = astr;
  101.     if (*sp == '^') {
  102.         circf++;
  103.         sp++;
  104.     }
  105.     if (wflag)
  106.         *ep++ = CBRC;
  107.     for (;;) {
  108.         if (ep >= &expbuf[ESIZE])
  109.             goto cerror;
  110.         if ((c = *sp++) != '*')
  111.             lastep = ep;
  112.         switch (c) {
  113.  
  114.         case '\0':
  115.             if (wflag)
  116.                 *ep++ = CLET;
  117.             *ep++ = CEOF;
  118.             return;
  119.  
  120.         case '.':
  121.             *ep++ = CDOT;
  122.             continue;
  123.  
  124.         case '*':
  125.             if (lastep==0)
  126.                 goto defchar;
  127.             *lastep =| STAR;
  128.             continue;
  129.  
  130.         case '$':
  131.             if (*sp != '\0')
  132.                 goto defchar;
  133.             *ep++ = CDOL;
  134.             continue;
  135.  
  136.         case '[':
  137.             *ep++ = CCL;
  138.             *ep++ = 0;
  139.             cclcnt = 1;
  140.             if ((c = *sp++) == '^') {
  141.                 c = *sp++;
  142.                 ep[-2] = NCCL;
  143.             }
  144.             do {
  145.                 *ep++ = c;
  146.                 cclcnt++;
  147.                 if (c=='\0' || ep >= &expbuf[ESIZE])
  148.                     goto cerror;
  149.             } while ((c = *sp++) != ']');
  150.             lastep[1] = cclcnt;
  151.             continue;
  152.  
  153.         case '\\':
  154.             if ((c = *sp++) == '\0')
  155.                 goto cerror;
  156.             if (c == '<') {
  157.                 *ep++ = CBRC;
  158.                 continue;
  159.             }
  160.             if (c == '>') {
  161.                 *ep++ = CLET;
  162.                 continue;
  163.             }
  164.         defchar:
  165.         default:
  166.             *ep++ = CCHR;
  167.             *ep++ = c;
  168.         }
  169.     }
  170.     cerror:
  171.     fprintf(stderr, "RE error\n");
  172. }
  173.  
  174. same(a, b)
  175.     register int a, b;
  176. {
  177.  
  178.     return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b));
  179. }
  180.  
  181. letter(c)
  182.     register int c;
  183. {
  184.  
  185.     if (c >= 'a' && c <= 'z')
  186.         return (c);
  187.     if (c >= 'A' && c <= 'Z')
  188.         return (c + 'a' - 'A');
  189.     return (0);
  190. }
  191.  
  192. execute(file)
  193. {
  194.     register char *p1, *p2;
  195.     register c;
  196.     int f;
  197.     char *ebp, *cbp;
  198.  
  199.     if (file) {
  200.         if ((f = open(file, 0)) < 0) {
  201.             fprintf(stderr, "Can't open %s\n", file);
  202.         }
  203.     } else
  204.         f = 0;
  205.     ebp = ibuf;
  206.     cbp = ibuf;
  207.     lnum = 0;
  208.     tln = 0;
  209.     blkno = -1;
  210.     for (;;) {
  211.         lnum++;
  212.         if((lnum&0377) == 0)
  213.             fflush(stdout);
  214.         p1 = linebuf;
  215.         p2 = cbp;
  216.         for (;;) {
  217.             if (p2 >= ebp) {
  218.                 if ((c = read(f, ibuf, 512)) <= 0) {
  219.                     close(f);
  220.                     if (cflag) {
  221.                         if (lflag) {
  222.                             if (tln)
  223.                             printf("%s\n", file);
  224.                         } else {
  225.                             if (nfile > 1)
  226.                                 printf("%s:", file);
  227.                             printf("%ld\n", tln);
  228.                         }
  229.                     }
  230.                     return;
  231.                 }
  232.                 blkno++;
  233.                 p2 = ibuf;
  234.                 ebp = ibuf+c;
  235.             }
  236.             if ((c = *p2++) == '\n')
  237.                 break;
  238.             if(c)
  239.             if (p1 < &linebuf[LBSIZE-1])
  240.                 *p1++ = c;
  241.         }
  242.         *p1++ = 0;
  243.         cbp = p2;
  244.         p1 = linebuf;
  245.         p2 = expbuf;
  246.         if (circf) {
  247.             if (advance(p1, p2))
  248.                 goto found;
  249.             goto nfound;
  250.         }
  251.         /* fast check for first character */
  252.         if (*p2==CCHR) {
  253.             c = p2[1];
  254.             do {
  255.                 if (*p1!=c && (!iflag || (c ^ *p1) != ' '
  256.                     || letter(c) != letter(*p1)))
  257.                     continue;
  258.                 if (advance(p1, p2))
  259.                     goto found;
  260.             } while (*p1++);
  261.             goto nfound;
  262.         }
  263.         /* regular algorithm */
  264.         do {
  265.             if (advance(p1, p2))
  266.                 goto found;
  267.         } while (*p1++);
  268.     nfound:
  269.         if (vflag)
  270.             succeed(file);
  271.         continue;
  272.     found:
  273.         if (vflag==0)
  274.             succeed(file);
  275.     }
  276. }
  277.  
  278. advance(alp, aep)
  279. {
  280.     register char *lp, *ep, *curlp;
  281.     char *nextep;
  282.  
  283.     lp = alp;
  284.     ep = aep;
  285.     for (;;) switch (*ep++) {
  286.  
  287.     case CCHR:
  288.         if (!same(*ep, *lp))
  289.             return (0);
  290.         ep++, lp++;
  291.         continue;
  292.  
  293.     case CDOT:
  294.         if (*lp++)
  295.             continue;
  296.         return(0);
  297.  
  298.     case CDOL:
  299.         if (*lp==0)
  300.             continue;
  301.         return(0);
  302.  
  303.     case CEOF:
  304.         return(1);
  305.  
  306.     case CCL:
  307.         if (cclass(ep, *lp++, 1)) {
  308.             ep =+ *ep;
  309.             continue;
  310.         }
  311.         return(0);
  312.  
  313.     case NCCL:
  314.         if (cclass(ep, *lp++, 0)) {
  315.             ep =+ *ep;
  316.             continue;
  317.         }
  318.         return(0);
  319.  
  320.     case CDOT|STAR:
  321.         curlp = lp;
  322.         while (*lp++);
  323.         goto star;
  324.  
  325.     case CCHR|STAR:
  326.         curlp = lp;
  327.         while (same(*lp, *ep))
  328.             lp++;
  329.         lp++;
  330.         ep++;
  331.         goto star;
  332.  
  333.     case CCL|STAR:
  334.     case NCCL|STAR:
  335.         curlp = lp;
  336.         while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
  337.         ep =+ *ep;
  338.         goto star;
  339.  
  340.     star:
  341.         do {
  342.             lp--;
  343.             if (advance(lp, ep))
  344.                 return(1);
  345.         } while (lp > curlp);
  346.         return(0);
  347.  
  348.     case CBRC:
  349.         if (lp == expbuf)
  350.             continue;
  351. #define    uletter(c)    (letter(c) || c == '_')
  352.         if (uletter(*lp) && !uletter(lp[-1]) && !digit(lp[-1]))
  353.             continue;
  354.         return (0);
  355.  
  356.     case CLET:
  357.         if (!uletter(*lp) && !digit(*lp))
  358.             continue;
  359.         return (0);
  360.  
  361.     default:
  362.         fprintf(stderr, "RE botch\n");
  363.     }
  364. }
  365.  
  366. cclass(aset, ac, af)
  367. {
  368.     register char *set, c;
  369.     register n;
  370.  
  371.     set = aset;
  372.     if ((c = ac) == 0)
  373.         return(0);
  374.     n = *set++;
  375.     while (--n)
  376.         if (n > 2 && set[1] == '-') {
  377.             if (c >= (set[0] & 0177) && c <= (set[2] & 0177))
  378.                 return (af);
  379.             set =+ 3;
  380.             n -= 2;
  381.         } else
  382.             if ((*set++ & 0177) == c)
  383.                 return(af);
  384.     return(!af);
  385. }
  386.  
  387. succeed(f)
  388. {
  389.     if (cflag) {
  390.         tln++;
  391.         return;
  392.     }
  393.     if (nfile > 1)
  394.         printf("%s:", f);
  395.     if (bflag)
  396.         printf("%l:", blkno);
  397.     if (nflag)
  398.         printf("%ld:", lnum);
  399.     printf("%s\n", linebuf);
  400. }
  401.  
  402. digit(c)
  403.     char c;
  404. {
  405.     return (c>='0' && c<='9');
  406. }
  407.