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