date and time created 88/10/18 21:50:57 by bostic
[unix-history] / usr / src / bin / expr / expr.y
CommitLineData
e95afa8a
BJ
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
20expression: expr NOARG = {
21 printf("%s\n", $1);
22 exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
23 }
24 ;
25
26
27expr: '(' 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)
54long atol();
55char **Av;
56int Ac;
57int Argi;
58
59char Mstring[1][128];
60char *malloc();
61extern int nbra;
62
63main(argc, argv) char **argv; {
64 Ac = argc;
65 Argi = 1;
66 Av = argv;
67 yyparse();
68}
69
70char *operators[] = { "|", "&", "+", "-", "*", "/", "%", ":",
71 "=", "==", "<", "<=", ">", ">=", "!=",
72 "match", "substr", "length", "index", "\0" };
73int op[] = { OR, AND, ADD, SUBT, MULT, DIV, REM, MCH,
74 EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
75 MATCH, SUBSTR, LENGTH, INDEX };
76yylex() {
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
94char *rel(op, r1, r2) register char *r1, *r2; {
b940afc0 95 register long i;
e95afa8a
BJ
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;
df3e00cc 106 case LEQ: i = i<=0; break;
e95afa8a
BJ
107 case NEQ: i = i!=0; break;
108 }
109 return i? "1": "0";
110}
111
112char *arith(op, r1, r2) char *r1, *r2; {
113 long i1, i2;
114 register char *rv;
115
e1d6f378
KB
116 if(!((ematch(r1, "[0-9]*$") || ematch(r1, "-[0-9]*$")) &&
117 (ematch(r2, "[0-9]*$") || ematch(r2, "-[0-9]*$"))))
e95afa8a
BJ
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);
6521d648 130 (void)sprintf(rv, "%ld", i1);
e95afa8a
BJ
131 return rv;
132}
133char *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
163char *substr(v, s, w) char *v, *s, *w; {
164register si, wi;
165register 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
179char *length(s) register char *s; {
180 register i = 0;
181 register char *rv;
182
183 while(*s++) ++i;
184
185 rv = malloc(8);
6521d648 186 (void)sprintf(rv, "%d", i);
e95afa8a
BJ
187 return rv;
188}
189
190char *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]) {
6521d648 197 (void)sprintf(rv = malloc(8), "%d", ++i);
e95afa8a
BJ
198 return rv;
199 }
200 return "0";
201}
202
203char *match(s, p)
204{
205 register char *rv;
206
6521d648 207 (void)sprintf(rv = malloc(8), "%d", ematch(s, p));
e95afa8a
BJ
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
223ematch(s, p)
224char *s;
225register char *p;
226{
227 static char expbuf[ESIZE];
228 char *compile();
229 register num;
230 extern char *braslist[], *braelist[], *loc2;
231
6ee2a9ff 232 compile(p, expbuf, &expbuf[ESIZE], 0);
e95afa8a
BJ
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
247errxx(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
269char *braslist[NBRA];
270char *braelist[NBRA];
271int nbra;
272char *loc1, *loc2, *locs;
273int sed;
274
275int circf;
276int low;
277int size;
278
279char bittab[] = {
280 1,
281 2,
282 4,
283 8,
284 16,
285 32,
286 64,
287 128
288};
289
290char *
291compile(instring, ep, endbuf, seof)
292register char *ep;
293char *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
469step(p1, p2)
470register 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
501advance(lp, ep)
502register 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
647getrnge(str)
648register char *str;
649{
650 low = *str++ & 0377;
15bd6011 651 size = (*str & 0377) == 255 ? 20000 : (*str & 0377) - low;
e95afa8a
BJ
652}
653
654ecmp(a, b, count)
655register char *a, *b;
656register 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
15bd6011 665static char *sccsid = "@(#)expr.y 4.7 (Berkeley) %G%";
e95afa8a
BJ
666yyerror(s)
667
668{
669 fprintf(stderr, "%s\n", s);
670 exit(2);
671}