xref: /onnv-gate/usr/src/ucbcmd/expr/expr.y (revision 523:4aeaed772941)
10Sstevel@tonic-gate %{
20Sstevel@tonic-gate /*
30Sstevel@tonic-gate  * CDDL HEADER START
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
60Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
70Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
80Sstevel@tonic-gate  * with the License.
90Sstevel@tonic-gate  *
100Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
110Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
120Sstevel@tonic-gate  * See the License for the specific language governing permissions
130Sstevel@tonic-gate  * and limitations under the License.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
160Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
170Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
180Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
190Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
200Sstevel@tonic-gate  *
210Sstevel@tonic-gate  * CDDL HEADER END
220Sstevel@tonic-gate  */
230Sstevel@tonic-gate %}
24*523Sbasabi /*
25*523Sbasabi  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26*523Sbasabi  * Use is subject to license terms.
27*523Sbasabi  */
28*523Sbasabi 
290Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
300Sstevel@tonic-gate /*	  All Rights Reserved	*/
310Sstevel@tonic-gate 
320Sstevel@tonic-gate %{
330Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
340Sstevel@tonic-gate %}
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /* Yacc productions for "expr" command: */
370Sstevel@tonic-gate 
380Sstevel@tonic-gate %{
390Sstevel@tonic-gate typedef	char *yystype;
400Sstevel@tonic-gate #define	YYSTYPE	yystype
410Sstevel@tonic-gate %}
420Sstevel@tonic-gate 
430Sstevel@tonic-gate %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
440Sstevel@tonic-gate %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /* operators listed below in increasing precedence: */
470Sstevel@tonic-gate %left OR
480Sstevel@tonic-gate %left AND
490Sstevel@tonic-gate %left EQ LT GT GEQ LEQ NEQ
500Sstevel@tonic-gate %left ADD SUBT
510Sstevel@tonic-gate %left MULT DIV REM
520Sstevel@tonic-gate %left MCH
530Sstevel@tonic-gate %left MATCH
540Sstevel@tonic-gate %left SUBSTR
550Sstevel@tonic-gate %left LENGTH INDEX
560Sstevel@tonic-gate %%
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /* a single `expression' is evaluated and printed: */
590Sstevel@tonic-gate 
600Sstevel@tonic-gate expression:	expr NOARG = {
610Sstevel@tonic-gate 			printf("%s\n", $1);
620Sstevel@tonic-gate 			exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
630Sstevel@tonic-gate 			}
640Sstevel@tonic-gate 	;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 
670Sstevel@tonic-gate expr:	'(' expr ')' = { $$ = $2; }
680Sstevel@tonic-gate 	| expr OR expr   = { $$ = conj(OR, $1, $3); }
690Sstevel@tonic-gate 	| expr AND expr   = { $$ = conj(AND, $1, $3); }
700Sstevel@tonic-gate 	| expr EQ expr   = { $$ = rel(EQ, $1, $3); }
710Sstevel@tonic-gate 	| expr GT expr   = { $$ = rel(GT, $1, $3); }
720Sstevel@tonic-gate 	| expr GEQ expr   = { $$ = rel(GEQ, $1, $3); }
730Sstevel@tonic-gate 	| expr LT expr   = { $$ = rel(LT, $1, $3); }
740Sstevel@tonic-gate 	| expr LEQ expr   = { $$ = rel(LEQ, $1, $3); }
750Sstevel@tonic-gate 	| expr NEQ expr   = { $$ = rel(NEQ, $1, $3); }
760Sstevel@tonic-gate 	| expr ADD expr   = { $$ = arith(ADD, $1, $3); }
770Sstevel@tonic-gate 	| expr SUBT expr   = { $$ = arith(SUBT, $1, $3); }
780Sstevel@tonic-gate 	| expr MULT expr   = { $$ = arith(MULT, $1, $3); }
790Sstevel@tonic-gate 	| expr DIV expr   = { $$ = arith(DIV, $1, $3); }
800Sstevel@tonic-gate 	| expr REM expr   = { $$ = arith(REM, $1, $3); }
810Sstevel@tonic-gate 	| expr MCH expr	 = { $$ = match($1, $3); }
820Sstevel@tonic-gate 	| MATCH expr expr = { $$ = match($2, $3); }
830Sstevel@tonic-gate 	| SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
840Sstevel@tonic-gate 	| LENGTH expr       = { $$ = length($2); }
850Sstevel@tonic-gate 	| INDEX expr expr = { $$ = index($2, $3); }
860Sstevel@tonic-gate 	| A_STRING
870Sstevel@tonic-gate 	;
880Sstevel@tonic-gate %%
890Sstevel@tonic-gate 
900Sstevel@tonic-gate #define ESIZE	256
910Sstevel@tonic-gate #define EQL(x,y) !strcmp(x,y)
920Sstevel@tonic-gate 
93*523Sbasabi #define INIT	char *sp = instring;
940Sstevel@tonic-gate #define GETC()		(*sp++)
950Sstevel@tonic-gate #define PEEKC()		(*sp)
960Sstevel@tonic-gate #define UNGETC(c)	(--sp)
97*523Sbasabi #define RETURN(c)	return(c)
980Sstevel@tonic-gate #define ERROR(c)	errxx(c)
990Sstevel@tonic-gate #include  <regexp.h>
1000Sstevel@tonic-gate #include  <malloc.h>
101*523Sbasabi #include  <stdlib.h>
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate char	**Av;
1040Sstevel@tonic-gate int	Ac;
1050Sstevel@tonic-gate int	Argi;
1060Sstevel@tonic-gate 
107*523Sbasabi char *ltoa(long l);
108*523Sbasabi 
1090Sstevel@tonic-gate char Mstring[1][128];
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate char *operator[] = {
1130Sstevel@tonic-gate 	"|", "&", "+", "-", "*", "/", "%", ":",
1140Sstevel@tonic-gate 	"=", "==", "<", "<=", ">", ">=", "!=",
1150Sstevel@tonic-gate 	"match", "substr", "length", "index", "\0" };
1160Sstevel@tonic-gate int op[] = {
1170Sstevel@tonic-gate 	OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
1180Sstevel@tonic-gate 	EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
1190Sstevel@tonic-gate 	MATCH, SUBSTR, LENGTH, INDEX };
120*523Sbasabi int
yylex(void)121*523Sbasabi yylex(void)
122*523Sbasabi {
123*523Sbasabi 	char *p;
124*523Sbasabi 	int i;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	if(Argi >= Ac) return NOARG;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	p = Av[Argi++];
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if((*p == '(' || *p == ')') && p[1] == '\0' )
1310Sstevel@tonic-gate 		return (int)*p;
1320Sstevel@tonic-gate 	for(i = 0; *operator[i]; ++i)
1330Sstevel@tonic-gate 		if(EQL(operator[i], p))
1340Sstevel@tonic-gate 			return op[i];
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	yylval = p;
1370Sstevel@tonic-gate 	return A_STRING;
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
140*523Sbasabi char *
rel(int oper,char * r1,char * r2)141*523Sbasabi rel(int oper, char *r1, char *r2)
1420Sstevel@tonic-gate {
143*523Sbasabi 	long i;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
1460Sstevel@tonic-gate 		i = atol(r1) - atol(r2);
1470Sstevel@tonic-gate 	else
1480Sstevel@tonic-gate 		i = strcmp(r1, r2);
1490Sstevel@tonic-gate 	switch(oper) {
1500Sstevel@tonic-gate 	case EQ:
1510Sstevel@tonic-gate 		i = i==0;
1520Sstevel@tonic-gate 		break;
1530Sstevel@tonic-gate 	case GT:
1540Sstevel@tonic-gate 		i = i>0;
1550Sstevel@tonic-gate 		break;
1560Sstevel@tonic-gate 	case GEQ:
1570Sstevel@tonic-gate 		i = i>=0;
1580Sstevel@tonic-gate 		break;
1590Sstevel@tonic-gate 	case LT:
1600Sstevel@tonic-gate 		i = i<0;
1610Sstevel@tonic-gate 		break;
1620Sstevel@tonic-gate 	case LEQ:
1630Sstevel@tonic-gate 		i = i<=0;
1640Sstevel@tonic-gate 		break;
1650Sstevel@tonic-gate 	case NEQ:
1660Sstevel@tonic-gate 		i = i!=0;
1670Sstevel@tonic-gate 		break;
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 	return i? "1": "0";
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
arith(oper,r1,r2)1720Sstevel@tonic-gate char *arith(oper, r1, r2) char *r1, *r2;
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate 	long i1, i2;
175*523Sbasabi 	char *rv;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
1780Sstevel@tonic-gate 		yyerror("non-numeric argument");
1790Sstevel@tonic-gate 	i1 = atol(r1);
1800Sstevel@tonic-gate 	i2 = atol(r2);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	switch(oper) {
1830Sstevel@tonic-gate 	case ADD:
1840Sstevel@tonic-gate 		i1 = i1 + i2;
1850Sstevel@tonic-gate 		break;
1860Sstevel@tonic-gate 	case SUBT:
1870Sstevel@tonic-gate 		i1 = i1 - i2;
1880Sstevel@tonic-gate 		break;
1890Sstevel@tonic-gate 	case MULT:
1900Sstevel@tonic-gate 		i1 = i1 * i2;
1910Sstevel@tonic-gate 		break;
1920Sstevel@tonic-gate 	case DIV:
1930Sstevel@tonic-gate 		if (i2 == 0)
1940Sstevel@tonic-gate 			yyerror("division by zero");
1950Sstevel@tonic-gate 		i1 = i1 / i2;
1960Sstevel@tonic-gate 		break;
1970Sstevel@tonic-gate 	case REM:
1980Sstevel@tonic-gate 		if (i2 == 0)
1990Sstevel@tonic-gate 			yyerror("division by zero");
2000Sstevel@tonic-gate 		i1 = i1 % i2;
2010Sstevel@tonic-gate 		break;
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 	rv = malloc(16);
2040Sstevel@tonic-gate 	(void) strcpy(rv, ltoa(i1));
2050Sstevel@tonic-gate 	return rv;
2060Sstevel@tonic-gate }
conj(oper,r1,r2)2070Sstevel@tonic-gate char *conj(oper, r1, r2) char *r1, *r2;
2080Sstevel@tonic-gate {
209*523Sbasabi 	char *rv;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	switch(oper) {
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	case OR:
2140Sstevel@tonic-gate 		if(EQL(r1, "0")
2150Sstevel@tonic-gate 		    || EQL(r1, ""))
2160Sstevel@tonic-gate 			if(EQL(r2, "0")
2170Sstevel@tonic-gate 			    || EQL(r2, ""))
2180Sstevel@tonic-gate 				rv = "0";
2190Sstevel@tonic-gate 			else
2200Sstevel@tonic-gate 				rv = r2;
2210Sstevel@tonic-gate 		else
2220Sstevel@tonic-gate 			rv = r1;
2230Sstevel@tonic-gate 		break;
2240Sstevel@tonic-gate 	case AND:
2250Sstevel@tonic-gate 		if(EQL(r1, "0")
2260Sstevel@tonic-gate 		    || EQL(r1, ""))
2270Sstevel@tonic-gate 			rv = "0";
2280Sstevel@tonic-gate 		else if(EQL(r2, "0")
2290Sstevel@tonic-gate 		    || EQL(r2, ""))
2300Sstevel@tonic-gate 			rv = "0";
2310Sstevel@tonic-gate 		else
2320Sstevel@tonic-gate 			rv = r1;
2330Sstevel@tonic-gate 		break;
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 	return rv;
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate 
238*523Sbasabi char *
substr(char * v,char * s,char * w)239*523Sbasabi substr(char *v, char *s, char *w)
240*523Sbasabi {
241*523Sbasabi 	int si, wi;
242*523Sbasabi 	char *res;
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	si = atol(s);
2450Sstevel@tonic-gate 	wi = atol(w);
2460Sstevel@tonic-gate 	while(--si) if(*v) ++v;
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	res = v;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	while(wi--) if(*v) ++v;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	*v = '\0';
2530Sstevel@tonic-gate 	return res;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate 
256*523Sbasabi char *
index(char * s,char * t)257*523Sbasabi index(char *s, char *t)
258*523Sbasabi {
259*523Sbasabi 	long i, j;
260*523Sbasabi 	char *rv;
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	for(i = 0; s[i] ; ++i)
2630Sstevel@tonic-gate 		for(j = 0; t[j] ; ++j)
2640Sstevel@tonic-gate 			if(s[i]==t[j]) {
2650Sstevel@tonic-gate 				(void) strcpy(rv = malloc(8), ltoa(++i));
2660Sstevel@tonic-gate 				return rv;
2670Sstevel@tonic-gate 			}
2680Sstevel@tonic-gate 	return "0";
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate 
271*523Sbasabi char *
length(char * s)272*523Sbasabi length(char *s)
273*523Sbasabi {
274*523Sbasabi 	long i = 0;
275*523Sbasabi 	char *rv;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	while(*s++) ++i;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	rv = malloc(8);
2800Sstevel@tonic-gate 	(void) strcpy(rv, ltoa(i));
2810Sstevel@tonic-gate 	return rv;
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
284*523Sbasabi char *
match(char * s,char * p)285*523Sbasabi match(char *s, char *p)
2860Sstevel@tonic-gate {
287*523Sbasabi 	char *rv;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	(void) strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
2900Sstevel@tonic-gate 	if(nbra) {
2910Sstevel@tonic-gate 		rv = malloc((unsigned) strlen(Mstring[0]) + 1);
2920Sstevel@tonic-gate 		(void) strcpy(rv, Mstring[0]);
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 	return rv;
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate 
297*523Sbasabi int
ematch(char * s,char * p)298*523Sbasabi ematch(char *s, char *p)
2990Sstevel@tonic-gate {
3000Sstevel@tonic-gate 	static char expbuf[ESIZE];
3010Sstevel@tonic-gate 	char *compile();
302*523Sbasabi 	int num;
3030Sstevel@tonic-gate 	extern char *braslist[], *braelist[], *loc2;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	compile(p, expbuf, &expbuf[ESIZE], 0);
3060Sstevel@tonic-gate 	if(nbra > 1)
3070Sstevel@tonic-gate 		yyerror("Too many '\\('s");
3080Sstevel@tonic-gate 	if(advance(s, expbuf)) {
3090Sstevel@tonic-gate 		if(nbra == 1) {
3100Sstevel@tonic-gate 			p = braslist[0];
3110Sstevel@tonic-gate 			num = braelist[0] - p;
3120Sstevel@tonic-gate 			if ((num > 127) || (num < 0)) yyerror("Paren problem");
3130Sstevel@tonic-gate 			(void) strncpy(Mstring[0], p, num);
3140Sstevel@tonic-gate 			Mstring[0][num] = '\0';
3150Sstevel@tonic-gate 		}
3160Sstevel@tonic-gate 		return(loc2-s);
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 	return(0);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
321*523Sbasabi int
errxx(int err)322*523Sbasabi errxx(int err)
3230Sstevel@tonic-gate {
324*523Sbasabi 	char *message;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	switch(err) {
3270Sstevel@tonic-gate 		case 11:
3280Sstevel@tonic-gate 			message = "Range endpoint too large";
3290Sstevel@tonic-gate 			break;
3300Sstevel@tonic-gate 		case 16:
3310Sstevel@tonic-gate 			message = "Bad number";
3320Sstevel@tonic-gate 			break;
3330Sstevel@tonic-gate 		case 25:
3340Sstevel@tonic-gate 			message = "``\\digit'' out of range";
3350Sstevel@tonic-gate 			break;
3360Sstevel@tonic-gate 		case 36:
3370Sstevel@tonic-gate 			message = "Illegal or missing delimiter";
3380Sstevel@tonic-gate 			break;
3390Sstevel@tonic-gate 		case 41:
3400Sstevel@tonic-gate 			message = "No remembered search string";
3410Sstevel@tonic-gate 			break;
3420Sstevel@tonic-gate 		case 42:
3430Sstevel@tonic-gate 			message = "\\( \\) imbalance";
3440Sstevel@tonic-gate 			break;
3450Sstevel@tonic-gate 		case 43:
3460Sstevel@tonic-gate 			message = "Too many \\(";
3470Sstevel@tonic-gate 			break;
3480Sstevel@tonic-gate 		case 44:
3490Sstevel@tonic-gate 			message = "More than 2 numbers given in \\{ \\}";
3500Sstevel@tonic-gate 			break;
3510Sstevel@tonic-gate 		case 45:
3520Sstevel@tonic-gate 			message = "} expected after \\";
3530Sstevel@tonic-gate 			break;
3540Sstevel@tonic-gate 		case 46:
3550Sstevel@tonic-gate 			message = "First number exceeds second in \\{ \\}";
3560Sstevel@tonic-gate 			break;
3570Sstevel@tonic-gate 		case 49:
3580Sstevel@tonic-gate 			message = "[ ] imbalance";
3590Sstevel@tonic-gate 			break;
3600Sstevel@tonic-gate 		case 50:
3610Sstevel@tonic-gate 			message = "Regular expression too long";
3620Sstevel@tonic-gate 			break;
3630Sstevel@tonic-gate 		default:
3640Sstevel@tonic-gate 			message = "Unknown regexp error code!!";
3650Sstevel@tonic-gate 			break;
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 	yyerror(message);
368*523Sbasabi 	/* NOTREACHED */
369*523Sbasabi 	return (0);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate 
372*523Sbasabi int
yyerror(char * s)373*523Sbasabi yyerror(char *s)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate 	(void) write(2, "expr: ", 6);
3760Sstevel@tonic-gate 	(void) write(2, s, (unsigned) strlen(s));
3770Sstevel@tonic-gate 	(void) write(2, "\n", 1);
3780Sstevel@tonic-gate 	exit(2);
379*523Sbasabi 	/* NOTREACHED */
380*523Sbasabi 	return (0);
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate 
383*523Sbasabi char *
ltoa(long l)384*523Sbasabi ltoa(long l)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate 	static char str[20];
387*523Sbasabi 	char *sp;
388*523Sbasabi 	int i;
389*523Sbasabi 	int neg;
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	if(l == 0x80000000L)
3920Sstevel@tonic-gate 		return "-2147483648";
3930Sstevel@tonic-gate 	neg = 0;
3940Sstevel@tonic-gate 	if(l < 0)
3950Sstevel@tonic-gate 		++neg, l = -l;
3960Sstevel@tonic-gate 	sp = &str[20];
3970Sstevel@tonic-gate 	*--sp = '\0';
3980Sstevel@tonic-gate 	do {
3990Sstevel@tonic-gate 		i = l % 10;
4000Sstevel@tonic-gate 		*--sp = '0' + i;
4010Sstevel@tonic-gate 		l /= 10;
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 	while(l);
4040Sstevel@tonic-gate 	if(neg)
4050Sstevel@tonic-gate 		*--sp = '-';
4060Sstevel@tonic-gate 	return sp;
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate 
409*523Sbasabi int
main(int argc,char ** argv)410*523Sbasabi main(int argc, char **argv)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate 	Ac = argc;
4130Sstevel@tonic-gate 	Argi = 1;
4140Sstevel@tonic-gate 	Av = argv;
4150Sstevel@tonic-gate 	yyparse();
416*523Sbasabi 	return (0);
4170Sstevel@tonic-gate }
418