%{ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ %} /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ %{ #pragma ident "%Z%%M% %I% %E% SMI" %} /* Yacc productions for "expr" command: */ %{ typedef char *yystype; #define YYSTYPE yystype %} %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH /* operators listed below in increasing precedence: */ %left OR %left AND %left EQ LT GT GEQ LEQ NEQ %left ADD SUBT %left MULT DIV REM %left MCH %left MATCH %left SUBSTR %left LENGTH INDEX %% /* a single `expression' is evaluated and printed: */ expression: expr NOARG = { printf("%s\n", $1); exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0); } ; expr: '(' expr ')' = { $$ = $2; } | expr OR expr = { $$ = conj(OR, $1, $3); } | expr AND expr = { $$ = conj(AND, $1, $3); } | expr EQ expr = { $$ = rel(EQ, $1, $3); } | expr GT expr = { $$ = rel(GT, $1, $3); } | expr GEQ expr = { $$ = rel(GEQ, $1, $3); } | expr LT expr = { $$ = rel(LT, $1, $3); } | expr LEQ expr = { $$ = rel(LEQ, $1, $3); } | expr NEQ expr = { $$ = rel(NEQ, $1, $3); } | expr ADD expr = { $$ = arith(ADD, $1, $3); } | expr SUBT expr = { $$ = arith(SUBT, $1, $3); } | expr MULT expr = { $$ = arith(MULT, $1, $3); } | expr DIV expr = { $$ = arith(DIV, $1, $3); } | expr REM expr = { $$ = arith(REM, $1, $3); } | expr MCH expr = { $$ = match($1, $3); } | MATCH expr expr = { $$ = match($2, $3); } | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); } | LENGTH expr = { $$ = length($2); } | INDEX expr expr = { $$ = index($2, $3); } | A_STRING ; %% #define ESIZE 256 #define EQL(x,y) !strcmp(x,y) #define INIT char *sp = instring; #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) return(c) #define ERROR(c) errxx(c) #include #include #include char **Av; int Ac; int Argi; char *ltoa(long l); char Mstring[1][128]; char *operator[] = { "|", "&", "+", "-", "*", "/", "%", ":", "=", "==", "<", "<=", ">", ">=", "!=", "match", "substr", "length", "index", "\0" }; int op[] = { OR, AND, ADD, SUBT, MULT, DIV, REM, MCH, EQ, EQ, LT, LEQ, GT, GEQ, NEQ, MATCH, SUBSTR, LENGTH, INDEX }; int yylex(void) { char *p; int i; if(Argi >= Ac) return NOARG; p = Av[Argi++]; if((*p == '(' || *p == ')') && p[1] == '\0' ) return (int)*p; for(i = 0; *operator[i]; ++i) if(EQL(operator[i], p)) return op[i]; yylval = p; return A_STRING; } char * rel(int oper, char *r1, char *r2) { long i; if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")) i = atol(r1) - atol(r2); else i = strcmp(r1, r2); switch(oper) { case EQ: i = i==0; break; case GT: i = i>0; break; case GEQ: i = i>=0; break; case LT: i = i<0; break; case LEQ: i = i<=0; break; case NEQ: i = i!=0; break; } return i? "1": "0"; } char *arith(oper, r1, r2) char *r1, *r2; { long i1, i2; char *rv; if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))) yyerror("non-numeric argument"); i1 = atol(r1); i2 = atol(r2); switch(oper) { case ADD: i1 = i1 + i2; break; case SUBT: i1 = i1 - i2; break; case MULT: i1 = i1 * i2; break; case DIV: if (i2 == 0) yyerror("division by zero"); i1 = i1 / i2; break; case REM: if (i2 == 0) yyerror("division by zero"); i1 = i1 % i2; break; } rv = malloc(16); (void) strcpy(rv, ltoa(i1)); return rv; } char *conj(oper, r1, r2) char *r1, *r2; { char *rv; switch(oper) { case OR: if(EQL(r1, "0") || EQL(r1, "")) if(EQL(r2, "0") || EQL(r2, "")) rv = "0"; else rv = r2; else rv = r1; break; case AND: if(EQL(r1, "0") || EQL(r1, "")) rv = "0"; else if(EQL(r2, "0") || EQL(r2, "")) rv = "0"; else rv = r1; break; } return rv; } char * substr(char *v, char *s, char *w) { int si, wi; char *res; si = atol(s); wi = atol(w); while(--si) if(*v) ++v; res = v; while(wi--) if(*v) ++v; *v = '\0'; return res; } char * index(char *s, char *t) { long i, j; char *rv; for(i = 0; s[i] ; ++i) for(j = 0; t[j] ; ++j) if(s[i]==t[j]) { (void) strcpy(rv = malloc(8), ltoa(++i)); return rv; } return "0"; } char * length(char *s) { long i = 0; char *rv; while(*s++) ++i; rv = malloc(8); (void) strcpy(rv, ltoa(i)); return rv; } char * match(char *s, char *p) { char *rv; (void) strcpy(rv=malloc(8), ltoa((long)ematch(s, p))); if(nbra) { rv = malloc((unsigned) strlen(Mstring[0]) + 1); (void) strcpy(rv, Mstring[0]); } return rv; } int ematch(char *s, char *p) { static char expbuf[ESIZE]; char *compile(); int num; extern char *braslist[], *braelist[], *loc2; compile(p, expbuf, &expbuf[ESIZE], 0); if(nbra > 1) yyerror("Too many '\\('s"); if(advance(s, expbuf)) { if(nbra == 1) { p = braslist[0]; num = braelist[0] - p; if ((num > 127) || (num < 0)) yyerror("Paren problem"); (void) strncpy(Mstring[0], p, num); Mstring[0][num] = '\0'; } return(loc2-s); } return(0); } int errxx(int err) { char *message; switch(err) { case 11: message = "Range endpoint too large"; break; case 16: message = "Bad number"; break; case 25: message = "``\\digit'' out of range"; break; case 36: message = "Illegal or missing delimiter"; break; case 41: message = "No remembered search string"; break; case 42: message = "\\( \\) imbalance"; break; case 43: message = "Too many \\("; break; case 44: message = "More than 2 numbers given in \\{ \\}"; break; case 45: message = "} expected after \\"; break; case 46: message = "First number exceeds second in \\{ \\}"; break; case 49: message = "[ ] imbalance"; break; case 50: message = "Regular expression too long"; break; default: message = "Unknown regexp error code!!"; break; } yyerror(message); /* NOTREACHED */ return (0); } int yyerror(char *s) { (void) write(2, "expr: ", 6); (void) write(2, s, (unsigned) strlen(s)); (void) write(2, "\n", 1); exit(2); /* NOTREACHED */ return (0); } char * ltoa(long l) { static char str[20]; char *sp; int i; int neg; if(l == 0x80000000L) return "-2147483648"; neg = 0; if(l < 0) ++neg, l = -l; sp = &str[20]; *--sp = '\0'; do { i = l % 10; *--sp = '0' + i; l /= 10; } while(l); if(neg) *--sp = '-'; return sp; } int main(int argc, char **argv) { Ac = argc; Argi = 1; Av = argv; yyparse(); return (0); }