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