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