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