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 /* 23*9078SStephen.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; 1284436Sstephh else if (np->u.func.s == L_fru) 1294436Sstephh nodep = eval_fru(np->u.func.arglist); 1304436Sstephh else if (np->u.func.s == L_asru) 1314436Sstephh nodep = eval_asru(np->u.func.arglist); 1324436Sstephh else 1334436Sstephh out(O_DIE, "%s: unexpected type: %s", 1344436Sstephh funcname, ptree_nodetype2str(np->t)); 1354436Sstephh if (try) { 1364436Sstephh if (eval_expr(nodep, ex, events, globals, croot, 1374436Sstephh arrowp, try, &val) && val.t == NODEPTR) 1384436Sstephh nodep = (struct node *)(uintptr_t)val.v; 1394436Sstephh else { 1404436Sstephh *dupedp = 1; 1414436Sstephh nodep = eval_dup(nodep, ex, events); 1424436Sstephh } 1434436Sstephh } 1444436Sstephh return (nodep); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* 1480Sstevel@tonic-gate * evaluate a variety of functions and place result in valuep. return 1 if 1490Sstevel@tonic-gate * function evaluation was successful; 0 if otherwise (e.g., the case of an 1500Sstevel@tonic-gate * invalid argument to the function) 1510Sstevel@tonic-gate */ 1520Sstevel@tonic-gate /*ARGSUSED*/ 1530Sstevel@tonic-gate static int 1544436Sstephh eval_func(struct node *funcnp, struct lut *ex, struct node *events[], 1550Sstevel@tonic-gate struct node *np, struct lut **globals, 1560Sstevel@tonic-gate struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep) 1570Sstevel@tonic-gate { 1580Sstevel@tonic-gate const char *funcname = funcnp->u.func.s; 1594436Sstephh int duped_lhs = 0, duped_rhs = 0, duped = 0; 1604436Sstephh struct node *lhs; 1614436Sstephh struct node *rhs; 1624436Sstephh struct config *cp; 1634436Sstephh struct node *nodep; 1644436Sstephh char *path; 1654436Sstephh struct evalue val; 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate if (funcname == L_within) { 1680Sstevel@tonic-gate /* within()'s are not really constraints -- always true */ 1690Sstevel@tonic-gate valuep->t = UINT64; 1700Sstevel@tonic-gate valuep->v = 1; 1710Sstevel@tonic-gate return (1); 1720Sstevel@tonic-gate } else if (funcname == L_is_under) { 1734436Sstephh lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals, 1744436Sstephh croot, arrowp, try, &duped_lhs); 1754436Sstephh rhs = eval_getname(funcnp, ex, events, np->u.expr.right, 1764436Sstephh globals, croot, arrowp, try, &duped_rhs); 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate valuep->t = UINT64; 1794436Sstephh valuep->v = begins_with(lhs, rhs, ex); 1800Sstevel@tonic-gate out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under("); 1810Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs); 1820Sstevel@tonic-gate out(O_ALTFP|O_VERB2|O_NONL, ","); 1830Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs); 1844436Sstephh out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v); 1850Sstevel@tonic-gate 1864436Sstephh if (duped_lhs) 1874436Sstephh tree_free(lhs); 1884436Sstephh if (duped_rhs) 1894436Sstephh tree_free(rhs); 1900Sstevel@tonic-gate return (1); 1912869Sgavinm } else if (funcname == L_confprop || funcname == L_confprop_defined) { 1922318Sstephh const char *s; 1932318Sstephh 1942318Sstephh /* for now s will point to a quote [see addconfigprop()] */ 1952318Sstephh ASSERT(np->u.expr.right->t == T_QUOTE); 1962318Sstephh 1974436Sstephh nodep = eval_getname(funcnp, ex, events, np->u.expr.left, 1984436Sstephh globals, croot, arrowp, try, &duped); 1994436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 2004436Sstephh cp = nodep->u.name.last->u.name.cp; 2014436Sstephh } else { 2024436Sstephh path = ipath2str(NULL, ipath(nodep)); 2034436Sstephh cp = config_lookup(croot, path, 0); 2044436Sstephh FREE((void *)path); 2054436Sstephh } 2062869Sgavinm if (cp == NULL) { 2074436Sstephh if (funcname == L_confprop) { 2084436Sstephh out(O_ALTFP|O_VERB3, "%s: path ", funcname); 2094436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 2104436Sstephh out(O_ALTFP|O_VERB3, " not found"); 2114436Sstephh valuep->v = (uintptr_t)stable(""); 2124436Sstephh valuep->t = STRING; 2134436Sstephh if (duped) 2144436Sstephh tree_free(nodep); 2154436Sstephh return (1); 2164436Sstephh } else { 2172869Sgavinm valuep->v = 0; 2182869Sgavinm valuep->t = UINT64; 2194436Sstephh if (duped) 2204436Sstephh tree_free(nodep); 2212869Sgavinm return (1); 2222869Sgavinm } 2232869Sgavinm } 2242318Sstephh s = config_getprop(cp, np->u.expr.right->u.quote.s); 2254436Sstephh if (s == NULL && strcmp(np->u.expr.right->u.quote.s, 2264436Sstephh "class-code") == 0) 2274436Sstephh s = config_getprop(cp, "CLASS-CODE"); 2282869Sgavinm if (s == NULL) { 2294436Sstephh if (funcname == L_confprop) { 2304436Sstephh out(O_ALTFP|O_VERB3|O_NONL, 2314436Sstephh "%s: \"%s\" not found for path ", 2324436Sstephh funcname, np->u.expr.right->u.quote.s); 2334436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 2344436Sstephh valuep->v = (uintptr_t)stable(""); 2354436Sstephh valuep->t = STRING; 2364436Sstephh if (duped) 2374436Sstephh tree_free(nodep); 2384436Sstephh return (1); 2394436Sstephh } else { 2402869Sgavinm valuep->v = 0; 2412869Sgavinm valuep->t = UINT64; 2424436Sstephh if (duped) 2434436Sstephh tree_free(nodep); 2442869Sgavinm return (1); 2452869Sgavinm } 2462869Sgavinm } 2472869Sgavinm 2482869Sgavinm if (funcname == L_confprop) { 2492869Sgavinm valuep->v = (uintptr_t)stable(s); 2502869Sgavinm valuep->t = STRING; 2514436Sstephh out(O_ALTFP|O_VERB3|O_NONL, " %s(\"", funcname); 2524436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep); 2534436Sstephh out(O_ALTFP|O_VERB3|O_NONL, 2544436Sstephh "\", \"%s\") = \"%s\" ", 2554436Sstephh np->u.expr.right->u.quote.s, 2562869Sgavinm (char *)(uintptr_t)valuep->v); 2572869Sgavinm } else { 2582869Sgavinm valuep->v = 1; 2592869Sgavinm valuep->t = UINT64; 2602869Sgavinm } 2614436Sstephh if (duped) 2624436Sstephh tree_free(nodep); 2634436Sstephh return (1); 2644436Sstephh } else if (funcname == L_is_connected) { 2654436Sstephh const char *connstrings[] = { "connected", "CONNECTED", NULL }; 2664436Sstephh struct config *cp[2]; 2674436Sstephh const char *matchthis[2], *s; 2684436Sstephh char *nameslist, *w; 2694436Sstephh int i, j; 2704436Sstephh 2714436Sstephh lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals, 2724436Sstephh croot, arrowp, try, &duped_lhs); 2734436Sstephh rhs = eval_getname(funcnp, ex, events, np->u.expr.right, 2744436Sstephh globals, croot, arrowp, try, &duped_rhs); 2754436Sstephh path = ipath2str(NULL, ipath(lhs)); 2764436Sstephh matchthis[1] = stable(path); 2774436Sstephh if (lhs->u.name.last->u.name.cp != NULL) 2784436Sstephh cp[0] = lhs->u.name.last->u.name.cp; 2794436Sstephh else 2804436Sstephh cp[0] = config_lookup(croot, path, 0); 2812869Sgavinm FREE((void *)path); 2824436Sstephh path = ipath2str(NULL, ipath(rhs)); 2834436Sstephh matchthis[0] = stable(path); 2844436Sstephh if (rhs->u.name.last->u.name.cp != NULL) 2854436Sstephh cp[1] = rhs->u.name.last->u.name.cp; 2864436Sstephh else 2874436Sstephh cp[1] = config_lookup(croot, path, 0); 2884436Sstephh FREE((void *)path); 2894436Sstephh if (duped_lhs) 2904436Sstephh tree_free(lhs); 2914436Sstephh if (duped_rhs) 2924436Sstephh tree_free(rhs); 2934436Sstephh 2944436Sstephh valuep->t = UINT64; 2954436Sstephh valuep->v = 0; 2964436Sstephh if (cp[0] == NULL || cp[1] == NULL) 2974436Sstephh return (1); 2984436Sstephh 2994436Sstephh /* to thine self always be connected */ 3004436Sstephh if (cp[0] == cp[1]) { 3014436Sstephh valuep->v = 1; 3024436Sstephh return (1); 3034436Sstephh } 3044436Sstephh 3054436Sstephh /* 3064436Sstephh * Extract "connected" property from each cp. Search this 3074436Sstephh * property for the name associated with the other cp[]. 3084436Sstephh */ 3094436Sstephh for (i = 0; i < 2 && valuep->v == 0; i++) { 3104436Sstephh for (j = 0; connstrings[j] != NULL && valuep->v == 0; 3114436Sstephh j++) { 3124436Sstephh s = config_getprop(cp[i], 3134436Sstephh stable(connstrings[j])); 3144436Sstephh if (s != NULL) { 3154436Sstephh nameslist = STRDUP(s); 3164436Sstephh w = strtok(nameslist, " ,"); 3174436Sstephh while (w != NULL) { 3184436Sstephh if (stable(w) == matchthis[i]) { 3194436Sstephh valuep->v = 1; 3204436Sstephh break; 3214436Sstephh } 3224436Sstephh w = strtok(NULL, " ,"); 3234436Sstephh } 3244436Sstephh FREE(nameslist); 3254436Sstephh } 3264436Sstephh } 3274436Sstephh } 3282318Sstephh return (1); 3294436Sstephh } else if (funcname == L_is_type) { 3304436Sstephh const char *typestrings[] = { "type", "TYPE", NULL }; 3314436Sstephh const char *s; 3324436Sstephh int i; 3334436Sstephh 3344436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals, 3354436Sstephh croot, arrowp, try, &duped); 3364436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 3374436Sstephh cp = nodep->u.name.last->u.name.cp; 3384436Sstephh } else { 3394436Sstephh path = ipath2str(NULL, ipath(nodep)); 3404436Sstephh cp = config_lookup(croot, path, 0); 3414436Sstephh FREE((void *)path); 3424436Sstephh } 3434436Sstephh if (duped) 3444436Sstephh tree_free(nodep); 3454436Sstephh 3464436Sstephh valuep->t = STRING; 3474436Sstephh valuep->v = (uintptr_t)stable(""); 3484436Sstephh if (cp == NULL) 3494436Sstephh return (1); 3504436Sstephh for (i = 0; typestrings[i] != NULL; i++) { 3514436Sstephh s = config_getprop(cp, stable(typestrings[i])); 3524436Sstephh if (s != NULL) { 3534436Sstephh valuep->v = (uintptr_t)stable(s); 3544436Sstephh break; 3554436Sstephh } 3564436Sstephh } 3574436Sstephh return (1); 3584436Sstephh } else if (funcname == L_is_on) { 3594436Sstephh const char *onstrings[] = { "on", "ON", NULL }; 3604436Sstephh const char *truestrings[] = { "yes", "YES", "y", "Y", 3614436Sstephh "true", "TRUE", "t", "T", "1", NULL }; 3624436Sstephh const char *s; 3634436Sstephh int i, j; 3644436Sstephh 3654436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals, 3664436Sstephh croot, arrowp, try, &duped); 3674436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 3684436Sstephh cp = nodep->u.name.last->u.name.cp; 3694436Sstephh } else { 3704436Sstephh path = ipath2str(NULL, ipath(nodep)); 3714436Sstephh cp = config_lookup(croot, path, 0); 3724436Sstephh FREE((void *)path); 3734436Sstephh } 3744436Sstephh if (duped) 3754436Sstephh tree_free(nodep); 3764436Sstephh 3774436Sstephh valuep->t = UINT64; 3784436Sstephh valuep->v = 0; 3794436Sstephh if (cp == NULL) 3804436Sstephh return (1); 3814436Sstephh for (i = 0; onstrings[i] != NULL; i++) { 3824436Sstephh s = config_getprop(cp, stable(onstrings[i])); 3834436Sstephh if (s != NULL) { 3844436Sstephh s = stable(s); 3854436Sstephh for (j = 0; truestrings[j] != NULL; j++) { 3864436Sstephh if (s == stable(truestrings[j])) { 3874436Sstephh valuep->v = 1; 3884436Sstephh return (1); 3894436Sstephh } 3904436Sstephh } 3914436Sstephh } 3924436Sstephh } 3934436Sstephh return (1); 3944436Sstephh } else if (funcname == L_is_present) { 3954436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals, 3964436Sstephh croot, arrowp, try, &duped); 3974436Sstephh if (nodep->u.name.last->u.name.cp != NULL) { 3984436Sstephh cp = nodep->u.name.last->u.name.cp; 3994436Sstephh } else { 4004436Sstephh path = ipath2str(NULL, ipath(nodep)); 4014436Sstephh cp = config_lookup(croot, path, 0); 4024436Sstephh FREE((void *)path); 4034436Sstephh } 4044436Sstephh if (duped) 4054436Sstephh tree_free(nodep); 4064436Sstephh 4074436Sstephh valuep->t = UINT64; 4084436Sstephh valuep->v = 0; 4094436Sstephh if (cp != NULL) 4104436Sstephh valuep->v = 1; 4114436Sstephh return (1); 4127275Sstephh } else if (funcname == L_has_fault) { 4137275Sstephh nvlist_t *asru = NULL, *fru = NULL, *rsrc = NULL; 4147275Sstephh 4157275Sstephh nodep = eval_getname(funcnp, ex, events, np->u.expr.left, 4167275Sstephh globals, croot, arrowp, try, &duped); 4177275Sstephh path = ipath2str(NULL, ipath(nodep)); 4187275Sstephh platform_units_translate(0, croot, &asru, &fru, &rsrc, path); 4198245SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, "has_fault("); 4208245SStephen.Hanson@Sun.COM ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.left); 4218245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2|O_NONL, ", \"%s\") ", 4228245SStephen.Hanson@Sun.COM np->u.expr.right->u.quote.s); 4237275Sstephh FREE((void *)path); 4247275Sstephh if (duped) 4257275Sstephh tree_free(nodep); 4267275Sstephh 4278245SStephen.Hanson@Sun.COM if (rsrc == NULL) { 4287275Sstephh valuep->v = 0; 4298245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "no path"); 4308245SStephen.Hanson@Sun.COM } else { 4317275Sstephh valuep->v = fmd_nvl_fmri_has_fault(Hdl, rsrc, 4327275Sstephh FMD_HAS_FAULT_RESOURCE, 4337275Sstephh strcmp(np->u.expr.right->u.quote.s, "") == 0 ? 4347275Sstephh NULL : (char *)np->u.expr.right->u.quote.s); 4358245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "returned %lld", valuep->v); 4368245SStephen.Hanson@Sun.COM } 4377275Sstephh valuep->t = UINT64; 4387275Sstephh return (1); 4394436Sstephh } else if (funcname == L_count) { 4404436Sstephh struct stats *statp; 4414436Sstephh struct istat_entry ent; 4424436Sstephh 4434436Sstephh ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t)); 4444436Sstephh 4454436Sstephh nodep = np->u.event.epname; 4464436Sstephh if (try) { 4474436Sstephh if (eval_expr(nodep, ex, events, globals, 4484436Sstephh croot, arrowp, try, &val) && val.t == NODEPTR) 4494436Sstephh nodep = (struct node *)(uintptr_t)val.v; 4504436Sstephh else { 4514436Sstephh duped = 1; 4524436Sstephh nodep = eval_dup(nodep, ex, events); 4534436Sstephh } 4544436Sstephh } 4554436Sstephh ent.ename = np->u.event.ename->u.name.s; 4564436Sstephh ent.ipath = ipath(nodep); 4574436Sstephh valuep->t = UINT64; 4584436Sstephh if ((statp = (struct stats *) 4594436Sstephh lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL) 4604436Sstephh valuep->v = 0; 4614436Sstephh else 4624436Sstephh valuep->v = stats_counter_value(statp); 4634436Sstephh if (duped) 4644436Sstephh tree_free(nodep); 4654436Sstephh return (1); 4664436Sstephh } else if (funcname == L_envprop) { 4674436Sstephh outfl(O_DIE, np->file, np->line, 4684436Sstephh "eval_func: %s not yet supported", funcname); 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate if (try) 4720Sstevel@tonic-gate return (0); 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate if (funcname == L_fru) { 4750Sstevel@tonic-gate valuep->t = NODEPTR; 4761717Swesolows valuep->v = (uintptr_t)eval_fru(np); 4770Sstevel@tonic-gate return (1); 4780Sstevel@tonic-gate } else if (funcname == L_asru) { 4790Sstevel@tonic-gate valuep->t = NODEPTR; 4801717Swesolows valuep->v = (uintptr_t)eval_asru(np); 4810Sstevel@tonic-gate return (1); 4821414Scindi } else if (funcname == L_defined) { 4831414Scindi ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str); 4841414Scindi valuep->t = UINT64; 4851414Scindi valuep->v = (lut_lookup(*globals, 4861414Scindi (void *)np->u.globid.s, NULL) != NULL); 4871414Scindi return (1); 4880Sstevel@tonic-gate } else if (funcname == L_call) { 4890Sstevel@tonic-gate return (! platform_call(np, globals, croot, arrowp, valuep)); 4900Sstevel@tonic-gate } else if (funcname == L_payloadprop) { 4911414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 4920Sstevel@tonic-gate "payloadprop(\"%s\") ", np->u.quote.s); 493186Sdb35262 4945204Sstephh if (arrowp->head->myevent->count == 0) { 4955204Sstephh /* 4965204Sstephh * Haven't seen this ereport yet, so must defer 4975204Sstephh */ 4985204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 4995204Sstephh return (0); 5005204Sstephh } else if (platform_payloadprop(np, valuep)) { 5011414Scindi /* platform_payloadprop() returned false */ 5025204Sstephh out(O_ALTFP|O_VERB, "not found."); 5035204Sstephh valuep->t = UNDEFINED; 5045204Sstephh return (1); 5051414Scindi } else { 506186Sdb35262 switch (valuep->t) { 507186Sdb35262 case UINT64: 508186Sdb35262 case NODEPTR: 5091414Scindi out(O_ALTFP|O_VERB2, "found: %llu", valuep->v); 510186Sdb35262 break; 511186Sdb35262 case STRING: 5121414Scindi out(O_ALTFP|O_VERB2, "found: \"%s\"", 5131717Swesolows (char *)(uintptr_t)valuep->v); 514186Sdb35262 break; 515186Sdb35262 default: 5161414Scindi out(O_ALTFP|O_VERB2, "found: undefined"); 517186Sdb35262 break; 518186Sdb35262 } 5191414Scindi return (1); 5201414Scindi } 5211414Scindi } else if (funcname == L_setpayloadprop) { 5221414Scindi struct evalue *payloadvalp; 5235204Sstephh int alloced = 0; 5241414Scindi 5251414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 5261414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE, 5271414Scindi ptree_nodetype2str(np->u.expr.left->t)); 5281414Scindi 529*9078SStephen.Hanson@Sun.COM if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE)) 5307197Sstephh return (0); 5317197Sstephh 5321414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 5331414Scindi "setpayloadprop: %s: %s=", 5341414Scindi arrowp->tail->myevent->enode->u.event.ename->u.name.s, 5351414Scindi np->u.expr.left->u.quote.s); 5361414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 5371414Scindi 5381414Scindi /* 5391414Scindi * allocate a struct evalue to hold the payload property's 5401414Scindi * value, unless we've been here already, in which case we 5411414Scindi * might calculate a different value, but we'll store it 5421414Scindi * in the already-allocated struct evalue. 5431414Scindi */ 5441414Scindi if ((payloadvalp = (struct evalue *)lut_lookup( 5451414Scindi arrowp->tail->myevent->payloadprops, 5461414Scindi (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) { 5471414Scindi payloadvalp = MALLOC(sizeof (*payloadvalp)); 5485204Sstephh alloced = 1; 5491414Scindi } 5501414Scindi 5514436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 5521414Scindi arrowp, try, payloadvalp)) { 5535204Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)"); 5545204Sstephh if (alloced) 5555204Sstephh FREE(payloadvalp); 5565204Sstephh return (0); 5571414Scindi } else { 5585204Sstephh if (payloadvalp->t == UNDEFINED) { 5595204Sstephh /* function is always true */ 5605204Sstephh out(O_ALTFP|O_VERB2, " (undefined)"); 5615204Sstephh valuep->t = UINT64; 5625204Sstephh valuep->v = 1; 5635204Sstephh return (1); 5645204Sstephh } 5651414Scindi if (payloadvalp->t == UINT64) 5661414Scindi out(O_ALTFP|O_VERB2, 5671414Scindi " (%llu)", payloadvalp->v); 5681414Scindi else 5691717Swesolows out(O_ALTFP|O_VERB2, " (\"%s\")", 5701717Swesolows (char *)(uintptr_t)payloadvalp->v); 5711414Scindi } 5721414Scindi 5731414Scindi /* add to table of payload properties for current problem */ 5741414Scindi arrowp->tail->myevent->payloadprops = 5751414Scindi lut_add(arrowp->tail->myevent->payloadprops, 5761414Scindi (void *)np->u.expr.left->u.quote.s, 5771414Scindi (void *)payloadvalp, NULL); 5781414Scindi 5791414Scindi /* function is always true */ 5801414Scindi valuep->t = UINT64; 5811414Scindi valuep->v = 1; 5821414Scindi return (1); 5837197Sstephh } else if (funcname == L_setserdn || funcname == L_setserdt || 5847197Sstephh funcname == L_setserdsuffix || funcname == L_setserdincrement) { 5857197Sstephh struct evalue *serdvalp; 5867197Sstephh int alloced = 0; 5877197Sstephh char *str; 5887197Sstephh struct event *flt = arrowp->tail->myevent; 5897197Sstephh 590*9078SStephen.Hanson@Sun.COM if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE)) 5917197Sstephh return (0); 5927197Sstephh 5937197Sstephh if (funcname == L_setserdn) 5947197Sstephh str = "n"; 5957197Sstephh else if (funcname == L_setserdt) 5967197Sstephh str = "t"; 5977197Sstephh else if (funcname == L_setserdsuffix) 5987197Sstephh str = "suffix"; 5997197Sstephh else if (funcname == L_setserdincrement) 6007197Sstephh str = "increment"; 6017197Sstephh 6027197Sstephh /* 6037197Sstephh * allocate a struct evalue to hold the serd property's 6047197Sstephh * value, unless we've been here already, in which case we 6057197Sstephh * might calculate a different value, but we'll store it 6067197Sstephh * in the already-allocated struct evalue. 6077197Sstephh */ 6087197Sstephh if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops, 6097392SScott.Davenport@Sun.COM (void *)str, (lut_cmp)strcmp)) == NULL) { 6107197Sstephh serdvalp = MALLOC(sizeof (*serdvalp)); 6117197Sstephh alloced = 1; 6127197Sstephh } 6137197Sstephh 6147197Sstephh if (!eval_expr(np, ex, events, globals, croot, arrowp, try, 6157197Sstephh serdvalp)) { 6167197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6177197Sstephh "setserd%s: %s: ", str, 6187197Sstephh flt->enode->u.event.ename->u.name.s); 6197197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 6207197Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)"); 6217197Sstephh if (alloced) 6227197Sstephh FREE(serdvalp); 6237197Sstephh return (0); 6247197Sstephh } else if (serdvalp->t == UNDEFINED) { 6257197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6267197Sstephh "setserd%s: %s: ", str, 6277197Sstephh flt->enode->u.event.ename->u.name.s); 6287197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 6297197Sstephh out(O_ALTFP|O_VERB2, " (undefined)"); 6307197Sstephh } else { 6317197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6327197Sstephh "setserd%s: %s: ", str, 6337197Sstephh flt->enode->u.event.ename->u.name.s); 6347197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 6357197Sstephh if ((funcname == L_setserdincrement || 6367197Sstephh funcname == L_setserdn) && serdvalp->t == STRING) { 6377197Sstephh serdvalp->t = UINT64; 6387197Sstephh serdvalp->v = strtoull((char *) 6397197Sstephh (uintptr_t)serdvalp->v, NULL, 0); 6407197Sstephh } 6417197Sstephh if (funcname == L_setserdt && serdvalp->t == UINT64) { 6427197Sstephh int len = snprintf(NULL, 0, "%lldns", 6437197Sstephh serdvalp->v); 6447197Sstephh char *buf = MALLOC(len + 1); 6457197Sstephh 6467197Sstephh (void) snprintf(buf, len + 1, "%lldns", 6477197Sstephh serdvalp->v); 6487197Sstephh serdvalp->t = STRING; 6497197Sstephh serdvalp->v = (uintptr_t)stable(buf); 6507197Sstephh FREE(buf); 6517197Sstephh } 6527392SScott.Davenport@Sun.COM 6537197Sstephh if (serdvalp->t == UINT64) 6547197Sstephh out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v); 6557197Sstephh else 6567197Sstephh out(O_ALTFP|O_VERB2, " (\"%s\")", 6577197Sstephh (char *)(uintptr_t)serdvalp->v); 6587197Sstephh flt->serdprops = lut_add(flt->serdprops, (void *)str, 6597392SScott.Davenport@Sun.COM (void *)serdvalp, (lut_cmp)strcmp); 6607197Sstephh } 6617197Sstephh valuep->t = UINT64; 6627197Sstephh valuep->v = 1; 6637197Sstephh return (1); 6641414Scindi } else if (funcname == L_payloadprop_defined) { 6651414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6661414Scindi "payloadprop_defined(\"%s\") ", np->u.quote.s); 6671414Scindi 6685204Sstephh if (arrowp->head->myevent->count == 0) { 6695204Sstephh /* 6705204Sstephh * Haven't seen this ereport yet, so must defer 6715204Sstephh */ 6725204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 6735204Sstephh return (0); 6745204Sstephh } else if (platform_payloadprop(np, NULL)) { 6751414Scindi /* platform_payloadprop() returned false */ 6761414Scindi valuep->v = 0; 6775204Sstephh out(O_ALTFP|O_VERB2, "not found."); 6781414Scindi } else { 6791414Scindi valuep->v = 1; 6801414Scindi out(O_ALTFP|O_VERB2, "found."); 6811414Scindi } 6821414Scindi valuep->t = UINT64; 6831414Scindi return (1); 6841414Scindi } else if (funcname == L_payloadprop_contains) { 6851414Scindi int nvals; 6861414Scindi struct evalue *vals; 6871414Scindi struct evalue cmpval; 6881414Scindi 6891414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 6901414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE, 6911414Scindi ptree_nodetype2str(np->u.expr.left->t)); 6921414Scindi 6931414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6941414Scindi "payloadprop_contains(\"%s\", ", 6951414Scindi np->u.expr.left->u.quote.s); 6961414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 6972869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, ") "); 6981414Scindi 6991414Scindi /* evaluate the expression we're comparing against */ 7004436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 7011414Scindi arrowp, try, &cmpval)) { 7021414Scindi out(O_ALTFP|O_VERB2|O_NONL, 7035204Sstephh "(cannot eval) "); 7045204Sstephh return (0); 7051414Scindi } else { 7062869Sgavinm switch (cmpval.t) { 7072869Sgavinm case UNDEFINED: 7082869Sgavinm out(O_ALTFP|O_VERB2, "(undefined type)"); 7092869Sgavinm break; 7102869Sgavinm 7112869Sgavinm case UINT64: 7121414Scindi out(O_ALTFP|O_VERB2, 7131414Scindi "(%llu) ", cmpval.v); 7142869Sgavinm break; 7152869Sgavinm 7162869Sgavinm case STRING: 7171414Scindi out(O_ALTFP|O_VERB2, 7181717Swesolows "(\"%s\") ", (char *)(uintptr_t)cmpval.v); 7192869Sgavinm break; 7202869Sgavinm 7212869Sgavinm case NODEPTR: 7222869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, "("); 7232869Sgavinm ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, 7242869Sgavinm (struct node *)(uintptr_t)(cmpval.v)); 7252869Sgavinm out(O_ALTFP|O_VERB2, ") "); 7262869Sgavinm break; 7272869Sgavinm } 7281414Scindi } 7291414Scindi 7301414Scindi /* get the payload values and check for a match */ 7311414Scindi vals = platform_payloadprop_values(np->u.expr.left->u.quote.s, 7321414Scindi &nvals); 7331414Scindi valuep->t = UINT64; 7341414Scindi valuep->v = 0; 7355204Sstephh if (arrowp->head->myevent->count == 0) { 7365204Sstephh /* 7375204Sstephh * Haven't seen this ereport yet, so must defer 7385204Sstephh */ 7395204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 7405204Sstephh return (0); 7415204Sstephh } else if (nvals == 0) { 7421414Scindi out(O_ALTFP|O_VERB2, "not found."); 7435204Sstephh return (1); 7441414Scindi } else { 7451414Scindi struct evalue preval; 7461414Scindi int i; 7471414Scindi 7481414Scindi out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals); 7491414Scindi 7501414Scindi for (i = 0; i < nvals; i++) { 7511414Scindi 7521414Scindi preval.t = vals[i].t; 7531414Scindi preval.v = vals[i].v; 7541414Scindi 7551414Scindi if (check_expr_args(&vals[i], &cmpval, 7561414Scindi UNDEFINED, np)) 7571414Scindi continue; 7581414Scindi 7591414Scindi /* 7601414Scindi * If we auto-converted the value to a 7611414Scindi * string, we need to free the 7621414Scindi * original tree value. 7631414Scindi */ 7641414Scindi if (preval.t == NODEPTR && 7651717Swesolows ((struct node *)(uintptr_t)(preval.v))->t == 7661717Swesolows T_NAME) { 7671717Swesolows tree_free((struct node *)(uintptr_t) 7681717Swesolows preval.v); 7691414Scindi } 7701414Scindi 7711414Scindi if (vals[i].v == cmpval.v) { 7721414Scindi valuep->v = 1; 7731414Scindi break; 7741414Scindi } 7751414Scindi } 776186Sdb35262 7771414Scindi if (valuep->v) 7781414Scindi out(O_ALTFP|O_VERB2, "match."); 7791414Scindi else 7801414Scindi out(O_ALTFP|O_VERB2, "no match."); 781186Sdb35262 7821414Scindi for (i = 0; i < nvals; i++) { 7831414Scindi if (vals[i].t == NODEPTR) { 7841717Swesolows tree_free((struct node *)(uintptr_t) 7851717Swesolows vals[i].v); 7861414Scindi break; 7871414Scindi } 788186Sdb35262 } 7891414Scindi FREE(vals); 7901414Scindi } 7911414Scindi return (1); 7921414Scindi } else if (funcname == L_confcall) { 7931414Scindi return (!platform_confcall(np, globals, croot, arrowp, valuep)); 7940Sstevel@tonic-gate } else 7950Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 7960Sstevel@tonic-gate "eval_func: unexpected func: %s", funcname); 7970Sstevel@tonic-gate /*NOTREACHED*/ 7981717Swesolows return (0); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8014436Sstephh /* 8024436Sstephh * defines for u.expr.temp - these are used for T_OR and T_AND so that if 8034436Sstephh * we worked out that part of the expression was true or false during an 8044436Sstephh * earlier eval_expr, then we don't need to dup that part. 8054436Sstephh */ 8060Sstevel@tonic-gate 8074436Sstephh #define EXPR_TEMP_BOTH_UNK 0 8084436Sstephh #define EXPR_TEMP_LHS_UNK 1 8094436Sstephh #define EXPR_TEMP_RHS_UNK 2 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate static struct node * 8124436Sstephh eval_dup(struct node *np, struct lut *ex, struct node *events[]) 8130Sstevel@tonic-gate { 8140Sstevel@tonic-gate struct node *newnp; 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate if (np == NULL) 8170Sstevel@tonic-gate return (NULL); 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate switch (np->t) { 8200Sstevel@tonic-gate case T_GLOBID: 8210Sstevel@tonic-gate return (tree_globid(np->u.globid.s, np->file, np->line)); 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate case T_ASSIGN: 8240Sstevel@tonic-gate case T_CONDIF: 8250Sstevel@tonic-gate case T_CONDELSE: 8260Sstevel@tonic-gate case T_NE: 8270Sstevel@tonic-gate case T_EQ: 8280Sstevel@tonic-gate case T_LT: 8290Sstevel@tonic-gate case T_LE: 8300Sstevel@tonic-gate case T_GT: 8310Sstevel@tonic-gate case T_GE: 8320Sstevel@tonic-gate case T_BITAND: 8330Sstevel@tonic-gate case T_BITOR: 8340Sstevel@tonic-gate case T_BITXOR: 8350Sstevel@tonic-gate case T_BITNOT: 8360Sstevel@tonic-gate case T_LSHIFT: 8370Sstevel@tonic-gate case T_RSHIFT: 8380Sstevel@tonic-gate case T_NOT: 8390Sstevel@tonic-gate case T_ADD: 8400Sstevel@tonic-gate case T_SUB: 8410Sstevel@tonic-gate case T_MUL: 8420Sstevel@tonic-gate case T_DIV: 8430Sstevel@tonic-gate case T_MOD: 8440Sstevel@tonic-gate return (tree_expr(np->t, 8454436Sstephh eval_dup(np->u.expr.left, ex, events), 8464436Sstephh eval_dup(np->u.expr.right, ex, events))); 8474436Sstephh case T_LIST: 8484436Sstephh case T_AND: 8494436Sstephh switch (np->u.expr.temp) { 8504436Sstephh case EXPR_TEMP_LHS_UNK: 8514436Sstephh return (eval_dup(np->u.expr.left, ex, events)); 8524436Sstephh case EXPR_TEMP_RHS_UNK: 8534436Sstephh return (eval_dup(np->u.expr.right, ex, events)); 8544436Sstephh default: 8554436Sstephh return (tree_expr(np->t, 8564436Sstephh eval_dup(np->u.expr.left, ex, events), 8574436Sstephh eval_dup(np->u.expr.right, ex, events))); 8584436Sstephh } 8594436Sstephh 8604436Sstephh case T_OR: 8614436Sstephh switch (np->u.expr.temp) { 8624436Sstephh case EXPR_TEMP_LHS_UNK: 8634436Sstephh return (eval_dup(np->u.expr.left, ex, events)); 8644436Sstephh case EXPR_TEMP_RHS_UNK: 8654436Sstephh return (eval_dup(np->u.expr.right, ex, events)); 8664436Sstephh default: 8674436Sstephh return (tree_expr(T_OR, 8684436Sstephh eval_dup(np->u.expr.left, ex, events), 8694436Sstephh eval_dup(np->u.expr.right, ex, events))); 8704436Sstephh } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate case T_NAME: { 8730Sstevel@tonic-gate struct iterinfo *iterinfop; 8744436Sstephh int got_matchf = 0; 8754436Sstephh int got_matcht = 0; 8764436Sstephh struct evalue value; 8774436Sstephh struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL; 8784436Sstephh struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest; 8790Sstevel@tonic-gate 8804436Sstephh /* 8814436Sstephh * Check if we already have a match of the nonwildcarded path 8824436Sstephh * in oldepname (check both to and from events). 8834436Sstephh */ 8844436Sstephh for (np1f = np, np2f = events[0]->u.event.oldepname; 8854436Sstephh np1f != NULL && np2f != NULL; 8864436Sstephh np1f = np1f->u.name.next, np2f = np2f->u.name.next) { 8874436Sstephh if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0) 8884436Sstephh break; 8894436Sstephh if (np1f->u.name.child->t != np2f->u.name.child->t) 8904436Sstephh break; 8914436Sstephh if (np1f->u.name.child->t == T_NUM && 8924436Sstephh np1f->u.name.child->u.ull != 8934436Sstephh np2f->u.name.child->u.ull) 8944436Sstephh break; 8954436Sstephh if (np1f->u.name.child->t == T_NAME && 8964436Sstephh strcmp(np1f->u.name.child->u.name.s, 8974436Sstephh np2f->u.name.child->u.name.s) != 0) 8984436Sstephh break; 8994436Sstephh got_matchf++; 9004436Sstephh } 9014436Sstephh for (np1t = np, np2t = events[1]->u.event.oldepname; 9024436Sstephh np1t != NULL && np2t != NULL; 9034436Sstephh np1t = np1t->u.name.next, np2t = np2t->u.name.next) { 9044436Sstephh if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0) 9054436Sstephh break; 9064436Sstephh if (np1t->u.name.child->t != np2t->u.name.child->t) 9074436Sstephh break; 9084436Sstephh if (np1t->u.name.child->t == T_NUM && 9094436Sstephh np1t->u.name.child->u.ull != 9104436Sstephh np2t->u.name.child->u.ull) 9114436Sstephh break; 9124436Sstephh if (np1t->u.name.child->t == T_NAME && 9134436Sstephh strcmp(np1t->u.name.child->u.name.s, 9144436Sstephh np2t->u.name.child->u.name.s) != 0) 9154436Sstephh break; 9164436Sstephh got_matcht++; 9174436Sstephh } 9184436Sstephh nprest = np; 9194436Sstephh if (got_matchf || got_matcht) { 9204436Sstephh /* 9214436Sstephh * so we are wildcarding. Copy ewname in full, plus 9224436Sstephh * matching section of oldepname. Use whichever gives 9234436Sstephh * the closest match. 9244436Sstephh */ 9254436Sstephh if (got_matchf > got_matcht) { 9264436Sstephh npstart = events[0]->u.event.ewname; 9274436Sstephh npcont = events[0]->u.event.oldepname; 9284436Sstephh npend = np2f; 9294436Sstephh nprest = np1f; 9304436Sstephh } else { 9314436Sstephh npstart = events[1]->u.event.ewname; 9324436Sstephh npcont = events[1]->u.event.oldepname; 9334436Sstephh npend = np2t; 9344436Sstephh nprest = np1t; 9354436Sstephh } 9364436Sstephh for (npref = npstart; npref != NULL; 9374436Sstephh npref = npref->u.name.next) { 9384436Sstephh newnp = newnode(T_NAME, np->file, np->line); 9394436Sstephh newnp->u.name.t = npref->u.name.t; 9404436Sstephh newnp->u.name.s = npref->u.name.s; 9414436Sstephh newnp->u.name.last = newnp; 9424436Sstephh newnp->u.name.it = npref->u.name.it; 9434436Sstephh newnp->u.name.cp = npref->u.name.cp; 9444436Sstephh newnp->u.name.child = 9454436Sstephh newnode(T_NUM, np->file, np->line); 9464436Sstephh if (eval_expr(npref->u.name.child, ex, events, 9470Sstevel@tonic-gate NULL, NULL, NULL, 1, &value) == 0 || 9480Sstevel@tonic-gate value.t != UINT64) { 9490Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 9500Sstevel@tonic-gate "eval_dup: could not resolve " 9510Sstevel@tonic-gate "iterator of %s", np->u.name.s); 9520Sstevel@tonic-gate } 9534436Sstephh newnp->u.name.child->u.ull = value.v; 9544436Sstephh if (retp == NULL) { 9554436Sstephh retp = newnp; 9564436Sstephh } else { 9574436Sstephh retp->u.name.last->u.name.next = newnp; 9584436Sstephh retp->u.name.last = newnp; 9594436Sstephh } 9600Sstevel@tonic-gate } 9614436Sstephh for (npref = npcont; npref != NULL && npref != npend; 9624436Sstephh npref = npref->u.name.next) { 9634436Sstephh newnp = newnode(T_NAME, np->file, np->line); 9644436Sstephh newnp->u.name.t = npref->u.name.t; 9654436Sstephh newnp->u.name.s = npref->u.name.s; 9664436Sstephh newnp->u.name.last = newnp; 9674436Sstephh newnp->u.name.it = npref->u.name.it; 9684436Sstephh newnp->u.name.cp = npref->u.name.cp; 9694436Sstephh newnp->u.name.child = 9704436Sstephh newnode(T_NUM, np->file, np->line); 9714436Sstephh if (eval_expr(npref->u.name.child, ex, events, 9724436Sstephh NULL, NULL, NULL, 1, &value) == 0 || 9734436Sstephh value.t != UINT64) { 9744436Sstephh outfl(O_DIE, np->file, np->line, 9754436Sstephh "eval_dup: could not resolve " 9764436Sstephh "iterator of %s", np->u.name.s); 9774436Sstephh } 9784436Sstephh newnp->u.name.child->u.ull = value.v; 9794436Sstephh if (retp == NULL) { 9804436Sstephh retp = newnp; 9814436Sstephh } else { 9824436Sstephh retp->u.name.last->u.name.next = newnp; 9834436Sstephh retp->u.name.last = newnp; 9844436Sstephh } 9854436Sstephh } 9864436Sstephh } else { 9874436Sstephh /* 9884436Sstephh * not wildcarding - check if explicit iterator 9894436Sstephh */ 9904436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 9914436Sstephh if (iterinfop != NULL) { 9924436Sstephh /* explicit iterator; not part of pathname */ 9934436Sstephh newnp = newnode(T_NUM, np->file, np->line); 9944436Sstephh newnp->u.ull = iterinfop->num; 9950Sstevel@tonic-gate return (newnp); 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate } 9984436Sstephh 9994436Sstephh /* 10004436Sstephh * finally, whether wildcarding or not, we need to copy the 10014436Sstephh * remaining part of the path (if any). This must be defined 10024436Sstephh * absolutely (no more expansion/wildcarding). 10034436Sstephh */ 10044436Sstephh for (npref = nprest; npref != NULL; 10054436Sstephh npref = npref->u.name.next) { 10064436Sstephh newnp = newnode(T_NAME, np->file, np->line); 10074436Sstephh newnp->u.name.t = npref->u.name.t; 10084436Sstephh newnp->u.name.s = npref->u.name.s; 10094436Sstephh newnp->u.name.last = newnp; 10104436Sstephh newnp->u.name.it = npref->u.name.it; 10114436Sstephh newnp->u.name.cp = npref->u.name.cp; 10124436Sstephh newnp->u.name.child = 10134436Sstephh newnode(T_NUM, np->file, np->line); 10144436Sstephh if (eval_expr(npref->u.name.child, ex, events, 10154436Sstephh NULL, NULL, NULL, 1, &value) == 0 || 10164436Sstephh value.t != UINT64) { 10174436Sstephh outfl(O_DIE, np->file, np->line, 10184436Sstephh "eval_dup: could not resolve " 10194436Sstephh "iterator of %s", np->u.name.s); 10204436Sstephh } 10214436Sstephh newnp->u.name.child->u.ull = value.v; 10224436Sstephh if (retp == NULL) { 10234436Sstephh retp = newnp; 10244436Sstephh } else { 10254436Sstephh retp->u.name.last->u.name.next = newnp; 10264436Sstephh retp->u.name.last = newnp; 10274436Sstephh } 10284436Sstephh } 10294436Sstephh return (retp); 10300Sstevel@tonic-gate } 10310Sstevel@tonic-gate 10321414Scindi case T_EVENT: 10331414Scindi newnp = newnode(T_NAME, np->file, np->line); 10341414Scindi 10351414Scindi newnp->u.name.t = np->u.event.ename->u.name.t; 10361414Scindi newnp->u.name.s = np->u.event.ename->u.name.s; 10371414Scindi newnp->u.name.it = np->u.event.ename->u.name.it; 10381414Scindi newnp->u.name.last = newnp; 10391414Scindi 10401414Scindi return (tree_event(newnp, 10414436Sstephh eval_dup(np->u.event.epname, ex, events), 10424436Sstephh eval_dup(np->u.event.eexprlist, ex, events))); 10431414Scindi 10440Sstevel@tonic-gate case T_FUNC: 10450Sstevel@tonic-gate return (tree_func(np->u.func.s, 10464436Sstephh eval_dup(np->u.func.arglist, ex, events), 10470Sstevel@tonic-gate np->file, np->line)); 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate case T_QUOTE: 10500Sstevel@tonic-gate newnp = newnode(T_QUOTE, np->file, np->line); 10510Sstevel@tonic-gate newnp->u.quote.s = np->u.quote.s; 10520Sstevel@tonic-gate return (newnp); 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate case T_NUM: 10550Sstevel@tonic-gate newnp = newnode(T_NUM, np->file, np->line); 10560Sstevel@tonic-gate newnp->u.ull = np->u.ull; 10570Sstevel@tonic-gate return (newnp); 10580Sstevel@tonic-gate 10597197Sstephh case T_TIMEVAL: 10607197Sstephh newnp = newnode(T_TIMEVAL, np->file, np->line); 10617197Sstephh newnp->u.ull = np->u.ull; 10627197Sstephh return (newnp); 10637197Sstephh 10640Sstevel@tonic-gate default: 10650Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 10660Sstevel@tonic-gate "eval_dup: unexpected node type: %s", 10670Sstevel@tonic-gate ptree_nodetype2str(np->t)); 10680Sstevel@tonic-gate } 10690Sstevel@tonic-gate /*NOTREACHED*/ 10701717Swesolows return (0); 10710Sstevel@tonic-gate } 10720Sstevel@tonic-gate 10730Sstevel@tonic-gate /* 10740Sstevel@tonic-gate * eval_potential -- see if constraint is potentially true 10750Sstevel@tonic-gate * 10760Sstevel@tonic-gate * this function is used at instance tree creation time to see if 10770Sstevel@tonic-gate * any constraints are already known to be false. if this function 10780Sstevel@tonic-gate * returns false, then the constraint will always be false and there's 10790Sstevel@tonic-gate * no need to include the propagation arrow in the instance tree. 10800Sstevel@tonic-gate * 10810Sstevel@tonic-gate * if this routine returns true, either the constraint is known to 10820Sstevel@tonic-gate * be always true (so there's no point in attaching the constraint 10830Sstevel@tonic-gate * to the propagation arrow in the instance tree), or the constraint 10840Sstevel@tonic-gate * contains "deferred" expressions like global variables or poller calls 10850Sstevel@tonic-gate * and so it must be evaluated during calls to fme_eval(). in this last 10860Sstevel@tonic-gate * case, where a constraint needs to be attached to the propagation arrow 10870Sstevel@tonic-gate * in the instance tree, this routine returns a newly created constraint 10880Sstevel@tonic-gate * in *newc where all the non-deferred things have been filled in. 10890Sstevel@tonic-gate * 10900Sstevel@tonic-gate * so in summary: 10910Sstevel@tonic-gate * 10920Sstevel@tonic-gate * return of false: constraint can never be true, *newc will be NULL. 10930Sstevel@tonic-gate * 10940Sstevel@tonic-gate * return of true with *newc unchanged: constraint will always be true. 10950Sstevel@tonic-gate * 10960Sstevel@tonic-gate * return of true with *newc changed: use new constraint in *newc. 10970Sstevel@tonic-gate * 10980Sstevel@tonic-gate * the lookup table for all explicit iterators, ex, is passed in. 10990Sstevel@tonic-gate * 11000Sstevel@tonic-gate * *newc can either be NULL on entry, or if can contain constraints from 11010Sstevel@tonic-gate * previous calls to eval_potential() (i.e. for building up an instance 11020Sstevel@tonic-gate * tree constraint from several potential constraints). if *newc already 11030Sstevel@tonic-gate * contains constraints, anything added to it will be joined by adding 11040Sstevel@tonic-gate * a T_AND node at the top of *newc. 11050Sstevel@tonic-gate */ 11060Sstevel@tonic-gate int 11074436Sstephh eval_potential(struct node *np, struct lut *ex, struct node *events[], 11082318Sstephh struct node **newc, struct config *croot) 11090Sstevel@tonic-gate { 11100Sstevel@tonic-gate struct node *newnp; 11110Sstevel@tonic-gate struct evalue value; 11120Sstevel@tonic-gate 11134436Sstephh if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) { 11140Sstevel@tonic-gate /* 11150Sstevel@tonic-gate * couldn't eval expression because 11160Sstevel@tonic-gate * it contains deferred items. make 11170Sstevel@tonic-gate * a duplicate expression with all the 11180Sstevel@tonic-gate * non-deferred items expanded. 11190Sstevel@tonic-gate */ 11204436Sstephh newnp = eval_dup(np, ex, events); 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate if (*newc == NULL) { 11230Sstevel@tonic-gate /* 11240Sstevel@tonic-gate * constraint is potentially true if deferred 11250Sstevel@tonic-gate * expression in newnp is true. *newc was NULL 11260Sstevel@tonic-gate * so new constraint is just the one in newnp. 11270Sstevel@tonic-gate */ 11280Sstevel@tonic-gate *newc = newnp; 11290Sstevel@tonic-gate return (1); 11300Sstevel@tonic-gate } else { 11310Sstevel@tonic-gate /* 11320Sstevel@tonic-gate * constraint is potentially true if deferred 11330Sstevel@tonic-gate * expression in newnp is true. *newc already 11340Sstevel@tonic-gate * contained a constraint so add an AND with the 11350Sstevel@tonic-gate * constraint in newnp. 11360Sstevel@tonic-gate */ 11370Sstevel@tonic-gate *newc = tree_expr(T_AND, *newc, newnp); 11380Sstevel@tonic-gate return (1); 11390Sstevel@tonic-gate } 11400Sstevel@tonic-gate } else if (value.t == UNDEFINED) { 11410Sstevel@tonic-gate /* constraint can never be true */ 11420Sstevel@tonic-gate return (0); 11430Sstevel@tonic-gate } else if (value.t == UINT64 && value.v == 0) { 11440Sstevel@tonic-gate /* constraint can never be true */ 11450Sstevel@tonic-gate return (0); 11460Sstevel@tonic-gate } else { 11470Sstevel@tonic-gate /* constraint is always true (nothing deferred to eval) */ 11480Sstevel@tonic-gate return (1); 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate } 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate static int 11530Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 11540Sstevel@tonic-gate struct node *np) 11550Sstevel@tonic-gate { 11561414Scindi /* auto-convert T_NAMES to strings */ 11571717Swesolows if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t == 11581717Swesolows T_NAME) { 11591717Swesolows char *s = ipath2str(NULL, 11601717Swesolows ipath((struct node *)(uintptr_t)lp->v)); 11611414Scindi lp->t = STRING; 11621717Swesolows lp->v = (uintptr_t)stable(s); 11631414Scindi FREE(s); 11641414Scindi out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"", 11651717Swesolows (char *)(uintptr_t)lp->v); 11661414Scindi } 11671414Scindi if (rp != NULL && 11681717Swesolows rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t == 11691717Swesolows T_NAME) { 11701717Swesolows char *s = ipath2str(NULL, 11711717Swesolows ipath((struct node *)(uintptr_t)rp->v)); 11721414Scindi rp->t = STRING; 11731717Swesolows rp->v = (uintptr_t)stable(s); 11741414Scindi FREE(s); 11751414Scindi out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"", 11761717Swesolows (char *)(uintptr_t)rp->v); 11771414Scindi } 11781414Scindi 11791414Scindi /* auto-convert strings to numbers */ 11801414Scindi if (dtype == UINT64) { 11811414Scindi if (lp->t == STRING) { 11821414Scindi lp->t = UINT64; 11831717Swesolows lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0); 11841414Scindi } 11851414Scindi if (rp != NULL && rp->t == STRING) { 11861414Scindi rp->t = UINT64; 11871717Swesolows rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0); 11881414Scindi } 11891414Scindi } 11901414Scindi 11910Sstevel@tonic-gate if (dtype != UNDEFINED && lp->t != dtype) { 11924436Sstephh outfl(O_DIE, np->file, np->line, 11934436Sstephh "invalid datatype of argument for operation %s", 11944436Sstephh ptree_nodetype2str(np->t)); 11954436Sstephh /* NOTREACHED */ 11960Sstevel@tonic-gate return (1); 11970Sstevel@tonic-gate } 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate if (rp != NULL && lp->t != rp->t) { 12004436Sstephh outfl(O_DIE, np->file, np->line, 12014436Sstephh "mismatch in datatype of arguments for operation %s", 12024436Sstephh ptree_nodetype2str(np->t)); 12034436Sstephh /* NOTREACHED */ 12040Sstevel@tonic-gate return (1); 12050Sstevel@tonic-gate } 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate return (0); 12080Sstevel@tonic-gate } 12090Sstevel@tonic-gate 12100Sstevel@tonic-gate /* 12110Sstevel@tonic-gate * eval_expr -- evaluate expression into *valuep 12120Sstevel@tonic-gate * 12130Sstevel@tonic-gate * the meaning of the return value depends on the input value of try. 12140Sstevel@tonic-gate * 12150Sstevel@tonic-gate * for try == 1: if any deferred items are encounted, bail out and return 12160Sstevel@tonic-gate * false. returns true if we made it through entire expression without 12170Sstevel@tonic-gate * hitting any deferred items. 12180Sstevel@tonic-gate * 12190Sstevel@tonic-gate * for try == 0: return true if all operations were performed successfully. 12200Sstevel@tonic-gate * return false if otherwise. for example, any of the following conditions 12210Sstevel@tonic-gate * will result in a false return value: 12220Sstevel@tonic-gate * - attempted use of an uninitialized global variable 12230Sstevel@tonic-gate * - failure in function evaluation 12240Sstevel@tonic-gate * - illegal arithmetic operation (argument out of range) 12250Sstevel@tonic-gate */ 12260Sstevel@tonic-gate int 12274436Sstephh eval_expr(struct node *np, struct lut *ex, struct node *events[], 12280Sstevel@tonic-gate struct lut **globals, struct config *croot, struct arrow *arrowp, 12290Sstevel@tonic-gate int try, struct evalue *valuep) 12300Sstevel@tonic-gate { 12310Sstevel@tonic-gate struct evalue *gval; 12320Sstevel@tonic-gate struct evalue lval; 12330Sstevel@tonic-gate struct evalue rval; 12340Sstevel@tonic-gate 12350Sstevel@tonic-gate if (np == NULL) { 12360Sstevel@tonic-gate valuep->t = UINT64; 12370Sstevel@tonic-gate valuep->v = 1; /* no constraint means "true" */ 12380Sstevel@tonic-gate return (1); 12390Sstevel@tonic-gate } 12400Sstevel@tonic-gate 12410Sstevel@tonic-gate valuep->t = UNDEFINED; 12420Sstevel@tonic-gate 12430Sstevel@tonic-gate switch (np->t) { 12440Sstevel@tonic-gate case T_GLOBID: 12450Sstevel@tonic-gate if (try) 12460Sstevel@tonic-gate return (0); 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate /* 12490Sstevel@tonic-gate * only handle case of getting (and not setting) the value 12500Sstevel@tonic-gate * of a global variable 12510Sstevel@tonic-gate */ 12520Sstevel@tonic-gate gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 12530Sstevel@tonic-gate if (gval == NULL) { 12540Sstevel@tonic-gate return (0); 12550Sstevel@tonic-gate } else { 12560Sstevel@tonic-gate valuep->t = gval->t; 12570Sstevel@tonic-gate valuep->v = gval->v; 12580Sstevel@tonic-gate return (1); 12590Sstevel@tonic-gate } 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate case T_ASSIGN: 12620Sstevel@tonic-gate if (try) 12630Sstevel@tonic-gate return (0); 12640Sstevel@tonic-gate 12650Sstevel@tonic-gate /* 12660Sstevel@tonic-gate * first evaluate rhs, then try to store value in lhs which 12670Sstevel@tonic-gate * should be a global variable 12680Sstevel@tonic-gate */ 12694436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 12704436Sstephh arrowp, try, &rval)) 12710Sstevel@tonic-gate return (0); 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate ASSERT(np->u.expr.left->t == T_GLOBID); 12740Sstevel@tonic-gate gval = lut_lookup(*globals, 12754436Sstephh (void *)np->u.expr.left->u.globid.s, NULL); 12760Sstevel@tonic-gate 12770Sstevel@tonic-gate if (gval == NULL) { 12780Sstevel@tonic-gate gval = MALLOC(sizeof (*gval)); 12790Sstevel@tonic-gate *globals = lut_add(*globals, 12804436Sstephh (void *) np->u.expr.left->u.globid.s, gval, NULL); 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate 12830Sstevel@tonic-gate gval->t = rval.t; 12840Sstevel@tonic-gate gval->v = rval.v; 12851414Scindi 12861414Scindi if (gval->t == UINT64) { 12871414Scindi out(O_ALTFP|O_VERB2, 12881414Scindi "assign $%s=%llu", 12891414Scindi np->u.expr.left->u.globid.s, gval->v); 12901414Scindi } else { 12911414Scindi out(O_ALTFP|O_VERB2, 12921414Scindi "assign $%s=\"%s\"", 12931717Swesolows np->u.expr.left->u.globid.s, 12941717Swesolows (char *)(uintptr_t)gval->v); 12951414Scindi } 12961414Scindi 12971414Scindi /* 12981414Scindi * but always return true -- an assignment should not 12991414Scindi * cause a constraint to be false. 13001414Scindi */ 13011414Scindi valuep->t = UINT64; 13021414Scindi valuep->v = 1; 13030Sstevel@tonic-gate return (1); 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate case T_EQ: 13060Sstevel@tonic-gate #define IMPLICIT_ASSIGN_IN_EQ 13070Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ 13080Sstevel@tonic-gate /* 13090Sstevel@tonic-gate * if lhs is an uninitialized global variable, perform 13100Sstevel@tonic-gate * an assignment. 13110Sstevel@tonic-gate * 13120Sstevel@tonic-gate * one insidious side effect of implicit assignment is 13130Sstevel@tonic-gate * that the "==" operator does not return a Boolean if 13140Sstevel@tonic-gate * implicit assignment was performed. 13150Sstevel@tonic-gate */ 13160Sstevel@tonic-gate if (try == 0 && 13170Sstevel@tonic-gate np->u.expr.left->t == T_GLOBID && 13180Sstevel@tonic-gate (gval = lut_lookup(*globals, 13194436Sstephh (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 13204436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 13214436Sstephh croot, arrowp, try, &rval)) 13220Sstevel@tonic-gate return (0); 13230Sstevel@tonic-gate 13240Sstevel@tonic-gate gval = MALLOC(sizeof (*gval)); 13250Sstevel@tonic-gate *globals = lut_add(*globals, 13264436Sstephh (void *) np->u.expr.left->u.globid.s, 13274436Sstephh gval, NULL); 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate gval->t = rval.t; 13300Sstevel@tonic-gate gval->v = rval.v; 13310Sstevel@tonic-gate valuep->t = rval.t; 13320Sstevel@tonic-gate valuep->v = rval.v; 13330Sstevel@tonic-gate return (1); 13340Sstevel@tonic-gate } 13350Sstevel@tonic-gate #endif /* IMPLICIT_ASSIGN_IN_EQ */ 13360Sstevel@tonic-gate 13374436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13384436Sstephh arrowp, try, &lval)) 13394436Sstephh return (0); 13404436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13414436Sstephh arrowp, try, &rval)) 13420Sstevel@tonic-gate return (0); 13434436Sstephh if (rval.t == UINT64 || lval.t == UINT64) { 13444436Sstephh if (check_expr_args(&lval, &rval, UINT64, np)) 13454436Sstephh return (0); 13464436Sstephh } else { 13474436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np)) 13484436Sstephh return (0); 13494436Sstephh } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate valuep->t = UINT64; 13520Sstevel@tonic-gate valuep->v = (lval.v == rval.v); 13530Sstevel@tonic-gate return (1); 13540Sstevel@tonic-gate 13550Sstevel@tonic-gate case T_LT: 13564436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13574436Sstephh arrowp, try, &lval)) 13580Sstevel@tonic-gate return (0); 13594436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13604436Sstephh arrowp, try, &rval)) 13610Sstevel@tonic-gate return (0); 13621414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 13630Sstevel@tonic-gate return (0); 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate valuep->t = UINT64; 13660Sstevel@tonic-gate valuep->v = (lval.v < rval.v); 13670Sstevel@tonic-gate return (1); 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate case T_LE: 13704436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13714436Sstephh arrowp, try, &lval)) 13720Sstevel@tonic-gate return (0); 13734436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13744436Sstephh arrowp, try, &rval)) 13750Sstevel@tonic-gate return (0); 13761414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 13770Sstevel@tonic-gate return (0); 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate valuep->t = UINT64; 13800Sstevel@tonic-gate valuep->v = (lval.v <= rval.v); 13810Sstevel@tonic-gate return (1); 13820Sstevel@tonic-gate 13830Sstevel@tonic-gate case T_GT: 13844436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13854436Sstephh arrowp, try, &lval)) 13860Sstevel@tonic-gate return (0); 13874436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13884436Sstephh arrowp, try, &rval)) 13890Sstevel@tonic-gate return (0); 13901414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 13910Sstevel@tonic-gate return (0); 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate valuep->t = UINT64; 13940Sstevel@tonic-gate valuep->v = (lval.v > rval.v); 13950Sstevel@tonic-gate return (1); 13960Sstevel@tonic-gate 13970Sstevel@tonic-gate case T_GE: 13984436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13994436Sstephh arrowp, try, &lval)) 14000Sstevel@tonic-gate return (0); 14014436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14024436Sstephh arrowp, try, &rval)) 14030Sstevel@tonic-gate return (0); 14041414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 14050Sstevel@tonic-gate return (0); 14060Sstevel@tonic-gate 14070Sstevel@tonic-gate valuep->t = UINT64; 14080Sstevel@tonic-gate valuep->v = (lval.v >= rval.v); 14090Sstevel@tonic-gate return (1); 14100Sstevel@tonic-gate 14110Sstevel@tonic-gate case T_BITAND: 14124436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14134436Sstephh arrowp, try, &lval)) 14140Sstevel@tonic-gate return (0); 14154436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14164436Sstephh arrowp, try, &rval)) 14170Sstevel@tonic-gate return (0); 14180Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14190Sstevel@tonic-gate return (0); 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate valuep->t = lval.t; 14220Sstevel@tonic-gate valuep->v = (lval.v & rval.v); 14230Sstevel@tonic-gate return (1); 14240Sstevel@tonic-gate 14250Sstevel@tonic-gate case T_BITOR: 14264436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14274436Sstephh arrowp, try, &lval)) 14280Sstevel@tonic-gate return (0); 14294436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14304436Sstephh arrowp, try, &rval)) 14310Sstevel@tonic-gate return (0); 14320Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14330Sstevel@tonic-gate return (0); 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate valuep->t = lval.t; 14360Sstevel@tonic-gate valuep->v = (lval.v | rval.v); 14370Sstevel@tonic-gate return (1); 14380Sstevel@tonic-gate 14390Sstevel@tonic-gate case T_BITXOR: 14404436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14414436Sstephh arrowp, try, &lval)) 14420Sstevel@tonic-gate return (0); 14434436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14444436Sstephh arrowp, try, &rval)) 14450Sstevel@tonic-gate return (0); 14460Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14470Sstevel@tonic-gate return (0); 14480Sstevel@tonic-gate 14490Sstevel@tonic-gate valuep->t = lval.t; 14500Sstevel@tonic-gate valuep->v = (lval.v ^ rval.v); 14510Sstevel@tonic-gate return (1); 14520Sstevel@tonic-gate 14530Sstevel@tonic-gate case T_BITNOT: 14544436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14554436Sstephh arrowp, try, &lval)) 14560Sstevel@tonic-gate return (0); 14570Sstevel@tonic-gate ASSERT(np->u.expr.right == NULL); 14580Sstevel@tonic-gate if (check_expr_args(&lval, NULL, UINT64, np)) 14590Sstevel@tonic-gate return (0); 14600Sstevel@tonic-gate 14610Sstevel@tonic-gate valuep->t = UINT64; 14620Sstevel@tonic-gate valuep->v = ~ lval.v; 14630Sstevel@tonic-gate return (1); 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate case T_LSHIFT: 14664436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14674436Sstephh arrowp, try, &lval)) 14680Sstevel@tonic-gate return (0); 14694436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14704436Sstephh arrowp, try, &rval)) 14710Sstevel@tonic-gate return (0); 14720Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14730Sstevel@tonic-gate return (0); 14740Sstevel@tonic-gate 14750Sstevel@tonic-gate valuep->t = UINT64; 14760Sstevel@tonic-gate valuep->v = (lval.v << rval.v); 14770Sstevel@tonic-gate return (1); 14780Sstevel@tonic-gate 14790Sstevel@tonic-gate case T_RSHIFT: 14804436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14814436Sstephh arrowp, try, &lval)) 14820Sstevel@tonic-gate return (0); 14834436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14844436Sstephh arrowp, try, &rval)) 14850Sstevel@tonic-gate return (0); 14860Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14870Sstevel@tonic-gate return (0); 14880Sstevel@tonic-gate 14890Sstevel@tonic-gate valuep->t = UINT64; 14900Sstevel@tonic-gate valuep->v = (lval.v >> rval.v); 14910Sstevel@tonic-gate return (1); 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate case T_CONDIF: { 14940Sstevel@tonic-gate struct node *retnp; 14950Sstevel@tonic-gate int dotrue = 0; 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate /* 14980Sstevel@tonic-gate * evaluate 14990Sstevel@tonic-gate * expression ? stmtA [ : stmtB ] 15000Sstevel@tonic-gate * 15010Sstevel@tonic-gate * first see if expression is true or false, then determine 15020Sstevel@tonic-gate * if stmtA (or stmtB, if it exists) should be evaluated. 15030Sstevel@tonic-gate * 15040Sstevel@tonic-gate * "dotrue = 1" means stmtA should be evaluated. 15050Sstevel@tonic-gate */ 15065204Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15075204Sstephh arrowp, try, &lval)) 15085204Sstephh return (0); 15095204Sstephh 15105204Sstephh if (lval.t != UNDEFINED && lval.v != 0) 15110Sstevel@tonic-gate dotrue = 1; 15120Sstevel@tonic-gate 15130Sstevel@tonic-gate ASSERT(np->u.expr.right != NULL); 15140Sstevel@tonic-gate if (np->u.expr.right->t == T_CONDELSE) { 15150Sstevel@tonic-gate if (dotrue) 15160Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.left; 15170Sstevel@tonic-gate else 15180Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.right; 15190Sstevel@tonic-gate } else { 15200Sstevel@tonic-gate /* no ELSE clause */ 15210Sstevel@tonic-gate if (dotrue) 15220Sstevel@tonic-gate retnp = np->u.expr.right; 15230Sstevel@tonic-gate else { 15244436Sstephh outfl(O_DIE, np->file, np->line, 15254436Sstephh "eval_expr: missing condelse"); 15260Sstevel@tonic-gate } 15270Sstevel@tonic-gate } 15280Sstevel@tonic-gate 15294436Sstephh if (!eval_expr(retnp, ex, events, globals, croot, 15304436Sstephh arrowp, try, valuep)) 15310Sstevel@tonic-gate return (0); 15320Sstevel@tonic-gate return (1); 15330Sstevel@tonic-gate } 15340Sstevel@tonic-gate 15350Sstevel@tonic-gate case T_CONDELSE: 15360Sstevel@tonic-gate /* 15370Sstevel@tonic-gate * shouldn't get here, since T_CONDELSE is supposed to be 15380Sstevel@tonic-gate * evaluated as part of T_CONDIF 15390Sstevel@tonic-gate */ 15400Sstevel@tonic-gate out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 15410Sstevel@tonic-gate ptree_nodetype2str(np->t)); 15424436Sstephh /*NOTREACHED*/ 15430Sstevel@tonic-gate 15440Sstevel@tonic-gate case T_NE: 15454436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15464436Sstephh arrowp, try, &lval)) 15474436Sstephh return (0); 15484436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15494436Sstephh arrowp, try, &rval)) 15500Sstevel@tonic-gate return (0); 15514436Sstephh if (rval.t == UINT64 || lval.t == UINT64) { 15524436Sstephh if (check_expr_args(&lval, &rval, UINT64, np)) 15534436Sstephh return (0); 15544436Sstephh } else { 15554436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np)) 15564436Sstephh return (0); 15574436Sstephh } 15580Sstevel@tonic-gate 15590Sstevel@tonic-gate valuep->t = UINT64; 15600Sstevel@tonic-gate valuep->v = (lval.v != rval.v); 15610Sstevel@tonic-gate return (1); 15620Sstevel@tonic-gate 15630Sstevel@tonic-gate case T_LIST: 15640Sstevel@tonic-gate case T_AND: 15654436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15664436Sstephh arrowp, try, valuep)) { 15673159Sstephh /* 15683159Sstephh * if lhs is unknown, still check rhs. If that 15695204Sstephh * is false we can return false irrespective of lhs 15703159Sstephh */ 15715204Sstephh if (!try) { 15725204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 15735204Sstephh return (0); 15745204Sstephh } 15754436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 15764436Sstephh croot, arrowp, try, valuep)) { 15774436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 15783159Sstephh return (0); 15794436Sstephh } 15804436Sstephh if (valuep->v != 0) { 15814436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK; 15823159Sstephh return (0); 15834436Sstephh } 15843159Sstephh } 15850Sstevel@tonic-gate if (valuep->v == 0) { 15860Sstevel@tonic-gate valuep->t = UINT64; 15870Sstevel@tonic-gate return (1); 15880Sstevel@tonic-gate } 15894436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15904436Sstephh arrowp, try, valuep)) { 15914436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK; 15920Sstevel@tonic-gate return (0); 15934436Sstephh } 15940Sstevel@tonic-gate valuep->t = UINT64; 15950Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1; 15960Sstevel@tonic-gate return (1); 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate case T_OR: 15994436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16004436Sstephh arrowp, try, valuep)) { 16013159Sstephh /* 16023159Sstephh * if lhs is unknown, still check rhs. If that 16035204Sstephh * is true we can return true irrespective of lhs 16043159Sstephh */ 16055204Sstephh if (!try) { 16065204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 16075204Sstephh return (0); 16085204Sstephh } 16094436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 16104436Sstephh croot, arrowp, try, valuep)) { 16114436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 16123159Sstephh return (0); 16134436Sstephh } 16144436Sstephh if (valuep->v == 0) { 16154436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK; 16163159Sstephh return (0); 16174436Sstephh } 16183159Sstephh } 16190Sstevel@tonic-gate if (valuep->v != 0) { 16200Sstevel@tonic-gate valuep->t = UINT64; 16210Sstevel@tonic-gate valuep->v = 1; 16220Sstevel@tonic-gate return (1); 16230Sstevel@tonic-gate } 16244436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16254436Sstephh arrowp, try, valuep)) { 16264436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK; 16270Sstevel@tonic-gate return (0); 16284436Sstephh } 16290Sstevel@tonic-gate valuep->t = UINT64; 16300Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1; 16310Sstevel@tonic-gate return (1); 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate case T_NOT: 16344436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16354436Sstephh arrowp, try, valuep)) 16360Sstevel@tonic-gate return (0); 16370Sstevel@tonic-gate valuep->t = UINT64; 16380Sstevel@tonic-gate valuep->v = ! valuep->v; 16390Sstevel@tonic-gate return (1); 16400Sstevel@tonic-gate 16410Sstevel@tonic-gate case T_ADD: 16424436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16434436Sstephh arrowp, try, &lval)) 16440Sstevel@tonic-gate return (0); 16454436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16464436Sstephh arrowp, try, &rval)) 16470Sstevel@tonic-gate return (0); 16480Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16490Sstevel@tonic-gate return (0); 16500Sstevel@tonic-gate 16510Sstevel@tonic-gate valuep->t = lval.t; 16520Sstevel@tonic-gate valuep->v = lval.v + rval.v; 16530Sstevel@tonic-gate return (1); 16540Sstevel@tonic-gate 16550Sstevel@tonic-gate case T_SUB: 16564436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16574436Sstephh arrowp, try, &lval)) 16580Sstevel@tonic-gate return (0); 16594436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16604436Sstephh arrowp, try, &rval)) 16610Sstevel@tonic-gate return (0); 16620Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16630Sstevel@tonic-gate return (0); 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate /* since valuep is unsigned, return false if lval.v < rval.v */ 16660Sstevel@tonic-gate if (lval.v < rval.v) { 16674436Sstephh outfl(O_DIE, np->file, np->line, 16684436Sstephh "eval_expr: T_SUB result is out of range"); 16690Sstevel@tonic-gate } 16700Sstevel@tonic-gate 16710Sstevel@tonic-gate valuep->t = lval.t; 16720Sstevel@tonic-gate valuep->v = lval.v - rval.v; 16730Sstevel@tonic-gate return (1); 16740Sstevel@tonic-gate 16750Sstevel@tonic-gate case T_MUL: 16764436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16774436Sstephh arrowp, try, &lval)) 16780Sstevel@tonic-gate return (0); 16794436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16804436Sstephh arrowp, try, &rval)) 16810Sstevel@tonic-gate return (0); 16820Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16830Sstevel@tonic-gate return (0); 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate valuep->t = lval.t; 16860Sstevel@tonic-gate valuep->v = lval.v * rval.v; 16870Sstevel@tonic-gate return (1); 16880Sstevel@tonic-gate 16890Sstevel@tonic-gate case T_DIV: 16904436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16914436Sstephh arrowp, try, &lval)) 16920Sstevel@tonic-gate return (0); 16934436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16944436Sstephh arrowp, try, &rval)) 16950Sstevel@tonic-gate return (0); 16960Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16970Sstevel@tonic-gate return (0); 16980Sstevel@tonic-gate 16990Sstevel@tonic-gate /* return false if dividing by zero */ 17000Sstevel@tonic-gate if (rval.v == 0) { 17014436Sstephh outfl(O_DIE, np->file, np->line, 17024436Sstephh "eval_expr: T_DIV division by zero"); 17030Sstevel@tonic-gate } 17040Sstevel@tonic-gate 17050Sstevel@tonic-gate valuep->t = lval.t; 17060Sstevel@tonic-gate valuep->v = lval.v / rval.v; 17070Sstevel@tonic-gate return (1); 17080Sstevel@tonic-gate 17090Sstevel@tonic-gate case T_MOD: 17104436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 17114436Sstephh arrowp, try, &lval)) 17120Sstevel@tonic-gate return (0); 17134436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 17144436Sstephh arrowp, try, &rval)) 17150Sstevel@tonic-gate return (0); 17160Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 17170Sstevel@tonic-gate return (0); 17180Sstevel@tonic-gate 17190Sstevel@tonic-gate /* return false if dividing by zero */ 17200Sstevel@tonic-gate if (rval.v == 0) { 17214436Sstephh outfl(O_DIE, np->file, np->line, 17224436Sstephh "eval_expr: T_MOD division by zero"); 17230Sstevel@tonic-gate } 17240Sstevel@tonic-gate 17250Sstevel@tonic-gate valuep->t = lval.t; 17260Sstevel@tonic-gate valuep->v = lval.v % rval.v; 17270Sstevel@tonic-gate return (1); 17280Sstevel@tonic-gate 17290Sstevel@tonic-gate case T_NAME: 17300Sstevel@tonic-gate if (try) { 17310Sstevel@tonic-gate struct iterinfo *iterinfop; 17324436Sstephh struct node *np1, *np2; 17334436Sstephh int i, gotmatch = 0; 17340Sstevel@tonic-gate 17350Sstevel@tonic-gate /* 17364436Sstephh * Check if we have an exact match of the nonwildcarded 17374436Sstephh * path in oldepname - if so we can just use the 17384436Sstephh * full wildcarded path in epname. 17390Sstevel@tonic-gate */ 17404436Sstephh for (i = 0; i < 1; i++) { 17414436Sstephh for (np1 = np, 17424436Sstephh np2 = events[i]->u.event.oldepname; 17434436Sstephh np1 != NULL && np2 != NULL; 17444436Sstephh np1 = np1->u.name.next, 17454436Sstephh np2 = np2->u.name.next) { 17464436Sstephh if (strcmp(np1->u.name.s, 17474436Sstephh np2->u.name.s) != 0) 17484436Sstephh break; 17494436Sstephh if (np1->u.name.child->t != 17504436Sstephh np2->u.name.child->t) 17514436Sstephh break; 17524436Sstephh if (np1->u.name.child->t == T_NUM && 17534436Sstephh np1->u.name.child->u.ull != 17544436Sstephh np2->u.name.child->u.ull) 17554436Sstephh break; 17564436Sstephh if (np1->u.name.child->t == T_NAME && 17574436Sstephh strcmp(np1->u.name.child->u.name.s, 17584436Sstephh np2->u.name.child->u.name.s) != 0) 17594436Sstephh break; 17604436Sstephh gotmatch++; 17614436Sstephh } 17624436Sstephh if (np1 == NULL && np2 == NULL) { 17634436Sstephh valuep->t = NODEPTR; 17644436Sstephh valuep->v = (uintptr_t) 17654436Sstephh events[i]->u.event.epname; 17664436Sstephh return (1); 17674436Sstephh } 17680Sstevel@tonic-gate } 17694436Sstephh if (!gotmatch) { 17704436Sstephh /* 17714436Sstephh * we're not wildcarding. However at 17724436Sstephh * itree_create() time, we can also expand 17734436Sstephh * simple iterators - so check for those. 17744436Sstephh */ 17754436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, 17764436Sstephh NULL); 17774436Sstephh if (iterinfop != NULL) { 17784436Sstephh valuep->t = UINT64; 17794436Sstephh valuep->v = 17804436Sstephh (unsigned long long)iterinfop->num; 17814436Sstephh return (1); 17824436Sstephh } 17834436Sstephh } 17844436Sstephh /* 17854436Sstephh * For anything else we'll have to wait for eval_dup(). 17864436Sstephh */ 17870Sstevel@tonic-gate return (0); 17880Sstevel@tonic-gate } 17890Sstevel@tonic-gate 17900Sstevel@tonic-gate /* return address of struct node */ 17910Sstevel@tonic-gate valuep->t = NODEPTR; 17921717Swesolows valuep->v = (uintptr_t)np; 17930Sstevel@tonic-gate return (1); 17940Sstevel@tonic-gate 17950Sstevel@tonic-gate case T_QUOTE: 17960Sstevel@tonic-gate valuep->t = STRING; 17971717Swesolows valuep->v = (uintptr_t)np->u.quote.s; 17980Sstevel@tonic-gate return (1); 17990Sstevel@tonic-gate 18000Sstevel@tonic-gate case T_FUNC: 18014436Sstephh return (eval_func(np, ex, events, np->u.func.arglist, 18024436Sstephh globals, croot, arrowp, try, valuep)); 18030Sstevel@tonic-gate 18040Sstevel@tonic-gate case T_NUM: 18057197Sstephh case T_TIMEVAL: 18060Sstevel@tonic-gate valuep->t = UINT64; 18070Sstevel@tonic-gate valuep->v = np->u.ull; 18080Sstevel@tonic-gate return (1); 18090Sstevel@tonic-gate 18100Sstevel@tonic-gate default: 18110Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 18120Sstevel@tonic-gate "eval_expr: unexpected node type: %s", 18130Sstevel@tonic-gate ptree_nodetype2str(np->t)); 18140Sstevel@tonic-gate } 18150Sstevel@tonic-gate /*NOTREACHED*/ 18161717Swesolows return (0); 18170Sstevel@tonic-gate } 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate /* 18200Sstevel@tonic-gate * eval_fru() and eval_asru() don't do much, but are called from a number 18210Sstevel@tonic-gate * of places. 18220Sstevel@tonic-gate */ 18234436Sstephh static struct node * 18240Sstevel@tonic-gate eval_fru(struct node *np) 18250Sstevel@tonic-gate { 18260Sstevel@tonic-gate ASSERT(np->t == T_NAME); 18270Sstevel@tonic-gate return (np); 18280Sstevel@tonic-gate } 18290Sstevel@tonic-gate 18304436Sstephh static struct node * 18310Sstevel@tonic-gate eval_asru(struct node *np) 18320Sstevel@tonic-gate { 18330Sstevel@tonic-gate ASSERT(np->t == T_NAME); 18340Sstevel@tonic-gate return (np); 18350Sstevel@tonic-gate } 1836