home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / expr.y < prev    next >
Encoding:
Text File  |  1979-01-10  |  10.6 KB  |  670 lines

  1. /* Yacc productions for "expr" command: */
  2.  
  3. %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
  4. %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
  5.  
  6. /* operators listed below in increasing precedence: */
  7. %left OR
  8. %left AND
  9. %left EQ LT GT GEQ LEQ NEQ
  10. %left ADD SUBT
  11. %left MULT DIV REM
  12. %left MCH
  13. %left MATCH
  14. %left SUBSTR
  15. %left LENGTH INDEX
  16. %%
  17.  
  18. /* a single `expression' is evaluated and printed: */
  19.  
  20. expression:    expr NOARG = {
  21.             printf("%s\n", $1);
  22.             exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
  23.             }
  24.     ;
  25.  
  26.  
  27. expr:    '(' expr ')' = { $$ = $2; }
  28.     | expr OR expr   = { $$ = conj(OR, $1, $3); }
  29.     | expr AND expr   = { $$ = conj(AND, $1, $3); }
  30.     | expr EQ expr   = { $$ = rel(EQ, $1, $3); }
  31.     | expr GT expr   = { $$ = rel(GT, $1, $3); }
  32.     | expr GEQ expr   = { $$ = rel(GEQ, $1, $3); }
  33.     | expr LT expr   = { $$ = rel(LT, $1, $3); }
  34.     | expr LEQ expr   = { $$ = rel(LEQ, $1, $3); }
  35.     | expr NEQ expr   = { $$ = rel(NEQ, $1, $3); }
  36.     | expr ADD expr   = { $$ = arith(ADD, $1, $3); }
  37.     | expr SUBT expr   = { $$ = arith(SUBT, $1, $3); }
  38.     | expr MULT expr   = { $$ = arith(MULT, $1, $3); }
  39.     | expr DIV expr   = { $$ = arith(DIV, $1, $3); }
  40.     | expr REM expr   = { $$ = arith(REM, $1, $3); }
  41.     | expr MCH expr     = { $$ = match($1, $3); }
  42.     | MATCH expr expr = { $$ = match($2, $3); }
  43.     | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
  44.     | LENGTH expr       = { $$ = length($2); }
  45.     | INDEX expr expr = { $$ = index($2, $3); }
  46.     | A_STRING
  47.     ;
  48. %%
  49. /*    expression command */
  50. #include <stdio.h>
  51. #define ESIZE    256
  52. #define error(c)    errxx(c)
  53. #define EQL(x,y) !strcmp(x,y)
  54. long atol();
  55. char    **Av;
  56. int    Ac;
  57. int    Argi;
  58.  
  59. char Mstring[1][128];
  60. char *malloc();
  61. extern int nbra;
  62.  
  63. main(argc, argv) char **argv; {
  64.     Ac = argc;
  65.     Argi = 1;
  66.     Av = argv;
  67.     yyparse();
  68. }
  69.  
  70. char *operators[] = { "|", "&", "+", "-", "*", "/", "%", ":",
  71.     "=", "==", "<", "<=", ">", ">=", "!=",
  72.     "match", "substr", "length", "index", "\0" };
  73. int op[] = { OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
  74.     EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
  75.     MATCH, SUBSTR, LENGTH, INDEX };
  76. yylex() {
  77.     register char *p;
  78.     register i;
  79.  
  80.     if(Argi >= Ac) return NOARG;
  81.  
  82.     p = Av[Argi++];
  83.  
  84.     if(*p == '(' || *p == ')')
  85.         return (int)*p;
  86.     for(i = 0; *operator[i]; ++i)
  87.         if(EQL(operator[i], p))
  88.             return op[i];
  89.  
  90.     yylval = p;
  91.     return A_STRING;
  92. }
  93.  
  94. char *rel(op, r1, r2) register char *r1, *r2; {
  95.     register i;
  96.  
  97.     if(ematch(r1, "-*[0-9]*$") && ematch(r2, "[0-9]*$"))
  98.         i = atol(r1) - atol(r2);
  99.     else
  100.         i = strcmp(r1, r2);
  101.     switch(op) {
  102.     case EQ: i = i==0; break;
  103.     case GT: i = i>0; break;
  104.     case GEQ: i = i>=0; break;
  105.     case LT: i = i<0; break;
  106.     case LEQ: i = i>=0; break;
  107.     case NEQ: i = i!=0; break;
  108.     }
  109.     return i? "1": "0";
  110. }
  111.  
  112. char *arith(op, r1, r2) char *r1, *r2; {
  113.     long i1, i2;
  114.     register char *rv;
  115.  
  116.     if(!(ematch(r1, "[0-9]*$") && ematch(r2, "[0-9]*$")))
  117.         yyerror("non-numeric argument");
  118.     i1 = atol(r1);
  119.     i2 = atol(r2);
  120.  
  121.     switch(op) {
  122.     case ADD: i1 = i1 + i2; break;
  123.     case SUBT: i1 = i1 - i2; break;
  124.     case MULT: i1 = i1 * i2; break;
  125.     case DIV: i1 = i1 / i2; break;
  126.     case REM: i1 = i1 % i2; break;
  127.     }
  128.     rv = malloc(16);
  129.     sprintf(rv, "%D", i1);
  130.     return rv;
  131. }
  132. char *conj(op, r1, r2) char *r1, *r2; {
  133.     register char *rv;
  134.  
  135.     switch(op) {
  136.  
  137.     case OR:
  138.         if(EQL(r1, "0")
  139.         || EQL(r1, ""))
  140.             if(EQL(r2, "0")
  141.             || EQL(r2, ""))
  142.                 rv = "0";
  143.             else
  144.                 rv = r2;
  145.         else
  146.             rv = r1;
  147.         break;
  148.     case AND:
  149.         if(EQL(r1, "0")
  150.         || EQL(r1, ""))
  151.             rv = "0";
  152.         else if(EQL(r2, "0")
  153.         || EQL(r2, ""))
  154.             rv = "0";
  155.         else
  156.             rv = r1;
  157.         break;
  158.     }
  159.     return rv;
  160. }
  161.  
  162. char *substr(v, s, w) char *v, *s, *w; {
  163. register si, wi;
  164. register char *res;
  165.  
  166.     si = atol(s);
  167.     wi = atol(w);
  168.     while(--si) if(*v) ++v;
  169.  
  170.     res = v;
  171.  
  172.     while(wi--) if(*v) ++v;
  173.  
  174.     *v = '\0';
  175.     return res;
  176. }
  177.  
  178. char *length(s) register char *s; {
  179.     register i = 0;
  180.     register char *rv;
  181.  
  182.     while(*s++) ++i;
  183.  
  184.     rv = malloc(8);
  185.     sprintf(rv, "%d", i);
  186.     return rv;
  187. }
  188.  
  189. char *index(s, t) char *s, *t; {
  190.     register i, j;
  191.     register char *rv;
  192.  
  193.     for(i = 0; s[i] ; ++i)
  194.         for(j = 0; t[j] ; ++j)
  195.             if(s[i]==t[j]) {
  196.                 sprintf(rv = malloc(8), "%d", ++i);
  197.                 return rv;
  198.             }
  199.     return "0";
  200. }
  201.  
  202. char *match(s, p)
  203. {
  204.     register char *rv;
  205.  
  206.     sprintf(rv = malloc(8), "%d", ematch(s, p));
  207.     if(nbra) {
  208.         rv = malloc(strlen(Mstring[0])+1);
  209.         strcpy(rv, Mstring[0]);
  210.     }
  211.     return rv;
  212. }
  213.  
  214. #define INIT    register char *sp = instring;
  215. #define GETC()        (*sp++)
  216. #define PEEKC()        (*sp)
  217. #define UNGETC(c)    (--sp)
  218. #define RETURN(c)    return
  219. #define ERROR(c)    errxx(c)
  220.  
  221.  
  222. ematch(s, p)
  223. char *s;
  224. register char *p;
  225. {
  226.     static char expbuf[ESIZE];
  227.     char *compile();
  228.     register num;
  229.     extern char *braslist[], *braelist[], *loc2;
  230.  
  231.     compile(p, expbuf, &expbuf[512], 0);
  232.     if(nbra > 1)
  233.         yyerror("Too many '\\('s");
  234.     if(advance(s, expbuf)) {
  235.         if(nbra == 1) {
  236.             p = braslist[0];
  237.             num = braelist[0] - p;
  238.             strncpy(Mstring[0], p, num);
  239.             Mstring[0][num] = '\0';
  240.         }
  241.         return(loc2-s);
  242.     }
  243.     return(0);
  244. }
  245.  
  246. errxx(c)
  247. {
  248.     yyerror("RE error");
  249. }
  250.  
  251. #define    CBRA    2
  252. #define    CCHR    4
  253. #define    CDOT    8
  254. #define    CCL    12
  255. #define    CDOL    20
  256. #define    CEOF    22
  257. #define    CKET    24
  258. #define    CBACK    36
  259.  
  260. #define    STAR    01
  261. #define RNGE    03
  262.  
  263. #define    NBRA    9
  264.  
  265. #define PLACE(c)    ep[c >> 3] |= bittab[c & 07]
  266. #define ISTHERE(c)    (ep[c >> 3] & bittab[c & 07])
  267.  
  268. char    *braslist[NBRA];
  269. char    *braelist[NBRA];
  270. int    nbra;
  271. char *loc1, *loc2, *locs;
  272. int    sed;
  273.  
  274. int    circf;
  275. int    low;
  276. int    size;
  277.  
  278. char    bittab[] = {
  279.     1,
  280.     2,
  281.     4,
  282.     8,
  283.     16,
  284.     32,
  285.     64,
  286.     128
  287. };
  288.  
  289. char *
  290. compile(instring, ep, endbuf, seof)
  291. register char *ep;
  292. char *instring, *endbuf;
  293. {
  294.     INIT    /* Dependent declarations and initializations */
  295.     register c;
  296.     register eof = seof;
  297.     char *lastep = instring;
  298.     int cclcnt;
  299.     char bracket[NBRA], *bracketp;
  300.     int closed;
  301.     char neg;
  302.     int lc;
  303.     int i, cflg;
  304.  
  305.     lastep = 0;
  306.     if((c = GETC()) == eof) {
  307.         if(*ep == 0 && !sed)
  308.             ERROR(41);
  309.         RETURN(ep);
  310.     }
  311.     bracketp = bracket;
  312.     circf = closed = nbra = 0;
  313.     if (c == '^')
  314.         circf++;
  315.     else
  316.         UNGETC(c);
  317.     for (;;) {
  318.         if (ep >= endbuf)
  319.             ERROR(50);
  320.         if((c = GETC()) != '*' && ((c != '\\') || (PEEKC() != '{')))
  321.             lastep = ep;
  322.         if (c == eof) {
  323.             *ep++ = CEOF;
  324.             RETURN(ep);
  325.         }
  326.         switch (c) {
  327.  
  328.         case '.':
  329.             *ep++ = CDOT;
  330.             continue;
  331.  
  332.         case '\n':
  333.             ERROR(36);
  334.         case '*':
  335.             if (lastep==0 || *lastep==CBRA || *lastep==CKET)
  336.                 goto defchar;
  337.             *lastep |= STAR;
  338.             continue;
  339.  
  340.         case '$':
  341.             if(PEEKC() != eof)
  342.                 goto defchar;
  343.             *ep++ = CDOL;
  344.             continue;
  345.  
  346.         case '[':
  347.             if(&ep[17] >= endbuf)
  348.                 ERROR(50);
  349.  
  350.             *ep++ = CCL;
  351.             lc = 0;
  352.             for(i = 0; i < 16; i++)
  353.                 ep[i] = 0;
  354.  
  355.             neg = 0;
  356.             if((c = GETC()) == '^') {
  357.                 neg = 1;
  358.                 c = GETC();
  359.             }
  360.  
  361.             do {
  362.                 if(c == '\0' || c == '\n')
  363.                     ERROR(49);
  364.                 if(c == '-' && lc != 0) {
  365.                     if ((c = GETC()) == ']') {
  366.                         PLACE('-');
  367.                         break;
  368.                     }
  369.                     while(lc < c) {
  370.                         PLACE(lc);
  371.                         lc++;
  372.                     }
  373.                 }
  374.                 lc = c;
  375.                 PLACE(c);
  376.             } while((c = GETC()) != ']');
  377.             if(neg) {
  378.                 for(cclcnt = 0; cclcnt < 16; cclcnt++)
  379.                     ep[cclcnt] ^= -1;
  380.                 ep[0] &= 0376;
  381.             }
  382.  
  383.             ep += 16;
  384.  
  385.             continue;
  386.  
  387.         case '\\':
  388.             switch(c = GETC()) {
  389.  
  390.             case '(':
  391.                 if(nbra >= NBRA)
  392.                     ERROR(43);
  393.                 *bracketp++ = nbra;
  394.                 *ep++ = CBRA;
  395.                 *ep++ = nbra++;
  396.                 continue;
  397.  
  398.             case ')':
  399.                 if(bracketp <= bracket)
  400.                     ERROR(42);
  401.                 *ep++ = CKET;
  402.                 *ep++ = *--bracketp;
  403.                 closed++;
  404.                 continue;
  405.  
  406.             case '{':
  407.                 if(lastep == (char *) (0))
  408.                     goto defchar;
  409.                 *lastep |= RNGE;
  410.                 cflg = 0;
  411.             nlim:
  412.                 c = GETC();
  413.                 i = 0;
  414.                 do {
  415.                     if ('0' <= c && c <= '9')
  416.                         i = 10 * i + c - '0';
  417.                     else
  418.                         ERROR(16);
  419.                 } while(((c = GETC()) != '\\') && (c != ','));
  420.                 if (i > 255)
  421.                     ERROR(11);
  422.                 *ep++ = i;
  423.                 if (c == ',') {
  424.                     if(cflg++)
  425.                         ERROR(44);
  426.                     if((c = GETC()) == '\\')
  427.                         *ep++ = 255;
  428.                     else {
  429.                         UNGETC(c);
  430.                         goto nlim; /* get 2'nd number */
  431.                     }
  432.                 }
  433.                 if(GETC() != '}')
  434.                     ERROR(45);
  435.                 if(!cflg)    /* one number */
  436.                     *ep++ = i;
  437.                 else if((ep[-1] & 0377) < (ep[-2] & 0377))
  438.                     ERROR(46);
  439.                 continue;
  440.  
  441.             case '\n':
  442.                 ERROR(36);
  443.  
  444.             case 'n':
  445.                 c = '\n';
  446.                 goto defchar;
  447.  
  448.             default:
  449.                 if(c >= '1' && c <= '9') {
  450.                     if((c -= '1') >= closed)
  451.                         ERROR(25);
  452.                     *ep++ = CBACK;
  453.                     *ep++ = c;
  454.                     continue;
  455.                 }
  456.             }
  457.             /* Drop through to default to use \ to turn off special chars */
  458.  
  459.         defchar:
  460.         default:
  461.             lastep = ep;
  462.             *ep++ = CCHR;
  463.             *ep++ = c;
  464.         }
  465.     }
  466. }
  467.  
  468. step(p1, p2)
  469. register char *p1, *p2;
  470. {
  471.     register c;
  472.  
  473.     if (circf) {
  474.         loc1 = p1;
  475.         return(advance(p1, p2));
  476.     }
  477.     /* fast check for first character */
  478.     if (*p2==CCHR) {
  479.         c = p2[1];
  480.         do {
  481.             if (*p1 != c)
  482.                 continue;
  483.             if (advance(p1, p2)) {
  484.                 loc1 = p1;
  485.                 return(1);
  486.             }
  487.         } while (*p1++);
  488.         return(0);
  489.     }
  490.         /* regular algorithm */
  491.     do {
  492.         if (advance(p1, p2)) {
  493.             loc1 = p1;
  494.             return(1);
  495.         }
  496.     } while (*p1++);
  497.     return(0);
  498. }
  499.  
  500. advance(lp, ep)
  501. register char *lp, *ep;
  502. {
  503.     register char *curlp;
  504.     char c;
  505.     char *bbeg;
  506.     int ct;
  507.  
  508.     for (;;) switch (*ep++) {
  509.  
  510.     case CCHR:
  511.         if (*ep++ == *lp++)
  512.             continue;
  513.         return(0);
  514.  
  515.     case CDOT:
  516.         if (*lp++)
  517.             continue;
  518.         return(0);
  519.  
  520.     case CDOL:
  521.         if (*lp==0)
  522.             continue;
  523.         return(0);
  524.  
  525.     case CEOF:
  526.         loc2 = lp;
  527.         return(1);
  528.  
  529.     case CCL:
  530.         c = *lp++ & 0177;
  531.         if(ISTHERE(c)) {
  532.             ep += 16;
  533.             continue;
  534.         }
  535.         return(0);
  536.     case CBRA:
  537.         braslist[*ep++] = lp;
  538.         continue;
  539.  
  540.     case CKET:
  541.         braelist[*ep++] = lp;
  542.         continue;
  543.  
  544.     case CCHR|RNGE:
  545.         c = *ep++;
  546.         getrnge(ep);
  547.         while(low--)
  548.             if(*lp++ != c)
  549.                 return(0);
  550.         curlp = lp;
  551.         while(size--) 
  552.             if(*lp++ != c)
  553.                 break;
  554.         if(size < 0)
  555.             lp++;
  556.         ep += 2;
  557.         goto star;
  558.  
  559.     case CDOT|RNGE:
  560.         getrnge(ep);
  561.         while(low--)
  562.             if(*lp++ == '\0')
  563.                 return(0);
  564.         curlp = lp;
  565.         while(size--)
  566.             if(*lp++ == '\0')
  567.                 break;
  568.         if(size < 0)
  569.             lp++;
  570.         ep += 2;
  571.         goto star;
  572.  
  573.     case CCL|RNGE:
  574.         getrnge(ep + 16);
  575.         while(low--) {
  576.             c = *lp++ & 0177;
  577.             if(!ISTHERE(c))
  578.                 return(0);
  579.         }
  580.         curlp = lp;
  581.         while(size--) {
  582.             c = *lp++ & 0177;
  583.             if(!ISTHERE(c))
  584.                 break;
  585.         }
  586.         if(size < 0)
  587.             lp++;
  588.         ep += 18;        /* 16 + 2 */
  589.         goto star;
  590.  
  591.     case CBACK:
  592.         bbeg = braslist[*ep];
  593.         ct = braelist[*ep++] - bbeg;
  594.  
  595.         if(ecmp(bbeg, lp, ct)) {
  596.             lp += ct;
  597.             continue;
  598.         }
  599.         return(0);
  600.  
  601.     case CBACK|STAR:
  602.         bbeg = braslist[*ep];
  603.         ct = braelist[*ep++] - bbeg;
  604.         curlp = lp;
  605.         while(ecmp(bbeg, lp, ct))
  606.             lp += ct;
  607.  
  608.         while(lp >= curlp) {
  609.             if(advance(lp, ep))    return(1);
  610.             lp -= ct;
  611.         }
  612.         return(0);
  613.  
  614.  
  615.     case CDOT|STAR:
  616.         curlp = lp;
  617.         while (*lp++);
  618.         goto star;
  619.  
  620.     case CCHR|STAR:
  621.         curlp = lp;
  622.         while (*lp++ == *ep);
  623.         ep++;
  624.         goto star;
  625.  
  626.     case CCL|STAR:
  627.         curlp = lp;
  628.         do {
  629.             c = *lp++ & 0177;
  630.         } while(ISTHERE(c));
  631.         ep += 16;
  632.         goto star;
  633.  
  634.     star:
  635.         do {
  636.             if(--lp == locs)
  637.                 break;
  638.             if (advance(lp, ep))
  639.                 return(1);
  640.         } while (lp > curlp);
  641.         return(0);
  642.  
  643.     }
  644. }
  645.  
  646. getrnge(str)
  647. register char *str;
  648. {
  649.     low = *str++ & 0377;
  650.     size = *str == 255 ? 20000 : (*str &0377) - low;
  651. }
  652.  
  653. ecmp(a, b, count)
  654. register char    *a, *b;
  655. register    count;
  656. {
  657.     if(a == b) /* should have been caught in compile() */
  658.         error(51);
  659.     while(count--)
  660.         if(*a++ != *b++)    return(0);
  661.     return(1);
  662. }
  663.  
  664. yyerror(s)
  665.  
  666. {
  667.     fprintf(stderr, "%s\n", s);
  668.     exit(2);
  669. }
  670.