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 (platform_payloadprop(np, valuep)) { 468 /* platform_payloadprop() returned false */ 469 out(O_ALTFP|O_VERB, "payloadprop \"%s\" not found.", 470 np->u.quote.s); 471 return (0); 472 } else { 473 switch (valuep->t) { 474 case UINT64: 475 case NODEPTR: 476 out(O_ALTFP|O_VERB2, "found: %llu", valuep->v); 477 break; 478 case STRING: 479 out(O_ALTFP|O_VERB2, "found: \"%s\"", 480 (char *)(uintptr_t)valuep->v); 481 break; 482 default: 483 out(O_ALTFP|O_VERB2, "found: undefined"); 484 break; 485 } 486 return (1); 487 } 488 } else if (funcname == L_setpayloadprop) { 489 struct evalue *payloadvalp; 490 491 ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 492 ASSERTinfo(np->u.expr.left->t == T_QUOTE, 493 ptree_nodetype2str(np->u.expr.left->t)); 494 495 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 496 "setpayloadprop: %s: %s=", 497 arrowp->tail->myevent->enode->u.event.ename->u.name.s, 498 np->u.expr.left->u.quote.s); 499 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 500 501 /* 502 * allocate a struct evalue to hold the payload property's 503 * value, unless we've been here already, in which case we 504 * might calculate a different value, but we'll store it 505 * in the already-allocated struct evalue. 506 */ 507 if ((payloadvalp = (struct evalue *)lut_lookup( 508 arrowp->tail->myevent->payloadprops, 509 (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) { 510 payloadvalp = MALLOC(sizeof (*payloadvalp)); 511 } 512 513 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 514 arrowp, try, payloadvalp)) { 515 out(O_ALTFP|O_VERB2, " (cannot eval, using zero)"); 516 payloadvalp->t = UINT64; 517 payloadvalp->v = 0; 518 } else { 519 if (payloadvalp->t == UINT64) 520 out(O_ALTFP|O_VERB2, 521 " (%llu)", payloadvalp->v); 522 else 523 out(O_ALTFP|O_VERB2, " (\"%s\")", 524 (char *)(uintptr_t)payloadvalp->v); 525 } 526 527 /* add to table of payload properties for current problem */ 528 arrowp->tail->myevent->payloadprops = 529 lut_add(arrowp->tail->myevent->payloadprops, 530 (void *)np->u.expr.left->u.quote.s, 531 (void *)payloadvalp, NULL); 532 533 /* function is always true */ 534 valuep->t = UINT64; 535 valuep->v = 1; 536 return (1); 537 } else if (funcname == L_payloadprop_defined) { 538 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 539 "payloadprop_defined(\"%s\") ", np->u.quote.s); 540 541 if (platform_payloadprop(np, NULL)) { 542 /* platform_payloadprop() returned false */ 543 valuep->v = 0; 544 out(O_ALTFP|O_VERB2, "payloadprop_defined: \"%s\" " 545 "not defined.", np->u.quote.s); 546 } else { 547 valuep->v = 1; 548 out(O_ALTFP|O_VERB2, "found."); 549 } 550 valuep->t = UINT64; 551 return (1); 552 } else if (funcname == L_payloadprop_contains) { 553 int nvals; 554 struct evalue *vals; 555 struct evalue cmpval; 556 557 ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 558 ASSERTinfo(np->u.expr.left->t == T_QUOTE, 559 ptree_nodetype2str(np->u.expr.left->t)); 560 561 outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 562 "payloadprop_contains(\"%s\", ", 563 np->u.expr.left->u.quote.s); 564 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 565 out(O_ALTFP|O_VERB2|O_NONL, ") "); 566 567 /* evaluate the expression we're comparing against */ 568 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 569 arrowp, try, &cmpval)) { 570 out(O_ALTFP|O_VERB2|O_NONL, 571 "(cannot eval, using zero) "); 572 cmpval.t = UINT64; 573 cmpval.v = 0; 574 } else { 575 switch (cmpval.t) { 576 case UNDEFINED: 577 out(O_ALTFP|O_VERB2, "(undefined type)"); 578 break; 579 580 case UINT64: 581 out(O_ALTFP|O_VERB2, 582 "(%llu) ", cmpval.v); 583 break; 584 585 case STRING: 586 out(O_ALTFP|O_VERB2, 587 "(\"%s\") ", (char *)(uintptr_t)cmpval.v); 588 break; 589 590 case NODEPTR: 591 out(O_ALTFP|O_VERB2|O_NONL, "("); 592 ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, 593 (struct node *)(uintptr_t)(cmpval.v)); 594 out(O_ALTFP|O_VERB2, ") "); 595 break; 596 } 597 } 598 599 /* get the payload values and check for a match */ 600 vals = platform_payloadprop_values(np->u.expr.left->u.quote.s, 601 &nvals); 602 valuep->t = UINT64; 603 valuep->v = 0; 604 if (nvals == 0) { 605 out(O_ALTFP|O_VERB2, "not found."); 606 return (0); 607 } else { 608 struct evalue preval; 609 int i; 610 611 out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals); 612 613 for (i = 0; i < nvals; i++) { 614 615 preval.t = vals[i].t; 616 preval.v = vals[i].v; 617 618 if (check_expr_args(&vals[i], &cmpval, 619 UNDEFINED, np)) 620 continue; 621 622 /* 623 * If we auto-converted the value to a 624 * string, we need to free the 625 * original tree value. 626 */ 627 if (preval.t == NODEPTR && 628 ((struct node *)(uintptr_t)(preval.v))->t == 629 T_NAME) { 630 tree_free((struct node *)(uintptr_t) 631 preval.v); 632 } 633 634 if (vals[i].v == cmpval.v) { 635 valuep->v = 1; 636 break; 637 } 638 } 639 640 if (valuep->v) 641 out(O_ALTFP|O_VERB2, "match."); 642 else 643 out(O_ALTFP|O_VERB2, "no match."); 644 645 for (i = 0; i < nvals; i++) { 646 if (vals[i].t == NODEPTR) { 647 tree_free((struct node *)(uintptr_t) 648 vals[i].v); 649 break; 650 } 651 } 652 FREE(vals); 653 } 654 return (1); 655 } else if (funcname == L_confcall) { 656 return (!platform_confcall(np, globals, croot, arrowp, valuep)); 657 } else 658 outfl(O_DIE, np->file, np->line, 659 "eval_func: unexpected func: %s", funcname); 660 /*NOTREACHED*/ 661 return (0); 662 } 663 664 /* 665 * defines for u.expr.temp - these are used for T_OR and T_AND so that if 666 * we worked out that part of the expression was true or false during an 667 * earlier eval_expr, then we don't need to dup that part. 668 */ 669 670 #define EXPR_TEMP_BOTH_UNK 0 671 #define EXPR_TEMP_LHS_UNK 1 672 #define EXPR_TEMP_RHS_UNK 2 673 674 static struct node * 675 eval_dup(struct node *np, struct lut *ex, struct node *events[]) 676 { 677 struct node *newnp; 678 679 if (np == NULL) 680 return (NULL); 681 682 switch (np->t) { 683 case T_GLOBID: 684 return (tree_globid(np->u.globid.s, np->file, np->line)); 685 686 case T_ASSIGN: 687 case T_CONDIF: 688 case T_CONDELSE: 689 case T_NE: 690 case T_EQ: 691 case T_LT: 692 case T_LE: 693 case T_GT: 694 case T_GE: 695 case T_BITAND: 696 case T_BITOR: 697 case T_BITXOR: 698 case T_BITNOT: 699 case T_LSHIFT: 700 case T_RSHIFT: 701 case T_NOT: 702 case T_ADD: 703 case T_SUB: 704 case T_MUL: 705 case T_DIV: 706 case T_MOD: 707 return (tree_expr(np->t, 708 eval_dup(np->u.expr.left, ex, events), 709 eval_dup(np->u.expr.right, ex, events))); 710 case T_LIST: 711 case T_AND: 712 switch (np->u.expr.temp) { 713 case EXPR_TEMP_LHS_UNK: 714 return (eval_dup(np->u.expr.left, ex, events)); 715 case EXPR_TEMP_RHS_UNK: 716 return (eval_dup(np->u.expr.right, ex, events)); 717 default: 718 return (tree_expr(np->t, 719 eval_dup(np->u.expr.left, ex, events), 720 eval_dup(np->u.expr.right, ex, events))); 721 } 722 723 case T_OR: 724 switch (np->u.expr.temp) { 725 case EXPR_TEMP_LHS_UNK: 726 return (eval_dup(np->u.expr.left, ex, events)); 727 case EXPR_TEMP_RHS_UNK: 728 return (eval_dup(np->u.expr.right, ex, events)); 729 default: 730 return (tree_expr(T_OR, 731 eval_dup(np->u.expr.left, ex, events), 732 eval_dup(np->u.expr.right, ex, events))); 733 } 734 735 case T_NAME: { 736 struct iterinfo *iterinfop; 737 int got_matchf = 0; 738 int got_matcht = 0; 739 struct evalue value; 740 struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL; 741 struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest; 742 743 /* 744 * Check if we already have a match of the nonwildcarded path 745 * in oldepname (check both to and from events). 746 */ 747 for (np1f = np, np2f = events[0]->u.event.oldepname; 748 np1f != NULL && np2f != NULL; 749 np1f = np1f->u.name.next, np2f = np2f->u.name.next) { 750 if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0) 751 break; 752 if (np1f->u.name.child->t != np2f->u.name.child->t) 753 break; 754 if (np1f->u.name.child->t == T_NUM && 755 np1f->u.name.child->u.ull != 756 np2f->u.name.child->u.ull) 757 break; 758 if (np1f->u.name.child->t == T_NAME && 759 strcmp(np1f->u.name.child->u.name.s, 760 np2f->u.name.child->u.name.s) != 0) 761 break; 762 got_matchf++; 763 } 764 for (np1t = np, np2t = events[1]->u.event.oldepname; 765 np1t != NULL && np2t != NULL; 766 np1t = np1t->u.name.next, np2t = np2t->u.name.next) { 767 if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0) 768 break; 769 if (np1t->u.name.child->t != np2t->u.name.child->t) 770 break; 771 if (np1t->u.name.child->t == T_NUM && 772 np1t->u.name.child->u.ull != 773 np2t->u.name.child->u.ull) 774 break; 775 if (np1t->u.name.child->t == T_NAME && 776 strcmp(np1t->u.name.child->u.name.s, 777 np2t->u.name.child->u.name.s) != 0) 778 break; 779 got_matcht++; 780 } 781 nprest = np; 782 if (got_matchf || got_matcht) { 783 /* 784 * so we are wildcarding. Copy ewname in full, plus 785 * matching section of oldepname. Use whichever gives 786 * the closest match. 787 */ 788 if (got_matchf > got_matcht) { 789 npstart = events[0]->u.event.ewname; 790 npcont = events[0]->u.event.oldepname; 791 npend = np2f; 792 nprest = np1f; 793 } else { 794 npstart = events[1]->u.event.ewname; 795 npcont = events[1]->u.event.oldepname; 796 npend = np2t; 797 nprest = np1t; 798 } 799 for (npref = npstart; npref != NULL; 800 npref = npref->u.name.next) { 801 newnp = newnode(T_NAME, np->file, np->line); 802 newnp->u.name.t = npref->u.name.t; 803 newnp->u.name.s = npref->u.name.s; 804 newnp->u.name.last = newnp; 805 newnp->u.name.it = npref->u.name.it; 806 newnp->u.name.cp = npref->u.name.cp; 807 newnp->u.name.child = 808 newnode(T_NUM, np->file, np->line); 809 if (eval_expr(npref->u.name.child, ex, events, 810 NULL, NULL, NULL, 1, &value) == 0 || 811 value.t != UINT64) { 812 outfl(O_DIE, np->file, np->line, 813 "eval_dup: could not resolve " 814 "iterator of %s", np->u.name.s); 815 } 816 newnp->u.name.child->u.ull = value.v; 817 if (retp == NULL) { 818 retp = newnp; 819 } else { 820 retp->u.name.last->u.name.next = newnp; 821 retp->u.name.last = newnp; 822 } 823 } 824 for (npref = npcont; npref != NULL && npref != npend; 825 npref = npref->u.name.next) { 826 newnp = newnode(T_NAME, np->file, np->line); 827 newnp->u.name.t = npref->u.name.t; 828 newnp->u.name.s = npref->u.name.s; 829 newnp->u.name.last = newnp; 830 newnp->u.name.it = npref->u.name.it; 831 newnp->u.name.cp = npref->u.name.cp; 832 newnp->u.name.child = 833 newnode(T_NUM, np->file, np->line); 834 if (eval_expr(npref->u.name.child, ex, events, 835 NULL, NULL, NULL, 1, &value) == 0 || 836 value.t != UINT64) { 837 outfl(O_DIE, np->file, np->line, 838 "eval_dup: could not resolve " 839 "iterator of %s", np->u.name.s); 840 } 841 newnp->u.name.child->u.ull = value.v; 842 if (retp == NULL) { 843 retp = newnp; 844 } else { 845 retp->u.name.last->u.name.next = newnp; 846 retp->u.name.last = newnp; 847 } 848 } 849 } else { 850 /* 851 * not wildcarding - check if explicit iterator 852 */ 853 iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 854 if (iterinfop != NULL) { 855 /* explicit iterator; not part of pathname */ 856 newnp = newnode(T_NUM, np->file, np->line); 857 newnp->u.ull = iterinfop->num; 858 return (newnp); 859 } 860 } 861 862 /* 863 * finally, whether wildcarding or not, we need to copy the 864 * remaining part of the path (if any). This must be defined 865 * absolutely (no more expansion/wildcarding). 866 */ 867 for (npref = nprest; npref != NULL; 868 npref = npref->u.name.next) { 869 newnp = newnode(T_NAME, np->file, np->line); 870 newnp->u.name.t = npref->u.name.t; 871 newnp->u.name.s = npref->u.name.s; 872 newnp->u.name.last = newnp; 873 newnp->u.name.it = npref->u.name.it; 874 newnp->u.name.cp = npref->u.name.cp; 875 newnp->u.name.child = 876 newnode(T_NUM, np->file, np->line); 877 if (eval_expr(npref->u.name.child, ex, events, 878 NULL, NULL, NULL, 1, &value) == 0 || 879 value.t != UINT64) { 880 outfl(O_DIE, np->file, np->line, 881 "eval_dup: could not resolve " 882 "iterator of %s", np->u.name.s); 883 } 884 newnp->u.name.child->u.ull = value.v; 885 if (retp == NULL) { 886 retp = newnp; 887 } else { 888 retp->u.name.last->u.name.next = newnp; 889 retp->u.name.last = newnp; 890 } 891 } 892 return (retp); 893 } 894 895 case T_EVENT: 896 newnp = newnode(T_NAME, np->file, np->line); 897 898 newnp->u.name.t = np->u.event.ename->u.name.t; 899 newnp->u.name.s = np->u.event.ename->u.name.s; 900 newnp->u.name.it = np->u.event.ename->u.name.it; 901 newnp->u.name.last = newnp; 902 903 return (tree_event(newnp, 904 eval_dup(np->u.event.epname, ex, events), 905 eval_dup(np->u.event.eexprlist, ex, events))); 906 907 case T_FUNC: 908 return (tree_func(np->u.func.s, 909 eval_dup(np->u.func.arglist, ex, events), 910 np->file, np->line)); 911 912 case T_QUOTE: 913 newnp = newnode(T_QUOTE, np->file, np->line); 914 newnp->u.quote.s = np->u.quote.s; 915 return (newnp); 916 917 case T_NUM: 918 newnp = newnode(T_NUM, np->file, np->line); 919 newnp->u.ull = np->u.ull; 920 return (newnp); 921 922 default: 923 outfl(O_DIE, np->file, np->line, 924 "eval_dup: unexpected node type: %s", 925 ptree_nodetype2str(np->t)); 926 } 927 /*NOTREACHED*/ 928 return (0); 929 } 930 931 /* 932 * eval_potential -- see if constraint is potentially true 933 * 934 * this function is used at instance tree creation time to see if 935 * any constraints are already known to be false. if this function 936 * returns false, then the constraint will always be false and there's 937 * no need to include the propagation arrow in the instance tree. 938 * 939 * if this routine returns true, either the constraint is known to 940 * be always true (so there's no point in attaching the constraint 941 * to the propagation arrow in the instance tree), or the constraint 942 * contains "deferred" expressions like global variables or poller calls 943 * and so it must be evaluated during calls to fme_eval(). in this last 944 * case, where a constraint needs to be attached to the propagation arrow 945 * in the instance tree, this routine returns a newly created constraint 946 * in *newc where all the non-deferred things have been filled in. 947 * 948 * so in summary: 949 * 950 * return of false: constraint can never be true, *newc will be NULL. 951 * 952 * return of true with *newc unchanged: constraint will always be true. 953 * 954 * return of true with *newc changed: use new constraint in *newc. 955 * 956 * the lookup table for all explicit iterators, ex, is passed in. 957 * 958 * *newc can either be NULL on entry, or if can contain constraints from 959 * previous calls to eval_potential() (i.e. for building up an instance 960 * tree constraint from several potential constraints). if *newc already 961 * contains constraints, anything added to it will be joined by adding 962 * a T_AND node at the top of *newc. 963 */ 964 int 965 eval_potential(struct node *np, struct lut *ex, struct node *events[], 966 struct node **newc, struct config *croot) 967 { 968 struct node *newnp; 969 struct evalue value; 970 971 if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) { 972 /* 973 * couldn't eval expression because 974 * it contains deferred items. make 975 * a duplicate expression with all the 976 * non-deferred items expanded. 977 */ 978 newnp = eval_dup(np, ex, events); 979 980 if (*newc == NULL) { 981 /* 982 * constraint is potentially true if deferred 983 * expression in newnp is true. *newc was NULL 984 * so new constraint is just the one in newnp. 985 */ 986 *newc = newnp; 987 return (1); 988 } else { 989 /* 990 * constraint is potentially true if deferred 991 * expression in newnp is true. *newc already 992 * contained a constraint so add an AND with the 993 * constraint in newnp. 994 */ 995 *newc = tree_expr(T_AND, *newc, newnp); 996 return (1); 997 } 998 } else if (value.t == UNDEFINED) { 999 /* constraint can never be true */ 1000 return (0); 1001 } else if (value.t == UINT64 && value.v == 0) { 1002 /* constraint can never be true */ 1003 return (0); 1004 } else { 1005 /* constraint is always true (nothing deferred to eval) */ 1006 return (1); 1007 } 1008 } 1009 1010 static int 1011 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 1012 struct node *np) 1013 { 1014 /* auto-convert T_NAMES to strings */ 1015 if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t == 1016 T_NAME) { 1017 char *s = ipath2str(NULL, 1018 ipath((struct node *)(uintptr_t)lp->v)); 1019 lp->t = STRING; 1020 lp->v = (uintptr_t)stable(s); 1021 FREE(s); 1022 out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"", 1023 (char *)(uintptr_t)lp->v); 1024 } 1025 if (rp != NULL && 1026 rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t == 1027 T_NAME) { 1028 char *s = ipath2str(NULL, 1029 ipath((struct node *)(uintptr_t)rp->v)); 1030 rp->t = STRING; 1031 rp->v = (uintptr_t)stable(s); 1032 FREE(s); 1033 out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"", 1034 (char *)(uintptr_t)rp->v); 1035 } 1036 1037 /* auto-convert strings to numbers */ 1038 if (dtype == UINT64) { 1039 if (lp->t == STRING) { 1040 lp->t = UINT64; 1041 lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0); 1042 } 1043 if (rp != NULL && rp->t == STRING) { 1044 rp->t = UINT64; 1045 rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0); 1046 } 1047 } 1048 1049 if (dtype != UNDEFINED && lp->t != dtype) { 1050 outfl(O_DIE, np->file, np->line, 1051 "invalid datatype of argument for operation %s", 1052 ptree_nodetype2str(np->t)); 1053 /* NOTREACHED */ 1054 return (1); 1055 } 1056 1057 if (rp != NULL && lp->t != rp->t) { 1058 outfl(O_DIE, np->file, np->line, 1059 "mismatch in datatype of arguments for operation %s", 1060 ptree_nodetype2str(np->t)); 1061 /* NOTREACHED */ 1062 return (1); 1063 } 1064 1065 return (0); 1066 } 1067 1068 /* 1069 * eval_expr -- evaluate expression into *valuep 1070 * 1071 * the meaning of the return value depends on the input value of try. 1072 * 1073 * for try == 1: if any deferred items are encounted, bail out and return 1074 * false. returns true if we made it through entire expression without 1075 * hitting any deferred items. 1076 * 1077 * for try == 0: return true if all operations were performed successfully. 1078 * return false if otherwise. for example, any of the following conditions 1079 * will result in a false return value: 1080 * - attempted use of an uninitialized global variable 1081 * - failure in function evaluation 1082 * - illegal arithmetic operation (argument out of range) 1083 */ 1084 int 1085 eval_expr(struct node *np, struct lut *ex, struct node *events[], 1086 struct lut **globals, struct config *croot, struct arrow *arrowp, 1087 int try, struct evalue *valuep) 1088 { 1089 struct evalue *gval; 1090 struct evalue lval; 1091 struct evalue rval; 1092 1093 if (np == NULL) { 1094 valuep->t = UINT64; 1095 valuep->v = 1; /* no constraint means "true" */ 1096 return (1); 1097 } 1098 1099 valuep->t = UNDEFINED; 1100 1101 switch (np->t) { 1102 case T_GLOBID: 1103 if (try) 1104 return (0); 1105 1106 /* 1107 * only handle case of getting (and not setting) the value 1108 * of a global variable 1109 */ 1110 gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 1111 if (gval == NULL) { 1112 return (0); 1113 } else { 1114 valuep->t = gval->t; 1115 valuep->v = gval->v; 1116 return (1); 1117 } 1118 1119 case T_ASSIGN: 1120 if (try) 1121 return (0); 1122 1123 /* 1124 * first evaluate rhs, then try to store value in lhs which 1125 * should be a global variable 1126 */ 1127 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1128 arrowp, try, &rval)) 1129 return (0); 1130 1131 ASSERT(np->u.expr.left->t == T_GLOBID); 1132 gval = lut_lookup(*globals, 1133 (void *)np->u.expr.left->u.globid.s, NULL); 1134 1135 if (gval == NULL) { 1136 gval = MALLOC(sizeof (*gval)); 1137 *globals = lut_add(*globals, 1138 (void *) np->u.expr.left->u.globid.s, gval, NULL); 1139 } 1140 1141 gval->t = rval.t; 1142 gval->v = rval.v; 1143 1144 if (gval->t == UINT64) { 1145 out(O_ALTFP|O_VERB2, 1146 "assign $%s=%llu", 1147 np->u.expr.left->u.globid.s, gval->v); 1148 } else { 1149 out(O_ALTFP|O_VERB2, 1150 "assign $%s=\"%s\"", 1151 np->u.expr.left->u.globid.s, 1152 (char *)(uintptr_t)gval->v); 1153 } 1154 1155 /* 1156 * but always return true -- an assignment should not 1157 * cause a constraint to be false. 1158 */ 1159 valuep->t = UINT64; 1160 valuep->v = 1; 1161 return (1); 1162 1163 case T_EQ: 1164 #define IMPLICIT_ASSIGN_IN_EQ 1165 #ifdef IMPLICIT_ASSIGN_IN_EQ 1166 /* 1167 * if lhs is an uninitialized global variable, perform 1168 * an assignment. 1169 * 1170 * one insidious side effect of implicit assignment is 1171 * that the "==" operator does not return a Boolean if 1172 * implicit assignment was performed. 1173 */ 1174 if (try == 0 && 1175 np->u.expr.left->t == T_GLOBID && 1176 (gval = lut_lookup(*globals, 1177 (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 1178 if (!eval_expr(np->u.expr.right, ex, events, globals, 1179 croot, arrowp, try, &rval)) 1180 return (0); 1181 1182 gval = MALLOC(sizeof (*gval)); 1183 *globals = lut_add(*globals, 1184 (void *) np->u.expr.left->u.globid.s, 1185 gval, NULL); 1186 1187 gval->t = rval.t; 1188 gval->v = rval.v; 1189 valuep->t = rval.t; 1190 valuep->v = rval.v; 1191 return (1); 1192 } 1193 #endif /* IMPLICIT_ASSIGN_IN_EQ */ 1194 1195 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1196 arrowp, try, &lval)) 1197 return (0); 1198 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1199 arrowp, try, &rval)) 1200 return (0); 1201 if (rval.t == UINT64 || lval.t == UINT64) { 1202 if (check_expr_args(&lval, &rval, UINT64, np)) 1203 return (0); 1204 } else { 1205 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 1206 return (0); 1207 } 1208 1209 valuep->t = UINT64; 1210 valuep->v = (lval.v == rval.v); 1211 return (1); 1212 1213 case T_LT: 1214 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1215 arrowp, try, &lval)) 1216 return (0); 1217 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1218 arrowp, try, &rval)) 1219 return (0); 1220 if (check_expr_args(&lval, &rval, UINT64, np)) 1221 return (0); 1222 1223 valuep->t = UINT64; 1224 valuep->v = (lval.v < rval.v); 1225 return (1); 1226 1227 case T_LE: 1228 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1229 arrowp, try, &lval)) 1230 return (0); 1231 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1232 arrowp, try, &rval)) 1233 return (0); 1234 if (check_expr_args(&lval, &rval, UINT64, np)) 1235 return (0); 1236 1237 valuep->t = UINT64; 1238 valuep->v = (lval.v <= rval.v); 1239 return (1); 1240 1241 case T_GT: 1242 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1243 arrowp, try, &lval)) 1244 return (0); 1245 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1246 arrowp, try, &rval)) 1247 return (0); 1248 if (check_expr_args(&lval, &rval, UINT64, np)) 1249 return (0); 1250 1251 valuep->t = UINT64; 1252 valuep->v = (lval.v > rval.v); 1253 return (1); 1254 1255 case T_GE: 1256 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1257 arrowp, try, &lval)) 1258 return (0); 1259 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1260 arrowp, try, &rval)) 1261 return (0); 1262 if (check_expr_args(&lval, &rval, UINT64, np)) 1263 return (0); 1264 1265 valuep->t = UINT64; 1266 valuep->v = (lval.v >= rval.v); 1267 return (1); 1268 1269 case T_BITAND: 1270 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1271 arrowp, try, &lval)) 1272 return (0); 1273 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1274 arrowp, try, &rval)) 1275 return (0); 1276 if (check_expr_args(&lval, &rval, UINT64, np)) 1277 return (0); 1278 1279 valuep->t = lval.t; 1280 valuep->v = (lval.v & rval.v); 1281 return (1); 1282 1283 case T_BITOR: 1284 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1285 arrowp, try, &lval)) 1286 return (0); 1287 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1288 arrowp, try, &rval)) 1289 return (0); 1290 if (check_expr_args(&lval, &rval, UINT64, np)) 1291 return (0); 1292 1293 valuep->t = lval.t; 1294 valuep->v = (lval.v | rval.v); 1295 return (1); 1296 1297 case T_BITXOR: 1298 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1299 arrowp, try, &lval)) 1300 return (0); 1301 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1302 arrowp, try, &rval)) 1303 return (0); 1304 if (check_expr_args(&lval, &rval, UINT64, np)) 1305 return (0); 1306 1307 valuep->t = lval.t; 1308 valuep->v = (lval.v ^ rval.v); 1309 return (1); 1310 1311 case T_BITNOT: 1312 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1313 arrowp, try, &lval)) 1314 return (0); 1315 ASSERT(np->u.expr.right == NULL); 1316 if (check_expr_args(&lval, NULL, UINT64, np)) 1317 return (0); 1318 1319 valuep->t = UINT64; 1320 valuep->v = ~ lval.v; 1321 return (1); 1322 1323 case T_LSHIFT: 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 = UINT64; 1334 valuep->v = (lval.v << rval.v); 1335 return (1); 1336 1337 case T_RSHIFT: 1338 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1339 arrowp, try, &lval)) 1340 return (0); 1341 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1342 arrowp, try, &rval)) 1343 return (0); 1344 if (check_expr_args(&lval, &rval, UINT64, np)) 1345 return (0); 1346 1347 valuep->t = UINT64; 1348 valuep->v = (lval.v >> rval.v); 1349 return (1); 1350 1351 case T_CONDIF: { 1352 struct node *retnp; 1353 int dotrue = 0; 1354 1355 /* 1356 * evaluate 1357 * expression ? stmtA [ : stmtB ] 1358 * 1359 * first see if expression is true or false, then determine 1360 * if stmtA (or stmtB, if it exists) should be evaluated. 1361 * 1362 * "dotrue = 1" means stmtA should be evaluated. 1363 */ 1364 if (eval_expr(np->u.expr.left, ex, events, globals, croot, 1365 arrowp, try, &lval) && 1366 lval.t != UNDEFINED && lval.v != 0) 1367 dotrue = 1; 1368 1369 ASSERT(np->u.expr.right != NULL); 1370 if (np->u.expr.right->t == T_CONDELSE) { 1371 if (dotrue) 1372 retnp = np->u.expr.right->u.expr.left; 1373 else 1374 retnp = np->u.expr.right->u.expr.right; 1375 } else { 1376 /* no ELSE clause */ 1377 if (dotrue) 1378 retnp = np->u.expr.right; 1379 else { 1380 outfl(O_DIE, np->file, np->line, 1381 "eval_expr: missing condelse"); 1382 } 1383 } 1384 1385 if (!eval_expr(retnp, ex, events, globals, croot, 1386 arrowp, try, valuep)) 1387 return (0); 1388 return (1); 1389 } 1390 1391 case T_CONDELSE: 1392 /* 1393 * shouldn't get here, since T_CONDELSE is supposed to be 1394 * evaluated as part of T_CONDIF 1395 */ 1396 out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 1397 ptree_nodetype2str(np->t)); 1398 /*NOTREACHED*/ 1399 1400 case T_NE: 1401 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1402 arrowp, try, &lval)) 1403 return (0); 1404 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1405 arrowp, try, &rval)) 1406 return (0); 1407 if (rval.t == UINT64 || lval.t == UINT64) { 1408 if (check_expr_args(&lval, &rval, UINT64, np)) 1409 return (0); 1410 } else { 1411 if (check_expr_args(&lval, &rval, UNDEFINED, np)) 1412 return (0); 1413 } 1414 1415 valuep->t = UINT64; 1416 valuep->v = (lval.v != rval.v); 1417 return (1); 1418 1419 case T_LIST: 1420 case T_AND: 1421 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1422 arrowp, try, valuep)) { 1423 /* 1424 * if lhs is unknown, still check rhs. If that 1425 * is false we can return false irrespectice of lhs 1426 */ 1427 if (!eval_expr(np->u.expr.right, ex, events, globals, 1428 croot, arrowp, try, valuep)) { 1429 np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 1430 return (0); 1431 } 1432 if (valuep->v != 0) { 1433 np->u.expr.temp = EXPR_TEMP_LHS_UNK; 1434 return (0); 1435 } 1436 } 1437 if (valuep->v == 0) { 1438 valuep->t = UINT64; 1439 return (1); 1440 } 1441 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1442 arrowp, try, valuep)) { 1443 np->u.expr.temp = EXPR_TEMP_RHS_UNK; 1444 return (0); 1445 } 1446 valuep->t = UINT64; 1447 valuep->v = valuep->v == 0 ? 0 : 1; 1448 return (1); 1449 1450 case T_OR: 1451 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1452 arrowp, try, valuep)) { 1453 /* 1454 * if lhs is unknown, still check rhs. If that 1455 * is true we can return true irrespectice of lhs 1456 */ 1457 if (!eval_expr(np->u.expr.right, ex, events, globals, 1458 croot, arrowp, try, valuep)) { 1459 np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 1460 return (0); 1461 } 1462 if (valuep->v == 0) { 1463 np->u.expr.temp = EXPR_TEMP_LHS_UNK; 1464 return (0); 1465 } 1466 } 1467 if (valuep->v != 0) { 1468 valuep->t = UINT64; 1469 valuep->v = 1; 1470 return (1); 1471 } 1472 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1473 arrowp, try, valuep)) { 1474 np->u.expr.temp = EXPR_TEMP_RHS_UNK; 1475 return (0); 1476 } 1477 valuep->t = UINT64; 1478 valuep->v = valuep->v == 0 ? 0 : 1; 1479 return (1); 1480 1481 case T_NOT: 1482 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1483 arrowp, try, valuep)) 1484 return (0); 1485 valuep->t = UINT64; 1486 valuep->v = ! valuep->v; 1487 return (1); 1488 1489 case T_ADD: 1490 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1491 arrowp, try, &lval)) 1492 return (0); 1493 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1494 arrowp, try, &rval)) 1495 return (0); 1496 if (check_expr_args(&lval, &rval, UINT64, np)) 1497 return (0); 1498 1499 valuep->t = lval.t; 1500 valuep->v = lval.v + rval.v; 1501 return (1); 1502 1503 case T_SUB: 1504 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1505 arrowp, try, &lval)) 1506 return (0); 1507 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1508 arrowp, try, &rval)) 1509 return (0); 1510 if (check_expr_args(&lval, &rval, UINT64, np)) 1511 return (0); 1512 1513 /* since valuep is unsigned, return false if lval.v < rval.v */ 1514 if (lval.v < rval.v) { 1515 outfl(O_DIE, np->file, np->line, 1516 "eval_expr: T_SUB result is out of range"); 1517 } 1518 1519 valuep->t = lval.t; 1520 valuep->v = lval.v - rval.v; 1521 return (1); 1522 1523 case T_MUL: 1524 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1525 arrowp, try, &lval)) 1526 return (0); 1527 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1528 arrowp, try, &rval)) 1529 return (0); 1530 if (check_expr_args(&lval, &rval, UINT64, np)) 1531 return (0); 1532 1533 valuep->t = lval.t; 1534 valuep->v = lval.v * rval.v; 1535 return (1); 1536 1537 case T_DIV: 1538 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1539 arrowp, try, &lval)) 1540 return (0); 1541 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1542 arrowp, try, &rval)) 1543 return (0); 1544 if (check_expr_args(&lval, &rval, UINT64, np)) 1545 return (0); 1546 1547 /* return false if dividing by zero */ 1548 if (rval.v == 0) { 1549 outfl(O_DIE, np->file, np->line, 1550 "eval_expr: T_DIV division by zero"); 1551 } 1552 1553 valuep->t = lval.t; 1554 valuep->v = lval.v / rval.v; 1555 return (1); 1556 1557 case T_MOD: 1558 if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 1559 arrowp, try, &lval)) 1560 return (0); 1561 if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 1562 arrowp, try, &rval)) 1563 return (0); 1564 if (check_expr_args(&lval, &rval, UINT64, np)) 1565 return (0); 1566 1567 /* return false if dividing by zero */ 1568 if (rval.v == 0) { 1569 outfl(O_DIE, np->file, np->line, 1570 "eval_expr: T_MOD division by zero"); 1571 } 1572 1573 valuep->t = lval.t; 1574 valuep->v = lval.v % rval.v; 1575 return (1); 1576 1577 case T_NAME: 1578 if (try) { 1579 struct iterinfo *iterinfop; 1580 struct node *np1, *np2; 1581 int i, gotmatch = 0; 1582 1583 /* 1584 * Check if we have an exact match of the nonwildcarded 1585 * path in oldepname - if so we can just use the 1586 * full wildcarded path in epname. 1587 */ 1588 for (i = 0; i < 1; i++) { 1589 for (np1 = np, 1590 np2 = events[i]->u.event.oldepname; 1591 np1 != NULL && np2 != NULL; 1592 np1 = np1->u.name.next, 1593 np2 = np2->u.name.next) { 1594 if (strcmp(np1->u.name.s, 1595 np2->u.name.s) != 0) 1596 break; 1597 if (np1->u.name.child->t != 1598 np2->u.name.child->t) 1599 break; 1600 if (np1->u.name.child->t == T_NUM && 1601 np1->u.name.child->u.ull != 1602 np2->u.name.child->u.ull) 1603 break; 1604 if (np1->u.name.child->t == T_NAME && 1605 strcmp(np1->u.name.child->u.name.s, 1606 np2->u.name.child->u.name.s) != 0) 1607 break; 1608 gotmatch++; 1609 } 1610 if (np1 == NULL && np2 == NULL) { 1611 valuep->t = NODEPTR; 1612 valuep->v = (uintptr_t) 1613 events[i]->u.event.epname; 1614 return (1); 1615 } 1616 } 1617 if (!gotmatch) { 1618 /* 1619 * we're not wildcarding. However at 1620 * itree_create() time, we can also expand 1621 * simple iterators - so check for those. 1622 */ 1623 iterinfop = lut_lookup(ex, (void *)np->u.name.s, 1624 NULL); 1625 if (iterinfop != NULL) { 1626 valuep->t = UINT64; 1627 valuep->v = 1628 (unsigned long long)iterinfop->num; 1629 return (1); 1630 } 1631 } 1632 /* 1633 * For anything else we'll have to wait for eval_dup(). 1634 */ 1635 return (0); 1636 } 1637 1638 /* return address of struct node */ 1639 valuep->t = NODEPTR; 1640 valuep->v = (uintptr_t)np; 1641 return (1); 1642 1643 case T_QUOTE: 1644 valuep->t = STRING; 1645 valuep->v = (uintptr_t)np->u.quote.s; 1646 return (1); 1647 1648 case T_FUNC: 1649 return (eval_func(np, ex, events, np->u.func.arglist, 1650 globals, croot, arrowp, try, valuep)); 1651 1652 case T_NUM: 1653 valuep->t = UINT64; 1654 valuep->v = np->u.ull; 1655 return (1); 1656 1657 default: 1658 outfl(O_DIE, np->file, np->line, 1659 "eval_expr: unexpected node type: %s", 1660 ptree_nodetype2str(np->t)); 1661 } 1662 /*NOTREACHED*/ 1663 return (0); 1664 } 1665 1666 /* 1667 * eval_fru() and eval_asru() don't do much, but are called from a number 1668 * of places. 1669 */ 1670 static struct node * 1671 eval_fru(struct node *np) 1672 { 1673 ASSERT(np->t == T_NAME); 1674 return (np); 1675 } 1676 1677 static struct node * 1678 eval_asru(struct node *np) 1679 { 1680 ASSERT(np->t == T_NAME); 1681 return (np); 1682 } 1683