10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51717Swesolows * Common Development and Distribution License (the "License"). 61717Swesolows * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211717Swesolows 220Sstevel@tonic-gate /* 239078SStephen.Hanson@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate * 260Sstevel@tonic-gate * eval.c -- constraint evaluation module 270Sstevel@tonic-gate * 280Sstevel@tonic-gate * this module evaluates constraints. 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include <stdio.h> 320Sstevel@tonic-gate #include <stdlib.h> 330Sstevel@tonic-gate #include <ctype.h> 340Sstevel@tonic-gate #include <string.h> 350Sstevel@tonic-gate #include "alloc.h" 360Sstevel@tonic-gate #include "out.h" 370Sstevel@tonic-gate #include "stable.h" 380Sstevel@tonic-gate #include "literals.h" 390Sstevel@tonic-gate #include "lut.h" 400Sstevel@tonic-gate #include "tree.h" 410Sstevel@tonic-gate #include "ptree.h" 420Sstevel@tonic-gate #include "itree.h" 431414Scindi #include "ipath.h" 440Sstevel@tonic-gate #include "eval.h" 450Sstevel@tonic-gate #include "config.h" 460Sstevel@tonic-gate #include "platform.h" 471414Scindi #include "fme.h" 481414Scindi #include "stats.h" 490Sstevel@tonic-gate 500Sstevel@tonic-gate static struct node *eval_dup(struct node *np, struct lut *ex, 514436Sstephh struct node *events[]); 521414Scindi static int check_expr_args(struct evalue *lp, struct evalue *rp, 531414Scindi enum datatype dtype, struct node *np); 544436Sstephh static struct node *eval_fru(struct node *np); 554436Sstephh static struct node *eval_asru(struct node *np); 560Sstevel@tonic-gate 577275Sstephh extern fmd_hdl_t *Hdl; /* handle from eft.c */ 587275Sstephh 590Sstevel@tonic-gate /* 600Sstevel@tonic-gate * begins_with -- return true if rhs path begins with everything in lhs path 610Sstevel@tonic-gate */ 620Sstevel@tonic-gate static int 634436Sstephh begins_with(struct node *lhs, struct node *rhs, struct lut *ex) 640Sstevel@tonic-gate { 650Sstevel@tonic-gate int lnum; 660Sstevel@tonic-gate int rnum; 674436Sstephh struct iterinfo *iterinfop; 680Sstevel@tonic-gate 690Sstevel@tonic-gate if (lhs == NULL) 700Sstevel@tonic-gate return (1); /* yep -- it all matched */ 710Sstevel@tonic-gate 720Sstevel@tonic-gate if (rhs == NULL) 730Sstevel@tonic-gate return (0); /* nope, ran out of rhs first */ 740Sstevel@tonic-gate 750Sstevel@tonic-gate ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str); 760Sstevel@tonic-gate ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str); 770Sstevel@tonic-gate 780Sstevel@tonic-gate if (lhs->u.name.s != rhs->u.name.s) 790Sstevel@tonic-gate return (0); /* nope, different component names */ 800Sstevel@tonic-gate 814436Sstephh if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) { 820Sstevel@tonic-gate lnum = (int)lhs->u.name.child->u.ull; 834436Sstephh } else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) { 844436Sstephh iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s, 854436Sstephh NULL); 864436Sstephh if (iterinfop != NULL) 874436Sstephh lnum = iterinfop->num; 884436Sstephh else 894436Sstephh out(O_DIE, "begins_with: unexpected lhs child"); 904436Sstephh } else { 910Sstevel@tonic-gate out(O_DIE, "begins_with: unexpected lhs child"); 924436Sstephh } 930Sstevel@tonic-gate 944436Sstephh if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) { 950Sstevel@tonic-gate rnum = (int)rhs->u.name.child->u.ull; 964436Sstephh } else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) { 974436Sstephh iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s, 984436Sstephh NULL); 994436Sstephh if (iterinfop != NULL) 1004436Sstephh rnum = iterinfop->num; 1014436Sstephh else 1024436Sstephh out(O_DIE, "begins_with: unexpected rhs child"); 1034436Sstephh } else { 1040Sstevel@tonic-gate out(O_DIE, "begins_with: unexpected rhs child"); 1054436Sstephh } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate if (lnum != rnum) 1080Sstevel@tonic-gate return (0); /* nope, instance numbers were different */ 1090Sstevel@tonic-gate 1104436Sstephh return (begins_with(lhs->u.name.next, rhs->u.name.next, ex)); 1114436Sstephh } 1124436Sstephh 1134436Sstephh /* 1144436Sstephh * eval_getname - used by eval_func to evaluate a name, preferably without using 1154436Sstephh * eval_dup (but if it does have to use eval_dup then the *dupedp flag is set). 1164436Sstephh */ 1174436Sstephh static struct node * 1184436Sstephh eval_getname(struct node *funcnp, struct lut *ex, struct node *events[], 1194436Sstephh struct node *np, struct lut **globals, 1204436Sstephh struct config *croot, struct arrow *arrowp, int try, int *dupedp) 1214436Sstephh { 1224436Sstephh struct node *nodep; 1234436Sstephh const char *funcname = funcnp->u.func.s; 1244436Sstephh struct evalue val; 1254436Sstephh 1264436Sstephh if (np->t == T_NAME) 1274436Sstephh nodep = np; 128*11202SStephen.Hanson@Sun.COM else if (np->t == T_FUNC && np->u.func.s == L_fru) 1294436Sstephh nodep = eval_fru(np->u.func.arglist); 130*11202SStephen.Hanson@Sun.COM else if (np->t == T_FUNC && np->u.func.s == L_asru) 1314436Sstephh nodep = eval_asru(np->u.func.arglist); 132*11202SStephen.Hanson@Sun.COM else if (np->t == T_FUNC) { 133*11202SStephen.Hanson@Sun.COM if (eval_expr(np, ex, events, globals, croot, arrowp, try, 134*11202SStephen.Hanson@Sun.COM &val) == 0) 135*11202SStephen.Hanson@Sun.COM /* 136*11202SStephen.Hanson@Sun.COM * Can't evaluate yet. Return null so constraint is 137*11202SStephen.Hanson@Sun.COM * deferred. 138*11202SStephen.Hanson@Sun.COM */ 139*11202SStephen.Hanson@Sun.COM return (NULL); 140*11202SStephen.Hanson@Sun.COM if (val.t == NODEPTR) 141*11202SStephen.Hanson@Sun.COM return ((struct node *)(uintptr_t)val.v); 142*11202SStephen.Hanson@Sun.COM else 143*11202SStephen.Hanson@Sun.COM /* 144*11202SStephen.Hanson@Sun.COM * just return the T_FUNC - which the caller will 145*11202SStephen.Hanson@Sun.COM * reject. 146*11202SStephen.Hanson@Sun.COM */ 147*11202SStephen.Hanson@Sun.COM return (np); 148*11202SStephen.Hanson@Sun.COM } else 1494436Sstephh out(O_DIE, "%s: unexpected type: %s", 1504436Sstephh funcname, ptree_nodetype2str(np->t)); 1514436Sstephh if (try) { 1524436Sstephh if (eval_expr(nodep, ex, events, globals, croot, 1534436Sstephh arrowp, try, &val) && val.t == NODEPTR) 1544436Sstephh nodep = (struct node *)(uintptr_t)val.v; 1554436Sstephh else { 1564436Sstephh *dupedp = 1; 1574436Sstephh nodep = eval_dup(nodep, ex, events); 1584436Sstephh } 1594436Sstephh } 1604436Sstephh return (nodep); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 163*11202SStephen.Hanson@Sun.COM /*ARGSUSED*/ 164*11202SStephen.Hanson@Sun.COM static int 165*11202SStephen.Hanson@Sun.COM eval_cat(struct node *np, struct lut *ex, struct node *events[], 166*11202SStephen.Hanson@Sun.COM struct lut **globals, struct config *croot, struct arrow *arrowp, 167*11202SStephen.Hanson@Sun.COM int try, struct evalue *valuep) 168*11202SStephen.Hanson@Sun.COM { 169*11202SStephen.Hanson@Sun.COM if (np->t == T_LIST) { 170*11202SStephen.Hanson@Sun.COM struct evalue lval; 171*11202SStephen.Hanson@Sun.COM struct evalue rval; 172*11202SStephen.Hanson@Sun.COM int len; 173*11202SStephen.Hanson@Sun.COM char *s; 174*11202SStephen.Hanson@Sun.COM 175*11202SStephen.Hanson@Sun.COM if (!eval_cat(np->u.expr.left, ex, events, globals, croot, 176*11202SStephen.Hanson@Sun.COM arrowp, try, &lval)) 177*11202SStephen.Hanson@Sun.COM return (0); 178*11202SStephen.Hanson@Sun.COM if (!eval_cat(np->u.expr.right, ex, events, globals, croot, 179*11202SStephen.Hanson@Sun.COM arrowp, try, &rval)) 180*11202SStephen.Hanson@Sun.COM return (0); 181*11202SStephen.Hanson@Sun.COM len = snprintf(NULL, 0, "%s%s", (char *)(uintptr_t)lval.v, 182*11202SStephen.Hanson@Sun.COM (char *)(uintptr_t)rval.v); 183*11202SStephen.Hanson@Sun.COM s = MALLOC(len + 1); 184*11202SStephen.Hanson@Sun.COM 185*11202SStephen.Hanson@Sun.COM (void) snprintf(s, len + 1, "%s%s", (char *)(uintptr_t)lval.v, 186*11202SStephen.Hanson@Sun.COM (char *)(uintptr_t)rval.v); 187*11202SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2, np->file, np->line, 188*11202SStephen.Hanson@Sun.COM "eval_cat: %s %s returns %s", (char *)(uintptr_t)lval.v, 189*11202SStephen.Hanson@Sun.COM (char *)(uintptr_t)rval.v, s); 190*11202SStephen.Hanson@Sun.COM valuep->t = STRING; 191*11202SStephen.Hanson@Sun.COM valuep->v = (uintptr_t)stable(s); 192*11202SStephen.Hanson@Sun.COM FREE(s); 193*11202SStephen.Hanson@Sun.COM } else { 194*11202SStephen.Hanson@Sun.COM if (!eval_expr(np, ex, events, globals, croot, 195*11202SStephen.Hanson@Sun.COM arrowp, try, valuep)) 196*11202SStephen.Hanson@Sun.COM return (0); 197*11202SStephen.Hanson@Sun.COM if (check_expr_args(valuep, NULL, STRING, np)) 198*11202SStephen.Hanson@Sun.COM return (0); 199*11202SStephen.Hanson@Sun.COM } 200*11202SStephen.Hanson@Sun.COM return (1); 201*11202SStephen.Hanson@Sun.COM } 202*11202SStephen.Hanson@Sun.COM 2030Sstevel@tonic-gate /* 2040Sstevel@tonic-gate * evaluate a variety of functions and place result in valuep. return 1 if 2050Sstevel@tonic-gate * function evaluation was successful; 0 if otherwise (e.g., the case of an 2060Sstevel@tonic-gate * invalid argument to the function) 2070Sstevel@tonic-gate */ 2080Sstevel@tonic-gate /*ARGSUSED*/ 2090Sstevel@tonic-gate static int 2104436Sstephh eval_func(struct node *funcnp, struct lut *ex, struct node *events[], 2110Sstevel@tonic-gate struct node *np, struct lut **globals, 2120Sstevel@tonic-gate struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep) 2130Sstevel@tonic-gate { 2140Sstevel@tonic-gate const char *funcname = funcnp->u.func.s; 2154436Sstephh int duped_lhs = 0, duped_rhs = 0, duped = 0; 2164436Sstephh struct node *lhs; 2174436Sstephh struct node *rhs; 2184436Sstephh struct config *cp; 2194436Sstephh struct node *nodep; 2204436Sstephh char *path; 2214436Sstephh struct evalue val; 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate if (funcname == L_within) { 2240Sstevel@tonic-gate /* within()'s are not really constraints -- always true */ 2250Sstevel@tonic-gate valuep->t = UINT64; 2260Sstevel@tonic-gate valuep->v = 1; 2270Sstevel@tonic-gate return (1); 2280Sstevel@tonic-gate } else if (funcname == L_is_under) { 2294436Sstephh lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals, 2304436Sstephh croot, arrowp, try, &duped_lhs); 2314436Sstephh rhs = eval_getname(funcnp, ex, events, np->u.expr.right, 2324436Sstephh globals, croot, arrowp, try, &duped_rhs); 233*11202SStephen.Hanson@Sun.COM if (!rhs || !lhs) 234*11202SStephen.Hanson@Sun.COM return (0); 235*11202SStephen.Hanson@Sun.COM if (rhs->t != T_NAME || lhs->t != T_NAME) { 236*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 237*11202SStephen.Hanson@Sun.COM return (1); 238*11202SStephen.Hanson@Sun.COM } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate valuep->t = UINT64; 2414436Sstephh valuep->v = begins_with(lhs, rhs, ex); 2420Sstevel@tonic-gate out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under("); 2430Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs); 2440Sstevel@tonic-gate out(O_ALTFP|O_VERB2|O_NONL, ","); 2450Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs); 2464436Sstephh out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v); 2470Sstevel@tonic-gate 2484436Sstephh if (duped_lhs) 2494436Sstephh tree_free(lhs); 2504436Sstephh if (duped_rhs) 2514436Sstephh tree_free(rhs); 2520Sstevel@tonic-gate return (1); 2532869Sgavinm } else if (funcname == L_confprop || funcname == L_confprop_defined) { 2542318Sstephh const char *s; 2552318Sstephh 2562318Sstephh /* for now s will point to a quote [see addconfigprop()] */ 2572318Sstephh ASSERT(np->u.expr.right->t == T_QUOTE); 2582318Sstephh 2594436Sstephh nodep = eval_getname(funcnp, ex, events, np->u.expr.left, 2604436Sstephh globals, croot, arrowp, try, &duped); 261*11202SStephen.Hanson@Sun.COM if (!nodep) 262*11202SStephen.Hanson@Sun.COM return (0); 263*11202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) { 264*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 265*11202SStephen.Hanson@Sun.COM return (1); 266*11202SStephen.Hanson@Sun.COM } 267*11202SStephen.Hanson@Sun.COM 2684436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 2694436Sstephh cp = nodep->u.name.last->u.name.cp; 2704436Sstephh } else { 2714436Sstephh path = ipath2str(NULL, ipath(nodep)); 2724436Sstephh cp = config_lookup(croot, path, 0); 2734436Sstephh FREE((void *)path); 2744436Sstephh } 2752869Sgavinm if (cp == NULL) { 2764436Sstephh if (funcname == L_confprop) { 2774436Sstephh out(O_ALTFP|O_VERB3, "%s: path ", funcname); 2784436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 2794436Sstephh out(O_ALTFP|O_VERB3, " not found"); 2804436Sstephh valuep->v = (uintptr_t)stable(""); 2814436Sstephh valuep->t = STRING; 2824436Sstephh if (duped) 2834436Sstephh tree_free(nodep); 2844436Sstephh return (1); 2854436Sstephh } else { 2862869Sgavinm valuep->v = 0; 2872869Sgavinm valuep->t = UINT64; 2884436Sstephh if (duped) 2894436Sstephh tree_free(nodep); 2902869Sgavinm return (1); 2912869Sgavinm } 2922869Sgavinm } 2932318Sstephh s = config_getprop(cp, np->u.expr.right->u.quote.s); 2944436Sstephh if (s == NULL && strcmp(np->u.expr.right->u.quote.s, 2954436Sstephh "class-code") == 0) 2964436Sstephh s = config_getprop(cp, "CLASS-CODE"); 2972869Sgavinm if (s == NULL) { 2984436Sstephh if (funcname == L_confprop) { 2994436Sstephh out(O_ALTFP|O_VERB3|O_NONL, 3004436Sstephh "%s: \"%s\" not found for path ", 3014436Sstephh funcname, np->u.expr.right->u.quote.s); 3024436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 3034436Sstephh valuep->v = (uintptr_t)stable(""); 3044436Sstephh valuep->t = STRING; 3054436Sstephh if (duped) 3064436Sstephh tree_free(nodep); 3074436Sstephh return (1); 3084436Sstephh } else { 3092869Sgavinm valuep->v = 0; 3102869Sgavinm valuep->t = UINT64; 3114436Sstephh if (duped) 3124436Sstephh tree_free(nodep); 3132869Sgavinm return (1); 3142869Sgavinm } 3152869Sgavinm } 3162869Sgavinm 3172869Sgavinm if (funcname == L_confprop) { 3182869Sgavinm valuep->v = (uintptr_t)stable(s); 3192869Sgavinm valuep->t = STRING; 3204436Sstephh out(O_ALTFP|O_VERB3|O_NONL, " %s(\"", funcname); 3214436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 3224436Sstephh out(O_ALTFP|O_VERB3|O_NONL, 3234436Sstephh "\", \"%s\") = \"%s\" ", 3244436Sstephh np->u.expr.right->u.quote.s, 3252869Sgavinm (char *)(uintptr_t)valuep->v); 3262869Sgavinm } else { 3272869Sgavinm valuep->v = 1; 3282869Sgavinm valuep->t = UINT64; 3292869Sgavinm } 3304436Sstephh if (duped) 3314436Sstephh tree_free(nodep); 3324436Sstephh return (1); 3334436Sstephh } else if (funcname == L_is_connected) { 3344436Sstephh const char *connstrings[] = { "connected", "CONNECTED", NULL }; 3354436Sstephh struct config *cp[2]; 3364436Sstephh const char *matchthis[2], *s; 3374436Sstephh char *nameslist, *w; 3384436Sstephh int i, j; 3394436Sstephh 3404436Sstephh lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals, 3414436Sstephh croot, arrowp, try, &duped_lhs); 3424436Sstephh rhs = eval_getname(funcnp, ex, events, np->u.expr.right, 3434436Sstephh globals, croot, arrowp, try, &duped_rhs); 344*11202SStephen.Hanson@Sun.COM if (!rhs || !lhs) 345*11202SStephen.Hanson@Sun.COM return (0); 346*11202SStephen.Hanson@Sun.COM if (rhs->t != T_NAME || lhs->t != T_NAME) { 347*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 348*11202SStephen.Hanson@Sun.COM return (1); 349*11202SStephen.Hanson@Sun.COM } 350*11202SStephen.Hanson@Sun.COM 3514436Sstephh path = ipath2str(NULL, ipath(lhs)); 3524436Sstephh matchthis[1] = stable(path); 3534436Sstephh if (lhs->u.name.last->u.name.cp != NULL) 3544436Sstephh cp[0] = lhs->u.name.last->u.name.cp; 3554436Sstephh else 3564436Sstephh cp[0] = config_lookup(croot, path, 0); 3572869Sgavinm FREE((void *)path); 3584436Sstephh path = ipath2str(NULL, ipath(rhs)); 3594436Sstephh matchthis[0] = stable(path); 3604436Sstephh if (rhs->u.name.last->u.name.cp != NULL) 3614436Sstephh cp[1] = rhs->u.name.last->u.name.cp; 3624436Sstephh else 3634436Sstephh cp[1] = config_lookup(croot, path, 0); 3644436Sstephh FREE((void *)path); 3654436Sstephh if (duped_lhs) 3664436Sstephh tree_free(lhs); 3674436Sstephh if (duped_rhs) 3684436Sstephh tree_free(rhs); 3694436Sstephh 3704436Sstephh valuep->t = UINT64; 3714436Sstephh valuep->v = 0; 3724436Sstephh if (cp[0] == NULL || cp[1] == NULL) 3734436Sstephh return (1); 3744436Sstephh 3754436Sstephh /* to thine self always be connected */ 3764436Sstephh if (cp[0] == cp[1]) { 3774436Sstephh valuep->v = 1; 3784436Sstephh return (1); 3794436Sstephh } 3804436Sstephh 3814436Sstephh /* 3824436Sstephh * Extract "connected" property from each cp. Search this 3834436Sstephh * property for the name associated with the other cp[]. 3844436Sstephh */ 3854436Sstephh for (i = 0; i < 2 && valuep->v == 0; i++) { 3864436Sstephh for (j = 0; connstrings[j] != NULL && valuep->v == 0; 3874436Sstephh j++) { 3884436Sstephh s = config_getprop(cp[i], 3894436Sstephh stable(connstrings[j])); 3904436Sstephh if (s != NULL) { 3914436Sstephh nameslist = STRDUP(s); 3924436Sstephh w = strtok(nameslist, " ,"); 3934436Sstephh while (w != NULL) { 3944436Sstephh if (stable(w) == matchthis[i]) { 3954436Sstephh valuep->v = 1; 3964436Sstephh break; 3974436Sstephh } 3984436Sstephh w = strtok(NULL, " ,"); 3994436Sstephh } 4004436Sstephh FREE(nameslist); 4014436Sstephh } 4024436Sstephh } 4034436Sstephh } 4042318Sstephh return (1); 4054436Sstephh } else if (funcname == L_is_type) { 4064436Sstephh const char *typestrings[] = { "type", "TYPE", NULL }; 4074436Sstephh const char *s; 4084436Sstephh int i; 4094436Sstephh 4104436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals, 4114436Sstephh croot, arrowp, try, &duped); 412*11202SStephen.Hanson@Sun.COM if (!nodep) 413*11202SStephen.Hanson@Sun.COM return (0); 414*11202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) { 415*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 416*11202SStephen.Hanson@Sun.COM return (1); 417*11202SStephen.Hanson@Sun.COM } 418*11202SStephen.Hanson@Sun.COM 4194436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 4204436Sstephh cp = nodep->u.name.last->u.name.cp; 4214436Sstephh } else { 4224436Sstephh path = ipath2str(NULL, ipath(nodep)); 4234436Sstephh cp = config_lookup(croot, path, 0); 4244436Sstephh FREE((void *)path); 4254436Sstephh } 4264436Sstephh if (duped) 4274436Sstephh tree_free(nodep); 4284436Sstephh 4294436Sstephh valuep->t = STRING; 4304436Sstephh valuep->v = (uintptr_t)stable(""); 4314436Sstephh if (cp == NULL) 4324436Sstephh return (1); 4334436Sstephh for (i = 0; typestrings[i] != NULL; i++) { 4344436Sstephh s = config_getprop(cp, stable(typestrings[i])); 4354436Sstephh if (s != NULL) { 4364436Sstephh valuep->v = (uintptr_t)stable(s); 4374436Sstephh break; 4384436Sstephh } 4394436Sstephh } 4404436Sstephh return (1); 4414436Sstephh } else if (funcname == L_is_on) { 4424436Sstephh const char *onstrings[] = { "on", "ON", NULL }; 4434436Sstephh const char *truestrings[] = { "yes", "YES", "y", "Y", 4444436Sstephh "true", "TRUE", "t", "T", "1", NULL }; 4454436Sstephh const char *s; 4464436Sstephh int i, j; 4474436Sstephh 4484436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals, 4494436Sstephh croot, arrowp, try, &duped); 450*11202SStephen.Hanson@Sun.COM if (!nodep) 451*11202SStephen.Hanson@Sun.COM return (0); 452*11202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) { 453*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 454*11202SStephen.Hanson@Sun.COM return (1); 455*11202SStephen.Hanson@Sun.COM } 456*11202SStephen.Hanson@Sun.COM 4574436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 4584436Sstephh cp = nodep->u.name.last->u.name.cp; 4594436Sstephh } else { 4604436Sstephh path = ipath2str(NULL, ipath(nodep)); 4614436Sstephh cp = config_lookup(croot, path, 0); 4624436Sstephh FREE((void *)path); 4634436Sstephh } 4644436Sstephh if (duped) 4654436Sstephh tree_free(nodep); 4664436Sstephh 4674436Sstephh valuep->t = UINT64; 4684436Sstephh valuep->v = 0; 4694436Sstephh if (cp == NULL) 4704436Sstephh return (1); 4714436Sstephh for (i = 0; onstrings[i] != NULL; i++) { 4724436Sstephh s = config_getprop(cp, stable(onstrings[i])); 4734436Sstephh if (s != NULL) { 4744436Sstephh s = stable(s); 4754436Sstephh for (j = 0; truestrings[j] != NULL; j++) { 4764436Sstephh if (s == stable(truestrings[j])) { 4774436Sstephh valuep->v = 1; 4784436Sstephh return (1); 4794436Sstephh } 4804436Sstephh } 4814436Sstephh } 4824436Sstephh } 4834436Sstephh return (1); 4844436Sstephh } else if (funcname == L_is_present) { 4854436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals, 4864436Sstephh croot, arrowp, try, &duped); 487*11202SStephen.Hanson@Sun.COM if (!nodep) 488*11202SStephen.Hanson@Sun.COM return (0); 489*11202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) { 490*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 491*11202SStephen.Hanson@Sun.COM return (1); 492*11202SStephen.Hanson@Sun.COM } 493*11202SStephen.Hanson@Sun.COM 4944436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 4954436Sstephh cp = nodep->u.name.last->u.name.cp; 4964436Sstephh } else { 4974436Sstephh path = ipath2str(NULL, ipath(nodep)); 4984436Sstephh cp = config_lookup(croot, path, 0); 4994436Sstephh FREE((void *)path); 5004436Sstephh } 5014436Sstephh if (duped) 5024436Sstephh tree_free(nodep); 5034436Sstephh 5044436Sstephh valuep->t = UINT64; 5054436Sstephh valuep->v = 0; 5064436Sstephh if (cp != NULL) 5074436Sstephh valuep->v = 1; 5084436Sstephh return (1); 5097275Sstephh } else if (funcname == L_has_fault) { 5107275Sstephh nvlist_t *asru = NULL, *fru = NULL, *rsrc = NULL; 5117275Sstephh 5127275Sstephh nodep = eval_getname(funcnp, ex, events, np->u.expr.left, 5137275Sstephh globals, croot, arrowp, try, &duped); 514*11202SStephen.Hanson@Sun.COM if (!nodep) 515*11202SStephen.Hanson@Sun.COM return (0); 516*11202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) { 517*11202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED; 518*11202SStephen.Hanson@Sun.COM return (1); 519*11202SStephen.Hanson@Sun.COM } 520*11202SStephen.Hanson@Sun.COM 5217275Sstephh path = ipath2str(NULL, ipath(nodep)); 5227275Sstephh platform_units_translate(0, croot, &asru, &fru, &rsrc, path); 5238245SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, "has_fault("); 524*11202SStephen.Hanson@Sun.COM ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, nodep); 525*11202SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2|O_NONL, "(%s), \"%s\") ", path, 5268245SStephen.Hanson@Sun.COM np->u.expr.right->u.quote.s); 5277275Sstephh FREE((void *)path); 5287275Sstephh if (duped) 5297275Sstephh tree_free(nodep); 5307275Sstephh 5318245SStephen.Hanson@Sun.COM if (rsrc == NULL) { 5327275Sstephh valuep->v = 0; 5338245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "no path"); 5348245SStephen.Hanson@Sun.COM } else { 5357275Sstephh valuep->v = fmd_nvl_fmri_has_fault(Hdl, rsrc, 5367275Sstephh FMD_HAS_FAULT_RESOURCE, 5377275Sstephh strcmp(np->u.expr.right->u.quote.s, "") == 0 ? 5387275Sstephh NULL : (char *)np->u.expr.right->u.quote.s); 5398245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "returned %lld", valuep->v); 5408245SStephen.Hanson@Sun.COM } 5417275Sstephh valuep->t = UINT64; 5427275Sstephh return (1); 5434436Sstephh } else if (funcname == L_count) { 5444436Sstephh struct stats *statp; 5454436Sstephh struct istat_entry ent; 5464436Sstephh 5474436Sstephh ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t)); 5484436Sstephh 5494436Sstephh nodep = np->u.event.epname; 5504436Sstephh if (try) { 5514436Sstephh if (eval_expr(nodep, ex, events, globals, 5524436Sstephh croot, arrowp, try, &val) && val.t == NODEPTR) 5534436Sstephh nodep = (struct node *)(uintptr_t)val.v; 5544436Sstephh else { 5554436Sstephh duped = 1; 5564436Sstephh nodep = eval_dup(nodep, ex, events); 5574436Sstephh } 5584436Sstephh } 5594436Sstephh ent.ename = np->u.event.ename->u.name.s; 5604436Sstephh ent.ipath = ipath(nodep); 5614436Sstephh valuep->t = UINT64; 5624436Sstephh if ((statp = (struct stats *) 5634436Sstephh lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL) 5644436Sstephh valuep->v = 0; 5654436Sstephh else 5664436Sstephh valuep->v = stats_counter_value(statp); 5674436Sstephh if (duped) 5684436Sstephh tree_free(nodep); 5694436Sstephh return (1); 5704436Sstephh } else if (funcname == L_envprop) { 5714436Sstephh outfl(O_DIE, np->file, np->line, 5724436Sstephh "eval_func: %s not yet supported", funcname); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate if (try) 5760Sstevel@tonic-gate return (0); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate if (funcname == L_fru) { 5790Sstevel@tonic-gate valuep->t = NODEPTR; 5801717Swesolows valuep->v = (uintptr_t)eval_fru(np); 5810Sstevel@tonic-gate return (1); 5820Sstevel@tonic-gate } else if (funcname == L_asru) { 5830Sstevel@tonic-gate valuep->t = NODEPTR; 5841717Swesolows valuep->v = (uintptr_t)eval_asru(np); 5850Sstevel@tonic-gate return (1); 5861414Scindi } else if (funcname == L_defined) { 5871414Scindi ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str); 5881414Scindi valuep->t = UINT64; 5891414Scindi valuep->v = (lut_lookup(*globals, 5901414Scindi (void *)np->u.globid.s, NULL) != NULL); 5911414Scindi return (1); 5920Sstevel@tonic-gate } else if (funcname == L_call) { 5930Sstevel@tonic-gate return (! platform_call(np, globals, croot, arrowp, valuep)); 5940Sstevel@tonic-gate } else if (funcname == L_payloadprop) { 5951414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 5960Sstevel@tonic-gate "payloadprop(\"%s\") ", np->u.quote.s); 597186Sdb35262 5985204Sstephh if (arrowp->head->myevent->count == 0) { 5995204Sstephh /* 6005204Sstephh * Haven't seen this ereport yet, so must defer 6015204Sstephh */ 6025204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 6035204Sstephh return (0); 6045204Sstephh } else if (platform_payloadprop(np, valuep)) { 6051414Scindi /* platform_payloadprop() returned false */ 6065204Sstephh out(O_ALTFP|O_VERB, "not found."); 6075204Sstephh valuep->t = UNDEFINED; 6085204Sstephh return (1); 6091414Scindi } else { 610186Sdb35262 switch (valuep->t) { 611*11202SStephen.Hanson@Sun.COM case NODEPTR: 612*11202SStephen.Hanson@Sun.COM if (((struct node *)(uintptr_t) 613*11202SStephen.Hanson@Sun.COM (valuep->v))->t == T_NAME) { 614*11202SStephen.Hanson@Sun.COM char *s = ipath2str(NULL, 615*11202SStephen.Hanson@Sun.COM ipath((struct node *) 616*11202SStephen.Hanson@Sun.COM (uintptr_t)valuep->v)); 617*11202SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, 618*11202SStephen.Hanson@Sun.COM "found: \"%s\"", s); 619*11202SStephen.Hanson@Sun.COM FREE(s); 620*11202SStephen.Hanson@Sun.COM } else 621*11202SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "found: %llu", 622*11202SStephen.Hanson@Sun.COM valuep->v); 623*11202SStephen.Hanson@Sun.COM break; 624186Sdb35262 case UINT64: 6251414Scindi out(O_ALTFP|O_VERB2, "found: %llu", valuep->v); 626186Sdb35262 break; 627186Sdb35262 case STRING: 6281414Scindi out(O_ALTFP|O_VERB2, "found: \"%s\"", 6291717Swesolows (char *)(uintptr_t)valuep->v); 630186Sdb35262 break; 631186Sdb35262 default: 6321414Scindi out(O_ALTFP|O_VERB2, "found: undefined"); 633186Sdb35262 break; 634186Sdb35262 } 6351414Scindi return (1); 6361414Scindi } 6371414Scindi } else if (funcname == L_setpayloadprop) { 6381414Scindi struct evalue *payloadvalp; 6395204Sstephh int alloced = 0; 6401414Scindi 6411414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 6421414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE, 6431414Scindi ptree_nodetype2str(np->u.expr.left->t)); 6441414Scindi 6459078SStephen.Hanson@Sun.COM if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE)) 6467197Sstephh return (0); 6477197Sstephh 6481414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6491414Scindi "setpayloadprop: %s: %s=", 6501414Scindi arrowp->tail->myevent->enode->u.event.ename->u.name.s, 6511414Scindi np->u.expr.left->u.quote.s); 6521414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 6531414Scindi 6541414Scindi /* 6551414Scindi * allocate a struct evalue to hold the payload property's 6561414Scindi * value, unless we've been here already, in which case we 6571414Scindi * might calculate a different value, but we'll store it 6581414Scindi * in the already-allocated struct evalue. 6591414Scindi */ 6601414Scindi if ((payloadvalp = (struct evalue *)lut_lookup( 6611414Scindi arrowp->tail->myevent->payloadprops, 6621414Scindi (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) { 6631414Scindi payloadvalp = MALLOC(sizeof (*payloadvalp)); 6645204Sstephh alloced = 1; 6651414Scindi } 6661414Scindi 6674436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 6681414Scindi arrowp, try, payloadvalp)) { 6695204Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)"); 6705204Sstephh if (alloced) 6715204Sstephh FREE(payloadvalp); 6725204Sstephh return (0); 6731414Scindi } else { 6745204Sstephh if (payloadvalp->t == UNDEFINED) { 6755204Sstephh /* function is always true */ 6765204Sstephh out(O_ALTFP|O_VERB2, " (undefined)"); 6775204Sstephh valuep->t = UINT64; 6785204Sstephh valuep->v = 1; 6795204Sstephh return (1); 6805204Sstephh } 6811414Scindi if (payloadvalp->t == UINT64) 6821414Scindi out(O_ALTFP|O_VERB2, 6831414Scindi " (%llu)", payloadvalp->v); 6841414Scindi else 6851717Swesolows out(O_ALTFP|O_VERB2, " (\"%s\")", 6861717Swesolows (char *)(uintptr_t)payloadvalp->v); 6871414Scindi } 6881414Scindi 6891414Scindi /* add to table of payload properties for current problem */ 6901414Scindi arrowp->tail->myevent->payloadprops = 6911414Scindi lut_add(arrowp->tail->myevent->payloadprops, 6921414Scindi (void *)np->u.expr.left->u.quote.s, 6931414Scindi (void *)payloadvalp, NULL); 6941414Scindi 6951414Scindi /* function is always true */ 6961414Scindi valuep->t = UINT64; 6971414Scindi valuep->v = 1; 6981414Scindi return (1); 699*11202SStephen.Hanson@Sun.COM } else if (funcname == L_cat) { 700*11202SStephen.Hanson@Sun.COM int retval = eval_cat(np, ex, events, globals, croot, 701*11202SStephen.Hanson@Sun.COM arrowp, try, valuep); 702*11202SStephen.Hanson@Sun.COM 703*11202SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2, np->file, np->line, 704*11202SStephen.Hanson@Sun.COM "cat: returns %s", (char *)(uintptr_t)valuep->v); 705*11202SStephen.Hanson@Sun.COM return (retval); 7067197Sstephh } else if (funcname == L_setserdn || funcname == L_setserdt || 7077197Sstephh funcname == L_setserdsuffix || funcname == L_setserdincrement) { 7087197Sstephh struct evalue *serdvalp; 7097197Sstephh int alloced = 0; 7107197Sstephh char *str; 7117197Sstephh struct event *flt = arrowp->tail->myevent; 7127197Sstephh 7139078SStephen.Hanson@Sun.COM if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE)) 7147197Sstephh return (0); 7157197Sstephh 7167197Sstephh if (funcname == L_setserdn) 7177197Sstephh str = "n"; 7187197Sstephh else if (funcname == L_setserdt) 7197197Sstephh str = "t"; 7207197Sstephh else if (funcname == L_setserdsuffix) 7217197Sstephh str = "suffix"; 7227197Sstephh else if (funcname == L_setserdincrement) 7237197Sstephh str = "increment"; 7247197Sstephh 7257197Sstephh /* 7267197Sstephh * allocate a struct evalue to hold the serd property's 7277197Sstephh * value, unless we've been here already, in which case we 7287197Sstephh * might calculate a different value, but we'll store it 7297197Sstephh * in the already-allocated struct evalue. 7307197Sstephh */ 7317197Sstephh if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops, 7327392SScott.Davenport@Sun.COM (void *)str, (lut_cmp)strcmp)) == NULL) { 7337197Sstephh serdvalp = MALLOC(sizeof (*serdvalp)); 7347197Sstephh alloced = 1; 7357197Sstephh } 7367197Sstephh 7377197Sstephh if (!eval_expr(np, ex, events, globals, croot, arrowp, try, 7387197Sstephh serdvalp)) { 7397197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 7407197Sstephh "setserd%s: %s: ", str, 7417197Sstephh flt->enode->u.event.ename->u.name.s); 7427197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 7437197Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)"); 7447197Sstephh if (alloced) 7457197Sstephh FREE(serdvalp); 7467197Sstephh return (0); 7477197Sstephh } else if (serdvalp->t == UNDEFINED) { 7487197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 7497197Sstephh "setserd%s: %s: ", str, 7507197Sstephh flt->enode->u.event.ename->u.name.s); 7517197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 7527197Sstephh out(O_ALTFP|O_VERB2, " (undefined)"); 7537197Sstephh } else { 7547197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 7557197Sstephh "setserd%s: %s: ", str, 7567197Sstephh flt->enode->u.event.ename->u.name.s); 7577197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 7587197Sstephh if ((funcname == L_setserdincrement || 7597197Sstephh funcname == L_setserdn) && serdvalp->t == STRING) { 7607197Sstephh serdvalp->t = UINT64; 7617197Sstephh serdvalp->v = strtoull((char *) 7627197Sstephh (uintptr_t)serdvalp->v, NULL, 0); 7637197Sstephh } 7647197Sstephh if (funcname == L_setserdt && serdvalp->t == UINT64) { 7657197Sstephh int len = snprintf(NULL, 0, "%lldns", 7667197Sstephh serdvalp->v); 7677197Sstephh char *buf = MALLOC(len + 1); 7687197Sstephh 7697197Sstephh (void) snprintf(buf, len + 1, "%lldns", 7707197Sstephh serdvalp->v); 7717197Sstephh serdvalp->t = STRING; 7727197Sstephh serdvalp->v = (uintptr_t)stable(buf); 7737197Sstephh FREE(buf); 7747197Sstephh } 77511031SDavid.Zhang@Sun.COM if (funcname == L_setserdsuffix && 77611031SDavid.Zhang@Sun.COM serdvalp->t == UINT64) { 77711031SDavid.Zhang@Sun.COM int len = snprintf(NULL, 0, "%lld", 77811031SDavid.Zhang@Sun.COM serdvalp->v); 77911031SDavid.Zhang@Sun.COM char *buf = MALLOC(len + 1); 78011031SDavid.Zhang@Sun.COM 78111031SDavid.Zhang@Sun.COM (void) snprintf(buf, len + 1, "%lld", 78211031SDavid.Zhang@Sun.COM serdvalp->v); 78311031SDavid.Zhang@Sun.COM serdvalp->t = STRING; 78411031SDavid.Zhang@Sun.COM serdvalp->v = (uintptr_t)stable(buf); 78511031SDavid.Zhang@Sun.COM FREE(buf); 78611031SDavid.Zhang@Sun.COM } 7877392SScott.Davenport@Sun.COM 7887197Sstephh if (serdvalp->t == UINT64) 7897197Sstephh out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v); 7907197Sstephh else 7917197Sstephh out(O_ALTFP|O_VERB2, " (\"%s\")", 7927197Sstephh (char *)(uintptr_t)serdvalp->v); 7937197Sstephh flt->serdprops = lut_add(flt->serdprops, (void *)str, 7947392SScott.Davenport@Sun.COM (void *)serdvalp, (lut_cmp)strcmp); 7957197Sstephh } 7967197Sstephh valuep->t = UINT64; 7977197Sstephh valuep->v = 1; 7987197Sstephh return (1); 7991414Scindi } else if (funcname == L_payloadprop_defined) { 8001414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 8011414Scindi "payloadprop_defined(\"%s\") ", np->u.quote.s); 8021414Scindi 8035204Sstephh if (arrowp->head->myevent->count == 0) { 8045204Sstephh /* 8055204Sstephh * Haven't seen this ereport yet, so must defer 8065204Sstephh */ 8075204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 8085204Sstephh return (0); 8095204Sstephh } else if (platform_payloadprop(np, NULL)) { 8101414Scindi /* platform_payloadprop() returned false */ 8111414Scindi valuep->v = 0; 8125204Sstephh out(O_ALTFP|O_VERB2, "not found."); 8131414Scindi } else { 8141414Scindi valuep->v = 1; 8151414Scindi out(O_ALTFP|O_VERB2, "found."); 8161414Scindi } 8171414Scindi valuep->t = UINT64; 8181414Scindi return (1); 8191414Scindi } else if (funcname == L_payloadprop_contains) { 8201414Scindi int nvals; 8211414Scindi struct evalue *vals; 8221414Scindi struct evalue cmpval; 8231414Scindi 8241414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 8251414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE, 8261414Scindi ptree_nodetype2str(np->u.expr.left->t)); 8271414Scindi 8281414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 8291414Scindi "payloadprop_contains(\"%s\", ", 8301414Scindi np->u.expr.left->u.quote.s); 8311414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 8322869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, ") "); 8331414Scindi 8341414Scindi /* evaluate the expression we're comparing against */ 8354436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 8361414Scindi arrowp, try, &cmpval)) { 8371414Scindi out(O_ALTFP|O_VERB2|O_NONL, 8385204Sstephh "(cannot eval) "); 8395204Sstephh return (0); 8401414Scindi } else { 8412869Sgavinm switch (cmpval.t) { 8422869Sgavinm case UNDEFINED: 8432869Sgavinm out(O_ALTFP|O_VERB2, "(undefined type)"); 8442869Sgavinm break; 8452869Sgavinm 8462869Sgavinm case UINT64: 8471414Scindi out(O_ALTFP|O_VERB2, 8481414Scindi "(%llu) ", cmpval.v); 8492869Sgavinm break; 8502869Sgavinm 8512869Sgavinm case STRING: 8521414Scindi out(O_ALTFP|O_VERB2, 8531717Swesolows "(\"%s\") ", (char *)(uintptr_t)cmpval.v); 8542869Sgavinm break; 8552869Sgavinm 8562869Sgavinm case NODEPTR: 8572869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, "("); 8582869Sgavinm ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, 8592869Sgavinm (struct node *)(uintptr_t)(cmpval.v)); 8602869Sgavinm out(O_ALTFP|O_VERB2, ") "); 8612869Sgavinm break; 8622869Sgavinm } 8631414Scindi } 8641414Scindi 8651414Scindi /* get the payload values and check for a match */ 8661414Scindi vals = platform_payloadprop_values(np->u.expr.left->u.quote.s, 8671414Scindi &nvals); 8681414Scindi valuep->t = UINT64; 8691414Scindi valuep->v = 0; 8705204Sstephh if (arrowp->head->myevent->count == 0) { 8715204Sstephh /* 8725204Sstephh * Haven't seen this ereport yet, so must defer 8735204Sstephh */ 8745204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 8755204Sstephh return (0); 8765204Sstephh } else if (nvals == 0) { 8771414Scindi out(O_ALTFP|O_VERB2, "not found."); 8785204Sstephh return (1); 8791414Scindi } else { 8801414Scindi struct evalue preval; 8811414Scindi int i; 8821414Scindi 8831414Scindi out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals); 8841414Scindi 8851414Scindi for (i = 0; i < nvals; i++) { 8861414Scindi 8871414Scindi preval.t = vals[i].t; 8881414Scindi preval.v = vals[i].v; 8891414Scindi 8901414Scindi if (check_expr_args(&vals[i], &cmpval, 8911414Scindi UNDEFINED, np)) 8921414Scindi continue; 8931414Scindi 8941414Scindi /* 8951414Scindi * If we auto-converted the value to a 8961414Scindi * string, we need to free the 8971414Scindi * original tree value. 8981414Scindi */ 8991414Scindi if (preval.t == NODEPTR && 9001717Swesolows ((struct node *)(uintptr_t)(preval.v))->t == 9011717Swesolows T_NAME) { 9021717Swesolows tree_free((struct node *)(uintptr_t) 9031717Swesolows preval.v); 9041414Scindi } 9051414Scindi 9061414Scindi if (vals[i].v == cmpval.v) { 9071414Scindi valuep->v = 1; 9081414Scindi break; 9091414Scindi } 9101414Scindi } 911186Sdb35262 9121414Scindi if (valuep->v) 9131414Scindi out(O_ALTFP|O_VERB2, "match."); 9141414Scindi else 9151414Scindi out(O_ALTFP|O_VERB2, "no match."); 916186Sdb35262 9171414Scindi for (i = 0; i < nvals; i++) { 9181414Scindi if (vals[i].t == NODEPTR) { 9191717Swesolows tree_free((struct node *)(uintptr_t) 9201717Swesolows vals[i].v); 9211414Scindi break; 9221414Scindi } 923186Sdb35262 } 9241414Scindi FREE(vals); 9251414Scindi } 9261414Scindi return (1); 9271414Scindi } else if (funcname == L_confcall) { 9281414Scindi return (!platform_confcall(np, globals, croot, arrowp, valuep)); 9290Sstevel@tonic-gate } else 9300Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 9310Sstevel@tonic-gate "eval_func: unexpected func: %s", funcname); 9320Sstevel@tonic-gate /*NOTREACHED*/ 9331717Swesolows return (0); 9340Sstevel@tonic-gate } 9350Sstevel@tonic-gate 9364436Sstephh /* 9374436Sstephh * defines for u.expr.temp - these are used for T_OR and T_AND so that if 9384436Sstephh * we worked out that part of the expression was true or false during an 9394436Sstephh * earlier eval_expr, then we don't need to dup that part. 9404436Sstephh */ 9410Sstevel@tonic-gate 9424436Sstephh #define EXPR_TEMP_BOTH_UNK 0 9434436Sstephh #define EXPR_TEMP_LHS_UNK 1 9444436Sstephh #define EXPR_TEMP_RHS_UNK 2 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate static struct node * 9474436Sstephh eval_dup(struct node *np, struct lut *ex, struct node *events[]) 9480Sstevel@tonic-gate { 9490Sstevel@tonic-gate struct node *newnp; 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate if (np == NULL) 9520Sstevel@tonic-gate return (NULL); 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate switch (np->t) { 9550Sstevel@tonic-gate case T_GLOBID: 9560Sstevel@tonic-gate return (tree_globid(np->u.globid.s, np->file, np->line)); 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate case T_ASSIGN: 9590Sstevel@tonic-gate case T_CONDIF: 9600Sstevel@tonic-gate case T_CONDELSE: 9610Sstevel@tonic-gate case T_NE: 9620Sstevel@tonic-gate case T_EQ: 9630Sstevel@tonic-gate case T_LT: 9640Sstevel@tonic-gate case T_LE: 9650Sstevel@tonic-gate case T_GT: 9660Sstevel@tonic-gate case T_GE: 9670Sstevel@tonic-gate case T_BITAND: 9680Sstevel@tonic-gate case T_BITOR: 9690Sstevel@tonic-gate case T_BITXOR: 9700Sstevel@tonic-gate case T_BITNOT: 9710Sstevel@tonic-gate case T_LSHIFT: 9720Sstevel@tonic-gate case T_RSHIFT: 9730Sstevel@tonic-gate case T_NOT: 9740Sstevel@tonic-gate case T_ADD: 9750Sstevel@tonic-gate case T_SUB: 9760Sstevel@tonic-gate case T_MUL: 9770Sstevel@tonic-gate case T_DIV: 9780Sstevel@tonic-gate case T_MOD: 9790Sstevel@tonic-gate return (tree_expr(np->t, 9804436Sstephh eval_dup(np->u.expr.left, ex, events), 9814436Sstephh eval_dup(np->u.expr.right, ex, events))); 9824436Sstephh case T_LIST: 9834436Sstephh case T_AND: 9844436Sstephh switch (np->u.expr.temp) { 9854436Sstephh case EXPR_TEMP_LHS_UNK: 9864436Sstephh return (eval_dup(np->u.expr.left, ex, events)); 9874436Sstephh case EXPR_TEMP_RHS_UNK: 9884436Sstephh return (eval_dup(np->u.expr.right, ex, events)); 9894436Sstephh default: 9904436Sstephh return (tree_expr(np->t, 9914436Sstephh eval_dup(np->u.expr.left, ex, events), 9924436Sstephh eval_dup(np->u.expr.right, ex, events))); 9934436Sstephh } 9944436Sstephh 9954436Sstephh case T_OR: 9964436Sstephh switch (np->u.expr.temp) { 9974436Sstephh case EXPR_TEMP_LHS_UNK: 9984436Sstephh return (eval_dup(np->u.expr.left, ex, events)); 9994436Sstephh case EXPR_TEMP_RHS_UNK: 10004436Sstephh return (eval_dup(np->u.expr.right, ex, events)); 10014436Sstephh default: 10024436Sstephh return (tree_expr(T_OR, 10034436Sstephh eval_dup(np->u.expr.left, ex, events), 10044436Sstephh eval_dup(np->u.expr.right, ex, events))); 10054436Sstephh } 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate case T_NAME: { 10080Sstevel@tonic-gate struct iterinfo *iterinfop; 10094436Sstephh int got_matchf = 0; 10104436Sstephh int got_matcht = 0; 10114436Sstephh struct evalue value; 10124436Sstephh struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL; 10134436Sstephh struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest; 10140Sstevel@tonic-gate 10154436Sstephh /* 10164436Sstephh * Check if we already have a match of the nonwildcarded path 10174436Sstephh * in oldepname (check both to and from events). 10184436Sstephh */ 10194436Sstephh for (np1f = np, np2f = events[0]->u.event.oldepname; 10204436Sstephh np1f != NULL && np2f != NULL; 10214436Sstephh np1f = np1f->u.name.next, np2f = np2f->u.name.next) { 10224436Sstephh if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0) 10234436Sstephh break; 10244436Sstephh if (np1f->u.name.child->t != np2f->u.name.child->t) 10254436Sstephh break; 10264436Sstephh if (np1f->u.name.child->t == T_NUM && 10274436Sstephh np1f->u.name.child->u.ull != 10284436Sstephh np2f->u.name.child->u.ull) 10294436Sstephh break; 10304436Sstephh if (np1f->u.name.child->t == T_NAME && 10314436Sstephh strcmp(np1f->u.name.child->u.name.s, 10324436Sstephh np2f->u.name.child->u.name.s) != 0) 10334436Sstephh break; 10344436Sstephh got_matchf++; 10354436Sstephh } 10364436Sstephh for (np1t = np, np2t = events[1]->u.event.oldepname; 10374436Sstephh np1t != NULL && np2t != NULL; 10384436Sstephh np1t = np1t->u.name.next, np2t = np2t->u.name.next) { 10394436Sstephh if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0) 10404436Sstephh break; 10414436Sstephh if (np1t->u.name.child->t != np2t->u.name.child->t) 10424436Sstephh break; 10434436Sstephh if (np1t->u.name.child->t == T_NUM && 10444436Sstephh np1t->u.name.child->u.ull != 10454436Sstephh np2t->u.name.child->u.ull) 10464436Sstephh break; 10474436Sstephh if (np1t->u.name.child->t == T_NAME && 10484436Sstephh strcmp(np1t->u.name.child->u.name.s, 10494436Sstephh np2t->u.name.child->u.name.s) != 0) 10504436Sstephh break; 10514436Sstephh got_matcht++; 10524436Sstephh } 10534436Sstephh nprest = np; 10544436Sstephh if (got_matchf || got_matcht) { 10554436Sstephh /* 10564436Sstephh * so we are wildcarding. Copy ewname in full, plus 10574436Sstephh * matching section of oldepname. Use whichever gives 10584436Sstephh * the closest match. 10594436Sstephh */ 10604436Sstephh if (got_matchf > got_matcht) { 10614436Sstephh npstart = events[0]->u.event.ewname; 10624436Sstephh npcont = events[0]->u.event.oldepname; 10634436Sstephh npend = np2f; 10644436Sstephh nprest = np1f; 10654436Sstephh } else { 10664436Sstephh npstart = events[1]->u.event.ewname; 10674436Sstephh npcont = events[1]->u.event.oldepname; 10684436Sstephh npend = np2t; 10694436Sstephh nprest = np1t; 10704436Sstephh } 10714436Sstephh for (npref = npstart; npref != NULL; 10724436Sstephh npref = npref->u.name.next) { 10734436Sstephh newnp = newnode(T_NAME, np->file, np->line); 10744436Sstephh newnp->u.name.t = npref->u.name.t; 10754436Sstephh newnp->u.name.s = npref->u.name.s; 10764436Sstephh newnp->u.name.last = newnp; 10774436Sstephh newnp->u.name.it = npref->u.name.it; 10784436Sstephh newnp->u.name.cp = npref->u.name.cp; 10794436Sstephh newnp->u.name.child = 10804436Sstephh newnode(T_NUM, np->file, np->line); 10814436Sstephh if (eval_expr(npref->u.name.child, ex, events, 10820Sstevel@tonic-gate NULL, NULL, NULL, 1, &value) == 0 || 10830Sstevel@tonic-gate value.t != UINT64) { 10840Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 10850Sstevel@tonic-gate "eval_dup: could not resolve " 10860Sstevel@tonic-gate "iterator of %s", np->u.name.s); 10870Sstevel@tonic-gate } 10884436Sstephh newnp->u.name.child->u.ull = value.v; 10894436Sstephh if (retp == NULL) { 10904436Sstephh retp = newnp; 10914436Sstephh } else { 10924436Sstephh retp->u.name.last->u.name.next = newnp; 10934436Sstephh retp->u.name.last = newnp; 10944436Sstephh } 10950Sstevel@tonic-gate } 10964436Sstephh for (npref = npcont; npref != NULL && npref != npend; 10974436Sstephh npref = npref->u.name.next) { 10984436Sstephh newnp = newnode(T_NAME, np->file, np->line); 10994436Sstephh newnp->u.name.t = npref->u.name.t; 11004436Sstephh newnp->u.name.s = npref->u.name.s; 11014436Sstephh newnp->u.name.last = newnp; 11024436Sstephh newnp->u.name.it = npref->u.name.it; 11034436Sstephh newnp->u.name.cp = npref->u.name.cp; 11044436Sstephh newnp->u.name.child = 11054436Sstephh newnode(T_NUM, np->file, np->line); 11064436Sstephh if (eval_expr(npref->u.name.child, ex, events, 11074436Sstephh NULL, NULL, NULL, 1, &value) == 0 || 11084436Sstephh value.t != UINT64) { 11094436Sstephh outfl(O_DIE, np->file, np->line, 11104436Sstephh "eval_dup: could not resolve " 11114436Sstephh "iterator of %s", np->u.name.s); 11124436Sstephh } 11134436Sstephh newnp->u.name.child->u.ull = value.v; 11144436Sstephh if (retp == NULL) { 11154436Sstephh retp = newnp; 11164436Sstephh } else { 11174436Sstephh retp->u.name.last->u.name.next = newnp; 11184436Sstephh retp->u.name.last = newnp; 11194436Sstephh } 11204436Sstephh } 11214436Sstephh } else { 11224436Sstephh /* 11234436Sstephh * not wildcarding - check if explicit iterator 11244436Sstephh */ 11254436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 11264436Sstephh if (iterinfop != NULL) { 11274436Sstephh /* explicit iterator; not part of pathname */ 11284436Sstephh newnp = newnode(T_NUM, np->file, np->line); 11294436Sstephh newnp->u.ull = iterinfop->num; 11300Sstevel@tonic-gate return (newnp); 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate } 11334436Sstephh 11344436Sstephh /* 11354436Sstephh * finally, whether wildcarding or not, we need to copy the 11364436Sstephh * remaining part of the path (if any). This must be defined 11374436Sstephh * absolutely (no more expansion/wildcarding). 11384436Sstephh */ 11394436Sstephh for (npref = nprest; npref != NULL; 11404436Sstephh npref = npref->u.name.next) { 11414436Sstephh newnp = newnode(T_NAME, np->file, np->line); 11424436Sstephh newnp->u.name.t = npref->u.name.t; 11434436Sstephh newnp->u.name.s = npref->u.name.s; 11444436Sstephh newnp->u.name.last = newnp; 11454436Sstephh newnp->u.name.it = npref->u.name.it; 11464436Sstephh newnp->u.name.cp = npref->u.name.cp; 11474436Sstephh newnp->u.name.child = 11484436Sstephh newnode(T_NUM, np->file, np->line); 11494436Sstephh if (eval_expr(npref->u.name.child, ex, events, 11504436Sstephh NULL, NULL, NULL, 1, &value) == 0 || 11514436Sstephh value.t != UINT64) { 11524436Sstephh outfl(O_DIE, np->file, np->line, 11534436Sstephh "eval_dup: could not resolve " 11544436Sstephh "iterator of %s", np->u.name.s); 11554436Sstephh } 11564436Sstephh newnp->u.name.child->u.ull = value.v; 11574436Sstephh if (retp == NULL) { 11584436Sstephh retp = newnp; 11594436Sstephh } else { 11604436Sstephh retp->u.name.last->u.name.next = newnp; 11614436Sstephh retp->u.name.last = newnp; 11624436Sstephh } 11634436Sstephh } 11644436Sstephh return (retp); 11650Sstevel@tonic-gate } 11660Sstevel@tonic-gate 11671414Scindi case T_EVENT: 11681414Scindi newnp = newnode(T_NAME, np->file, np->line); 11691414Scindi 11701414Scindi newnp->u.name.t = np->u.event.ename->u.name.t; 11711414Scindi newnp->u.name.s = np->u.event.ename->u.name.s; 11721414Scindi newnp->u.name.it = np->u.event.ename->u.name.it; 11731414Scindi newnp->u.name.last = newnp; 11741414Scindi 11751414Scindi return (tree_event(newnp, 11764436Sstephh eval_dup(np->u.event.epname, ex, events), 11774436Sstephh eval_dup(np->u.event.eexprlist, ex, events))); 11781414Scindi 11790Sstevel@tonic-gate case T_FUNC: 11800Sstevel@tonic-gate return (tree_func(np->u.func.s, 11814436Sstephh eval_dup(np->u.func.arglist, ex, events), 11820Sstevel@tonic-gate np->file, np->line)); 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate case T_QUOTE: 11850Sstevel@tonic-gate newnp = newnode(T_QUOTE, np->file, np->line); 11860Sstevel@tonic-gate newnp->u.quote.s = np->u.quote.s; 11870Sstevel@tonic-gate return (newnp); 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate case T_NUM: 11900Sstevel@tonic-gate newnp = newnode(T_NUM, np->file, np->line); 11910Sstevel@tonic-gate newnp->u.ull = np->u.ull; 11920Sstevel@tonic-gate return (newnp); 11930Sstevel@tonic-gate 11947197Sstephh case T_TIMEVAL: 11957197Sstephh newnp = newnode(T_TIMEVAL, np->file, np->line); 11967197Sstephh newnp->u.ull = np->u.ull; 11977197Sstephh return (newnp); 11987197Sstephh 11990Sstevel@tonic-gate default: 12000Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 12010Sstevel@tonic-gate "eval_dup: unexpected node type: %s", 12020Sstevel@tonic-gate ptree_nodetype2str(np->t)); 12030Sstevel@tonic-gate } 12040Sstevel@tonic-gate /*NOTREACHED*/ 12051717Swesolows return (0); 12060Sstevel@tonic-gate } 12070Sstevel@tonic-gate 12080Sstevel@tonic-gate /* 12090Sstevel@tonic-gate * eval_potential -- see if constraint is potentially true 12100Sstevel@tonic-gate * 12110Sstevel@tonic-gate * this function is used at instance tree creation time to see if 12120Sstevel@tonic-gate * any constraints are already known to be false. if this function 12130Sstevel@tonic-gate * returns false, then the constraint will always be false and there's 12140Sstevel@tonic-gate * no need to include the propagation arrow in the instance tree. 12150Sstevel@tonic-gate * 12160Sstevel@tonic-gate * if this routine returns true, either the constraint is known to 12170Sstevel@tonic-gate * be always true (so there's no point in attaching the constraint 12180Sstevel@tonic-gate * to the propagation arrow in the instance tree), or the constraint 12190Sstevel@tonic-gate * contains "deferred" expressions like global variables or poller calls 12200Sstevel@tonic-gate * and so it must be evaluated during calls to fme_eval(). in this last 12210Sstevel@tonic-gate * case, where a constraint needs to be attached to the propagation arrow 12220Sstevel@tonic-gate * in the instance tree, this routine returns a newly created constraint 12230Sstevel@tonic-gate * in *newc where all the non-deferred things have been filled in. 12240Sstevel@tonic-gate * 12250Sstevel@tonic-gate * so in summary: 12260Sstevel@tonic-gate * 12270Sstevel@tonic-gate * return of false: constraint can never be true, *newc will be NULL. 12280Sstevel@tonic-gate * 12290Sstevel@tonic-gate * return of true with *newc unchanged: constraint will always be true. 12300Sstevel@tonic-gate * 12310Sstevel@tonic-gate * return of true with *newc changed: use new constraint in *newc. 12320Sstevel@tonic-gate * 12330Sstevel@tonic-gate * the lookup table for all explicit iterators, ex, is passed in. 12340Sstevel@tonic-gate * 12350Sstevel@tonic-gate * *newc can either be NULL on entry, or if can contain constraints from 12360Sstevel@tonic-gate * previous calls to eval_potential() (i.e. for building up an instance 12370Sstevel@tonic-gate * tree constraint from several potential constraints). if *newc already 12380Sstevel@tonic-gate * contains constraints, anything added to it will be joined by adding 12390Sstevel@tonic-gate * a T_AND node at the top of *newc. 12400Sstevel@tonic-gate */ 12410Sstevel@tonic-gate int 12424436Sstephh eval_potential(struct node *np, struct lut *ex, struct node *events[], 12432318Sstephh struct node **newc, struct config *croot) 12440Sstevel@tonic-gate { 12450Sstevel@tonic-gate struct node *newnp; 12460Sstevel@tonic-gate struct evalue value; 12470Sstevel@tonic-gate 12484436Sstephh if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) { 12490Sstevel@tonic-gate /* 12500Sstevel@tonic-gate * couldn't eval expression because 12510Sstevel@tonic-gate * it contains deferred items. make 12520Sstevel@tonic-gate * a duplicate expression with all the 12530Sstevel@tonic-gate * non-deferred items expanded. 12540Sstevel@tonic-gate */ 12554436Sstephh newnp = eval_dup(np, ex, events); 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate if (*newc == NULL) { 12580Sstevel@tonic-gate /* 12590Sstevel@tonic-gate * constraint is potentially true if deferred 12600Sstevel@tonic-gate * expression in newnp is true. *newc was NULL 12610Sstevel@tonic-gate * so new constraint is just the one in newnp. 12620Sstevel@tonic-gate */ 12630Sstevel@tonic-gate *newc = newnp; 12640Sstevel@tonic-gate return (1); 12650Sstevel@tonic-gate } else { 12660Sstevel@tonic-gate /* 12670Sstevel@tonic-gate * constraint is potentially true if deferred 12680Sstevel@tonic-gate * expression in newnp is true. *newc already 12690Sstevel@tonic-gate * contained a constraint so add an AND with the 12700Sstevel@tonic-gate * constraint in newnp. 12710Sstevel@tonic-gate */ 12720Sstevel@tonic-gate *newc = tree_expr(T_AND, *newc, newnp); 12730Sstevel@tonic-gate return (1); 12740Sstevel@tonic-gate } 12750Sstevel@tonic-gate } else if (value.t == UNDEFINED) { 12760Sstevel@tonic-gate /* constraint can never be true */ 12770Sstevel@tonic-gate return (0); 12780Sstevel@tonic-gate } else if (value.t == UINT64 && value.v == 0) { 12790Sstevel@tonic-gate /* constraint can never be true */ 12800Sstevel@tonic-gate return (0); 12810Sstevel@tonic-gate } else { 12820Sstevel@tonic-gate /* constraint is always true (nothing deferred to eval) */ 12830Sstevel@tonic-gate return (1); 12840Sstevel@tonic-gate } 12850Sstevel@tonic-gate } 12860Sstevel@tonic-gate 12870Sstevel@tonic-gate static int 12880Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 12890Sstevel@tonic-gate struct node *np) 12900Sstevel@tonic-gate { 12911414Scindi /* auto-convert T_NAMES to strings */ 12921717Swesolows if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t == 12931717Swesolows T_NAME) { 12941717Swesolows char *s = ipath2str(NULL, 12951717Swesolows ipath((struct node *)(uintptr_t)lp->v)); 12961414Scindi lp->t = STRING; 12971717Swesolows lp->v = (uintptr_t)stable(s); 12981414Scindi FREE(s); 12991414Scindi out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"", 13001717Swesolows (char *)(uintptr_t)lp->v); 13011414Scindi } 13021414Scindi if (rp != NULL && 13031717Swesolows rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t == 13041717Swesolows T_NAME) { 13051717Swesolows char *s = ipath2str(NULL, 13061717Swesolows ipath((struct node *)(uintptr_t)rp->v)); 13071414Scindi rp->t = STRING; 13081717Swesolows rp->v = (uintptr_t)stable(s); 13091414Scindi FREE(s); 13101414Scindi out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"", 13111717Swesolows (char *)(uintptr_t)rp->v); 13121414Scindi } 13131414Scindi 1314*11202SStephen.Hanson@Sun.COM /* auto-convert numbers to strings */ 1315*11202SStephen.Hanson@Sun.COM if (dtype == STRING) { 1316*11202SStephen.Hanson@Sun.COM if (lp->t == UINT64) { 1317*11202SStephen.Hanson@Sun.COM int len = snprintf(NULL, 0, "%llx", lp->v); 1318*11202SStephen.Hanson@Sun.COM char *s = MALLOC(len + 1); 1319*11202SStephen.Hanson@Sun.COM 1320*11202SStephen.Hanson@Sun.COM (void) snprintf(s, len + 1, "%llx", lp->v); 1321*11202SStephen.Hanson@Sun.COM lp->t = STRING; 1322*11202SStephen.Hanson@Sun.COM lp->v = (uintptr_t)stable(s); 1323*11202SStephen.Hanson@Sun.COM FREE(s); 1324*11202SStephen.Hanson@Sun.COM } 1325*11202SStephen.Hanson@Sun.COM if (rp != NULL && rp->t == UINT64) { 1326*11202SStephen.Hanson@Sun.COM int len = snprintf(NULL, 0, "%llx", rp->v); 1327*11202SStephen.Hanson@Sun.COM char *s = MALLOC(len + 1); 1328*11202SStephen.Hanson@Sun.COM 1329*11202SStephen.Hanson@Sun.COM (void) snprintf(s, len + 1, "%llx", rp->v); 1330*11202SStephen.Hanson@Sun.COM rp->t = STRING; 1331*11202SStephen.Hanson@Sun.COM rp->v = (uintptr_t)stable(s); 1332*11202SStephen.Hanson@Sun.COM FREE(s); 1333*11202SStephen.Hanson@Sun.COM } 1334*11202SStephen.Hanson@Sun.COM } 1335*11202SStephen.Hanson@Sun.COM 13361414Scindi /* auto-convert strings to numbers */ 13371414Scindi if (dtype == UINT64) { 13381414Scindi if (lp->t == STRING) { 13391414Scindi lp->t = UINT64; 13401717Swesolows lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0); 13411414Scindi } 13421414Scindi if (rp != NULL && rp->t == STRING) { 13431414Scindi rp->t = UINT64; 13441717Swesolows rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0); 13451414Scindi } 13461414Scindi } 13471414Scindi 13480Sstevel@tonic-gate if (dtype != UNDEFINED && lp->t != dtype) { 13494436Sstephh outfl(O_DIE, np->file, np->line, 13504436Sstephh "invalid datatype of argument for operation %s", 13514436Sstephh ptree_nodetype2str(np->t)); 13524436Sstephh /* NOTREACHED */ 13530Sstevel@tonic-gate return (1); 13540Sstevel@tonic-gate } 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate if (rp != NULL && lp->t != rp->t) { 13574436Sstephh outfl(O_DIE, np->file, np->line, 13584436Sstephh "mismatch in datatype of arguments for operation %s", 13594436Sstephh ptree_nodetype2str(np->t)); 13604436Sstephh /* NOTREACHED */ 13610Sstevel@tonic-gate return (1); 13620Sstevel@tonic-gate } 13630Sstevel@tonic-gate 13640Sstevel@tonic-gate return (0); 13650Sstevel@tonic-gate } 13660Sstevel@tonic-gate 13670Sstevel@tonic-gate /* 13680Sstevel@tonic-gate * eval_expr -- evaluate expression into *valuep 13690Sstevel@tonic-gate * 13700Sstevel@tonic-gate * the meaning of the return value depends on the input value of try. 13710Sstevel@tonic-gate * 13720Sstevel@tonic-gate * for try == 1: if any deferred items are encounted, bail out and return 13730Sstevel@tonic-gate * false. returns true if we made it through entire expression without 13740Sstevel@tonic-gate * hitting any deferred items. 13750Sstevel@tonic-gate * 13760Sstevel@tonic-gate * for try == 0: return true if all operations were performed successfully. 13770Sstevel@tonic-gate * return false if otherwise. for example, any of the following conditions 13780Sstevel@tonic-gate * will result in a false return value: 13790Sstevel@tonic-gate * - attempted use of an uninitialized global variable 13800Sstevel@tonic-gate * - failure in function evaluation 13810Sstevel@tonic-gate * - illegal arithmetic operation (argument out of range) 13820Sstevel@tonic-gate */ 13830Sstevel@tonic-gate int 13844436Sstephh eval_expr(struct node *np, struct lut *ex, struct node *events[], 13850Sstevel@tonic-gate struct lut **globals, struct config *croot, struct arrow *arrowp, 13860Sstevel@tonic-gate int try, struct evalue *valuep) 13870Sstevel@tonic-gate { 13880Sstevel@tonic-gate struct evalue *gval; 13890Sstevel@tonic-gate struct evalue lval; 13900Sstevel@tonic-gate struct evalue rval; 13910Sstevel@tonic-gate 13920Sstevel@tonic-gate if (np == NULL) { 13930Sstevel@tonic-gate valuep->t = UINT64; 13940Sstevel@tonic-gate valuep->v = 1; /* no constraint means "true" */ 13950Sstevel@tonic-gate return (1); 13960Sstevel@tonic-gate } 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate valuep->t = UNDEFINED; 13990Sstevel@tonic-gate 14000Sstevel@tonic-gate switch (np->t) { 14010Sstevel@tonic-gate case T_GLOBID: 14020Sstevel@tonic-gate if (try) 14030Sstevel@tonic-gate return (0); 14040Sstevel@tonic-gate 14050Sstevel@tonic-gate /* 14060Sstevel@tonic-gate * only handle case of getting (and not setting) the value 14070Sstevel@tonic-gate * of a global variable 14080Sstevel@tonic-gate */ 14090Sstevel@tonic-gate gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 14100Sstevel@tonic-gate if (gval == NULL) { 14110Sstevel@tonic-gate return (0); 14120Sstevel@tonic-gate } else { 14130Sstevel@tonic-gate valuep->t = gval->t; 14140Sstevel@tonic-gate valuep->v = gval->v; 14150Sstevel@tonic-gate return (1); 14160Sstevel@tonic-gate } 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate case T_ASSIGN: 14190Sstevel@tonic-gate if (try) 14200Sstevel@tonic-gate return (0); 14210Sstevel@tonic-gate 14220Sstevel@tonic-gate /* 14230Sstevel@tonic-gate * first evaluate rhs, then try to store value in lhs which 14240Sstevel@tonic-gate * should be a global variable 14250Sstevel@tonic-gate */ 14264436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14274436Sstephh arrowp, try, &rval)) 14280Sstevel@tonic-gate return (0); 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate ASSERT(np->u.expr.left->t == T_GLOBID); 14310Sstevel@tonic-gate gval = lut_lookup(*globals, 14324436Sstephh (void *)np->u.expr.left->u.globid.s, NULL); 14330Sstevel@tonic-gate 14340Sstevel@tonic-gate if (gval == NULL) { 14350Sstevel@tonic-gate gval = MALLOC(sizeof (*gval)); 14360Sstevel@tonic-gate *globals = lut_add(*globals, 14374436Sstephh (void *) np->u.expr.left->u.globid.s, gval, NULL); 14380Sstevel@tonic-gate } 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate gval->t = rval.t; 14410Sstevel@tonic-gate gval->v = rval.v; 14421414Scindi 14431414Scindi if (gval->t == UINT64) { 14441414Scindi out(O_ALTFP|O_VERB2, 14451414Scindi "assign $%s=%llu", 14461414Scindi np->u.expr.left->u.globid.s, gval->v); 14471414Scindi } else { 14481414Scindi out(O_ALTFP|O_VERB2, 14491414Scindi "assign $%s=\"%s\"", 14501717Swesolows np->u.expr.left->u.globid.s, 14511717Swesolows (char *)(uintptr_t)gval->v); 14521414Scindi } 14531414Scindi 14541414Scindi /* 14551414Scindi * but always return true -- an assignment should not 14561414Scindi * cause a constraint to be false. 14571414Scindi */ 14581414Scindi valuep->t = UINT64; 14591414Scindi valuep->v = 1; 14600Sstevel@tonic-gate return (1); 14610Sstevel@tonic-gate 14620Sstevel@tonic-gate case T_EQ: 14630Sstevel@tonic-gate #define IMPLICIT_ASSIGN_IN_EQ 14640Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ 14650Sstevel@tonic-gate /* 14660Sstevel@tonic-gate * if lhs is an uninitialized global variable, perform 14670Sstevel@tonic-gate * an assignment. 14680Sstevel@tonic-gate * 14690Sstevel@tonic-gate * one insidious side effect of implicit assignment is 14700Sstevel@tonic-gate * that the "==" operator does not return a Boolean if 14710Sstevel@tonic-gate * implicit assignment was performed. 14720Sstevel@tonic-gate */ 14730Sstevel@tonic-gate if (try == 0 && 14740Sstevel@tonic-gate np->u.expr.left->t == T_GLOBID && 14750Sstevel@tonic-gate (gval = lut_lookup(*globals, 14764436Sstephh (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 14774436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 14784436Sstephh croot, arrowp, try, &rval)) 14790Sstevel@tonic-gate return (0); 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate gval = MALLOC(sizeof (*gval)); 14820Sstevel@tonic-gate *globals = lut_add(*globals, 14834436Sstephh (void *) np->u.expr.left->u.globid.s, 14844436Sstephh gval, NULL); 14850Sstevel@tonic-gate 14860Sstevel@tonic-gate gval->t = rval.t; 14870Sstevel@tonic-gate gval->v = rval.v; 14880Sstevel@tonic-gate valuep->t = rval.t; 14890Sstevel@tonic-gate valuep->v = rval.v; 14900Sstevel@tonic-gate return (1); 14910Sstevel@tonic-gate } 14920Sstevel@tonic-gate #endif /* IMPLICIT_ASSIGN_IN_EQ */ 14930Sstevel@tonic-gate 14944436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14954436Sstephh arrowp, try, &lval)) 14964436Sstephh return (0); 14974436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14984436Sstephh arrowp, try, &rval)) 14990Sstevel@tonic-gate return (0); 15004436Sstephh if (rval.t == UINT64 || lval.t == UINT64) { 15014436Sstephh if (check_expr_args(&lval, &rval, UINT64, np)) 15024436Sstephh return (0); 15034436Sstephh } else { 15044436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np)) 15054436Sstephh return (0); 15064436Sstephh } 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate valuep->t = UINT64; 15090Sstevel@tonic-gate valuep->v = (lval.v == rval.v); 15100Sstevel@tonic-gate return (1); 15110Sstevel@tonic-gate 15120Sstevel@tonic-gate case T_LT: 15134436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15144436Sstephh arrowp, try, &lval)) 15150Sstevel@tonic-gate return (0); 15164436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15174436Sstephh arrowp, try, &rval)) 15180Sstevel@tonic-gate return (0); 15191414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 15200Sstevel@tonic-gate return (0); 15210Sstevel@tonic-gate 15220Sstevel@tonic-gate valuep->t = UINT64; 15230Sstevel@tonic-gate valuep->v = (lval.v < rval.v); 15240Sstevel@tonic-gate return (1); 15250Sstevel@tonic-gate 15260Sstevel@tonic-gate case T_LE: 15274436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15284436Sstephh arrowp, try, &lval)) 15290Sstevel@tonic-gate return (0); 15304436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15314436Sstephh arrowp, try, &rval)) 15320Sstevel@tonic-gate return (0); 15331414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 15340Sstevel@tonic-gate return (0); 15350Sstevel@tonic-gate 15360Sstevel@tonic-gate valuep->t = UINT64; 15370Sstevel@tonic-gate valuep->v = (lval.v <= rval.v); 15380Sstevel@tonic-gate return (1); 15390Sstevel@tonic-gate 15400Sstevel@tonic-gate case T_GT: 15414436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15424436Sstephh arrowp, try, &lval)) 15430Sstevel@tonic-gate return (0); 15444436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15454436Sstephh arrowp, try, &rval)) 15460Sstevel@tonic-gate return (0); 15471414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 15480Sstevel@tonic-gate return (0); 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate valuep->t = UINT64; 15510Sstevel@tonic-gate valuep->v = (lval.v > rval.v); 15520Sstevel@tonic-gate return (1); 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate case T_GE: 15554436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15564436Sstephh arrowp, try, &lval)) 15570Sstevel@tonic-gate return (0); 15584436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15594436Sstephh arrowp, try, &rval)) 15600Sstevel@tonic-gate return (0); 15611414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 15620Sstevel@tonic-gate return (0); 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate valuep->t = UINT64; 15650Sstevel@tonic-gate valuep->v = (lval.v >= rval.v); 15660Sstevel@tonic-gate return (1); 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate case T_BITAND: 15694436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15704436Sstephh arrowp, try, &lval)) 15710Sstevel@tonic-gate return (0); 15724436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15734436Sstephh arrowp, try, &rval)) 15740Sstevel@tonic-gate return (0); 15750Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 15760Sstevel@tonic-gate return (0); 15770Sstevel@tonic-gate 15780Sstevel@tonic-gate valuep->t = lval.t; 15790Sstevel@tonic-gate valuep->v = (lval.v & rval.v); 15800Sstevel@tonic-gate return (1); 15810Sstevel@tonic-gate 15820Sstevel@tonic-gate case T_BITOR: 15834436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15844436Sstephh arrowp, try, &lval)) 15850Sstevel@tonic-gate return (0); 15864436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15874436Sstephh arrowp, try, &rval)) 15880Sstevel@tonic-gate return (0); 15890Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 15900Sstevel@tonic-gate return (0); 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate valuep->t = lval.t; 15930Sstevel@tonic-gate valuep->v = (lval.v | rval.v); 15940Sstevel@tonic-gate return (1); 15950Sstevel@tonic-gate 15960Sstevel@tonic-gate case T_BITXOR: 15974436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15984436Sstephh arrowp, try, &lval)) 15990Sstevel@tonic-gate return (0); 16004436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16014436Sstephh arrowp, try, &rval)) 16020Sstevel@tonic-gate return (0); 16030Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16040Sstevel@tonic-gate return (0); 16050Sstevel@tonic-gate 16060Sstevel@tonic-gate valuep->t = lval.t; 16070Sstevel@tonic-gate valuep->v = (lval.v ^ rval.v); 16080Sstevel@tonic-gate return (1); 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate case T_BITNOT: 16114436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16124436Sstephh arrowp, try, &lval)) 16130Sstevel@tonic-gate return (0); 16140Sstevel@tonic-gate ASSERT(np->u.expr.right == NULL); 16150Sstevel@tonic-gate if (check_expr_args(&lval, NULL, UINT64, np)) 16160Sstevel@tonic-gate return (0); 16170Sstevel@tonic-gate 16180Sstevel@tonic-gate valuep->t = UINT64; 16190Sstevel@tonic-gate valuep->v = ~ lval.v; 16200Sstevel@tonic-gate return (1); 16210Sstevel@tonic-gate 16220Sstevel@tonic-gate case T_LSHIFT: 16234436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16244436Sstephh arrowp, try, &lval)) 16250Sstevel@tonic-gate return (0); 16264436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16274436Sstephh arrowp, try, &rval)) 16280Sstevel@tonic-gate return (0); 16290Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16300Sstevel@tonic-gate return (0); 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate valuep->t = UINT64; 16330Sstevel@tonic-gate valuep->v = (lval.v << rval.v); 16340Sstevel@tonic-gate return (1); 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate case T_RSHIFT: 16374436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16384436Sstephh arrowp, try, &lval)) 16390Sstevel@tonic-gate return (0); 16404436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16414436Sstephh arrowp, try, &rval)) 16420Sstevel@tonic-gate return (0); 16430Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16440Sstevel@tonic-gate return (0); 16450Sstevel@tonic-gate 16460Sstevel@tonic-gate valuep->t = UINT64; 16470Sstevel@tonic-gate valuep->v = (lval.v >> rval.v); 16480Sstevel@tonic-gate return (1); 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate case T_CONDIF: { 16510Sstevel@tonic-gate struct node *retnp; 16520Sstevel@tonic-gate int dotrue = 0; 16530Sstevel@tonic-gate 16540Sstevel@tonic-gate /* 16550Sstevel@tonic-gate * evaluate 16560Sstevel@tonic-gate * expression ? stmtA [ : stmtB ] 16570Sstevel@tonic-gate * 16580Sstevel@tonic-gate * first see if expression is true or false, then determine 16590Sstevel@tonic-gate * if stmtA (or stmtB, if it exists) should be evaluated. 16600Sstevel@tonic-gate * 16610Sstevel@tonic-gate * "dotrue = 1" means stmtA should be evaluated. 16620Sstevel@tonic-gate */ 16635204Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16645204Sstephh arrowp, try, &lval)) 16655204Sstephh return (0); 16665204Sstephh 16675204Sstephh if (lval.t != UNDEFINED && lval.v != 0) 16680Sstevel@tonic-gate dotrue = 1; 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate ASSERT(np->u.expr.right != NULL); 16710Sstevel@tonic-gate if (np->u.expr.right->t == T_CONDELSE) { 16720Sstevel@tonic-gate if (dotrue) 16730Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.left; 16740Sstevel@tonic-gate else 16750Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.right; 16760Sstevel@tonic-gate } else { 16770Sstevel@tonic-gate /* no ELSE clause */ 16780Sstevel@tonic-gate if (dotrue) 16790Sstevel@tonic-gate retnp = np->u.expr.right; 16800Sstevel@tonic-gate else { 16814436Sstephh outfl(O_DIE, np->file, np->line, 16824436Sstephh "eval_expr: missing condelse"); 16830Sstevel@tonic-gate } 16840Sstevel@tonic-gate } 16850Sstevel@tonic-gate 16864436Sstephh if (!eval_expr(retnp, ex, events, globals, croot, 16874436Sstephh arrowp, try, valuep)) 16880Sstevel@tonic-gate return (0); 16890Sstevel@tonic-gate return (1); 16900Sstevel@tonic-gate } 16910Sstevel@tonic-gate 16920Sstevel@tonic-gate case T_CONDELSE: 16930Sstevel@tonic-gate /* 16940Sstevel@tonic-gate * shouldn't get here, since T_CONDELSE is supposed to be 16950Sstevel@tonic-gate * evaluated as part of T_CONDIF 16960Sstevel@tonic-gate */ 16970Sstevel@tonic-gate out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 16980Sstevel@tonic-gate ptree_nodetype2str(np->t)); 16994436Sstephh /*NOTREACHED*/ 17000Sstevel@tonic-gate 17010Sstevel@tonic-gate case T_NE: 17024436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 17034436Sstephh arrowp, try, &lval)) 17044436Sstephh return (0); 17054436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 17064436Sstephh arrowp, try, &rval)) 17070Sstevel@tonic-gate return (0); 17084436Sstephh if (rval.t == UINT64 || lval.t == UINT64) { 17094436Sstephh if (check_expr_args(&lval, &rval, UINT64, np)) 17104436Sstephh return (0); 17114436Sstephh } else { 17124436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np)) 17134436Sstephh return (0); 17144436Sstephh } 17150Sstevel@tonic-gate 17160Sstevel@tonic-gate valuep->t = UINT64; 17170Sstevel@tonic-gate valuep->v = (lval.v != rval.v); 17180Sstevel@tonic-gate return (1); 17190Sstevel@tonic-gate 17200Sstevel@tonic-gate case T_LIST: 17210Sstevel@tonic-gate case T_AND: 17224436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 17234436Sstephh arrowp, try, valuep)) { 17243159Sstephh /* 17253159Sstephh * if lhs is unknown, still check rhs. If that 17265204Sstephh * is false we can return false irrespective of lhs 17273159Sstephh */ 17285204Sstephh if (!try) { 17295204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 17305204Sstephh return (0); 17315204Sstephh } 17324436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 17334436Sstephh croot, arrowp, try, valuep)) { 17344436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 17353159Sstephh return (0); 17364436Sstephh } 17374436Sstephh if (valuep->v != 0) { 17384436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK; 17393159Sstephh return (0); 17404436Sstephh } 17413159Sstephh } 17420Sstevel@tonic-gate if (valuep->v == 0) { 17430Sstevel@tonic-gate valuep->t = UINT64; 17440Sstevel@tonic-gate return (1); 17450Sstevel@tonic-gate } 17464436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 17474436Sstephh arrowp, try, valuep)) { 17484436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK; 17490Sstevel@tonic-gate return (0); 17504436Sstephh } 17510Sstevel@tonic-gate valuep->t = UINT64; 17520Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1; 17530Sstevel@tonic-gate return (1); 17540Sstevel@tonic-gate 17550Sstevel@tonic-gate case T_OR: 17564436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 17574436Sstephh arrowp, try, valuep)) { 17583159Sstephh /* 17593159Sstephh * if lhs is unknown, still check rhs. If that 17605204Sstephh * is true we can return true irrespective of lhs 17613159Sstephh */ 17625204Sstephh if (!try) { 17635204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 17645204Sstephh return (0); 17655204Sstephh } 17664436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 17674436Sstephh croot, arrowp, try, valuep)) { 17684436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 17693159Sstephh return (0); 17704436Sstephh } 17714436Sstephh if (valuep->v == 0) { 17724436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK; 17733159Sstephh return (0); 17744436Sstephh } 17753159Sstephh } 17760Sstevel@tonic-gate if (valuep->v != 0) { 17770Sstevel@tonic-gate valuep->t = UINT64; 17780Sstevel@tonic-gate valuep->v = 1; 17790Sstevel@tonic-gate return (1); 17800Sstevel@tonic-gate } 17814436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 17824436Sstephh arrowp, try, valuep)) { 17834436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK; 17840Sstevel@tonic-gate return (0); 17854436Sstephh } 17860Sstevel@tonic-gate valuep->t = UINT64; 17870Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1; 17880Sstevel@tonic-gate return (1); 17890Sstevel@tonic-gate 17900Sstevel@tonic-gate case T_NOT: 17914436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 17924436Sstephh arrowp, try, valuep)) 17930Sstevel@tonic-gate return (0); 17940Sstevel@tonic-gate valuep->t = UINT64; 17950Sstevel@tonic-gate valuep->v = ! valuep->v; 17960Sstevel@tonic-gate return (1); 17970Sstevel@tonic-gate 17980Sstevel@tonic-gate case T_ADD: 17994436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 18004436Sstephh arrowp, try, &lval)) 18010Sstevel@tonic-gate return (0); 18024436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 18034436Sstephh arrowp, try, &rval)) 18040Sstevel@tonic-gate return (0); 18050Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 18060Sstevel@tonic-gate return (0); 18070Sstevel@tonic-gate 18080Sstevel@tonic-gate valuep->t = lval.t; 18090Sstevel@tonic-gate valuep->v = lval.v + rval.v; 18100Sstevel@tonic-gate return (1); 18110Sstevel@tonic-gate 18120Sstevel@tonic-gate case T_SUB: 18134436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 18144436Sstephh arrowp, try, &lval)) 18150Sstevel@tonic-gate return (0); 18164436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 18174436Sstephh arrowp, try, &rval)) 18180Sstevel@tonic-gate return (0); 18190Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 18200Sstevel@tonic-gate return (0); 18210Sstevel@tonic-gate 18220Sstevel@tonic-gate /* since valuep is unsigned, return false if lval.v < rval.v */ 18230Sstevel@tonic-gate if (lval.v < rval.v) { 18244436Sstephh outfl(O_DIE, np->file, np->line, 18254436Sstephh "eval_expr: T_SUB result is out of range"); 18260Sstevel@tonic-gate } 18270Sstevel@tonic-gate 18280Sstevel@tonic-gate valuep->t = lval.t; 18290Sstevel@tonic-gate valuep->v = lval.v - rval.v; 18300Sstevel@tonic-gate return (1); 18310Sstevel@tonic-gate 18320Sstevel@tonic-gate case T_MUL: 18334436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 18344436Sstephh arrowp, try, &lval)) 18350Sstevel@tonic-gate return (0); 18364436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 18374436Sstephh arrowp, try, &rval)) 18380Sstevel@tonic-gate return (0); 18390Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 18400Sstevel@tonic-gate return (0); 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate valuep->t = lval.t; 18430Sstevel@tonic-gate valuep->v = lval.v * rval.v; 18440Sstevel@tonic-gate return (1); 18450Sstevel@tonic-gate 18460Sstevel@tonic-gate case T_DIV: 18474436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 18484436Sstephh arrowp, try, &lval)) 18490Sstevel@tonic-gate return (0); 18504436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 18514436Sstephh arrowp, try, &rval)) 18520Sstevel@tonic-gate return (0); 18530Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 18540Sstevel@tonic-gate return (0); 18550Sstevel@tonic-gate 18560Sstevel@tonic-gate /* return false if dividing by zero */ 18570Sstevel@tonic-gate if (rval.v == 0) { 18584436Sstephh outfl(O_DIE, np->file, np->line, 18594436Sstephh "eval_expr: T_DIV division by zero"); 18600Sstevel@tonic-gate } 18610Sstevel@tonic-gate 18620Sstevel@tonic-gate valuep->t = lval.t; 18630Sstevel@tonic-gate valuep->v = lval.v / rval.v; 18640Sstevel@tonic-gate return (1); 18650Sstevel@tonic-gate 18660Sstevel@tonic-gate case T_MOD: 18674436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 18684436Sstephh arrowp, try, &lval)) 18690Sstevel@tonic-gate return (0); 18704436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 18714436Sstephh arrowp, try, &rval)) 18720Sstevel@tonic-gate return (0); 18730Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 18740Sstevel@tonic-gate return (0); 18750Sstevel@tonic-gate 18760Sstevel@tonic-gate /* return false if dividing by zero */ 18770Sstevel@tonic-gate if (rval.v == 0) { 18784436Sstephh outfl(O_DIE, np->file, np->line, 18794436Sstephh "eval_expr: T_MOD division by zero"); 18800Sstevel@tonic-gate } 18810Sstevel@tonic-gate 18820Sstevel@tonic-gate valuep->t = lval.t; 18830Sstevel@tonic-gate valuep->v = lval.v % rval.v; 18840Sstevel@tonic-gate return (1); 18850Sstevel@tonic-gate 18860Sstevel@tonic-gate case T_NAME: 18870Sstevel@tonic-gate if (try) { 18880Sstevel@tonic-gate struct iterinfo *iterinfop; 18894436Sstephh struct node *np1, *np2; 18904436Sstephh int i, gotmatch = 0; 18910Sstevel@tonic-gate 18920Sstevel@tonic-gate /* 18934436Sstephh * Check if we have an exact match of the nonwildcarded 18944436Sstephh * path in oldepname - if so we can just use the 18954436Sstephh * full wildcarded path in epname. 18960Sstevel@tonic-gate */ 18974436Sstephh for (i = 0; i < 1; i++) { 18984436Sstephh for (np1 = np, 18994436Sstephh np2 = events[i]->u.event.oldepname; 19004436Sstephh np1 != NULL && np2 != NULL; 19014436Sstephh np1 = np1->u.name.next, 19024436Sstephh np2 = np2->u.name.next) { 19034436Sstephh if (strcmp(np1->u.name.s, 19044436Sstephh np2->u.name.s) != 0) 19054436Sstephh break; 19064436Sstephh if (np1->u.name.child->t != 19074436Sstephh np2->u.name.child->t) 19084436Sstephh break; 19094436Sstephh if (np1->u.name.child->t == T_NUM && 19104436Sstephh np1->u.name.child->u.ull != 19114436Sstephh np2->u.name.child->u.ull) 19124436Sstephh break; 19134436Sstephh if (np1->u.name.child->t == T_NAME && 19144436Sstephh strcmp(np1->u.name.child->u.name.s, 19154436Sstephh np2->u.name.child->u.name.s) != 0) 19164436Sstephh break; 19174436Sstephh gotmatch++; 19184436Sstephh } 19194436Sstephh if (np1 == NULL && np2 == NULL) { 19204436Sstephh valuep->t = NODEPTR; 19214436Sstephh valuep->v = (uintptr_t) 19224436Sstephh events[i]->u.event.epname; 19234436Sstephh return (1); 19244436Sstephh } 19250Sstevel@tonic-gate } 19264436Sstephh if (!gotmatch) { 19274436Sstephh /* 19284436Sstephh * we're not wildcarding. However at 19294436Sstephh * itree_create() time, we can also expand 19304436Sstephh * simple iterators - so check for those. 19314436Sstephh */ 19324436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, 19334436Sstephh NULL); 19344436Sstephh if (iterinfop != NULL) { 19354436Sstephh valuep->t = UINT64; 19364436Sstephh valuep->v = 19374436Sstephh (unsigned long long)iterinfop->num; 19384436Sstephh return (1); 19394436Sstephh } 19404436Sstephh } 19414436Sstephh /* 19424436Sstephh * For anything else we'll have to wait for eval_dup(). 19434436Sstephh */ 19440Sstevel@tonic-gate return (0); 19450Sstevel@tonic-gate } 19460Sstevel@tonic-gate 19470Sstevel@tonic-gate /* return address of struct node */ 19480Sstevel@tonic-gate valuep->t = NODEPTR; 19491717Swesolows valuep->v = (uintptr_t)np; 19500Sstevel@tonic-gate return (1); 19510Sstevel@tonic-gate 19520Sstevel@tonic-gate case T_QUOTE: 19530Sstevel@tonic-gate valuep->t = STRING; 19541717Swesolows valuep->v = (uintptr_t)np->u.quote.s; 19550Sstevel@tonic-gate return (1); 19560Sstevel@tonic-gate 19570Sstevel@tonic-gate case T_FUNC: 19584436Sstephh return (eval_func(np, ex, events, np->u.func.arglist, 19594436Sstephh globals, croot, arrowp, try, valuep)); 19600Sstevel@tonic-gate 19610Sstevel@tonic-gate case T_NUM: 19627197Sstephh case T_TIMEVAL: 19630Sstevel@tonic-gate valuep->t = UINT64; 19640Sstevel@tonic-gate valuep->v = np->u.ull; 19650Sstevel@tonic-gate return (1); 19660Sstevel@tonic-gate 19670Sstevel@tonic-gate default: 19680Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 19690Sstevel@tonic-gate "eval_expr: unexpected node type: %s", 19700Sstevel@tonic-gate ptree_nodetype2str(np->t)); 19710Sstevel@tonic-gate } 19720Sstevel@tonic-gate /*NOTREACHED*/ 19731717Swesolows return (0); 19740Sstevel@tonic-gate } 19750Sstevel@tonic-gate 19760Sstevel@tonic-gate /* 19770Sstevel@tonic-gate * eval_fru() and eval_asru() don't do much, but are called from a number 19780Sstevel@tonic-gate * of places. 19790Sstevel@tonic-gate */ 19804436Sstephh static struct node * 19810Sstevel@tonic-gate eval_fru(struct node *np) 19820Sstevel@tonic-gate { 19830Sstevel@tonic-gate ASSERT(np->t == T_NAME); 19840Sstevel@tonic-gate return (np); 19850Sstevel@tonic-gate } 19860Sstevel@tonic-gate 19874436Sstephh static struct node * 19880Sstevel@tonic-gate eval_asru(struct node *np) 19890Sstevel@tonic-gate { 19900Sstevel@tonic-gate ASSERT(np->t == T_NAME); 19910Sstevel@tonic-gate return (np); 19920Sstevel@tonic-gate } 1993