Home | History | Annotate | Download | only in expr
      1 %{
      2 /*
      3  * CDDL HEADER START
      4  *
      5  * The contents of this file are subject to the terms of the
      6  * Common Development and Distribution License, Version 1.0 only
      7  * (the "License").  You may not use this file except in compliance
      8  * with the License.
      9  *
     10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     11  * or http://www.opensolaris.org/os/licensing.
     12  * See the License for the specific language governing permissions
     13  * and limitations under the License.
     14  *
     15  * When distributing Covered Code, include this CDDL HEADER in each
     16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     17  * If applicable, add the following below this CDDL HEADER, with the
     18  * fields enclosed by brackets "[]" replaced with your own identifying
     19  * information: Portions Copyright [yyyy] [name of copyright owner]
     20  *
     21  * CDDL HEADER END
     22  */
     23 %}
     24 /*
     25  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     26  * Use is subject to license terms.
     27  */
     28 
     29 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     30 /*	  All Rights Reserved	*/
     31 
     32 %{
     33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     34 %}
     35 
     36 /* Yacc productions for "expr" command: */
     37 
     38 %{
     39 typedef	char *yystype;
     40 #define	YYSTYPE	yystype
     41 %}
     42 
     43 %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
     44 %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
     45 
     46 /* operators listed below in increasing precedence: */
     47 %left OR
     48 %left AND
     49 %left EQ LT GT GEQ LEQ NEQ
     50 %left ADD SUBT
     51 %left MULT DIV REM
     52 %left MCH
     53 %left MATCH
     54 %left SUBSTR
     55 %left LENGTH INDEX
     56 %%
     57 
     58 /* a single `expression' is evaluated and printed: */
     59 
     60 expression:	expr NOARG = {
     61 			printf("%s\n", $1);
     62 			exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
     63 			}
     64 	;
     65 
     66 
     67 expr:	'(' expr ')' = { $$ = $2; }
     68 	| expr OR expr   = { $$ = conj(OR, $1, $3); }
     69 	| expr AND expr   = { $$ = conj(AND, $1, $3); }
     70 	| expr EQ expr   = { $$ = rel(EQ, $1, $3); }
     71 	| expr GT expr   = { $$ = rel(GT, $1, $3); }
     72 	| expr GEQ expr   = { $$ = rel(GEQ, $1, $3); }
     73 	| expr LT expr   = { $$ = rel(LT, $1, $3); }
     74 	| expr LEQ expr   = { $$ = rel(LEQ, $1, $3); }
     75 	| expr NEQ expr   = { $$ = rel(NEQ, $1, $3); }
     76 	| expr ADD expr   = { $$ = arith(ADD, $1, $3); }
     77 	| expr SUBT expr   = { $$ = arith(SUBT, $1, $3); }
     78 	| expr MULT expr   = { $$ = arith(MULT, $1, $3); }
     79 	| expr DIV expr   = { $$ = arith(DIV, $1, $3); }
     80 	| expr REM expr   = { $$ = arith(REM, $1, $3); }
     81 	| expr MCH expr	 = { $$ = match($1, $3); }
     82 	| MATCH expr expr = { $$ = match($2, $3); }
     83 	| SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
     84 	| LENGTH expr       = { $$ = length($2); }
     85 	| INDEX expr expr = { $$ = index($2, $3); }
     86 	| A_STRING
     87 	;
     88 %%
     89 
     90 #define ESIZE	256
     91 #define EQL(x,y) !strcmp(x,y)
     92 
     93 #define INIT	char *sp = instring;
     94 #define GETC()		(*sp++)
     95 #define PEEKC()		(*sp)
     96 #define UNGETC(c)	(--sp)
     97 #define RETURN(c)	return(c)
     98 #define ERROR(c)	errxx(c)
     99 #include  <regexp.h>
    100 #include  <malloc.h>
    101 #include  <stdlib.h>
    102 
    103 char	**Av;
    104 int	Ac;
    105 int	Argi;
    106 
    107 char *ltoa(long l);
    108 
    109 char Mstring[1][128];
    110 
    111 
    112 char *operator[] = {
    113 	"|", "&", "+", "-", "*", "/", "%", ":",
    114 	"=", "==", "<", "<=", ">", ">=", "!=",
    115 	"match", "substr", "length", "index", "\0" };
    116 int op[] = {
    117 	OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
    118 	EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
    119 	MATCH, SUBSTR, LENGTH, INDEX };
    120 int
    121 yylex(void)
    122 {
    123 	char *p;
    124 	int i;
    125 
    126 	if(Argi >= Ac) return NOARG;
    127 
    128 	p = Av[Argi++];
    129 
    130 	if((*p == '(' || *p == ')') && p[1] == '\0' )
    131 		return (int)*p;
    132 	for(i = 0; *operator[i]; ++i)
    133 		if(EQL(operator[i], p))
    134 			return op[i];
    135 
    136 	yylval = p;
    137 	return A_STRING;
    138 }
    139 
    140 char *
    141 rel(int oper, char *r1, char *r2)
    142 {
    143 	long i;
    144 
    145 	if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
    146 		i = atol(r1) - atol(r2);
    147 	else
    148 		i = strcmp(r1, r2);
    149 	switch(oper) {
    150 	case EQ:
    151 		i = i==0;
    152 		break;
    153 	case GT:
    154 		i = i>0;
    155 		break;
    156 	case GEQ:
    157 		i = i>=0;
    158 		break;
    159 	case LT:
    160 		i = i<0;
    161 		break;
    162 	case LEQ:
    163 		i = i<=0;
    164 		break;
    165 	case NEQ:
    166 		i = i!=0;
    167 		break;
    168 	}
    169 	return i? "1": "0";
    170 }
    171 
    172 char *arith(oper, r1, r2) char *r1, *r2;
    173 {
    174 	long i1, i2;
    175 	char *rv;
    176 
    177 	if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
    178 		yyerror("non-numeric argument");
    179 	i1 = atol(r1);
    180 	i2 = atol(r2);
    181 
    182 	switch(oper) {
    183 	case ADD:
    184 		i1 = i1 + i2;
    185 		break;
    186 	case SUBT:
    187 		i1 = i1 - i2;
    188 		break;
    189 	case MULT:
    190 		i1 = i1 * i2;
    191 		break;
    192 	case DIV:
    193 		if (i2 == 0)
    194 			yyerror("division by zero");
    195 		i1 = i1 / i2;
    196 		break;
    197 	case REM:
    198 		if (i2 == 0)
    199 			yyerror("division by zero");
    200 		i1 = i1 % i2;
    201 		break;
    202 	}
    203 	rv = malloc(16);
    204 	(void) strcpy(rv, ltoa(i1));
    205 	return rv;
    206 }
    207 char *conj(oper, r1, r2) char *r1, *r2;
    208 {
    209 	char *rv;
    210 
    211 	switch(oper) {
    212 
    213 	case OR:
    214 		if(EQL(r1, "0")
    215 		    || EQL(r1, ""))
    216 			if(EQL(r2, "0")
    217 			    || EQL(r2, ""))
    218 				rv = "0";
    219 			else
    220 				rv = r2;
    221 		else
    222 			rv = r1;
    223 		break;
    224 	case AND:
    225 		if(EQL(r1, "0")
    226 		    || EQL(r1, ""))
    227 			rv = "0";
    228 		else if(EQL(r2, "0")
    229 		    || EQL(r2, ""))
    230 			rv = "0";
    231 		else
    232 			rv = r1;
    233 		break;
    234 	}
    235 	return rv;
    236 }
    237 
    238 char *
    239 substr(char *v, char *s, char *w)
    240 {
    241 	int si, wi;
    242 	char *res;
    243 
    244 	si = atol(s);
    245 	wi = atol(w);
    246 	while(--si) if(*v) ++v;
    247 
    248 	res = v;
    249 
    250 	while(wi--) if(*v) ++v;
    251 
    252 	*v = '\0';
    253 	return res;
    254 }
    255 
    256 char *
    257 index(char *s, char *t)
    258 {
    259 	long i, j;
    260 	char *rv;
    261 
    262 	for(i = 0; s[i] ; ++i)
    263 		for(j = 0; t[j] ; ++j)
    264 			if(s[i]==t[j]) {
    265 				(void) strcpy(rv = malloc(8), ltoa(++i));
    266 				return rv;
    267 			}
    268 	return "0";
    269 }
    270 
    271 char *
    272 length(char *s)
    273 {
    274 	long i = 0;
    275 	char *rv;
    276 
    277 	while(*s++) ++i;
    278 
    279 	rv = malloc(8);
    280 	(void) strcpy(rv, ltoa(i));
    281 	return rv;
    282 }
    283 
    284 char *
    285 match(char *s, char *p)
    286 {
    287 	char *rv;
    288 
    289 	(void) strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
    290 	if(nbra) {
    291 		rv = malloc((unsigned) strlen(Mstring[0]) + 1);
    292 		(void) strcpy(rv, Mstring[0]);
    293 	}
    294 	return rv;
    295 }
    296 
    297 int
    298 ematch(char *s, char *p)
    299 {
    300 	static char expbuf[ESIZE];
    301 	char *compile();
    302 	int num;
    303 	extern char *braslist[], *braelist[], *loc2;
    304 
    305 	compile(p, expbuf, &expbuf[ESIZE], 0);
    306 	if(nbra > 1)
    307 		yyerror("Too many '\\('s");
    308 	if(advance(s, expbuf)) {
    309 		if(nbra == 1) {
    310 			p = braslist[0];
    311 			num = braelist[0] - p;
    312 			if ((num > 127) || (num < 0)) yyerror("Paren problem");
    313 			(void) strncpy(Mstring[0], p, num);
    314 			Mstring[0][num] = '\0';
    315 		}
    316 		return(loc2-s);
    317 	}
    318 	return(0);
    319 }
    320 
    321 int
    322 errxx(int err)
    323 {
    324 	char *message;
    325 
    326 	switch(err) {
    327 		case 11:
    328 			message = "Range endpoint too large";
    329 			break;
    330 		case 16:
    331 			message = "Bad number";
    332 			break;
    333 		case 25:
    334 			message = "``\\digit'' out of range";
    335 			break;
    336 		case 36:
    337 			message = "Illegal or missing delimiter";
    338 			break;
    339 		case 41:
    340 			message = "No remembered search string";
    341 			break;
    342 		case 42:
    343 			message = "\\( \\) imbalance";
    344 			break;
    345 		case 43:
    346 			message = "Too many \\(";
    347 			break;
    348 		case 44:
    349 			message = "More than 2 numbers given in \\{ \\}";
    350 			break;
    351 		case 45:
    352 			message = "} expected after \\";
    353 			break;
    354 		case 46:
    355 			message = "First number exceeds second in \\{ \\}";
    356 			break;
    357 		case 49:
    358 			message = "[ ] imbalance";
    359 			break;
    360 		case 50:
    361 			message = "Regular expression too long";
    362 			break;
    363 		default:
    364 			message = "Unknown regexp error code!!";
    365 			break;
    366 	}
    367 	yyerror(message);
    368 	/* NOTREACHED */
    369 	return (0);
    370 }
    371 
    372 int
    373 yyerror(char *s)
    374 {
    375 	(void) write(2, "expr: ", 6);
    376 	(void) write(2, s, (unsigned) strlen(s));
    377 	(void) write(2, "\n", 1);
    378 	exit(2);
    379 	/* NOTREACHED */
    380 	return (0);
    381 }
    382 
    383 char *
    384 ltoa(long l)
    385 {
    386 	static char str[20];
    387 	char *sp;
    388 	int i;
    389 	int neg;
    390 
    391 	if(l == 0x80000000L)
    392 		return "-2147483648";
    393 	neg = 0;
    394 	if(l < 0)
    395 		++neg, l = -l;
    396 	sp = &str[20];
    397 	*--sp = '\0';
    398 	do {
    399 		i = l % 10;
    400 		*--sp = '0' + i;
    401 		l /= 10;
    402 	}
    403 	while(l);
    404 	if(neg)
    405 		*--sp = '-';
    406 	return sp;
    407 }
    408 
    409 int
    410 main(int argc, char **argv)
    411 {
    412 	Ac = argc;
    413 	Argi = 1;
    414 	Av = argv;
    415 	yyparse();
    416 	return (0);
    417 }
    418