xref: /original-bsd/bin/expr/expr.y (revision d0e3910b)
14c0d4567Sbill /* Yacc productions for "expr" command: */
24c0d4567Sbill 
34c0d4567Sbill %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
44c0d4567Sbill %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
54c0d4567Sbill 
64c0d4567Sbill /* operators listed below in increasing precedence: */
74c0d4567Sbill %left OR
84c0d4567Sbill %left AND
94c0d4567Sbill %left EQ LT GT GEQ LEQ NEQ
104c0d4567Sbill %left ADD SUBT
114c0d4567Sbill %left MULT DIV REM
124c0d4567Sbill %left MCH
134c0d4567Sbill %left MATCH
144c0d4567Sbill %left SUBSTR
154c0d4567Sbill %left LENGTH INDEX
164c0d4567Sbill %%
174c0d4567Sbill 
184c0d4567Sbill /* a single `expression' is evaluated and printed: */
194c0d4567Sbill 
204c0d4567Sbill expression:	expr NOARG = {
214c0d4567Sbill 			printf("%s\n", $1);
224c0d4567Sbill 			exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
234c0d4567Sbill 			}
244c0d4567Sbill 	;
254c0d4567Sbill 
264c0d4567Sbill 
274c0d4567Sbill expr:	'(' expr ')' = { $$ = $2; }
284c0d4567Sbill 	| expr OR expr   = { $$ = conj(OR, $1, $3); }
294c0d4567Sbill 	| expr AND expr   = { $$ = conj(AND, $1, $3); }
304c0d4567Sbill 	| expr EQ expr   = { $$ = rel(EQ, $1, $3); }
314c0d4567Sbill 	| expr GT expr   = { $$ = rel(GT, $1, $3); }
324c0d4567Sbill 	| expr GEQ expr   = { $$ = rel(GEQ, $1, $3); }
334c0d4567Sbill 	| expr LT expr   = { $$ = rel(LT, $1, $3); }
344c0d4567Sbill 	| expr LEQ expr   = { $$ = rel(LEQ, $1, $3); }
354c0d4567Sbill 	| expr NEQ expr   = { $$ = rel(NEQ, $1, $3); }
364c0d4567Sbill 	| expr ADD expr   = { $$ = arith(ADD, $1, $3); }
374c0d4567Sbill 	| expr SUBT expr   = { $$ = arith(SUBT, $1, $3); }
384c0d4567Sbill 	| expr MULT expr   = { $$ = arith(MULT, $1, $3); }
394c0d4567Sbill 	| expr DIV expr   = { $$ = arith(DIV, $1, $3); }
404c0d4567Sbill 	| expr REM expr   = { $$ = arith(REM, $1, $3); }
414c0d4567Sbill 	| expr MCH expr	 = { $$ = match($1, $3); }
424c0d4567Sbill 	| MATCH expr expr = { $$ = match($2, $3); }
434c0d4567Sbill 	| SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
444c0d4567Sbill 	| LENGTH expr       = { $$ = length($2); }
454c0d4567Sbill 	| INDEX expr expr = { $$ = index($2, $3); }
464c0d4567Sbill 	| A_STRING
474c0d4567Sbill 	;
484c0d4567Sbill %%
494c0d4567Sbill /*	expression command */
504c0d4567Sbill #include <stdio.h>
514c0d4567Sbill #define ESIZE	256
524c0d4567Sbill #define error(c)	errxx(c)
534c0d4567Sbill #define EQL(x,y) !strcmp(x,y)
544c0d4567Sbill long atol();
554c0d4567Sbill char	**Av;
564c0d4567Sbill int	Ac;
574c0d4567Sbill int	Argi;
584c0d4567Sbill 
594c0d4567Sbill char Mstring[1][128];
604c0d4567Sbill char *malloc();
614c0d4567Sbill extern int nbra;
624c0d4567Sbill 
634c0d4567Sbill main(argc, argv) char **argv; {
644c0d4567Sbill 	Ac = argc;
654c0d4567Sbill 	Argi = 1;
664c0d4567Sbill 	Av = argv;
674c0d4567Sbill 	yyparse();
684c0d4567Sbill }
694c0d4567Sbill 
704c0d4567Sbill char *operators[] = { "|", "&", "+", "-", "*", "/", "%", ":",
714c0d4567Sbill 	"=", "==", "<", "<=", ">", ">=", "!=",
724c0d4567Sbill 	"match", "substr", "length", "index", "\0" };
734c0d4567Sbill int op[] = { OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
744c0d4567Sbill 	EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
754c0d4567Sbill 	MATCH, SUBSTR, LENGTH, INDEX };
764c0d4567Sbill yylex() {
774c0d4567Sbill 	register char *p;
784c0d4567Sbill 	register i;
794c0d4567Sbill 
804c0d4567Sbill 	if(Argi >= Ac) return NOARG;
814c0d4567Sbill 
824c0d4567Sbill 	p = Av[Argi++];
834c0d4567Sbill 
844c0d4567Sbill 	if(*p == '(' || *p == ')')
854c0d4567Sbill 		return (int)*p;
864c0d4567Sbill 	for(i = 0; *operators[i]; ++i)
874c0d4567Sbill 		if(EQL(operators[i], p))
884c0d4567Sbill 			return op[i];
894c0d4567Sbill 
904c0d4567Sbill 	yylval = p;
914c0d4567Sbill 	return A_STRING;
924c0d4567Sbill }
934c0d4567Sbill 
944c0d4567Sbill char *rel(op, r1, r2) register char *r1, *r2; {
95264c46cbSsam 	register long i;
964c0d4567Sbill 
974c0d4567Sbill 	if(ematch(r1, "-*[0-9]*$") && ematch(r2, "[0-9]*$"))
984c0d4567Sbill 		i = atol(r1) - atol(r2);
994c0d4567Sbill 	else
1004c0d4567Sbill 		i = strcmp(r1, r2);
1014c0d4567Sbill 	switch(op) {
1024c0d4567Sbill 	case EQ: i = i==0; break;
1034c0d4567Sbill 	case GT: i = i>0; break;
1044c0d4567Sbill 	case GEQ: i = i>=0; break;
1054c0d4567Sbill 	case LT: i = i<0; break;
10656abee86Swnj 	case LEQ: i = i<=0; break;
1074c0d4567Sbill 	case NEQ: i = i!=0; break;
1084c0d4567Sbill 	}
1094c0d4567Sbill 	return i? "1": "0";
1104c0d4567Sbill }
1114c0d4567Sbill 
1124c0d4567Sbill char *arith(op, r1, r2) char *r1, *r2; {
1134c0d4567Sbill 	long i1, i2;
1144c0d4567Sbill 	register char *rv;
1154c0d4567Sbill 
116a9c19d04Sbostic 	if(!((ematch(r1, "[0-9]*$") || ematch(r1, "-[0-9]*$")) &&
117a9c19d04Sbostic 	     (ematch(r2, "[0-9]*$") || ematch(r2, "-[0-9]*$"))))
1184c0d4567Sbill 		yyerror("non-numeric argument");
1194c0d4567Sbill 	i1 = atol(r1);
1204c0d4567Sbill 	i2 = atol(r2);
1214c0d4567Sbill 
1224c0d4567Sbill 	switch(op) {
1234c0d4567Sbill 	case ADD: i1 = i1 + i2; break;
1244c0d4567Sbill 	case SUBT: i1 = i1 - i2; break;
1254c0d4567Sbill 	case MULT: i1 = i1 * i2; break;
1264c0d4567Sbill 	case DIV: i1 = i1 / i2; break;
1274c0d4567Sbill 	case REM: i1 = i1 % i2; break;
1284c0d4567Sbill 	}
1294c0d4567Sbill 	rv = malloc(16);
130f703d710Sbostic 	(void)sprintf(rv, "%ld", i1);
1314c0d4567Sbill 	return rv;
1324c0d4567Sbill }
1334c0d4567Sbill char *conj(op, r1, r2) char *r1, *r2; {
1344c0d4567Sbill 	register char *rv;
1354c0d4567Sbill 
1364c0d4567Sbill 	switch(op) {
1374c0d4567Sbill 
1384c0d4567Sbill 	case OR:
1394c0d4567Sbill 		if(EQL(r1, "0")
1404c0d4567Sbill 		|| EQL(r1, ""))
1414c0d4567Sbill 			if(EQL(r2, "0")
1424c0d4567Sbill 			|| EQL(r2, ""))
1434c0d4567Sbill 				rv = "0";
1444c0d4567Sbill 			else
1454c0d4567Sbill 				rv = r2;
1464c0d4567Sbill 		else
1474c0d4567Sbill 			rv = r1;
1484c0d4567Sbill 		break;
1494c0d4567Sbill 	case AND:
1504c0d4567Sbill 		if(EQL(r1, "0")
1514c0d4567Sbill 		|| EQL(r1, ""))
1524c0d4567Sbill 			rv = "0";
1534c0d4567Sbill 		else if(EQL(r2, "0")
1544c0d4567Sbill 		|| EQL(r2, ""))
1554c0d4567Sbill 			rv = "0";
1564c0d4567Sbill 		else
1574c0d4567Sbill 			rv = r1;
1584c0d4567Sbill 		break;
1594c0d4567Sbill 	}
1604c0d4567Sbill 	return rv;
1614c0d4567Sbill }
1624c0d4567Sbill 
1634c0d4567Sbill char *substr(v, s, w) char *v, *s, *w; {
1644c0d4567Sbill register si, wi;
1654c0d4567Sbill register char *res;
1664c0d4567Sbill 
1674c0d4567Sbill 	si = atol(s);
1684c0d4567Sbill 	wi = atol(w);
1694c0d4567Sbill 	while(--si) if(*v) ++v;
1704c0d4567Sbill 
1714c0d4567Sbill 	res = v;
1724c0d4567Sbill 
1734c0d4567Sbill 	while(wi--) if(*v) ++v;
1744c0d4567Sbill 
1754c0d4567Sbill 	*v = '\0';
1764c0d4567Sbill 	return res;
1774c0d4567Sbill }
1784c0d4567Sbill 
1794c0d4567Sbill char *length(s) register char *s; {
1804c0d4567Sbill 	register i = 0;
1814c0d4567Sbill 	register char *rv;
1824c0d4567Sbill 
1834c0d4567Sbill 	while(*s++) ++i;
1844c0d4567Sbill 
1854c0d4567Sbill 	rv = malloc(8);
186f703d710Sbostic 	(void)sprintf(rv, "%d", i);
1874c0d4567Sbill 	return rv;
1884c0d4567Sbill }
1894c0d4567Sbill 
1904c0d4567Sbill char *index(s, t) char *s, *t; {
1914c0d4567Sbill 	register i, j;
1924c0d4567Sbill 	register char *rv;
1934c0d4567Sbill 
1944c0d4567Sbill 	for(i = 0; s[i] ; ++i)
1954c0d4567Sbill 		for(j = 0; t[j] ; ++j)
1964c0d4567Sbill 			if(s[i]==t[j]) {
197f703d710Sbostic 				(void)sprintf(rv = malloc(8), "%d", ++i);
1984c0d4567Sbill 				return rv;
1994c0d4567Sbill 			}
2004c0d4567Sbill 	return "0";
2014c0d4567Sbill }
2024c0d4567Sbill 
2034c0d4567Sbill char *match(s, p)
2044c0d4567Sbill {
2054c0d4567Sbill 	register char *rv;
2064c0d4567Sbill 
207f703d710Sbostic 	(void)sprintf(rv = malloc(8), "%d", ematch(s, p));
2084c0d4567Sbill 	if(nbra) {
2094c0d4567Sbill 		rv = malloc(strlen(Mstring[0])+1);
2104c0d4567Sbill 		strcpy(rv, Mstring[0]);
2114c0d4567Sbill 	}
2124c0d4567Sbill 	return rv;
2134c0d4567Sbill }
2144c0d4567Sbill 
2154c0d4567Sbill #define INIT	register char *sp = instring;
2164c0d4567Sbill #define GETC()		(*sp++)
2174c0d4567Sbill #define PEEKC()		(*sp)
2184c0d4567Sbill #define UNGETC(c)	(--sp)
2194c0d4567Sbill #define RETURN(c)	return
2204c0d4567Sbill #define ERROR(c)	errxx(c)
2214c0d4567Sbill 
2224c0d4567Sbill 
2234c0d4567Sbill ematch(s, p)
2244c0d4567Sbill char *s;
2254c0d4567Sbill register char *p;
2264c0d4567Sbill {
2274c0d4567Sbill 	static char expbuf[ESIZE];
2284c0d4567Sbill 	char *compile();
2294c0d4567Sbill 	register num;
2304c0d4567Sbill 	extern char *braslist[], *braelist[], *loc2;
2314c0d4567Sbill 
232e74403baSralph 	compile(p, expbuf, &expbuf[ESIZE], 0);
2334c0d4567Sbill 	if(nbra > 1)
2344c0d4567Sbill 		yyerror("Too many '\\('s");
2354c0d4567Sbill 	if(advance(s, expbuf)) {
2364c0d4567Sbill 		if(nbra == 1) {
2374c0d4567Sbill 			p = braslist[0];
2384c0d4567Sbill 			num = braelist[0] - p;
2394c0d4567Sbill 			strncpy(Mstring[0], p, num);
2404c0d4567Sbill 			Mstring[0][num] = '\0';
2414c0d4567Sbill 		}
2424c0d4567Sbill 		return(loc2-s);
2434c0d4567Sbill 	}
2444c0d4567Sbill 	return(0);
2454c0d4567Sbill }
2464c0d4567Sbill 
2474c0d4567Sbill errxx(c)
2484c0d4567Sbill {
2494c0d4567Sbill 	yyerror("RE error");
2504c0d4567Sbill }
2514c0d4567Sbill 
2524c0d4567Sbill #define	CBRA	2
2534c0d4567Sbill #define	CCHR	4
2544c0d4567Sbill #define	CDOT	8
2554c0d4567Sbill #define	CCL	12
2564c0d4567Sbill #define	CDOL	20
2574c0d4567Sbill #define	CEOF	22
2584c0d4567Sbill #define	CKET	24
2594c0d4567Sbill #define	CBACK	36
2604c0d4567Sbill 
2614c0d4567Sbill #define	STAR	01
2624c0d4567Sbill #define RNGE	03
2634c0d4567Sbill 
2644c0d4567Sbill #define	NBRA	9
2654c0d4567Sbill 
2664c0d4567Sbill #define PLACE(c)	ep[c >> 3] |= bittab[c & 07]
2674c0d4567Sbill #define ISTHERE(c)	(ep[c >> 3] & bittab[c & 07])
2684c0d4567Sbill 
2694c0d4567Sbill char	*braslist[NBRA];
2704c0d4567Sbill char	*braelist[NBRA];
2714c0d4567Sbill int	nbra;
2724c0d4567Sbill char *loc1, *loc2, *locs;
2734c0d4567Sbill int	sed;
2744c0d4567Sbill 
2754c0d4567Sbill int	circf;
2764c0d4567Sbill int	low;
2774c0d4567Sbill int	size;
2784c0d4567Sbill 
2794c0d4567Sbill char	bittab[] = {
2804c0d4567Sbill 	1,
2814c0d4567Sbill 	2,
2824c0d4567Sbill 	4,
2834c0d4567Sbill 	8,
2844c0d4567Sbill 	16,
2854c0d4567Sbill 	32,
2864c0d4567Sbill 	64,
2874c0d4567Sbill 	128
2884c0d4567Sbill };
2894c0d4567Sbill 
2904c0d4567Sbill char *
2914c0d4567Sbill compile(instring, ep, endbuf, seof)
2924c0d4567Sbill register char *ep;
2934c0d4567Sbill char *instring, *endbuf;
2944c0d4567Sbill {
2954c0d4567Sbill 	INIT	/* Dependent declarations and initializations */
2964c0d4567Sbill 	register c;
2974c0d4567Sbill 	register eof = seof;
2984c0d4567Sbill 	char *lastep = instring;
2994c0d4567Sbill 	int cclcnt;
3004c0d4567Sbill 	char bracket[NBRA], *bracketp;
3014c0d4567Sbill 	int closed;
3024c0d4567Sbill 	char neg;
3034c0d4567Sbill 	int lc;
3044c0d4567Sbill 	int i, cflg;
3054c0d4567Sbill 
3064c0d4567Sbill 	lastep = 0;
3074c0d4567Sbill 	if((c = GETC()) == eof) {
3084c0d4567Sbill 		if(*ep == 0 && !sed)
3094c0d4567Sbill 			ERROR(41);
3104c0d4567Sbill 		RETURN(ep);
3114c0d4567Sbill 	}
3124c0d4567Sbill 	bracketp = bracket;
3134c0d4567Sbill 	circf = closed = nbra = 0;
3144c0d4567Sbill 	if (c == '^')
3154c0d4567Sbill 		circf++;
3164c0d4567Sbill 	else
3174c0d4567Sbill 		UNGETC(c);
3184c0d4567Sbill 	for (;;) {
3194c0d4567Sbill 		if (ep >= endbuf)
3204c0d4567Sbill 			ERROR(50);
3214c0d4567Sbill 		if((c = GETC()) != '*' && ((c != '\\') || (PEEKC() != '{')))
3224c0d4567Sbill 			lastep = ep;
3234c0d4567Sbill 		if (c == eof) {
3244c0d4567Sbill 			*ep++ = CEOF;
3254c0d4567Sbill 			RETURN(ep);
3264c0d4567Sbill 		}
3274c0d4567Sbill 		switch (c) {
3284c0d4567Sbill 
3294c0d4567Sbill 		case '.':
3304c0d4567Sbill 			*ep++ = CDOT;
3314c0d4567Sbill 			continue;
3324c0d4567Sbill 
3334c0d4567Sbill 		case '\n':
3344c0d4567Sbill 			ERROR(36);
3354c0d4567Sbill 		case '*':
3364c0d4567Sbill 			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
3374c0d4567Sbill 				goto defchar;
3384c0d4567Sbill 			*lastep |= STAR;
3394c0d4567Sbill 			continue;
3404c0d4567Sbill 
3414c0d4567Sbill 		case '$':
3424c0d4567Sbill 			if(PEEKC() != eof)
3434c0d4567Sbill 				goto defchar;
3444c0d4567Sbill 			*ep++ = CDOL;
3454c0d4567Sbill 			continue;
3464c0d4567Sbill 
3474c0d4567Sbill 		case '[':
3484c0d4567Sbill 			if(&ep[17] >= endbuf)
3494c0d4567Sbill 				ERROR(50);
3504c0d4567Sbill 
3514c0d4567Sbill 			*ep++ = CCL;
3524c0d4567Sbill 			lc = 0;
3534c0d4567Sbill 			for(i = 0; i < 16; i++)
3544c0d4567Sbill 				ep[i] = 0;
3554c0d4567Sbill 
3564c0d4567Sbill 			neg = 0;
3574c0d4567Sbill 			if((c = GETC()) == '^') {
3584c0d4567Sbill 				neg = 1;
3594c0d4567Sbill 				c = GETC();
3604c0d4567Sbill 			}
3614c0d4567Sbill 
3624c0d4567Sbill 			do {
3634c0d4567Sbill 				if(c == '\0' || c == '\n')
3644c0d4567Sbill 					ERROR(49);
3654c0d4567Sbill 				if(c == '-' && lc != 0) {
3664c0d4567Sbill 					if ((c = GETC()) == ']') {
3674c0d4567Sbill 						PLACE('-');
3684c0d4567Sbill 						break;
3694c0d4567Sbill 					}
3704c0d4567Sbill 					while(lc < c) {
3714c0d4567Sbill 						PLACE(lc);
3724c0d4567Sbill 						lc++;
3734c0d4567Sbill 					}
3744c0d4567Sbill 				}
3754c0d4567Sbill 				lc = c;
3764c0d4567Sbill 				PLACE(c);
3774c0d4567Sbill 			} while((c = GETC()) != ']');
3784c0d4567Sbill 			if(neg) {
3794c0d4567Sbill 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
3804c0d4567Sbill 					ep[cclcnt] ^= -1;
3814c0d4567Sbill 				ep[0] &= 0376;
3824c0d4567Sbill 			}
3834c0d4567Sbill 
3844c0d4567Sbill 			ep += 16;
3854c0d4567Sbill 
3864c0d4567Sbill 			continue;
3874c0d4567Sbill 
3884c0d4567Sbill 		case '\\':
3894c0d4567Sbill 			switch(c = GETC()) {
3904c0d4567Sbill 
3914c0d4567Sbill 			case '(':
3924c0d4567Sbill 				if(nbra >= NBRA)
3934c0d4567Sbill 					ERROR(43);
3944c0d4567Sbill 				*bracketp++ = nbra;
3954c0d4567Sbill 				*ep++ = CBRA;
3964c0d4567Sbill 				*ep++ = nbra++;
3974c0d4567Sbill 				continue;
3984c0d4567Sbill 
3994c0d4567Sbill 			case ')':
4004c0d4567Sbill 				if(bracketp <= bracket)
4014c0d4567Sbill 					ERROR(42);
4024c0d4567Sbill 				*ep++ = CKET;
4034c0d4567Sbill 				*ep++ = *--bracketp;
4044c0d4567Sbill 				closed++;
4054c0d4567Sbill 				continue;
4064c0d4567Sbill 
4074c0d4567Sbill 			case '{':
4084c0d4567Sbill 				if(lastep == (char *) (0))
4094c0d4567Sbill 					goto defchar;
4104c0d4567Sbill 				*lastep |= RNGE;
4114c0d4567Sbill 				cflg = 0;
4124c0d4567Sbill 			nlim:
4134c0d4567Sbill 				c = GETC();
4144c0d4567Sbill 				i = 0;
4154c0d4567Sbill 				do {
4164c0d4567Sbill 					if ('0' <= c && c <= '9')
4174c0d4567Sbill 						i = 10 * i + c - '0';
4184c0d4567Sbill 					else
4194c0d4567Sbill 						ERROR(16);
4204c0d4567Sbill 				} while(((c = GETC()) != '\\') && (c != ','));
4214c0d4567Sbill 				if (i > 255)
4224c0d4567Sbill 					ERROR(11);
4234c0d4567Sbill 				*ep++ = i;
4244c0d4567Sbill 				if (c == ',') {
4254c0d4567Sbill 					if(cflg++)
4264c0d4567Sbill 						ERROR(44);
4274c0d4567Sbill 					if((c = GETC()) == '\\')
4284c0d4567Sbill 						*ep++ = 255;
4294c0d4567Sbill 					else {
4304c0d4567Sbill 						UNGETC(c);
4314c0d4567Sbill 						goto nlim; /* get 2'nd number */
4324c0d4567Sbill 					}
4334c0d4567Sbill 				}
4344c0d4567Sbill 				if(GETC() != '}')
4354c0d4567Sbill 					ERROR(45);
4364c0d4567Sbill 				if(!cflg)	/* one number */
4374c0d4567Sbill 					*ep++ = i;
4384c0d4567Sbill 				else if((ep[-1] & 0377) < (ep[-2] & 0377))
4394c0d4567Sbill 					ERROR(46);
4404c0d4567Sbill 				continue;
4414c0d4567Sbill 
4424c0d4567Sbill 			case '\n':
4434c0d4567Sbill 				ERROR(36);
4444c0d4567Sbill 
4454c0d4567Sbill 			case 'n':
4464c0d4567Sbill 				c = '\n';
4474c0d4567Sbill 				goto defchar;
4484c0d4567Sbill 
4494c0d4567Sbill 			default:
4504c0d4567Sbill 				if(c >= '1' && c <= '9') {
4514c0d4567Sbill 					if((c -= '1') >= closed)
4524c0d4567Sbill 						ERROR(25);
4534c0d4567Sbill 					*ep++ = CBACK;
4544c0d4567Sbill 					*ep++ = c;
4554c0d4567Sbill 					continue;
4564c0d4567Sbill 				}
4574c0d4567Sbill 			}
4584c0d4567Sbill 			/* Drop through to default to use \ to turn off special chars */
4594c0d4567Sbill 
4604c0d4567Sbill 		defchar:
4614c0d4567Sbill 		default:
4624c0d4567Sbill 			lastep = ep;
4634c0d4567Sbill 			*ep++ = CCHR;
4644c0d4567Sbill 			*ep++ = c;
4654c0d4567Sbill 		}
4664c0d4567Sbill 	}
4674c0d4567Sbill }
4684c0d4567Sbill 
4694c0d4567Sbill step(p1, p2)
4704c0d4567Sbill register char *p1, *p2;
4714c0d4567Sbill {
4724c0d4567Sbill 	register c;
4734c0d4567Sbill 
4744c0d4567Sbill 	if (circf) {
4754c0d4567Sbill 		loc1 = p1;
4764c0d4567Sbill 		return(advance(p1, p2));
4774c0d4567Sbill 	}
4784c0d4567Sbill 	/* fast check for first character */
4794c0d4567Sbill 	if (*p2==CCHR) {
4804c0d4567Sbill 		c = p2[1];
4814c0d4567Sbill 		do {
4824c0d4567Sbill 			if (*p1 != c)
4834c0d4567Sbill 				continue;
4844c0d4567Sbill 			if (advance(p1, p2)) {
4854c0d4567Sbill 				loc1 = p1;
4864c0d4567Sbill 				return(1);
4874c0d4567Sbill 			}
4884c0d4567Sbill 		} while (*p1++);
4894c0d4567Sbill 		return(0);
4904c0d4567Sbill 	}
4914c0d4567Sbill 		/* regular algorithm */
4924c0d4567Sbill 	do {
4934c0d4567Sbill 		if (advance(p1, p2)) {
4944c0d4567Sbill 			loc1 = p1;
4954c0d4567Sbill 			return(1);
4964c0d4567Sbill 		}
4974c0d4567Sbill 	} while (*p1++);
4984c0d4567Sbill 	return(0);
4994c0d4567Sbill }
5004c0d4567Sbill 
5014c0d4567Sbill advance(lp, ep)
5024c0d4567Sbill register char *lp, *ep;
5034c0d4567Sbill {
5044c0d4567Sbill 	register char *curlp;
5054c0d4567Sbill 	char c;
5064c0d4567Sbill 	char *bbeg;
5074c0d4567Sbill 	int ct;
5084c0d4567Sbill 
5094c0d4567Sbill 	for (;;) switch (*ep++) {
5104c0d4567Sbill 
5114c0d4567Sbill 	case CCHR:
5124c0d4567Sbill 		if (*ep++ == *lp++)
5134c0d4567Sbill 			continue;
5144c0d4567Sbill 		return(0);
5154c0d4567Sbill 
5164c0d4567Sbill 	case CDOT:
5174c0d4567Sbill 		if (*lp++)
5184c0d4567Sbill 			continue;
5194c0d4567Sbill 		return(0);
5204c0d4567Sbill 
5214c0d4567Sbill 	case CDOL:
5224c0d4567Sbill 		if (*lp==0)
5234c0d4567Sbill 			continue;
5244c0d4567Sbill 		return(0);
5254c0d4567Sbill 
5264c0d4567Sbill 	case CEOF:
5274c0d4567Sbill 		loc2 = lp;
5284c0d4567Sbill 		return(1);
5294c0d4567Sbill 
5304c0d4567Sbill 	case CCL:
5314c0d4567Sbill 		c = *lp++ & 0177;
5324c0d4567Sbill 		if(ISTHERE(c)) {
5334c0d4567Sbill 			ep += 16;
5344c0d4567Sbill 			continue;
5354c0d4567Sbill 		}
5364c0d4567Sbill 		return(0);
5374c0d4567Sbill 	case CBRA:
5384c0d4567Sbill 		braslist[*ep++] = lp;
5394c0d4567Sbill 		continue;
5404c0d4567Sbill 
5414c0d4567Sbill 	case CKET:
5424c0d4567Sbill 		braelist[*ep++] = lp;
5434c0d4567Sbill 		continue;
5444c0d4567Sbill 
5454c0d4567Sbill 	case CCHR|RNGE:
5464c0d4567Sbill 		c = *ep++;
5474c0d4567Sbill 		getrnge(ep);
5484c0d4567Sbill 		while(low--)
5494c0d4567Sbill 			if(*lp++ != c)
5504c0d4567Sbill 				return(0);
5514c0d4567Sbill 		curlp = lp;
5524c0d4567Sbill 		while(size--)
5534c0d4567Sbill 			if(*lp++ != c)
5544c0d4567Sbill 				break;
5554c0d4567Sbill 		if(size < 0)
5564c0d4567Sbill 			lp++;
5574c0d4567Sbill 		ep += 2;
5584c0d4567Sbill 		goto star;
5594c0d4567Sbill 
5604c0d4567Sbill 	case CDOT|RNGE:
5614c0d4567Sbill 		getrnge(ep);
5624c0d4567Sbill 		while(low--)
5634c0d4567Sbill 			if(*lp++ == '\0')
5644c0d4567Sbill 				return(0);
5654c0d4567Sbill 		curlp = lp;
5664c0d4567Sbill 		while(size--)
5674c0d4567Sbill 			if(*lp++ == '\0')
5684c0d4567Sbill 				break;
5694c0d4567Sbill 		if(size < 0)
5704c0d4567Sbill 			lp++;
5714c0d4567Sbill 		ep += 2;
5724c0d4567Sbill 		goto star;
5734c0d4567Sbill 
5744c0d4567Sbill 	case CCL|RNGE:
5754c0d4567Sbill 		getrnge(ep + 16);
5764c0d4567Sbill 		while(low--) {
5774c0d4567Sbill 			c = *lp++ & 0177;
5784c0d4567Sbill 			if(!ISTHERE(c))
5794c0d4567Sbill 				return(0);
5804c0d4567Sbill 		}
5814c0d4567Sbill 		curlp = lp;
5824c0d4567Sbill 		while(size--) {
5834c0d4567Sbill 			c = *lp++ & 0177;
5844c0d4567Sbill 			if(!ISTHERE(c))
5854c0d4567Sbill 				break;
5864c0d4567Sbill 		}
5874c0d4567Sbill 		if(size < 0)
5884c0d4567Sbill 			lp++;
5894c0d4567Sbill 		ep += 18;		/* 16 + 2 */
5904c0d4567Sbill 		goto star;
5914c0d4567Sbill 
5924c0d4567Sbill 	case CBACK:
5934c0d4567Sbill 		bbeg = braslist[*ep];
5944c0d4567Sbill 		ct = braelist[*ep++] - bbeg;
5954c0d4567Sbill 
5964c0d4567Sbill 		if(ecmp(bbeg, lp, ct)) {
5974c0d4567Sbill 			lp += ct;
5984c0d4567Sbill 			continue;
5994c0d4567Sbill 		}
6004c0d4567Sbill 		return(0);
6014c0d4567Sbill 
6024c0d4567Sbill 	case CBACK|STAR:
6034c0d4567Sbill 		bbeg = braslist[*ep];
6044c0d4567Sbill 		ct = braelist[*ep++] - bbeg;
6054c0d4567Sbill 		curlp = lp;
6064c0d4567Sbill 		while(ecmp(bbeg, lp, ct))
6074c0d4567Sbill 			lp += ct;
6084c0d4567Sbill 
6094c0d4567Sbill 		while(lp >= curlp) {
6104c0d4567Sbill 			if(advance(lp, ep))	return(1);
6114c0d4567Sbill 			lp -= ct;
6124c0d4567Sbill 		}
6134c0d4567Sbill 		return(0);
6144c0d4567Sbill 
6154c0d4567Sbill 
6164c0d4567Sbill 	case CDOT|STAR:
6174c0d4567Sbill 		curlp = lp;
6184c0d4567Sbill 		while (*lp++);
6194c0d4567Sbill 		goto star;
6204c0d4567Sbill 
6214c0d4567Sbill 	case CCHR|STAR:
6224c0d4567Sbill 		curlp = lp;
6234c0d4567Sbill 		while (*lp++ == *ep);
6244c0d4567Sbill 		ep++;
6254c0d4567Sbill 		goto star;
6264c0d4567Sbill 
6274c0d4567Sbill 	case CCL|STAR:
6284c0d4567Sbill 		curlp = lp;
6294c0d4567Sbill 		do {
6304c0d4567Sbill 			c = *lp++ & 0177;
6314c0d4567Sbill 		} while(ISTHERE(c));
6324c0d4567Sbill 		ep += 16;
6334c0d4567Sbill 		goto star;
6344c0d4567Sbill 
6354c0d4567Sbill 	star:
6364c0d4567Sbill 		do {
6374c0d4567Sbill 			if(--lp == locs)
6384c0d4567Sbill 				break;
6394c0d4567Sbill 			if (advance(lp, ep))
6404c0d4567Sbill 				return(1);
6414c0d4567Sbill 		} while (lp > curlp);
6424c0d4567Sbill 		return(0);
6434c0d4567Sbill 
6444c0d4567Sbill 	}
6454c0d4567Sbill }
6464c0d4567Sbill 
6474c0d4567Sbill getrnge(str)
6484c0d4567Sbill register char *str;
6494c0d4567Sbill {
6504c0d4567Sbill 	low = *str++ & 0377;
651*d0e3910bSbostic 	size = (*str & 0377) == 255 ? 20000 : (*str & 0377) - low;
6524c0d4567Sbill }
6534c0d4567Sbill 
6544c0d4567Sbill ecmp(a, b, count)
6554c0d4567Sbill register char	*a, *b;
6564c0d4567Sbill register	count;
6574c0d4567Sbill {
6584c0d4567Sbill 	if(a == b) /* should have been caught in compile() */
6594c0d4567Sbill 		error(51);
6604c0d4567Sbill 	while(count--)
6614c0d4567Sbill 		if(*a++ != *b++)	return(0);
6624c0d4567Sbill 	return(1);
6634c0d4567Sbill }
6644c0d4567Sbill 
665*d0e3910bSbostic static char *sccsid = "@(#)expr.y	4.7 (Berkeley) 04/24/88";
6664c0d4567Sbill yyerror(s)
6674c0d4567Sbill 
6684c0d4567Sbill {
6694c0d4567Sbill 	fprintf(stderr, "%s\n", s);
6704c0d4567Sbill 	exit(2);
6714c0d4567Sbill }
672