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 out(O_ALTFP|O_VERB, "cached: %llu", valuep->v); 182 return (1); 183 } else if (platform_payloadprop(np, valuep)) { 184 /* platform_payloadprop() returned false, pass it on */ 185 out(O_ALTFP|O_VERB, "failed."); 186 return (0); 187 } else { 188 /* got back true, cache the value */ 189 funcnp->u.func.cachedval = 190 MALLOC(sizeof (struct evalue)); 191 *(struct evalue *)(funcnp->u.func.cachedval) = 192 *valuep; 193 out(O_ALTFP|O_VERB, "returned: %llu", valuep->v); 194 return (1); 195 } 196 } else 197 outfl(O_DIE, np->file, np->line, 198 "eval_func: unexpected func: %s", funcname); 199 /*NOTREACHED*/ 200 } 201 202 static struct node * 203 eval_wildcardedname(struct node *np, struct lut *ex, struct node *epnames[]) 204 { 205 struct node *npstart, *npend, *npref, *newnp; 206 struct node *np1, *np2, *retp; 207 int i; 208 209 if (epnames == NULL || epnames[0] == NULL) 210 return (NULL); 211 212 for (i = 0; epnames[i] != NULL; i++) { 213 if (tree_namecmp(np, epnames[i]) == 0) 214 return (NULL); 215 } 216 217 /* 218 * get to this point if np does not match any of the entries in 219 * epnames. check if np is a path that must preceded by a wildcard 220 * portion. for this case we must first determine which epnames[] 221 * entry should be used for wildcarding. 222 */ 223 npstart = NULL; 224 for (i = 0; epnames[i] != NULL; i++) { 225 for (npref = epnames[i]; npref; npref = npref->u.name.next) { 226 if (npref->u.name.s == np->u.name.s) { 227 for (np1 = npref, np2 = np; 228 np1 != NULL && np2 != NULL; 229 np1 = np1->u.name.next, 230 np2 = np2->u.name.next) { 231 if (np1->u.name.s != np2->u.name.s) 232 break; 233 } 234 if (np2 == NULL) { 235 npstart = epnames[i]; 236 npend = npref; 237 if (np1 == NULL) 238 break; 239 } 240 } 241 } 242 243 if (npstart != NULL) 244 break; 245 } 246 247 if (npstart == NULL) { 248 /* no match; np is not a path to be wildcarded */ 249 return (NULL); 250 } 251 252 /* 253 * dup (npstart -- npend) which is the wildcarded portion. all 254 * children should be T_NUMs. 255 */ 256 retp = NULL; 257 for (npref = npstart; 258 ! (npref == NULL || npref == npend); 259 npref = npref->u.name.next) { 260 newnp = newnode(T_NAME, np->file, np->line); 261 262 newnp->u.name.t = npref->u.name.t; 263 newnp->u.name.s = npref->u.name.s; 264 newnp->u.name.last = newnp; 265 newnp->u.name.it = npref->u.name.it; 266 newnp->u.name.cp = npref->u.name.cp; 267 268 ASSERT(npref->u.name.child != NULL); 269 ASSERT(npref->u.name.child->t == T_NUM); 270 newnp->u.name.child = newnode(T_NUM, np->file, np->line); 271 newnp->u.name.child->u.ull = npref->u.name.child->u.ull; 272 273 if (retp == NULL) { 274 retp = newnp; 275 } else { 276 retp->u.name.last->u.name.next = newnp; 277 retp->u.name.last = newnp; 278 } 279 } 280 281 ASSERT(retp != NULL); 282 283 /* now append the nonwildcarded portion */ 284 retp = tree_name_append(retp, eval_dup(np, ex, NULL)); 285 286 return (retp); 287 } 288 289 static struct node * 290 eval_dup(struct node *np, struct lut *ex, struct node *epnames[]) 291 { 292 struct node *newnp; 293 294 if (np == NULL) 295 return (NULL); 296 297 switch (np->t) { 298 case T_GLOBID: 299 return (tree_globid(np->u.globid.s, np->file, np->line)); 300 301 case T_ASSIGN: 302 case T_CONDIF: 303 case T_CONDELSE: 304 case T_NE: 305 case T_EQ: 306 case T_LT: 307 case T_LE: 308 case T_GT: 309 case T_GE: 310 case T_BITAND: 311 case T_BITOR: 312 case T_BITXOR: 313 case T_BITNOT: 314 case T_LSHIFT: 315 case T_RSHIFT: 316 case T_LIST: 317 case T_AND: 318 case T_OR: 319 case T_NOT: 320 case T_ADD: 321 case T_SUB: 322 case T_MUL: 323 case T_DIV: 324 case T_MOD: 325 return (tree_expr(np->t, 326 eval_dup(np->u.expr.left, ex, epnames), 327 eval_dup(np->u.expr.right, ex, epnames))); 328 329 case T_NAME: { 330 struct iterinfo *iterinfop; 331 struct node *newchild = NULL; 332 333 iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 334 if (iterinfop != NULL) { 335 /* explicit iterator; not part of pathname */ 336 newnp = newnode(T_NUM, np->file, np->line); 337 newnp->u.ull = iterinfop->num; 338 return (newnp); 339 } 340 341 /* see if np is a path with wildcard portion */ 342 newnp = eval_wildcardedname(np, ex, epnames); 343 if (newnp != NULL) 344 return (newnp); 345 346 /* turn off wildcarding for child */ 347 newchild = eval_dup(np->u.name.child, ex, NULL); 348 349 if (newchild != NULL) { 350 if (newchild->t != T_NUM) { 351 /* 352 * not a number, eh? we must resolve this 353 * to a number. 354 */ 355 struct evalue value; 356 357 if (eval_expr(newchild, ex, epnames, 358 NULL, NULL, NULL, 1, &value) == 0 || 359 value.t != UINT64) { 360 outfl(O_DIE, np->file, np->line, 361 "eval_dup: could not resolve " 362 "iterator of %s", np->u.name.s); 363 } 364 365 tree_free(newchild); 366 newchild = newnode(T_NUM, np->file, np->line); 367 newchild->u.ull = value.v; 368 } 369 370 newnp = newnode(np->t, np->file, np->line); 371 newnp->u.name.s = np->u.name.s; 372 newnp->u.name.it = np->u.name.it; 373 newnp->u.name.cp = np->u.name.cp; 374 375 newnp->u.name.last = newnp; 376 newnp->u.name.child = newchild; 377 378 if (np->u.name.next != NULL) { 379 /* turn off wildcarding for next */ 380 return (tree_name_append(newnp, 381 eval_dup(np->u.name.next, ex, NULL))); 382 } else { 383 return (newnp); 384 } 385 } else { 386 outfl(O_DIE, np->file, np->line, 387 "eval_dup: internal error: \"%s\" is neither " 388 "an iterator nor a pathname", np->u.name.s); 389 } 390 /*NOTREACHED*/ 391 break; 392 } 393 394 case T_FUNC: 395 return (tree_func(np->u.func.s, 396 eval_dup(np->u.func.arglist, ex, epnames), 397 np->file, np->line)); 398 399 case T_QUOTE: 400 newnp = newnode(T_QUOTE, np->file, np->line); 401 newnp->u.quote.s = np->u.quote.s; 402 return (newnp); 403 404 case T_NUM: 405 newnp = newnode(T_NUM, np->file, np->line); 406 newnp->u.ull = np->u.ull; 407 return (newnp); 408 409 default: 410 outfl(O_DIE, np->file, np->line, 411 "eval_dup: unexpected node type: %s", 412 ptree_nodetype2str(np->t)); 413 } 414 /*NOTREACHED*/ 415 } 416 417 /* 418 * eval_potential -- see if constraint is potentially true 419 * 420 * this function is used at instance tree creation time to see if 421 * any constraints are already known to be false. if this function 422 * returns false, then the constraint will always be false and there's 423 * no need to include the propagation arrow in the instance tree. 424 * 425 * if this routine returns true, either the constraint is known to 426 * be always true (so there's no point in attaching the constraint 427 * to the propagation arrow in the instance tree), or the constraint 428 * contains "deferred" expressions like global variables or poller calls 429 * and so it must be evaluated during calls to fme_eval(). in this last 430 * case, where a constraint needs to be attached to the propagation arrow 431 * in the instance tree, this routine returns a newly created constraint 432 * in *newc where all the non-deferred things have been filled in. 433 * 434 * so in summary: 435 * 436 * return of false: constraint can never be true, *newc will be NULL. 437 * 438 * return of true with *newc unchanged: constraint will always be true. 439 * 440 * return of true with *newc changed: use new constraint in *newc. 441 * 442 * the lookup table for all explicit iterators, ex, is passed in. 443 * 444 * *newc can either be NULL on entry, or if can contain constraints from 445 * previous calls to eval_potential() (i.e. for building up an instance 446 * tree constraint from several potential constraints). if *newc already 447 * contains constraints, anything added to it will be joined by adding 448 * a T_AND node at the top of *newc. 449 */ 450 int 451 eval_potential(struct node *np, struct lut *ex, struct node *epnames[], 452 struct node **newc) 453 { 454 struct node *newnp; 455 struct evalue value; 456 457 if (eval_expr(np, ex, epnames, NULL, NULL, NULL, 1, &value) == 0) { 458 /* 459 * couldn't eval expression because 460 * it contains deferred items. make 461 * a duplicate expression with all the 462 * non-deferred items expanded. 463 */ 464 newnp = eval_dup(np, ex, epnames); 465 466 if (*newc == NULL) { 467 /* 468 * constraint is potentially true if deferred 469 * expression in newnp is true. *newc was NULL 470 * so new constraint is just the one in newnp. 471 */ 472 *newc = newnp; 473 return (1); 474 } else { 475 /* 476 * constraint is potentially true if deferred 477 * expression in newnp is true. *newc already 478 * contained a constraint so add an AND with the 479 * constraint in newnp. 480 */ 481 *newc = tree_expr(T_AND, *newc, newnp); 482 return (1); 483 } 484 } else if (value.t == UNDEFINED) { 485 /* constraint can never be true */ 486 return (0); 487 } else if (value.t == UINT64 && value.v == 0) { 488 /* constraint can never be true */ 489 return (0); 490 } else { 491 /* constraint is always true (nothing deferred to eval) */ 492 return (1); 493 } 494 } 495 496 static int 497 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 498 struct node *np) 499 { 500 if (dtype != UNDEFINED && lp->t != dtype) { 501 outfl(O_OK, np->file, np->line, 502 "invalid datatype of argument for operation %s", 503 ptree_nodetype2str(np->t)); 504 return (1); 505 } 506 507 if (rp != NULL && lp->t != rp->t) { 508 outfl(O_OK, np->file, np->line, 509 "mismatch in datatype of arguments for operation %s", 510 ptree_nodetype2str(np->t)); 511 return (1); 512 } 513 514 return (0); 515 } 516 517 /* 518 * eval_expr -- evaluate expression into *valuep 519 * 520 * the meaning of the return value depends on the input value of try. 521 * 522 * for try == 1: if any deferred items are encounted, bail out and return 523 * false. returns true if we made it through entire expression without 524 * hitting any deferred items. 525 * 526 * for try == 0: return true if all operations were performed successfully. 527 * return false if otherwise. for example, any of the following conditions 528 * will result in a false return value: 529 * - attempted use of an uninitialized global variable 530 * - failure in function evaluation 531 * - illegal arithmetic operation (argument out of range) 532 */ 533 int 534 eval_expr(struct node *np, struct lut *ex, struct node *epnames[], 535 struct lut **globals, struct config *croot, struct arrow *arrowp, 536 int try, struct evalue *valuep) 537 { 538 struct evalue *gval; 539 struct evalue lval; 540 struct evalue rval; 541 542 if (np == NULL) { 543 valuep->t = UINT64; 544 valuep->v = 1; /* no constraint means "true" */ 545 return (1); 546 } 547 548 valuep->t = UNDEFINED; 549 550 switch (np->t) { 551 case T_GLOBID: 552 if (try) 553 return (0); 554 555 /* 556 * only handle case of getting (and not setting) the value 557 * of a global variable 558 */ 559 gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 560 if (gval == NULL) { 561 valuep->t = UNDEFINED; 562 return (0); 563 } else { 564 valuep->t = gval->t; 565 valuep->v = gval->v; 566 return (1); 567 } 568 569 case T_ASSIGN: 570 if (try) 571 return (0); 572 573 /* 574 * first evaluate rhs, then try to store value in lhs which 575 * should be a global variable 576 */ 577 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 578 arrowp, try, &rval)) 579 return (0); 580 581 ASSERT(np->u.expr.left->t == T_GLOBID); 582 gval = lut_lookup(*globals, 583 (void *)np->u.expr.left->u.globid.s, NULL); 584 585 if (gval == NULL) { 586 gval = MALLOC(sizeof (*gval)); 587 *globals = lut_add(*globals, 588 (void *) np->u.expr.left->u.globid.s, 589 gval, NULL); 590 } 591 592 gval->t = rval.t; 593 gval->v = rval.v; 594 valuep->t = rval.t; 595 valuep->v = rval.v; 596 return (1); 597 598 case T_EQ: 599 #define IMPLICIT_ASSIGN_IN_EQ 600 #ifdef IMPLICIT_ASSIGN_IN_EQ 601 /* 602 * if lhs is an uninitialized global variable, perform 603 * an assignment. 604 * 605 * one insidious side effect of implicit assignment is 606 * that the "==" operator does not return a Boolean if 607 * implicit assignment was performed. 608 */ 609 if (try == 0 && 610 np->u.expr.left->t == T_GLOBID && 611 (gval = lut_lookup(*globals, 612 (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 613 if (!eval_expr(np->u.expr.right, ex, epnames, globals, 614 croot, arrowp, try, &rval)) 615 return (0); 616 617 gval = MALLOC(sizeof (*gval)); 618 *globals = lut_add(*globals, 619 (void *) np->u.expr.left->u.globid.s, 620 gval, NULL); 621 622 gval->t = rval.t; 623 gval->v = rval.v; 624 valuep->t = rval.t; 625 valuep->v = rval.v; 626 return (1); 627 } 628 #endif /* IMPLICIT_ASSIGN_IN_EQ */ 629 630 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 631 arrowp, try, &lval)) 632 return (0); 633 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 634 arrowp, try, &rval)) 635 return (0); 636 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 637 return (0); 638 639 valuep->t = UINT64; 640 valuep->v = (lval.v == rval.v); 641 return (1); 642 643 case T_LT: 644 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 645 arrowp, try, &lval)) 646 return (0); 647 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 648 arrowp, try, &rval)) 649 return (0); 650 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 651 return (0); 652 653 valuep->t = UINT64; 654 valuep->v = (lval.v < rval.v); 655 return (1); 656 657 case T_LE: 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_GT: 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_GE: 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_BITAND: 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, UINT64, np)) 707 return (0); 708 709 valuep->t = lval.t; 710 valuep->v = (lval.v & rval.v); 711 return (1); 712 713 case T_BITOR: 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, UINT64, np)) 721 return (0); 722 723 valuep->t = lval.t; 724 valuep->v = (lval.v | rval.v); 725 return (1); 726 727 case T_BITXOR: 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_BITNOT: 742 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 743 arrowp, try, &lval)) 744 return (0); 745 ASSERT(np->u.expr.right == NULL); 746 if (check_expr_args(&lval, NULL, UINT64, np)) 747 return (0); 748 749 valuep->t = UINT64; 750 valuep->v = ~ lval.v; 751 return (1); 752 753 case T_LSHIFT: 754 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 755 arrowp, try, &lval)) 756 return (0); 757 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 758 arrowp, try, &rval)) 759 return (0); 760 if (check_expr_args(&lval, &rval, UINT64, np)) 761 return (0); 762 763 valuep->t = UINT64; 764 valuep->v = (lval.v << rval.v); 765 return (1); 766 767 case T_RSHIFT: 768 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 769 arrowp, try, &lval)) 770 return (0); 771 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 772 arrowp, try, &rval)) 773 return (0); 774 if (check_expr_args(&lval, &rval, UINT64, np)) 775 return (0); 776 777 valuep->t = UINT64; 778 valuep->v = (lval.v >> rval.v); 779 return (1); 780 781 case T_CONDIF: { 782 struct node *retnp; 783 int dotrue = 0; 784 785 /* 786 * evaluate 787 * expression ? stmtA [ : stmtB ] 788 * 789 * first see if expression is true or false, then determine 790 * if stmtA (or stmtB, if it exists) should be evaluated. 791 * 792 * "dotrue = 1" means stmtA should be evaluated. 793 */ 794 if (eval_expr(np->u.expr.left, ex, epnames, globals, croot, 795 arrowp, try, &lval) && 796 lval.t != UNDEFINED && lval.v != 0) 797 dotrue = 1; 798 799 ASSERT(np->u.expr.right != NULL); 800 if (np->u.expr.right->t == T_CONDELSE) { 801 if (dotrue) 802 retnp = np->u.expr.right->u.expr.left; 803 else 804 retnp = np->u.expr.right->u.expr.right; 805 } else { 806 /* no ELSE clause */ 807 if (dotrue) 808 retnp = np->u.expr.right; 809 else { 810 valuep->t = UINT64; 811 valuep->v = 0; 812 return (0); 813 } 814 } 815 816 if (!eval_expr(retnp, ex, epnames, globals, croot, 817 arrowp, try, valuep)) 818 return (0); 819 return (1); 820 } 821 822 case T_CONDELSE: 823 /* 824 * shouldn't get here, since T_CONDELSE is supposed to be 825 * evaluated as part of T_CONDIF 826 */ 827 out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 828 ptree_nodetype2str(np->t)); 829 return (0); 830 831 case T_NE: 832 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 833 arrowp, try, &lval)) 834 return (0); 835 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 836 arrowp, try, &rval)) 837 return (0); 838 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 839 return (0); 840 841 valuep->t = UINT64; 842 valuep->v = (lval.v != rval.v); 843 return (1); 844 845 case T_LIST: 846 case T_AND: 847 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 848 arrowp, try, valuep)) 849 return (0); 850 if (valuep->v == 0) { 851 valuep->t = UINT64; 852 return (1); 853 } 854 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 855 arrowp, try, valuep)) 856 return (0); 857 valuep->t = UINT64; 858 valuep->v = valuep->v == 0 ? 0 : 1; 859 return (1); 860 861 case T_OR: 862 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 863 arrowp, try, valuep)) 864 return (0); 865 if (valuep->v != 0) { 866 valuep->t = UINT64; 867 valuep->v = 1; 868 return (1); 869 } 870 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 871 arrowp, try, valuep)) 872 return (0); 873 valuep->t = UINT64; 874 valuep->v = valuep->v == 0 ? 0 : 1; 875 return (1); 876 877 case T_NOT: 878 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 879 arrowp, try, valuep)) 880 return (0); 881 valuep->t = UINT64; 882 valuep->v = ! valuep->v; 883 return (1); 884 885 case T_ADD: 886 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 887 arrowp, try, &lval)) 888 return (0); 889 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 890 arrowp, try, &rval)) 891 return (0); 892 if (check_expr_args(&lval, &rval, UINT64, np)) 893 return (0); 894 895 valuep->t = lval.t; 896 valuep->v = lval.v + rval.v; 897 return (1); 898 899 case T_SUB: 900 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 901 arrowp, try, &lval)) 902 return (0); 903 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 904 arrowp, try, &rval)) 905 return (0); 906 if (check_expr_args(&lval, &rval, UINT64, np)) 907 return (0); 908 909 /* since valuep is unsigned, return false if lval.v < rval.v */ 910 if (lval.v < rval.v) { 911 out(O_ERR, "eval_expr: T_SUB result is out of range"); 912 valuep->t = UNDEFINED; 913 return (0); 914 } 915 916 valuep->t = lval.t; 917 valuep->v = lval.v - rval.v; 918 return (1); 919 920 case T_MUL: 921 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 922 arrowp, try, &lval)) 923 return (0); 924 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 925 arrowp, try, &rval)) 926 return (0); 927 if (check_expr_args(&lval, &rval, UINT64, np)) 928 return (0); 929 930 valuep->t = lval.t; 931 valuep->v = lval.v * rval.v; 932 return (1); 933 934 case T_DIV: 935 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 936 arrowp, try, &lval)) 937 return (0); 938 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 939 arrowp, try, &rval)) 940 return (0); 941 if (check_expr_args(&lval, &rval, UINT64, np)) 942 return (0); 943 944 /* return false if dividing by zero */ 945 if (rval.v == 0) { 946 out(O_ERR, "eval_expr: T_DIV division by zero"); 947 valuep->t = UNDEFINED; 948 return (0); 949 } 950 951 valuep->t = lval.t; 952 valuep->v = lval.v / rval.v; 953 return (1); 954 955 case T_MOD: 956 if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot, 957 arrowp, try, &lval)) 958 return (0); 959 if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot, 960 arrowp, try, &rval)) 961 return (0); 962 if (check_expr_args(&lval, &rval, UINT64, np)) 963 return (0); 964 965 /* return false if dividing by zero */ 966 if (rval.v == 0) { 967 out(O_ERR, "eval_expr: T_MOD division by zero"); 968 valuep->t = UNDEFINED; 969 return (0); 970 } 971 972 valuep->t = lval.t; 973 valuep->v = lval.v % rval.v; 974 return (1); 975 976 case T_NAME: 977 if (try) { 978 struct iterinfo *iterinfop; 979 980 /* 981 * at itree_create() time, we can expand simple 982 * iterators. anything else we'll punt on. 983 */ 984 iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 985 if (iterinfop != NULL) { 986 /* explicit iterator; not part of pathname */ 987 valuep->t = UINT64; 988 valuep->v = (unsigned long long)iterinfop->num; 989 return (1); 990 } 991 return (0); 992 } 993 994 /* return address of struct node */ 995 valuep->t = NODEPTR; 996 valuep->v = (unsigned long long)np; 997 return (1); 998 999 case T_QUOTE: 1000 valuep->t = STRING; 1001 valuep->v = (unsigned long long)np->u.quote.s; 1002 return (1); 1003 1004 case T_FUNC: 1005 return (eval_func(np, ex, epnames, np->u.func.arglist, 1006 globals, croot, arrowp, try, valuep)); 1007 1008 case T_NUM: 1009 valuep->t = UINT64; 1010 valuep->v = np->u.ull; 1011 return (1); 1012 1013 default: 1014 outfl(O_DIE, np->file, np->line, 1015 "eval_expr: unexpected node type: %s", 1016 ptree_nodetype2str(np->t)); 1017 } 1018 /*NOTREACHED*/ 1019 } 1020 1021 /* 1022 * eval_fru() and eval_asru() don't do much, but are called from a number 1023 * of places. 1024 */ 1025 struct node * 1026 eval_fru(struct node *np) 1027 { 1028 ASSERT(np->t == T_NAME); 1029 return (np); 1030 } 1031 1032 struct node * 1033 eval_asru(struct node *np) 1034 { 1035 ASSERT(np->t == T_NAME); 1036 return (np); 1037 } 1038