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