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