1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * eval.c -- constraint evaluation module 27 * 28 * this module evaluates constraints. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <ctype.h> 36 #include <string.h> 37 #include "alloc.h" 38 #include "out.h" 39 #include "stable.h" 40 #include "literals.h" 41 #include "lut.h" 42 #include "tree.h" 43 #include "ptree.h" 44 #include "itree.h" 45 #include "eval.h" 46 #include "config.h" 47 #include "platform.h" 48 49 50 static struct node *eval_dup(struct node *np, struct lut *ex, 51 struct node *epnames[]); 52 53 /* 54 * begins_with -- return true if rhs path begins with everything in lhs path 55 */ 56 static int 57 begins_with(struct node *lhs, struct node *rhs) 58 { 59 int lnum; 60 int rnum; 61 62 if (lhs == NULL) 63 return (1); /* yep -- it all matched */ 64 65 if (rhs == NULL) 66 return (0); /* nope, ran out of rhs first */ 67 68 ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str); 69 ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str); 70 71 if (lhs->u.name.s != rhs->u.name.s) 72 return (0); /* nope, different component names */ 73 74 if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) 75 lnum = (int)lhs->u.name.child->u.ull; 76 else 77 out(O_DIE, "begins_with: unexpected lhs child"); 78 79 if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) 80 rnum = (int)rhs->u.name.child->u.ull; 81 else 82 out(O_DIE, "begins_with: unexpected rhs child"); 83 84 if (lnum != rnum) 85 return (0); /* nope, instance numbers were different */ 86 87 return (begins_with(lhs->u.name.next, rhs->u.name.next)); 88 } 89 90 /* 91 * evaluate a variety of functions and place result in valuep. return 1 if 92 * function evaluation was successful; 0 if otherwise (e.g., the case of an 93 * invalid argument to the function) 94 */ 95 /*ARGSUSED*/ 96 static int 97 eval_func(struct node *funcnp, struct lut *ex, struct node *epnames[], 98 struct node *np, struct lut **globals, 99 struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep) 100 { 101 const char *funcname = funcnp->u.func.s; 102 103 if (funcname == L_within) { 104 /* within()'s are not really constraints -- always true */ 105 valuep->t = UINT64; 106 valuep->v = 1; 107 return (1); 108 } else if (funcname == L_is_under) { 109 struct node *lhs; 110 struct node *rhs; 111 112 if (np->u.expr.left->t == T_NAME) 113 lhs = np->u.expr.left; 114 else if (np->u.expr.left->u.func.s == L_fru) 115 lhs = eval_fru(np->u.expr.left->u.func.arglist); 116 else if (np->u.expr.left->u.func.s == L_asru) 117 lhs = eval_asru(np->u.expr.left->u.func.arglist); 118 else 119 out(O_DIE, "is_under: unexpected lhs type: %s", 120 ptree_nodetype2str(np->u.expr.left->t)); 121 122 if (np->u.expr.right->t == T_NAME) 123 rhs = np->u.expr.right; 124 else if (np->u.expr.right->u.func.s == L_fru) 125 rhs = eval_fru(np->u.expr.right->u.func.arglist); 126 else if (np->u.expr.right->u.func.s == L_asru) 127 rhs = eval_asru(np->u.expr.right->u.func.arglist); 128 else 129 out(O_DIE, "is_under: unexpected rhs type: %s", 130 ptree_nodetype2str(np->u.expr.right->t)); 131 132 /* eval_dup will expand wildcards, iterators, etc... */ 133 lhs = eval_dup(lhs, ex, epnames); 134 rhs = eval_dup(rhs, ex, epnames); 135 valuep->t = UINT64; 136 valuep->v = begins_with(lhs, rhs); 137 138 out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under("); 139 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs); 140 out(O_ALTFP|O_VERB2|O_NONL, ","); 141 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs); 142 out(O_ALTFP|O_VERB2, ") returned %d", (int)valuep->v); 143 144 tree_free(lhs); 145 tree_free(rhs); 146 147 return (1); 148 } 149 150 if (try) 151 return (0); 152 153 if (funcname == L_fru) { 154 valuep->t = NODEPTR; 155 valuep->v = (unsigned long long)eval_fru(np); 156 return (1); 157 } else if (funcname == L_asru) { 158 valuep->t = NODEPTR; 159 valuep->v = (unsigned long long)eval_asru(np); 160 return (1); 161 } else if (funcname == L_call) { 162 return (! platform_call(np, globals, croot, arrowp, valuep)); 163 } else if (funcname == L_is_connected) { 164 return (! config_is_connected(np, croot, valuep)); 165 } else if (funcname == L_is_on) { 166 return (! config_is_on(np, croot, valuep)); 167 } else if (funcname == L_is_present) { 168 return (! config_is_present(np, croot, valuep)); 169 } else if (funcname == L_is_type) { 170 return (! config_is_type(np, croot, valuep)); 171 } else if (funcname == L_confprop) { 172 return (! config_confprop(np, croot, valuep)); 173 } else if (funcname == L_envprop) { 174 outfl(O_DIE, np->file, np->line, 175 "eval_func: %s not yet supported", funcname); 176 } else if (funcname == L_payloadprop) { 177 outfl(O_ALTFP|O_VERB|O_NONL, np->file, np->line, 178 "payloadprop(\"%s\") ", np->u.quote.s); 179 if (funcnp->u.func.cachedval != NULL) { 180 *valuep = *(struct evalue *)(funcnp->u.func.cachedval); 181 182 switch (valuep->t) { 183 case UINT64: 184 case NODEPTR: 185 out(O_ALTFP|O_VERB, "cached: %llu", valuep->v); 186 break; 187 case STRING: 188 out(O_ALTFP|O_VERB, "cached: \"%s\"", 189 (char *)valuep->v); 190 break; 191 default: 192 out(O_ALTFP|O_VERB, "undefined"); 193 break; 194 } 195 196 return (1); 197 } else if (platform_payloadprop(np, valuep)) { 198 /* platform_payloadprop() returned false, pass it on */ 199 out(O_ALTFP|O_VERB, "failed."); 200 return (0); 201 } else { 202 /* got back true, cache the value */ 203 funcnp->u.func.cachedval = 204 MALLOC(sizeof (struct evalue)); 205 *(struct evalue *)(funcnp->u.func.cachedval) = 206 *valuep; 207 208 switch (valuep->t) { 209 case UINT64: 210 case NODEPTR: 211 out(O_ALTFP|O_VERB, "cached: %llu", valuep->v); 212 break; 213 case STRING: 214 out(O_ALTFP|O_VERB, "cached: \"%s\"", 215 (char *)valuep->v); 216 break; 217 default: 218 out(O_ALTFP|O_VERB, "undefined"); 219 break; 220 } 221 222 return (1); 223 } 224 } else 225 outfl(O_DIE, np->file, np->line, 226 "eval_func: unexpected func: %s", funcname); 227 /*NOTREACHED*/ 228 } 229 230 static struct node * 231 eval_wildcardedname(struct node *np, struct lut *ex, struct node *epnames[]) 232 { 233 struct node *npstart, *npend, *npref, *newnp; 234 struct node *np1, *np2, *retp; 235 int i; 236 237 if (epnames == NULL || epnames[0] == NULL) 238 return (NULL); 239 240 for (i = 0; epnames[i] != NULL; i++) { 241 if (tree_namecmp(np, epnames[i]) == 0) 242 return (NULL); 243 } 244 245 /* 246 * get to this point if np does not match any of the entries in 247 * epnames. check if np is a path that must preceded by a wildcard 248 * portion. for this case we must first determine which epnames[] 249 * entry should be used for wildcarding. 250 */ 251 npstart = NULL; 252 for (i = 0; epnames[i] != NULL; i++) { 253 for (npref = epnames[i]; npref; npref = npref->u.name.next) { 254 if (npref->u.name.s == np->u.name.s) { 255 for (np1 = npref, np2 = np; 256 np1 != NULL && np2 != NULL; 257 np1 = np1->u.name.next, 258 np2 = np2->u.name.next) { 259 if (np1->u.name.s != np2->u.name.s) 260 break; 261 } 262 if (np2 == NULL) { 263 npstart = epnames[i]; 264 npend = npref; 265 if (np1 == NULL) 266 break; 267 } 268 } 269 } 270 271 if (npstart != NULL) 272 break; 273 } 274 275 if (npstart == NULL) { 276 /* no match; np is not a path to be wildcarded */ 277 return (NULL); 278 } 279 280 /* 281 * dup (npstart -- npend) which is the wildcarded portion. all 282 * children should be T_NUMs. 283 */ 284 retp = NULL; 285 for (npref = npstart; 286 ! (npref == NULL || npref == npend); 287 npref = npref->u.name.next) { 288 newnp = newnode(T_NAME, np->file, np->line); 289 290 newnp->u.name.t = npref->u.name.t; 291 newnp->u.name.s = npref->u.name.s; 292 newnp->u.name.last = newnp; 293 newnp->u.name.it = npref->u.name.it; 294 newnp->u.name.cp = npref->u.name.cp; 295 296 ASSERT(npref->u.name.child != NULL); 297 ASSERT(npref->u.name.child->t == T_NUM); 298 newnp->u.name.child = newnode(T_NUM, np->file, np->line); 299 newnp->u.name.child->u.ull = npref->u.name.child->u.ull; 300 301 if (retp == NULL) { 302 retp = newnp; 303 } else { 304 retp->u.name.last->u.name.next = newnp; 305 retp->u.name.last = newnp; 306 } 307 } 308 309 ASSERT(retp != NULL); 310 311 /* now append the nonwildcarded portion */ 312 retp = tree_name_append(retp, eval_dup(np, ex, NULL)); 313 314 return (retp); 315 } 316 317 static struct node * 318 eval_dup(struct node *np, struct lut *ex, struct node *epnames[]) 319 { 320 struct node *newnp; 321 322 if (np == NULL) 323 return (NULL); 324 325 switch (np->t) { 326 case T_GLOBID: 327 return (tree_globid(np->u.globid.s, np->file, np->line)); 328 329 case T_ASSIGN: 330 case T_CONDIF: 331 case T_CONDELSE: 332 case T_NE: 333 case T_EQ: 334 case T_LT: 335 case T_LE: 336 case T_GT: 337 case T_GE: 338 case T_BITAND: 339 case T_BITOR: 340 case T_BITXOR: 341 case T_BITNOT: 342 case T_LSHIFT: 343 case T_RSHIFT: 344 case T_LIST: 345 case T_AND: 346 case T_OR: 347 case T_NOT: 348 case T_ADD: 349 case T_SUB: 350 case T_MUL: 351 case T_DIV: 352 case T_MOD: 353 return (tree_expr(np->t, 354 eval_dup(np->u.expr.left, ex, epnames), 355 eval_dup(np->u.expr.right, ex, epnames))); 356 357 case T_NAME: { 358 struct iterinfo *iterinfop; 359 struct node *newchild = NULL; 360 361 iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 362 if (iterinfop != NULL) { 363 /* explicit iterator; not part of pathname */ 364 newnp = newnode(T_NUM, np->file, np->line); 365 newnp->u.ull = iterinfop->num; 366 return (newnp); 367 } 368 369 /* see if np is a path with wildcard portion */ 370 newnp = eval_wildcardedname(np, ex, epnames); 371 if (newnp != NULL) 372 return (newnp); 373 374 /* turn off wildcarding for child */ 375 newchild = eval_dup(np->u.name.child, ex, NULL); 376 377 if (newchild != NULL) { 378 if (newchild->t != T_NUM) { 379 /* 380 * not a number, eh? we must resolve this 381 * to a number. 382 */ 383 struct evalue value; 384 385 if (eval_expr(newchild, ex, epnames, 386 NULL, NULL, NULL, 1, &value) == 0 || 387 value.t != UINT64) { 388 outfl(O_DIE, np->file, np->line, 389 "eval_dup: could not resolve " 390 "iterator of %s", np->u.name.s); 391 } 392 393 tree_free(newchild); 394 newchild = newnode(T_NUM, np->file, np->line); 395 newchild->u.ull = value.v; 396 } 397 398 newnp = newnode(np->t, np->file, np->line); 399 newnp->u.name.s = np->u.name.s; 400 newnp->u.name.it = np->u.name.it; 401 newnp->u.name.cp = np->u.name.cp; 402 403 newnp->u.name.last = newnp; 404 newnp->u.name.child = newchild; 405 406 if (np->u.name.next != NULL) { 407 /* turn off wildcarding for next */ 408 return (tree_name_append(newnp, 409 eval_dup(np->u.name.next, ex, NULL))); 410 } else { 411 return (newnp); 412 } 413 } else { 414 outfl(O_DIE, np->file, np->line, 415 "eval_dup: internal error: \"%s\" is neither " 416 "an iterator nor a pathname", np->u.name.s); 417 } 418 /*NOTREACHED*/ 419 break; 420 } 421 422 case T_FUNC: 423 return (tree_func(np->u.func.s, 424 eval_dup(np->u.func.arglist, ex, epnames), 425 np->file, np->line)); 426 427 case T_QUOTE: 428 newnp = newnode(T_QUOTE, np->file, np->line); 429 newnp->u.quote.s = np->u.quote.s; 430 return (newnp); 431 432 case T_NUM: 433 newnp = newnode(T_NUM, np->file, np->line); 434 newnp->u.ull = np->u.ull; 435 return (newnp); 436 437 default: 438 outfl(O_DIE, np->file, np->line, 439 "eval_dup: unexpected node type: %s", 440 ptree_nodetype2str(np->t)); 441 } 442 /*NOTREACHED*/ 443 } 444 445 /* 446 * eval_potential -- see if constraint is potentially true 447 * 448 * this function is used at instance tree creation time to see if 449 * any constraints are already known to be false. if this function 450 * returns false, then the constraint will always be false and there's 451 * no need to include the propagation arrow in the instance tree. 452 * 453 * if this routine returns true, either the constraint is known to 454 * be always true (so there's no point in attaching the constraint 455 * to the propagation arrow in the instance tree), or the constraint 456 * contains "deferred" expressions like global variables or poller calls 457 * and so it must be evaluated during calls to fme_eval(). in this last 458 * case, where a constraint needs to be attached to the propagation arrow 459 * in the instance tree, this routine returns a newly created constraint 460 * in *newc where all the non-deferred things have been filled in. 461 * 462 * so in summary: 463 * 464 * return of false: constraint can never be true, *newc will be NULL. 465 * 466 * return of true with *newc unchanged: constraint will always be true. 467 * 468 * return of true with *newc changed: use new constraint in *newc. 469 * 470 * the lookup table for all explicit iterators, ex, is passed in. 471 * 472 * *newc can either be NULL on entry, or if can contain constraints from 473 * previous calls to eval_potential() (i.e. for building up an instance 474 * tree constraint from several potential constraints). if *newc already 475 * contains constraints, anything added to it will be joined by adding 476 * a T_AND node at the top of *newc. 477 */ 478 int 479 eval_potential(struct node *np, struct lut *ex, struct node *epnames[], 480 struct node **newc) 481 { 482 struct node *newnp; 483 struct evalue value; 484 485 if (eval_expr(np, ex, epnames, NULL, NULL, NULL, 1, &value) == 0) { 486 /* 487 * couldn't eval expression because 488 * it contains deferred items. make 489 * a duplicate expression with all the 490 * non-deferred items expanded. 491 */ 492 newnp = eval_dup(np, ex, epnames); 493 494 if (*newc == NULL) { 495 /* 496 * constraint is potentially true if deferred 497 * expression in newnp is true. *newc was NULL 498 * so new constraint is just the one in newnp. 499 */ 500 *newc = newnp; 501 return (1); 502 } else { 503 /* 504 * constraint is potentially true if deferred 505 * expression in newnp is true. *newc already 506 * contained a constraint so add an AND with the 507 * constraint in newnp. 508 */ 509 *newc = tree_expr(T_AND, *newc, newnp); 510 return (1); 511 } 512 } else if (value.t == UNDEFINED) { 513 /* constraint can never be true */ 514 return (0); 515 } else if (value.t == UINT64 && value.v == 0) { 516 /* constraint can never be true */ 517 return (0); 518 } else { 519 /* constraint is always true (nothing deferred to eval) */ 520 return (1); 521 } 522 } 523 524 static int 525 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 526 struct node *np) 527 { 528 if (dtype != UNDEFINED && lp->t != dtype) { 529 outfl(O_OK, np->file, np->line, 530 "invalid datatype of argument for operation %s", 531 ptree_nodetype2str(np->t)); 532 return (1); 533 } 534 535 if (rp != NULL && lp->t != rp->t) { 536 outfl(O_OK, np->file, np->line, 537 "mismatch in datatype of arguments for operation %s", 538 ptree_nodetype2str(np->t)); 539 return (1); 540 } 541 542 return (0); 543 } 544 545 /* 546 * eval_expr -- evaluate expression into *valuep 547 * 548 * the meaning of the return value depends on the input value of try. 549 * 550 * for try == 1: if any deferred items are encounted, bail out and return 551 * false. returns true if we made it through entire expression without 552 * hitting any deferred items. 553 * 554 * for try == 0: return true if all operations were performed successfully. 555 * return false if otherwise. for example, any of the following conditions 556 * will result in a false return value: 557 * - attempted use of an uninitialized global variable 558 * - failure in function evaluation 559 * - illegal arithmetic operation (argument out of range) 560 */ 561 int 562 eval_expr(struct node *np, struct lut *ex, struct node *epnames[], 563 struct lut **globals, struct config *croot, struct arrow *arrowp, 564 int try, struct evalue *valuep) 565 { 566 struct evalue *gval; 567 struct evalue lval; 568 struct evalue rval; 569 570 if (np == NULL) { 571 valuep->t = UINT64; 572 valuep->v = 1; /* no constraint means "true" */ 573 return (1); 574 } 575 576 valuep->t = UNDEFINED; 577 578 switch (np->t) { 579 case T_GLOBID: 580 if (try) 581 return (0); 582 583 /* 584 * only handle case of getting (and not setting) the value 585 * of a global variable 586 */ 587 gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 588 if (gval == NULL) { 589 valuep->t = UNDEFINED; 590 return (0); 591 } else { 592 valuep->t = gval->t; 593 valuep->v = gval->v; 594 return (1); 595 } 596 597 case T_ASSIGN: 598 if (try) 599 return (0); 600 601 /* 602 * first evaluate rhs, then try to store value in lhs which 603 * should be a global variable 604 */ 605 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 606 arrowp, try, &rval)) 607 return (0); 608 609 ASSERT(np->u.expr.left->t == T_GLOBID); 610 gval = lut_lookup(*globals, 611 (void *)np->u.expr.left->u.globid.s, NULL); 612 613 if (gval == NULL) { 614 gval = MALLOC(sizeof (*gval)); 615 *globals = lut_add(*globals, 616 (void *) np->u.expr.left->u.globid.s, 617 gval, NULL); 618 } 619 620 gval->t = rval.t; 621 gval->v = rval.v; 622 valuep->t = rval.t; 623 valuep->v = rval.v; 624 return (1); 625 626 case T_EQ: 627 #define IMPLICIT_ASSIGN_IN_EQ 628 #ifdef IMPLICIT_ASSIGN_IN_EQ 629 /* 630 * if lhs is an uninitialized global variable, perform 631 * an assignment. 632 * 633 * one insidious side effect of implicit assignment is 634 * that the "==" operator does not return a Boolean if 635 * implicit assignment was performed. 636 */ 637 if (try == 0 && 638 np->u.expr.left->t == T_GLOBID && 639 (gval = lut_lookup(*globals, 640 (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 641 if (!eval_expr(np->u.expr.right, ex, epnames, globals, 642 croot, arrowp, try, &rval)) 643 return (0); 644 645 gval = MALLOC(sizeof (*gval)); 646 *globals = lut_add(*globals, 647 (void *) np->u.expr.left->u.globid.s, 648 gval, NULL); 649 650 gval->t = rval.t; 651 gval->v = rval.v; 652 valuep->t = rval.t; 653 valuep->v = rval.v; 654 return (1); 655 } 656 #endif /* IMPLICIT_ASSIGN_IN_EQ */ 657 658 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 659 arrowp, try, &lval)) 660 return (0); 661 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 662 arrowp, try, &rval)) 663 return (0); 664 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 665 return (0); 666 667 valuep->t = UINT64; 668 valuep->v = (lval.v == rval.v); 669 return (1); 670 671 case T_LT: 672 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 673 arrowp, try, &lval)) 674 return (0); 675 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 676 arrowp, try, &rval)) 677 return (0); 678 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 679 return (0); 680 681 valuep->t = UINT64; 682 valuep->v = (lval.v < rval.v); 683 return (1); 684 685 case T_LE: 686 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 687 arrowp, try, &lval)) 688 return (0); 689 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 690 arrowp, try, &rval)) 691 return (0); 692 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 693 return (0); 694 695 valuep->t = UINT64; 696 valuep->v = (lval.v <= rval.v); 697 return (1); 698 699 case T_GT: 700 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 701 arrowp, try, &lval)) 702 return (0); 703 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 704 arrowp, try, &rval)) 705 return (0); 706 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 707 return (0); 708 709 valuep->t = UINT64; 710 valuep->v = (lval.v > rval.v); 711 return (1); 712 713 case T_GE: 714 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 715 arrowp, try, &lval)) 716 return (0); 717 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 718 arrowp, try, &rval)) 719 return (0); 720 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 721 return (0); 722 723 valuep->t = UINT64; 724 valuep->v = (lval.v >= rval.v); 725 return (1); 726 727 case T_BITAND: 728 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 729 arrowp, try, &lval)) 730 return (0); 731 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 732 arrowp, try, &rval)) 733 return (0); 734 if (check_expr_args(&lval, &rval, UINT64, np)) 735 return (0); 736 737 valuep->t = lval.t; 738 valuep->v = (lval.v & rval.v); 739 return (1); 740 741 case T_BITOR: 742 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 743 arrowp, try, &lval)) 744 return (0); 745 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 746 arrowp, try, &rval)) 747 return (0); 748 if (check_expr_args(&lval, &rval, UINT64, np)) 749 return (0); 750 751 valuep->t = lval.t; 752 valuep->v = (lval.v | rval.v); 753 return (1); 754 755 case T_BITXOR: 756 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 757 arrowp, try, &lval)) 758 return (0); 759 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 760 arrowp, try, &rval)) 761 return (0); 762 if (check_expr_args(&lval, &rval, UINT64, np)) 763 return (0); 764 765 valuep->t = lval.t; 766 valuep->v = (lval.v ^ rval.v); 767 return (1); 768 769 case T_BITNOT: 770 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 771 arrowp, try, &lval)) 772 return (0); 773 ASSERT(np->u.expr.right == NULL); 774 if (check_expr_args(&lval, NULL, UINT64, np)) 775 return (0); 776 777 valuep->t = UINT64; 778 valuep->v = ~ lval.v; 779 return (1); 780 781 case T_LSHIFT: 782 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 783 arrowp, try, &lval)) 784 return (0); 785 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 786 arrowp, try, &rval)) 787 return (0); 788 if (check_expr_args(&lval, &rval, UINT64, np)) 789 return (0); 790 791 valuep->t = UINT64; 792 valuep->v = (lval.v << rval.v); 793 return (1); 794 795 case T_RSHIFT: 796 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 797 arrowp, try, &lval)) 798 return (0); 799 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 800 arrowp, try, &rval)) 801 return (0); 802 if (check_expr_args(&lval, &rval, UINT64, np)) 803 return (0); 804 805 valuep->t = UINT64; 806 valuep->v = (lval.v >> rval.v); 807 return (1); 808 809 case T_CONDIF: { 810 struct node *retnp; 811 int dotrue = 0; 812 813 /* 814 * evaluate 815 * expression ? stmtA [ : stmtB ] 816 * 817 * first see if expression is true or false, then determine 818 * if stmtA (or stmtB, if it exists) should be evaluated. 819 * 820 * "dotrue = 1" means stmtA should be evaluated. 821 */ 822 if (eval_expr(np->u.expr.left, ex, epnames, globals, croot, 823 arrowp, try, &lval) && 824 lval.t != UNDEFINED && lval.v != 0) 825 dotrue = 1; 826 827 ASSERT(np->u.expr.right != NULL); 828 if (np->u.expr.right->t == T_CONDELSE) { 829 if (dotrue) 830 retnp = np->u.expr.right->u.expr.left; 831 else 832 retnp = np->u.expr.right->u.expr.right; 833 } else { 834 /* no ELSE clause */ 835 if (dotrue) 836 retnp = np->u.expr.right; 837 else { 838 valuep->t = UINT64; 839 valuep->v = 0; 840 return (0); 841 } 842 } 843 844 if (!eval_expr(retnp, ex, epnames, globals, croot, 845 arrowp, try, valuep)) 846 return (0); 847 return (1); 848 } 849 850 case T_CONDELSE: 851 /* 852 * shouldn't get here, since T_CONDELSE is supposed to be 853 * evaluated as part of T_CONDIF 854 */ 855 out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 856 ptree_nodetype2str(np->t)); 857 return (0); 858 859 case T_NE: 860 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 861 arrowp, try, &lval)) 862 return (0); 863 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 864 arrowp, try, &rval)) 865 return (0); 866 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 867 return (0); 868 869 valuep->t = UINT64; 870 valuep->v = (lval.v != rval.v); 871 return (1); 872 873 case T_LIST: 874 case T_AND: 875 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 876 arrowp, try, valuep)) 877 return (0); 878 if (valuep->v == 0) { 879 valuep->t = UINT64; 880 return (1); 881 } 882 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 883 arrowp, try, valuep)) 884 return (0); 885 valuep->t = UINT64; 886 valuep->v = valuep->v == 0 ? 0 : 1; 887 return (1); 888 889 case T_OR: 890 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 891 arrowp, try, valuep)) 892 return (0); 893 if (valuep->v != 0) { 894 valuep->t = UINT64; 895 valuep->v = 1; 896 return (1); 897 } 898 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 899 arrowp, try, valuep)) 900 return (0); 901 valuep->t = UINT64; 902 valuep->v = valuep->v == 0 ? 0 : 1; 903 return (1); 904 905 case T_NOT: 906 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 907 arrowp, try, valuep)) 908 return (0); 909 valuep->t = UINT64; 910 valuep->v = ! valuep->v; 911 return (1); 912 913 case T_ADD: 914 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 915 arrowp, try, &lval)) 916 return (0); 917 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 918 arrowp, try, &rval)) 919 return (0); 920 if (check_expr_args(&lval, &rval, UINT64, np)) 921 return (0); 922 923 valuep->t = lval.t; 924 valuep->v = lval.v + rval.v; 925 return (1); 926 927 case T_SUB: 928 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 929 arrowp, try, &lval)) 930 return (0); 931 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 932 arrowp, try, &rval)) 933 return (0); 934 if (check_expr_args(&lval, &rval, UINT64, np)) 935 return (0); 936 937 /* since valuep is unsigned, return false if lval.v < rval.v */ 938 if (lval.v < rval.v) { 939 out(O_ERR, "eval_expr: T_SUB result is out of range"); 940 valuep->t = UNDEFINED; 941 return (0); 942 } 943 944 valuep->t = lval.t; 945 valuep->v = lval.v - rval.v; 946 return (1); 947 948 case T_MUL: 949 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 950 arrowp, try, &lval)) 951 return (0); 952 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 953 arrowp, try, &rval)) 954 return (0); 955 if (check_expr_args(&lval, &rval, UINT64, np)) 956 return (0); 957 958 valuep->t = lval.t; 959 valuep->v = lval.v * rval.v; 960 return (1); 961 962 case T_DIV: 963 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 964 arrowp, try, &lval)) 965 return (0); 966 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 967 arrowp, try, &rval)) 968 return (0); 969 if (check_expr_args(&lval, &rval, UINT64, np)) 970 return (0); 971 972 /* return false if dividing by zero */ 973 if (rval.v == 0) { 974 out(O_ERR, "eval_expr: T_DIV division by zero"); 975 valuep->t = UNDEFINED; 976 return (0); 977 } 978 979 valuep->t = lval.t; 980 valuep->v = lval.v / rval.v; 981 return (1); 982 983 case T_MOD: 984 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 985 arrowp, try, &lval)) 986 return (0); 987 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 988 arrowp, try, &rval)) 989 return (0); 990 if (check_expr_args(&lval, &rval, UINT64, np)) 991 return (0); 992 993 /* return false if dividing by zero */ 994 if (rval.v == 0) { 995 out(O_ERR, "eval_expr: T_MOD division by zero"); 996 valuep->t = UNDEFINED; 997 return (0); 998 } 999 1000 valuep->t = lval.t; 1001 valuep->v = lval.v % rval.v; 1002 return (1); 1003 1004 case T_NAME: 1005 if (try) { 1006 struct iterinfo *iterinfop; 1007 1008 /* 1009 * at itree_create() time, we can expand simple 1010 * iterators. anything else we'll punt on. 1011 */ 1012 iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 1013 if (iterinfop != NULL) { 1014 /* explicit iterator; not part of pathname */ 1015 valuep->t = UINT64; 1016 valuep->v = (unsigned long long)iterinfop->num; 1017 return (1); 1018 } 1019 return (0); 1020 } 1021 1022 /* return address of struct node */ 1023 valuep->t = NODEPTR; 1024 valuep->v = (unsigned long long)np; 1025 return (1); 1026 1027 case T_QUOTE: 1028 valuep->t = STRING; 1029 valuep->v = (unsigned long long)np->u.quote.s; 1030 return (1); 1031 1032 case T_FUNC: 1033 return (eval_func(np, ex, epnames, np->u.func.arglist, 1034 globals, croot, arrowp, try, valuep)); 1035 1036 case T_NUM: 1037 valuep->t = UINT64; 1038 valuep->v = np->u.ull; 1039 return (1); 1040 1041 default: 1042 outfl(O_DIE, np->file, np->line, 1043 "eval_expr: unexpected node type: %s", 1044 ptree_nodetype2str(np->t)); 1045 } 1046 /*NOTREACHED*/ 1047 } 1048 1049 /* 1050 * eval_fru() and eval_asru() don't do much, but are called from a number 1051 * of places. 1052 */ 1053 struct node * 1054 eval_fru(struct node *np) 1055 { 1056 ASSERT(np->t == T_NAME); 1057 return (np); 1058 } 1059 1060 struct node * 1061 eval_asru(struct node *np) 1062 { 1063 ASSERT(np->t == T_NAME); 1064 return (np); 1065 } 1066