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