|
|
1.1 root 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; *operators[i]; ++i)
87: if(EQL(operators[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 long 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: static char *sccsid = "@(#)expr.y 4.3 (Berkeley) 6/30/83";
665: yyerror(s)
666:
667: {
668: fprintf(stderr, "%s\n", s);
669: exit(2);
670: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.