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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 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 "ipath.h" 46 #include "eval.h" 47 #include "config.h" 48 #include "platform.h" 49 #include "fme.h" 50 #include "stats.h" 51 52 static struct node *eval_dup(struct node *np, struct lut *ex, 53 struct node *events[]); 54 static int check_expr_args(struct evalue *lp, struct evalue *rp, 55 enum datatype dtype, struct node *np); 56 static struct node *eval_fru(struct node *np); 57 static struct node *eval_asru(struct node *np); 58 59 /* 60 * begins_with -- return true if rhs path begins with everything in lhs path 61 */ 62 static int 63 begins_with(struct node *lhs, struct node *rhs, struct lut *ex) 64 { 65 int lnum; 66 int rnum; 67 struct iterinfo *iterinfop; 68 69 if (lhs == NULL) 70 return (1); /* yep -- it all matched */ 71 72 if (rhs == NULL) 73 return (0); /* nope, ran out of rhs first */ 74 75 ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str); 76 ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str); 77 78 if (lhs->u.name.s != rhs->u.name.s) 79 return (0); /* nope, different component names */ 80 81 if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) { 82 lnum = (int)lhs->u.name.child->u.ull; 83 } else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) { 84 iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s, 85 NULL); 86 if (iterinfop != NULL) 87 lnum = iterinfop->num; 88 else 89 out(O_DIE, "begins_with: unexpected lhs child"); 90 } else { 91 out(O_DIE, "begins_with: unexpected lhs child"); 92 } 93 94 if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) { 95 rnum = (int)rhs->u.name.child->u.ull; 96 } else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) { 97 iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s, 98 NULL); 99 if (iterinfop != NULL) 100 rnum = iterinfop->num; 101 else 102 out(O_DIE, "begins_with: unexpected rhs child"); 103 } else { 104 out(O_DIE, "begins_with: unexpected rhs child"); 105 } 106 107 if (lnum != rnum) 108 return (0); /* nope, instance numbers were different */ 109 110 return (begins_with(lhs->u.name.next, rhs->u.name.next, ex)); 111 } 112 113 /* 114 * eval_getname - used by eval_func to evaluate a name, preferably without using 115 * eval_dup (but if it does have to use eval_dup then the *dupedp flag is set). 116 */ 117 static struct node * 118 eval_getname(struct node *funcnp, struct lut *ex, struct node *events[], 119 struct node *np, struct lut **globals, 120 struct config *croot, struct arrow *arrowp, int try, int *dupedp) 121 { 122 struct node *nodep; 123 const char *funcname = funcnp->u.func.s; 124 struct evalue val; 125 126 if (np->t == T_NAME) 127 nodep = np; 128 else if (np->u.func.s == L_fru) 129 nodep = eval_fru(np->u.func.arglist); 130 else if (np->u.func.s == L_asru) 131 nodep = eval_asru(np->u.func.arglist); 132 else 133 out(O_DIE, "%s: unexpected type: %s", 134 funcname, ptree_nodetype2str(np->t)); 135 if (try) { 136 if (eval_expr(nodep, ex, events, globals, croot, 137 arrowp, try, &val) && val.t == NODEPTR) 138 nodep = (struct node *)(uintptr_t)val.v; 139 else { 140 *dupedp = 1; 141 nodep = eval_dup(nodep, ex, events); 142 } 143 } 144 return (nodep); 145 } 146 147 /* 148 * evaluate a variety of functions and place result in valuep. return 1 if 149 * function evaluation was successful; 0 if otherwise (e.g., the case of an 150 * invalid argument to the function) 151 */ 152 /*ARGSUSED*/ 153 static int 154 eval_func(struct node *funcnp, struct lut *ex, struct node *events[], 155 struct node *np, struct lut **globals, 156 struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep) 157 { 158 const char *funcname = funcnp->u.func.s; 159 int duped_lhs = 0, duped_rhs = 0, duped = 0; 160 struct node *lhs; 161 struct node *rhs; 162 struct config *cp; 163 struct node *nodep; 164 char *path; 165 struct evalue val; 166 167 if (funcname == L_within) { 168 /* within()'s are not really constraints -- always true */ 169 valuep->t = UINT64; 170 valuep->v = 1; 171 return (1); 172 } else if (funcname == L_is_under) { 173 lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals, 174 croot, arrowp, try, &duped_lhs); 175 rhs = eval_getname(funcnp, ex, events, np->u.expr.right, 176 globals, croot, arrowp, try, &duped_rhs); 177 178 valuep->t = UINT64; 179 valuep->v = begins_with(lhs, rhs, ex); 180 out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under("); 181 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs); 182 out(O_ALTFP|O_VERB2|O_NONL, ","); 183 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs); 184 out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v); 185 186 if (duped_lhs) 187 tree_free(lhs); 188 if (duped_rhs) 189 tree_free(rhs); 190 return (1); 191 } else if (funcname == L_confprop || funcname == L_confprop_defined) { 192 const char *s; 193 194 /* for now s will point to a quote [see addconfigprop()] */ 195 ASSERT(np->u.expr.right->t == T_QUOTE); 196 197 nodep = eval_getname(funcnp, ex, events, np->u.expr.left, 198 globals, croot, arrowp, try, &duped); 199 if (nodep->u.name.last->u.name.cp != NULL) { 200 cp = nodep->u.name.last->u.name.cp; 201 } else { 202 path = ipath2str(NULL, ipath(nodep)); 203 cp = config_lookup(croot, path, 0); 204 FREE((void *)path); 205 } 206 if (cp == NULL) { 207 if (funcname == L_confprop) { 208 out(O_ALTFP|O_VERB3, "%s: path ", funcname); 209 ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 210 out(O_ALTFP|O_VERB3, " not found"); 211 valuep->v = (uintptr_t)stable(""); 212 valuep->t = STRING; 213 if (duped) 214 tree_free(nodep); 215 return (1); 216 } else { 217 valuep->v = 0; 218 valuep->t = UINT64; 219 if (duped) 220 tree_free(nodep); 221 return (1); 222 } 223 } 224 s = config_getprop(cp, np->u.expr.right->u.quote.s); 225 if (s == NULL && strcmp(np->u.expr.right->u.quote.s, 226 "class-code") == 0) 227 s = config_getprop(cp, "CLASS-CODE"); 228 if (s == NULL) { 229 if (funcname == L_confprop) { 230 out(O_ALTFP|O_VERB3|O_NONL, 231 "%s: \"%s\" not found for path ", 232 funcname, np->u.expr.right->u.quote.s); 233 ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 234 valuep->v = (uintptr_t)stable(""); 235 valuep->t = STRING; 236 if (duped) 237 tree_free(nodep); 238 return (1); 239 } else { 240 valuep->v = 0; 241 valuep->t = UINT64; 242 if (duped) 243 tree_free(nodep); 244 return (1); 245 } 246 } 247 248 if (funcname == L_confprop) { 249 valuep->v = (uintptr_t)stable(s); 250 valuep->t = STRING; 251 out(O_ALTFP|O_VERB3|O_NONL, " %s(\"", funcname); 252 ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 253 out(O_ALTFP|O_VERB3|O_NONL, 254 "\", \"%s\") = \"%s\" ", 255 np->u.expr.right->u.quote.s, 256 (char *)(uintptr_t)valuep->v); 257 } else { 258 valuep->v = 1; 259 valuep->t = UINT64; 260 } 261 if (duped) 262 tree_free(nodep); 263 return (1); 264 } else if (funcname == L_is_connected) { 265 const char *connstrings[] = { "connected", "CONNECTED", NULL }; 266 struct config *cp[2]; 267 const char *matchthis[2], *s; 268 char *nameslist, *w; 269 int i, j; 270 271 lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals, 272 croot, arrowp, try, &duped_lhs); 273 rhs = eval_getname(funcnp, ex, events, np->u.expr.right, 274 globals, croot, arrowp, try, &duped_rhs); 275 path = ipath2str(NULL, ipath(lhs)); 276 matchthis[1] = stable(path); 277 if (lhs->u.name.last->u.name.cp != NULL) 278 cp[0] = lhs->u.name.last->u.name.cp; 279 else 280 cp[0] = config_lookup(croot, path, 0); 281 FREE((void *)path); 282 path = ipath2str(NULL, ipath(rhs)); 283 matchthis[0] = stable(path); 284 if (rhs->u.name.last->u.name.cp != NULL) 285 cp[1] = rhs->u.name.last->u.name.cp; 286 else 287 cp[1] = config_lookup(croot, path, 0); 288 FREE((void *)path); 289 if (duped_lhs) 290 tree_free(lhs); 291 if (duped_rhs) 292 tree_free(rhs); 293 294 valuep->t = UINT64; 295 valuep->v = 0; 296 if (cp[0] == NULL || cp[1] == NULL) 297 return (1); 298 299 /* to thine self always be connected */ 300 if (cp[0] == cp[1]) { 301 valuep->v = 1; 302 return (1); 303 } 304 305 /* 306 * Extract "connected" property from each cp. Search this 307 * property for the name associated with the other cp[]. 308 */ 309 for (i = 0; i < 2 && valuep->v == 0; i++) { 310 for (j = 0; connstrings[j] != NULL && valuep->v == 0; 311 j++) { 312 s = config_getprop(cp[i], 313 stable(connstrings[j])); 314 if (s != NULL) { 315 nameslist = STRDUP(s); 316 w = strtok(nameslist, " ,"); 317 while (w != NULL) { 318 if (stable(w) == matchthis[i]) { 319 valuep->v = 1; 320 break; 321 } 322 w = strtok(NULL, " ,"); 323 } 324 FREE(nameslist); 325 } 326 } 327 } 328 return (1); 329 } else if (funcname == L_is_type) { 330 const char *typestrings[] = { "type", "TYPE", NULL }; 331 const char *s; 332 int i; 333 334 nodep = eval_getname(funcnp, ex, events, np, globals, 335 croot, arrowp, try, &duped); 336 if (nodep->u.name.last->u.name.cp != NULL) { 337 cp = nodep->u.name.last->u.name.cp; 338 } else { 339 path = ipath2str(NULL, ipath(nodep)); 340 cp = config_lookup(croot, path, 0); 341 FREE((void *)path); 342 } 343 if (duped) 344 tree_free(nodep); 345 346 valuep->t = STRING; 347 valuep->v = (uintptr_t)stable(""); 348 if (cp == NULL) 349 return (1); 350 for (i = 0; typestrings[i] != NULL; i++) { 351 s = config_getprop(cp, stable(typestrings[i])); 352 if (s != NULL) { 353 valuep->v = (uintptr_t)stable(s); 354 break; 355 } 356 } 357 return (1); 358 } else if (funcname == L_is_on) { 359 const char *onstrings[] = { "on", "ON", NULL }; 360 const char *truestrings[] = { "yes", "YES", "y", "Y", 361 "true", "TRUE", "t", "T", "1", NULL }; 362 const char *s; 363 int i, j; 364 365 nodep = eval_getname(funcnp, ex, events, np, globals, 366 croot, arrowp, try, &duped); 367 if (nodep->u.name.last->u.name.cp != NULL) { 368 cp = nodep->u.name.last->u.name.cp; 369 } else { 370 path = ipath2str(NULL, ipath(nodep)); 371 cp = config_lookup(croot, path, 0); 372 FREE((void *)path); 373 } 374 if (duped) 375 tree_free(nodep); 376 377 valuep->t = UINT64; 378 valuep->v = 0; 379 if (cp == NULL) 380 return (1); 381 for (i = 0; onstrings[i] != NULL; i++) { 382 s = config_getprop(cp, stable(onstrings[i])); 383 if (s != NULL) { 384 s = stable(s); 385 for (j = 0; truestrings[j] != NULL; j++) { 386 if (s == stable(truestrings[j])) { 387 valuep->v = 1; 388 return (1); 389 } 390 } 391 } 392 } 393 return (1); 394 } else if (funcname == L_is_present) { 395 nodep = eval_getname(funcnp, ex, events, np, globals, 396 croot, arrowp, try, &duped); 397 if (nodep->u.name.last->u.name.cp != NULL) { 398 cp = nodep->u.name.last->u.name.cp; 399 } else { 400 path = ipath2str(NULL, ipath(nodep)); 401 cp = config_lookup(croot, path, 0); 402 FREE((void *)path); 403 } 404 if (duped) 405 tree_free(nodep); 406 407 valuep->t = UINT64; 408 valuep->v = 0; 409 if (cp != NULL) 410 valuep->v = 1; 411 return (1); 412 } else if (funcname == L_count) { 413 struct stats *statp; 414 struct istat_entry ent; 415 416 ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t)); 417 418 nodep = np->u.event.epname; 419 if (try) { 420 if (eval_expr(nodep, ex, events, globals, 421 croot, arrowp, try, &val) && val.t == NODEPTR) 422 nodep = (struct node *)(uintptr_t)val.v; 423 else { 424 duped = 1; 425 nodep = eval_dup(nodep, ex, events); 426 } 427 } 428 ent.ename = np->u.event.ename->u.name.s; 429 ent.ipath = ipath(nodep); 430 valuep->t = UINT64; 431 if ((statp = (struct stats *) 432 lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL) 433 valuep->v = 0; 434 else 435 valuep->v = stats_counter_value(statp); 436 if (duped) 437 tree_free(nodep); 438 return (1); 439 } else if (funcname == L_envprop) { 440 outfl(O_DIE, np->file, np->line, 441 "eval_func: %s not yet supported", funcname); 442 } 443 444 if (try) 445 return (0); 446 447 if (funcname == L_fru) { 448 valuep->t = NODEPTR; 449 valuep->v = (uintptr_t)eval_fru(np); 450 return (1); 451 } else if (funcname == L_asru) { 452 valuep->t = NODEPTR; 453 valuep->v = (uintptr_t)eval_asru(np); 454 return (1); 455 } else if (funcname == L_defined) { 456 ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str); 457 valuep->t = UINT64; 458 valuep->v = (lut_lookup(*globals, 459 (void *)np->u.globid.s, NULL) != NULL); 460 return (1); 461 } else if (funcname == L_call) { 462 return (! platform_call(np, globals, croot, arrowp, valuep)); 463 } else if (funcname == L_payloadprop) { 464 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 465 "payloadprop(\"%s\") ", np->u.quote.s); 466 467 if (arrowp->head->myevent->count == 0) { 468 /* 469 * Haven't seen this ereport yet, so must defer 470 */ 471 out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 472 return (0); 473 } else if (platform_payloadprop(np, valuep)) { 474 /* platform_payloadprop() returned false */ 475 out(O_ALTFP|O_VERB, "not found."); 476 valuep->t = UNDEFINED; 477 return (1); 478 } else { 479 switch (valuep->t) { 480 case UINT64: 481 case NODEPTR: 482 out(O_ALTFP|O_VERB2, "found: %llu", valuep->v); 483 break; 484 case STRING: 485 out(O_ALTFP|O_VERB2, "found: \"%s\"", 486 (char *)(uintptr_t)valuep->v); 487 break; 488 default: 489 out(O_ALTFP|O_VERB2, "found: undefined"); 490 break; 491 } 492 return (1); 493 } 494 } else if (funcname == L_setpayloadprop) { 495 struct evalue *payloadvalp; 496 int alloced = 0; 497 498 ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 499 ASSERTinfo(np->u.expr.left->t == T_QUOTE, 500 ptree_nodetype2str(np->u.expr.left->t)); 501 502 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 503 "setpayloadprop: %s: %s=", 504 arrowp->tail->myevent->enode->u.event.ename->u.name.s, 505 np->u.expr.left->u.quote.s); 506 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 507 508 /* 509 * allocate a struct evalue to hold the payload property's 510 * value, unless we've been here already, in which case we 511 * might calculate a different value, but we'll store it 512 * in the already-allocated struct evalue. 513 */ 514 if ((payloadvalp = (struct evalue *)lut_lookup( 515 arrowp->tail->myevent->payloadprops, 516 (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) { 517 payloadvalp = MALLOC(sizeof (*payloadvalp)); 518 alloced = 1; 519 } 520 521 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 522 arrowp, try, payloadvalp)) { 523 out(O_ALTFP|O_VERB2, " (cannot eval)"); 524 if (alloced) 525 FREE(payloadvalp); 526 return (0); 527 } else { 528 if (payloadvalp->t == UNDEFINED) { 529 /* function is always true */ 530 out(O_ALTFP|O_VERB2, " (undefined)"); 531 valuep->t = UINT64; 532 valuep->v = 1; 533 return (1); 534 } 535 if (payloadvalp->t == UINT64) 536 out(O_ALTFP|O_VERB2, 537 " (%llu)", payloadvalp->v); 538 else 539 out(O_ALTFP|O_VERB2, " (\"%s\")", 540 (char *)(uintptr_t)payloadvalp->v); 541 } 542 543 /* add to table of payload properties for current problem */ 544 arrowp->tail->myevent->payloadprops = 545 lut_add(arrowp->tail->myevent->payloadprops, 546 (void *)np->u.expr.left->u.quote.s, 547 (void *)payloadvalp, NULL); 548 549 /* function is always true */ 550 valuep->t = UINT64; 551 valuep->v = 1; 552 return (1); 553 } else if (funcname == L_payloadprop_defined) { 554 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 555 "payloadprop_defined(\"%s\") ", np->u.quote.s); 556 557 if (arrowp->head->myevent->count == 0) { 558 /* 559 * Haven't seen this ereport yet, so must defer 560 */ 561 out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 562 return (0); 563 } else if (platform_payloadprop(np, NULL)) { 564 /* platform_payloadprop() returned false */ 565 valuep->v = 0; 566 out(O_ALTFP|O_VERB2, "not found."); 567 } else { 568 valuep->v = 1; 569 out(O_ALTFP|O_VERB2, "found."); 570 } 571 valuep->t = UINT64; 572 return (1); 573 } else if (funcname == L_payloadprop_contains) { 574 int nvals; 575 struct evalue *vals; 576 struct evalue cmpval; 577 578 ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 579 ASSERTinfo(np->u.expr.left->t == T_QUOTE, 580 ptree_nodetype2str(np->u.expr.left->t)); 581 582 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 583 "payloadprop_contains(\"%s\", ", 584 np->u.expr.left->u.quote.s); 585 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 586 out(O_ALTFP|O_VERB2|O_NONL, ") "); 587 588 /* evaluate the expression we're comparing against */ 589 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 590 arrowp, try, &cmpval)) { 591 out(O_ALTFP|O_VERB2|O_NONL, 592 "(cannot eval) "); 593 return (0); 594 } else { 595 switch (cmpval.t) { 596 case UNDEFINED: 597 out(O_ALTFP|O_VERB2, "(undefined type)"); 598 break; 599 600 case UINT64: 601 out(O_ALTFP|O_VERB2, 602 "(%llu) ", cmpval.v); 603 break; 604 605 case STRING: 606 out(O_ALTFP|O_VERB2, 607 "(\"%s\") ", (char *)(uintptr_t)cmpval.v); 608 break; 609 610 case NODEPTR: 611 out(O_ALTFP|O_VERB2|O_NONL, "("); 612 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, 613 (struct node *)(uintptr_t)(cmpval.v)); 614 out(O_ALTFP|O_VERB2, ") "); 615 break; 616 } 617 } 618 619 /* get the payload values and check for a match */ 620 vals = platform_payloadprop_values(np->u.expr.left->u.quote.s, 621 &nvals); 622 valuep->t = UINT64; 623 valuep->v = 0; 624 if (arrowp->head->myevent->count == 0) { 625 /* 626 * Haven't seen this ereport yet, so must defer 627 */ 628 out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 629 return (0); 630 } else if (nvals == 0) { 631 out(O_ALTFP|O_VERB2, "not found."); 632 return (1); 633 } else { 634 struct evalue preval; 635 int i; 636 637 out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals); 638 639 for (i = 0; i < nvals; i++) { 640 641 preval.t = vals[i].t; 642 preval.v = vals[i].v; 643 644 if (check_expr_args(&vals[i], &cmpval, 645 UNDEFINED, np)) 646 continue; 647 648 /* 649 * If we auto-converted the value to a 650 * string, we need to free the 651 * original tree value. 652 */ 653 if (preval.t == NODEPTR && 654 ((struct node *)(uintptr_t)(preval.v))->t == 655 T_NAME) { 656 tree_free((struct node *)(uintptr_t) 657 preval.v); 658 } 659 660 if (vals[i].v == cmpval.v) { 661 valuep->v = 1; 662 break; 663 } 664 } 665 666 if (valuep->v) 667 out(O_ALTFP|O_VERB2, "match."); 668 else 669 out(O_ALTFP|O_VERB2, "no match."); 670 671 for (i = 0; i < nvals; i++) { 672 if (vals[i].t == NODEPTR) { 673 tree_free((struct node *)(uintptr_t) 674 vals[i].v); 675 break; 676 } 677 } 678 FREE(vals); 679 } 680 return (1); 681 } else if (funcname == L_confcall) { 682 return (!platform_confcall(np, globals, croot, arrowp, valuep)); 683 } else 684 outfl(O_DIE, np->file, np->line, 685 "eval_func: unexpected func: %s", funcname); 686 /*NOTREACHED*/ 687 return (0); 688 } 689 690 /* 691 * defines for u.expr.temp - these are used for T_OR and T_AND so that if 692 * we worked out that part of the expression was true or false during an 693 * earlier eval_expr, then we don't need to dup that part. 694 */ 695 696 #define EXPR_TEMP_BOTH_UNK 0 697 #define EXPR_TEMP_LHS_UNK 1 698 #define EXPR_TEMP_RHS_UNK 2 699 700 static struct node * 701 eval_dup(struct node *np, struct lut *ex, struct node *events[]) 702 { 703 struct node *newnp; 704 705 if (np == NULL) 706 return (NULL); 707 708 switch (np->t) { 709 case T_GLOBID: 710 return (tree_globid(np->u.globid.s, np->file, np->line)); 711 712 case T_ASSIGN: 713 case T_CONDIF: 714 case T_CONDELSE: 715 case T_NE: 716 case T_EQ: 717 case T_LT: 718 case T_LE: 719 case T_GT: 720 case T_GE: 721 case T_BITAND: 722 case T_BITOR: 723 case T_BITXOR: 724 case T_BITNOT: 725 case T_LSHIFT: 726 case T_RSHIFT: 727 case T_NOT: 728 case T_ADD: 729 case T_SUB: 730 case T_MUL: 731 case T_DIV: 732 case T_MOD: 733 return (tree_expr(np->t, 734 eval_dup(np->u.expr.left, ex, events), 735 eval_dup(np->u.expr.right, ex, events))); 736 case T_LIST: 737 case T_AND: 738 switch (np->u.expr.temp) { 739 case EXPR_TEMP_LHS_UNK: 740 return (eval_dup(np->u.expr.left, ex, events)); 741 case EXPR_TEMP_RHS_UNK: 742 return (eval_dup(np->u.expr.right, ex, events)); 743 default: 744 return (tree_expr(np->t, 745 eval_dup(np->u.expr.left, ex, events), 746 eval_dup(np->u.expr.right, ex, events))); 747 } 748 749 case T_OR: 750 switch (np->u.expr.temp) { 751 case EXPR_TEMP_LHS_UNK: 752 return (eval_dup(np->u.expr.left, ex, events)); 753 case EXPR_TEMP_RHS_UNK: 754 return (eval_dup(np->u.expr.right, ex, events)); 755 default: 756 return (tree_expr(T_OR, 757 eval_dup(np->u.expr.left, ex, events), 758 eval_dup(np->u.expr.right, ex, events))); 759 } 760 761 case T_NAME: { 762 struct iterinfo *iterinfop; 763 int got_matchf = 0; 764 int got_matcht = 0; 765 struct evalue value; 766 struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL; 767 struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest; 768 769 /* 770 * Check if we already have a match of the nonwildcarded path 771 * in oldepname (check both to and from events). 772 */ 773 for (np1f = np, np2f = events[0]->u.event.oldepname; 774 np1f != NULL && np2f != NULL; 775 np1f = np1f->u.name.next, np2f = np2f->u.name.next) { 776 if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0) 777 break; 778 if (np1f->u.name.child->t != np2f->u.name.child->t) 779 break; 780 if (np1f->u.name.child->t == T_NUM && 781 np1f->u.name.child->u.ull != 782 np2f->u.name.child->u.ull) 783 break; 784 if (np1f->u.name.child->t == T_NAME && 785 strcmp(np1f->u.name.child->u.name.s, 786 np2f->u.name.child->u.name.s) != 0) 787 break; 788 got_matchf++; 789 } 790 for (np1t = np, np2t = events[1]->u.event.oldepname; 791 np1t != NULL && np2t != NULL; 792 np1t = np1t->u.name.next, np2t = np2t->u.name.next) { 793 if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0) 794 break; 795 if (np1t->u.name.child->t != np2t->u.name.child->t) 796 break; 797 if (np1t->u.name.child->t == T_NUM && 798 np1t->u.name.child->u.ull != 799 np2t->u.name.child->u.ull) 800 break; 801 if (np1t->u.name.child->t == T_NAME && 802 strcmp(np1t->u.name.child->u.name.s, 803 np2t->u.name.child->u.name.s) != 0) 804 break; 805 got_matcht++; 806 } 807 nprest = np; 808 if (got_matchf || got_matcht) { 809 /* 810 * so we are wildcarding. Copy ewname in full, plus 811 * matching section of oldepname. Use whichever gives 812 * the closest match. 813 */ 814 if (got_matchf > got_matcht) { 815 npstart = events[0]->u.event.ewname; 816 npcont = events[0]->u.event.oldepname; 817 npend = np2f; 818 nprest = np1f; 819 } else { 820 npstart = events[1]->u.event.ewname; 821 npcont = events[1]->u.event.oldepname; 822 npend = np2t; 823 nprest = np1t; 824 } 825 for (npref = npstart; npref != NULL; 826 npref = npref->u.name.next) { 827 newnp = newnode(T_NAME, np->file, np->line); 828 newnp->u.name.t = npref->u.name.t; 829 newnp->u.name.s = npref->u.name.s; 830 newnp->u.name.last = newnp; 831 newnp->u.name.it = npref->u.name.it; 832 newnp->u.name.cp = npref->u.name.cp; 833 newnp->u.name.child = 834 newnode(T_NUM, np->file, np->line); 835 if (eval_expr(npref->u.name.child, ex, events, 836 NULL, NULL, NULL, 1, &value) == 0 || 837 value.t != UINT64) { 838 outfl(O_DIE, np->file, np->line, 839 "eval_dup: could not resolve " 840 "iterator of %s", np->u.name.s); 841 } 842 newnp->u.name.child->u.ull = value.v; 843 if (retp == NULL) { 844 retp = newnp; 845 } else { 846 retp->u.name.last->u.name.next = newnp; 847 retp->u.name.last = newnp; 848 } 849 } 850 for (npref = npcont; npref != NULL && npref != npend; 851 npref = npref->u.name.next) { 852 newnp = newnode(T_NAME, np->file, np->line); 853 newnp->u.name.t = npref->u.name.t; 854 newnp->u.name.s = npref->u.name.s; 855 newnp->u.name.last = newnp; 856 newnp->u.name.it = npref->u.name.it; 857 newnp->u.name.cp = npref->u.name.cp; 858 newnp->u.name.child = 859 newnode(T_NUM, np->file, np->line); 860 if (eval_expr(npref->u.name.child, ex, events, 861 NULL, NULL, NULL, 1, &value) == 0 || 862 value.t != UINT64) { 863 outfl(O_DIE, np->file, np->line, 864 "eval_dup: could not resolve " 865 "iterator of %s", np->u.name.s); 866 } 867 newnp->u.name.child->u.ull = value.v; 868 if (retp == NULL) { 869 retp = newnp; 870 } else { 871 retp->u.name.last->u.name.next = newnp; 872 retp->u.name.last = newnp; 873 } 874 } 875 } else { 876 /* 877 * not wildcarding - check if explicit iterator 878 */ 879 iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 880 if (iterinfop != NULL) { 881 /* explicit iterator; not part of pathname */ 882 newnp = newnode(T_NUM, np->file, np->line); 883 newnp->u.ull = iterinfop->num; 884 return (newnp); 885 } 886 } 887 888 /* 889 * finally, whether wildcarding or not, we need to copy the 890 * remaining part of the path (if any). This must be defined 891 * absolutely (no more expansion/wildcarding). 892 */ 893 for (npref = nprest; npref != NULL; 894 npref = npref->u.name.next) { 895 newnp = newnode(T_NAME, np->file, np->line); 896 newnp->u.name.t = npref->u.name.t; 897 newnp->u.name.s = npref->u.name.s; 898 newnp->u.name.last = newnp; 899 newnp->u.name.it = npref->u.name.it; 900 newnp->u.name.cp = npref->u.name.cp; 901 newnp->u.name.child = 902 newnode(T_NUM, np->file, np->line); 903 if (eval_expr(npref->u.name.child, ex, events, 904 NULL, NULL, NULL, 1, &value) == 0 || 905 value.t != UINT64) { 906 outfl(O_DIE, np->file, np->line, 907 "eval_dup: could not resolve " 908 "iterator of %s", np->u.name.s); 909 } 910 newnp->u.name.child->u.ull = value.v; 911 if (retp == NULL) { 912 retp = newnp; 913 } else { 914 retp->u.name.last->u.name.next = newnp; 915 retp->u.name.last = newnp; 916 } 917 } 918 return (retp); 919 } 920 921 case T_EVENT: 922 newnp = newnode(T_NAME, np->file, np->line); 923 924 newnp->u.name.t = np->u.event.ename->u.name.t; 925 newnp->u.name.s = np->u.event.ename->u.name.s; 926 newnp->u.name.it = np->u.event.ename->u.name.it; 927 newnp->u.name.last = newnp; 928 929 return (tree_event(newnp, 930 eval_dup(np->u.event.epname, ex, events), 931 eval_dup(np->u.event.eexprlist, ex, events))); 932 933 case T_FUNC: 934 return (tree_func(np->u.func.s, 935 eval_dup(np->u.func.arglist, ex, events), 936 np->file, np->line)); 937 938 case T_QUOTE: 939 newnp = newnode(T_QUOTE, np->file, np->line); 940 newnp->u.quote.s = np->u.quote.s; 941 return (newnp); 942 943 case T_NUM: 944 newnp = newnode(T_NUM, np->file, np->line); 945 newnp->u.ull = np->u.ull; 946 return (newnp); 947 948 default: 949 outfl(O_DIE, np->file, np->line, 950 "eval_dup: unexpected node type: %s", 951 ptree_nodetype2str(np->t)); 952 } 953 /*NOTREACHED*/ 954 return (0); 955 } 956 957 /* 958 * eval_potential -- see if constraint is potentially true 959 * 960 * this function is used at instance tree creation time to see if 961 * any constraints are already known to be false. if this function 962 * returns false, then the constraint will always be false and there's 963 * no need to include the propagation arrow in the instance tree. 964 * 965 * if this routine returns true, either the constraint is known to 966 * be always true (so there's no point in attaching the constraint 967 * to the propagation arrow in the instance tree), or the constraint 968 * contains "deferred" expressions like global variables or poller calls 969 * and so it must be evaluated during calls to fme_eval(). in this last 970 * case, where a constraint needs to be attached to the propagation arrow 971 * in the instance tree, this routine returns a newly created constraint 972 * in *newc where all the non-deferred things have been filled in. 973 * 974 * so in summary: 975 * 976 * return of false: constraint can never be true, *newc will be NULL. 977 * 978 * return of true with *newc unchanged: constraint will always be true. 979 * 980 * return of true with *newc changed: use new constraint in *newc. 981 * 982 * the lookup table for all explicit iterators, ex, is passed in. 983 * 984 * *newc can either be NULL on entry, or if can contain constraints from 985 * previous calls to eval_potential() (i.e. for building up an instance 986 * tree constraint from several potential constraints). if *newc already 987 * contains constraints, anything added to it will be joined by adding 988 * a T_AND node at the top of *newc. 989 */ 990 int 991 eval_potential(struct node *np, struct lut *ex, struct node *events[], 992 struct node **newc, struct config *croot) 993 { 994 struct node *newnp; 995 struct evalue value; 996 997 if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) { 998 /* 999 * couldn't eval expression because 1000 * it contains deferred items. make 1001 * a duplicate expression with all the 1002 * non-deferred items expanded. 1003 */ 1004 newnp = eval_dup(np, ex, events); 1005 1006 if (*newc == NULL) { 1007 /* 1008 * constraint is potentially true if deferred 1009 * expression in newnp is true. *newc was NULL 1010 * so new constraint is just the one in newnp. 1011 */ 1012 *newc = newnp; 1013 return (1); 1014 } else { 1015 /* 1016 * constraint is potentially true if deferred 1017 * expression in newnp is true. *newc already 1018 * contained a constraint so add an AND with the 1019 * constraint in newnp. 1020 */ 1021 *newc = tree_expr(T_AND, *newc, newnp); 1022 return (1); 1023 } 1024 } else if (value.t == UNDEFINED) { 1025 /* constraint can never be true */ 1026 return (0); 1027 } else if (value.t == UINT64 && value.v == 0) { 1028 /* constraint can never be true */ 1029 return (0); 1030 } else { 1031 /* constraint is always true (nothing deferred to eval) */ 1032 return (1); 1033 } 1034 } 1035 1036 static int 1037 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 1038 struct node *np) 1039 { 1040 /* auto-convert T_NAMES to strings */ 1041 if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t == 1042 T_NAME) { 1043 char *s = ipath2str(NULL, 1044 ipath((struct node *)(uintptr_t)lp->v)); 1045 lp->t = STRING; 1046 lp->v = (uintptr_t)stable(s); 1047 FREE(s); 1048 out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"", 1049 (char *)(uintptr_t)lp->v); 1050 } 1051 if (rp != NULL && 1052 rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t == 1053 T_NAME) { 1054 char *s = ipath2str(NULL, 1055 ipath((struct node *)(uintptr_t)rp->v)); 1056 rp->t = STRING; 1057 rp->v = (uintptr_t)stable(s); 1058 FREE(s); 1059 out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"", 1060 (char *)(uintptr_t)rp->v); 1061 } 1062 1063 /* auto-convert strings to numbers */ 1064 if (dtype == UINT64) { 1065 if (lp->t == STRING) { 1066 lp->t = UINT64; 1067 lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0); 1068 } 1069 if (rp != NULL && rp->t == STRING) { 1070 rp->t = UINT64; 1071 rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0); 1072 } 1073 } 1074 1075 if (dtype != UNDEFINED && lp->t != dtype) { 1076 outfl(O_DIE, np->file, np->line, 1077 "invalid datatype of argument for operation %s", 1078 ptree_nodetype2str(np->t)); 1079 /* NOTREACHED */ 1080 return (1); 1081 } 1082 1083 if (rp != NULL && lp->t != rp->t) { 1084 outfl(O_DIE, np->file, np->line, 1085 "mismatch in datatype of arguments for operation %s", 1086 ptree_nodetype2str(np->t)); 1087 /* NOTREACHED */ 1088 return (1); 1089 } 1090 1091 return (0); 1092 } 1093 1094 /* 1095 * eval_expr -- evaluate expression into *valuep 1096 * 1097 * the meaning of the return value depends on the input value of try. 1098 * 1099 * for try == 1: if any deferred items are encounted, bail out and return 1100 * false. returns true if we made it through entire expression without 1101 * hitting any deferred items. 1102 * 1103 * for try == 0: return true if all operations were performed successfully. 1104 * return false if otherwise. for example, any of the following conditions 1105 * will result in a false return value: 1106 * - attempted use of an uninitialized global variable 1107 * - failure in function evaluation 1108 * - illegal arithmetic operation (argument out of range) 1109 */ 1110 int 1111 eval_expr(struct node *np, struct lut *ex, struct node *events[], 1112 struct lut **globals, struct config *croot, struct arrow *arrowp, 1113 int try, struct evalue *valuep) 1114 { 1115 struct evalue *gval; 1116 struct evalue lval; 1117 struct evalue rval; 1118 1119 if (np == NULL) { 1120 valuep->t = UINT64; 1121 valuep->v = 1; /* no constraint means "true" */ 1122 return (1); 1123 } 1124 1125 valuep->t = UNDEFINED; 1126 1127 switch (np->t) { 1128 case T_GLOBID: 1129 if (try) 1130 return (0); 1131 1132 /* 1133 * only handle case of getting (and not setting) the value 1134 * of a global variable 1135 */ 1136 gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 1137 if (gval == NULL) { 1138 return (0); 1139 } else { 1140 valuep->t = gval->t; 1141 valuep->v = gval->v; 1142 return (1); 1143 } 1144 1145 case T_ASSIGN: 1146 if (try) 1147 return (0); 1148 1149 /* 1150 * first evaluate rhs, then try to store value in lhs which 1151 * should be a global variable 1152 */ 1153 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1154 arrowp, try, &rval)) 1155 return (0); 1156 1157 ASSERT(np->u.expr.left->t == T_GLOBID); 1158 gval = lut_lookup(*globals, 1159 (void *)np->u.expr.left->u.globid.s, NULL); 1160 1161 if (gval == NULL) { 1162 gval = MALLOC(sizeof (*gval)); 1163 *globals = lut_add(*globals, 1164 (void *) np->u.expr.left->u.globid.s, gval, NULL); 1165 } 1166 1167 gval->t = rval.t; 1168 gval->v = rval.v; 1169 1170 if (gval->t == UINT64) { 1171 out(O_ALTFP|O_VERB2, 1172 "assign $%s=%llu", 1173 np->u.expr.left->u.globid.s, gval->v); 1174 } else { 1175 out(O_ALTFP|O_VERB2, 1176 "assign $%s=\"%s\"", 1177 np->u.expr.left->u.globid.s, 1178 (char *)(uintptr_t)gval->v); 1179 } 1180 1181 /* 1182 * but always return true -- an assignment should not 1183 * cause a constraint to be false. 1184 */ 1185 valuep->t = UINT64; 1186 valuep->v = 1; 1187 return (1); 1188 1189 case T_EQ: 1190 #define IMPLICIT_ASSIGN_IN_EQ 1191 #ifdef IMPLICIT_ASSIGN_IN_EQ 1192 /* 1193 * if lhs is an uninitialized global variable, perform 1194 * an assignment. 1195 * 1196 * one insidious side effect of implicit assignment is 1197 * that the "==" operator does not return a Boolean if 1198 * implicit assignment was performed. 1199 */ 1200 if (try == 0 && 1201 np->u.expr.left->t == T_GLOBID && 1202 (gval = lut_lookup(*globals, 1203 (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 1204 if (!eval_expr(np->u.expr.right, ex, events, globals, 1205 croot, arrowp, try, &rval)) 1206 return (0); 1207 1208 gval = MALLOC(sizeof (*gval)); 1209 *globals = lut_add(*globals, 1210 (void *) np->u.expr.left->u.globid.s, 1211 gval, NULL); 1212 1213 gval->t = rval.t; 1214 gval->v = rval.v; 1215 valuep->t = rval.t; 1216 valuep->v = rval.v; 1217 return (1); 1218 } 1219 #endif /* IMPLICIT_ASSIGN_IN_EQ */ 1220 1221 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1222 arrowp, try, &lval)) 1223 return (0); 1224 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1225 arrowp, try, &rval)) 1226 return (0); 1227 if (rval.t == UINT64 || lval.t == UINT64) { 1228 if (check_expr_args(&lval, &rval, UINT64, np)) 1229 return (0); 1230 } else { 1231 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 1232 return (0); 1233 } 1234 1235 valuep->t = UINT64; 1236 valuep->v = (lval.v == rval.v); 1237 return (1); 1238 1239 case T_LT: 1240 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1241 arrowp, try, &lval)) 1242 return (0); 1243 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1244 arrowp, try, &rval)) 1245 return (0); 1246 if (check_expr_args(&lval, &rval, UINT64, np)) 1247 return (0); 1248 1249 valuep->t = UINT64; 1250 valuep->v = (lval.v < rval.v); 1251 return (1); 1252 1253 case T_LE: 1254 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1255 arrowp, try, &lval)) 1256 return (0); 1257 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1258 arrowp, try, &rval)) 1259 return (0); 1260 if (check_expr_args(&lval, &rval, UINT64, np)) 1261 return (0); 1262 1263 valuep->t = UINT64; 1264 valuep->v = (lval.v <= rval.v); 1265 return (1); 1266 1267 case T_GT: 1268 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1269 arrowp, try, &lval)) 1270 return (0); 1271 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1272 arrowp, try, &rval)) 1273 return (0); 1274 if (check_expr_args(&lval, &rval, UINT64, np)) 1275 return (0); 1276 1277 valuep->t = UINT64; 1278 valuep->v = (lval.v > rval.v); 1279 return (1); 1280 1281 case T_GE: 1282 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1283 arrowp, try, &lval)) 1284 return (0); 1285 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1286 arrowp, try, &rval)) 1287 return (0); 1288 if (check_expr_args(&lval, &rval, UINT64, np)) 1289 return (0); 1290 1291 valuep->t = UINT64; 1292 valuep->v = (lval.v >= rval.v); 1293 return (1); 1294 1295 case T_BITAND: 1296 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1297 arrowp, try, &lval)) 1298 return (0); 1299 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1300 arrowp, try, &rval)) 1301 return (0); 1302 if (check_expr_args(&lval, &rval, UINT64, np)) 1303 return (0); 1304 1305 valuep->t = lval.t; 1306 valuep->v = (lval.v & rval.v); 1307 return (1); 1308 1309 case T_BITOR: 1310 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1311 arrowp, try, &lval)) 1312 return (0); 1313 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1314 arrowp, try, &rval)) 1315 return (0); 1316 if (check_expr_args(&lval, &rval, UINT64, np)) 1317 return (0); 1318 1319 valuep->t = lval.t; 1320 valuep->v = (lval.v | rval.v); 1321 return (1); 1322 1323 case T_BITXOR: 1324 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1325 arrowp, try, &lval)) 1326 return (0); 1327 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1328 arrowp, try, &rval)) 1329 return (0); 1330 if (check_expr_args(&lval, &rval, UINT64, np)) 1331 return (0); 1332 1333 valuep->t = lval.t; 1334 valuep->v = (lval.v ^ rval.v); 1335 return (1); 1336 1337 case T_BITNOT: 1338 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1339 arrowp, try, &lval)) 1340 return (0); 1341 ASSERT(np->u.expr.right == NULL); 1342 if (check_expr_args(&lval, NULL, UINT64, np)) 1343 return (0); 1344 1345 valuep->t = UINT64; 1346 valuep->v = ~ lval.v; 1347 return (1); 1348 1349 case T_LSHIFT: 1350 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1351 arrowp, try, &lval)) 1352 return (0); 1353 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1354 arrowp, try, &rval)) 1355 return (0); 1356 if (check_expr_args(&lval, &rval, UINT64, np)) 1357 return (0); 1358 1359 valuep->t = UINT64; 1360 valuep->v = (lval.v << rval.v); 1361 return (1); 1362 1363 case T_RSHIFT: 1364 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1365 arrowp, try, &lval)) 1366 return (0); 1367 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1368 arrowp, try, &rval)) 1369 return (0); 1370 if (check_expr_args(&lval, &rval, UINT64, np)) 1371 return (0); 1372 1373 valuep->t = UINT64; 1374 valuep->v = (lval.v >> rval.v); 1375 return (1); 1376 1377 case T_CONDIF: { 1378 struct node *retnp; 1379 int dotrue = 0; 1380 1381 /* 1382 * evaluate 1383 * expression ? stmtA [ : stmtB ] 1384 * 1385 * first see if expression is true or false, then determine 1386 * if stmtA (or stmtB, if it exists) should be evaluated. 1387 * 1388 * "dotrue = 1" means stmtA should be evaluated. 1389 */ 1390 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1391 arrowp, try, &lval)) 1392 return (0); 1393 1394 if (lval.t != UNDEFINED && lval.v != 0) 1395 dotrue = 1; 1396 1397 ASSERT(np->u.expr.right != NULL); 1398 if (np->u.expr.right->t == T_CONDELSE) { 1399 if (dotrue) 1400 retnp = np->u.expr.right->u.expr.left; 1401 else 1402 retnp = np->u.expr.right->u.expr.right; 1403 } else { 1404 /* no ELSE clause */ 1405 if (dotrue) 1406 retnp = np->u.expr.right; 1407 else { 1408 outfl(O_DIE, np->file, np->line, 1409 "eval_expr: missing condelse"); 1410 } 1411 } 1412 1413 if (!eval_expr(retnp, ex, events, globals, croot, 1414 arrowp, try, valuep)) 1415 return (0); 1416 return (1); 1417 } 1418 1419 case T_CONDELSE: 1420 /* 1421 * shouldn't get here, since T_CONDELSE is supposed to be 1422 * evaluated as part of T_CONDIF 1423 */ 1424 out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 1425 ptree_nodetype2str(np->t)); 1426 /*NOTREACHED*/ 1427 1428 case T_NE: 1429 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1430 arrowp, try, &lval)) 1431 return (0); 1432 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1433 arrowp, try, &rval)) 1434 return (0); 1435 if (rval.t == UINT64 || lval.t == UINT64) { 1436 if (check_expr_args(&lval, &rval, UINT64, np)) 1437 return (0); 1438 } else { 1439 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 1440 return (0); 1441 } 1442 1443 valuep->t = UINT64; 1444 valuep->v = (lval.v != rval.v); 1445 return (1); 1446 1447 case T_LIST: 1448 case T_AND: 1449 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1450 arrowp, try, valuep)) { 1451 /* 1452 * if lhs is unknown, still check rhs. If that 1453 * is false we can return false irrespective of lhs 1454 */ 1455 if (!try) { 1456 np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 1457 return (0); 1458 } 1459 if (!eval_expr(np->u.expr.right, ex, events, globals, 1460 croot, arrowp, try, valuep)) { 1461 np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 1462 return (0); 1463 } 1464 if (valuep->v != 0) { 1465 np->u.expr.temp = EXPR_TEMP_LHS_UNK; 1466 return (0); 1467 } 1468 } 1469 if (valuep->v == 0) { 1470 valuep->t = UINT64; 1471 return (1); 1472 } 1473 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1474 arrowp, try, valuep)) { 1475 np->u.expr.temp = EXPR_TEMP_RHS_UNK; 1476 return (0); 1477 } 1478 valuep->t = UINT64; 1479 valuep->v = valuep->v == 0 ? 0 : 1; 1480 return (1); 1481 1482 case T_OR: 1483 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1484 arrowp, try, valuep)) { 1485 /* 1486 * if lhs is unknown, still check rhs. If that 1487 * is true we can return true irrespective of lhs 1488 */ 1489 if (!try) { 1490 np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 1491 return (0); 1492 } 1493 if (!eval_expr(np->u.expr.right, ex, events, globals, 1494 croot, arrowp, try, valuep)) { 1495 np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 1496 return (0); 1497 } 1498 if (valuep->v == 0) { 1499 np->u.expr.temp = EXPR_TEMP_LHS_UNK; 1500 return (0); 1501 } 1502 } 1503 if (valuep->v != 0) { 1504 valuep->t = UINT64; 1505 valuep->v = 1; 1506 return (1); 1507 } 1508 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1509 arrowp, try, valuep)) { 1510 np->u.expr.temp = EXPR_TEMP_RHS_UNK; 1511 return (0); 1512 } 1513 valuep->t = UINT64; 1514 valuep->v = valuep->v == 0 ? 0 : 1; 1515 return (1); 1516 1517 case T_NOT: 1518 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1519 arrowp, try, valuep)) 1520 return (0); 1521 valuep->t = UINT64; 1522 valuep->v = ! valuep->v; 1523 return (1); 1524 1525 case T_ADD: 1526 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1527 arrowp, try, &lval)) 1528 return (0); 1529 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1530 arrowp, try, &rval)) 1531 return (0); 1532 if (check_expr_args(&lval, &rval, UINT64, np)) 1533 return (0); 1534 1535 valuep->t = lval.t; 1536 valuep->v = lval.v + rval.v; 1537 return (1); 1538 1539 case T_SUB: 1540 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1541 arrowp, try, &lval)) 1542 return (0); 1543 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1544 arrowp, try, &rval)) 1545 return (0); 1546 if (check_expr_args(&lval, &rval, UINT64, np)) 1547 return (0); 1548 1549 /* since valuep is unsigned, return false if lval.v < rval.v */ 1550 if (lval.v < rval.v) { 1551 outfl(O_DIE, np->file, np->line, 1552 "eval_expr: T_SUB result is out of range"); 1553 } 1554 1555 valuep->t = lval.t; 1556 valuep->v = lval.v - rval.v; 1557 return (1); 1558 1559 case T_MUL: 1560 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1561 arrowp, try, &lval)) 1562 return (0); 1563 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1564 arrowp, try, &rval)) 1565 return (0); 1566 if (check_expr_args(&lval, &rval, UINT64, np)) 1567 return (0); 1568 1569 valuep->t = lval.t; 1570 valuep->v = lval.v * rval.v; 1571 return (1); 1572 1573 case T_DIV: 1574 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1575 arrowp, try, &lval)) 1576 return (0); 1577 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1578 arrowp, try, &rval)) 1579 return (0); 1580 if (check_expr_args(&lval, &rval, UINT64, np)) 1581 return (0); 1582 1583 /* return false if dividing by zero */ 1584 if (rval.v == 0) { 1585 outfl(O_DIE, np->file, np->line, 1586 "eval_expr: T_DIV division by zero"); 1587 } 1588 1589 valuep->t = lval.t; 1590 valuep->v = lval.v / rval.v; 1591 return (1); 1592 1593 case T_MOD: 1594 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1595 arrowp, try, &lval)) 1596 return (0); 1597 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1598 arrowp, try, &rval)) 1599 return (0); 1600 if (check_expr_args(&lval, &rval, UINT64, np)) 1601 return (0); 1602 1603 /* return false if dividing by zero */ 1604 if (rval.v == 0) { 1605 outfl(O_DIE, np->file, np->line, 1606 "eval_expr: T_MOD division by zero"); 1607 } 1608 1609 valuep->t = lval.t; 1610 valuep->v = lval.v % rval.v; 1611 return (1); 1612 1613 case T_NAME: 1614 if (try) { 1615 struct iterinfo *iterinfop; 1616 struct node *np1, *np2; 1617 int i, gotmatch = 0; 1618 1619 /* 1620 * Check if we have an exact match of the nonwildcarded 1621 * path in oldepname - if so we can just use the 1622 * full wildcarded path in epname. 1623 */ 1624 for (i = 0; i < 1; i++) { 1625 for (np1 = np, 1626 np2 = events[i]->u.event.oldepname; 1627 np1 != NULL && np2 != NULL; 1628 np1 = np1->u.name.next, 1629 np2 = np2->u.name.next) { 1630 if (strcmp(np1->u.name.s, 1631 np2->u.name.s) != 0) 1632 break; 1633 if (np1->u.name.child->t != 1634 np2->u.name.child->t) 1635 break; 1636 if (np1->u.name.child->t == T_NUM && 1637 np1->u.name.child->u.ull != 1638 np2->u.name.child->u.ull) 1639 break; 1640 if (np1->u.name.child->t == T_NAME && 1641 strcmp(np1->u.name.child->u.name.s, 1642 np2->u.name.child->u.name.s) != 0) 1643 break; 1644 gotmatch++; 1645 } 1646 if (np1 == NULL && np2 == NULL) { 1647 valuep->t = NODEPTR; 1648 valuep->v = (uintptr_t) 1649 events[i]->u.event.epname; 1650 return (1); 1651 } 1652 } 1653 if (!gotmatch) { 1654 /* 1655 * we're not wildcarding. However at 1656 * itree_create() time, we can also expand 1657 * simple iterators - so check for those. 1658 */ 1659 iterinfop = lut_lookup(ex, (void *)np->u.name.s, 1660 NULL); 1661 if (iterinfop != NULL) { 1662 valuep->t = UINT64; 1663 valuep->v = 1664 (unsigned long long)iterinfop->num; 1665 return (1); 1666 } 1667 } 1668 /* 1669 * For anything else we'll have to wait for eval_dup(). 1670 */ 1671 return (0); 1672 } 1673 1674 /* return address of struct node */ 1675 valuep->t = NODEPTR; 1676 valuep->v = (uintptr_t)np; 1677 return (1); 1678 1679 case T_QUOTE: 1680 valuep->t = STRING; 1681 valuep->v = (uintptr_t)np->u.quote.s; 1682 return (1); 1683 1684 case T_FUNC: 1685 return (eval_func(np, ex, events, np->u.func.arglist, 1686 globals, croot, arrowp, try, valuep)); 1687 1688 case T_NUM: 1689 valuep->t = UINT64; 1690 valuep->v = np->u.ull; 1691 return (1); 1692 1693 default: 1694 outfl(O_DIE, np->file, np->line, 1695 "eval_expr: unexpected node type: %s", 1696 ptree_nodetype2str(np->t)); 1697 } 1698 /*NOTREACHED*/ 1699 return (0); 1700 } 1701 1702 /* 1703 * eval_fru() and eval_asru() don't do much, but are called from a number 1704 * of places. 1705 */ 1706 static struct node * 1707 eval_fru(struct node *np) 1708 { 1709 ASSERT(np->t == T_NAME); 1710 return (np); 1711 } 1712 1713 static struct node * 1714 eval_asru(struct node *np) 1715 { 1716 ASSERT(np->t == T_NAME); 1717 return (np); 1718 } 1719