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*7197Sstephh * Copyright 2008 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 #pragma ident "%Z%%M% %I% %E% SMI" 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <stdio.h> 340Sstevel@tonic-gate #include <stdlib.h> 350Sstevel@tonic-gate #include <ctype.h> 360Sstevel@tonic-gate #include <string.h> 370Sstevel@tonic-gate #include "alloc.h" 380Sstevel@tonic-gate #include "out.h" 390Sstevel@tonic-gate #include "stable.h" 400Sstevel@tonic-gate #include "literals.h" 410Sstevel@tonic-gate #include "lut.h" 420Sstevel@tonic-gate #include "tree.h" 430Sstevel@tonic-gate #include "ptree.h" 440Sstevel@tonic-gate #include "itree.h" 451414Scindi #include "ipath.h" 460Sstevel@tonic-gate #include "eval.h" 470Sstevel@tonic-gate #include "config.h" 480Sstevel@tonic-gate #include "platform.h" 491414Scindi #include "fme.h" 501414Scindi #include "stats.h" 510Sstevel@tonic-gate 520Sstevel@tonic-gate static struct node *eval_dup(struct node *np, struct lut *ex, 534436Sstephh struct node *events[]); 541414Scindi static int check_expr_args(struct evalue *lp, struct evalue *rp, 551414Scindi enum datatype dtype, struct node *np); 564436Sstephh static struct node *eval_fru(struct node *np); 574436Sstephh static struct node *eval_asru(struct node *np); 580Sstevel@tonic-gate 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); 4124436Sstephh } else if (funcname == L_count) { 4134436Sstephh struct stats *statp; 4144436Sstephh struct istat_entry ent; 4154436Sstephh 4164436Sstephh ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t)); 4174436Sstephh 4184436Sstephh nodep = np->u.event.epname; 4194436Sstephh if (try) { 4204436Sstephh if (eval_expr(nodep, ex, events, globals, 4214436Sstephh croot, arrowp, try, &val) && val.t == NODEPTR) 4224436Sstephh nodep = (struct node *)(uintptr_t)val.v; 4234436Sstephh else { 4244436Sstephh duped = 1; 4254436Sstephh nodep = eval_dup(nodep, ex, events); 4264436Sstephh } 4274436Sstephh } 4284436Sstephh ent.ename = np->u.event.ename->u.name.s; 4294436Sstephh ent.ipath = ipath(nodep); 4304436Sstephh valuep->t = UINT64; 4314436Sstephh if ((statp = (struct stats *) 4324436Sstephh lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL) 4334436Sstephh valuep->v = 0; 4344436Sstephh else 4354436Sstephh valuep->v = stats_counter_value(statp); 4364436Sstephh if (duped) 4374436Sstephh tree_free(nodep); 4384436Sstephh return (1); 4394436Sstephh } else if (funcname == L_envprop) { 4404436Sstephh outfl(O_DIE, np->file, np->line, 4414436Sstephh "eval_func: %s not yet supported", funcname); 4420Sstevel@tonic-gate } 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate if (try) 4450Sstevel@tonic-gate return (0); 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate if (funcname == L_fru) { 4480Sstevel@tonic-gate valuep->t = NODEPTR; 4491717Swesolows valuep->v = (uintptr_t)eval_fru(np); 4500Sstevel@tonic-gate return (1); 4510Sstevel@tonic-gate } else if (funcname == L_asru) { 4520Sstevel@tonic-gate valuep->t = NODEPTR; 4531717Swesolows valuep->v = (uintptr_t)eval_asru(np); 4540Sstevel@tonic-gate return (1); 4551414Scindi } else if (funcname == L_defined) { 4561414Scindi ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str); 4571414Scindi valuep->t = UINT64; 4581414Scindi valuep->v = (lut_lookup(*globals, 4591414Scindi (void *)np->u.globid.s, NULL) != NULL); 4601414Scindi return (1); 4610Sstevel@tonic-gate } else if (funcname == L_call) { 4620Sstevel@tonic-gate return (! platform_call(np, globals, croot, arrowp, valuep)); 4630Sstevel@tonic-gate } else if (funcname == L_payloadprop) { 4641414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 4650Sstevel@tonic-gate "payloadprop(\"%s\") ", np->u.quote.s); 466186Sdb35262 4675204Sstephh if (arrowp->head->myevent->count == 0) { 4685204Sstephh /* 4695204Sstephh * Haven't seen this ereport yet, so must defer 4705204Sstephh */ 4715204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 4725204Sstephh return (0); 4735204Sstephh } else if (platform_payloadprop(np, valuep)) { 4741414Scindi /* platform_payloadprop() returned false */ 4755204Sstephh out(O_ALTFP|O_VERB, "not found."); 4765204Sstephh valuep->t = UNDEFINED; 4775204Sstephh return (1); 4781414Scindi } else { 479186Sdb35262 switch (valuep->t) { 480186Sdb35262 case UINT64: 481186Sdb35262 case NODEPTR: 4821414Scindi out(O_ALTFP|O_VERB2, "found: %llu", valuep->v); 483186Sdb35262 break; 484186Sdb35262 case STRING: 4851414Scindi out(O_ALTFP|O_VERB2, "found: \"%s\"", 4861717Swesolows (char *)(uintptr_t)valuep->v); 487186Sdb35262 break; 488186Sdb35262 default: 4891414Scindi out(O_ALTFP|O_VERB2, "found: undefined"); 490186Sdb35262 break; 491186Sdb35262 } 4921414Scindi return (1); 4931414Scindi } 4941414Scindi } else if (funcname == L_setpayloadprop) { 4951414Scindi struct evalue *payloadvalp; 4965204Sstephh int alloced = 0; 4971414Scindi 4981414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 4991414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE, 5001414Scindi ptree_nodetype2str(np->u.expr.left->t)); 5011414Scindi 502*7197Sstephh if (arrowp->head->myevent->count == 0) 503*7197Sstephh return (0); 504*7197Sstephh 5051414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 5061414Scindi "setpayloadprop: %s: %s=", 5071414Scindi arrowp->tail->myevent->enode->u.event.ename->u.name.s, 5081414Scindi np->u.expr.left->u.quote.s); 5091414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 5101414Scindi 5111414Scindi /* 5121414Scindi * allocate a struct evalue to hold the payload property's 5131414Scindi * value, unless we've been here already, in which case we 5141414Scindi * might calculate a different value, but we'll store it 5151414Scindi * in the already-allocated struct evalue. 5161414Scindi */ 5171414Scindi if ((payloadvalp = (struct evalue *)lut_lookup( 5181414Scindi arrowp->tail->myevent->payloadprops, 5191414Scindi (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) { 5201414Scindi payloadvalp = MALLOC(sizeof (*payloadvalp)); 5215204Sstephh alloced = 1; 5221414Scindi } 5231414Scindi 5244436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 5251414Scindi arrowp, try, payloadvalp)) { 5265204Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)"); 5275204Sstephh if (alloced) 5285204Sstephh FREE(payloadvalp); 5295204Sstephh return (0); 5301414Scindi } else { 5315204Sstephh if (payloadvalp->t == UNDEFINED) { 5325204Sstephh /* function is always true */ 5335204Sstephh out(O_ALTFP|O_VERB2, " (undefined)"); 5345204Sstephh valuep->t = UINT64; 5355204Sstephh valuep->v = 1; 5365204Sstephh return (1); 5375204Sstephh } 5381414Scindi if (payloadvalp->t == UINT64) 5391414Scindi out(O_ALTFP|O_VERB2, 5401414Scindi " (%llu)", payloadvalp->v); 5411414Scindi else 5421717Swesolows out(O_ALTFP|O_VERB2, " (\"%s\")", 5431717Swesolows (char *)(uintptr_t)payloadvalp->v); 5441414Scindi } 5451414Scindi 5461414Scindi /* add to table of payload properties for current problem */ 5471414Scindi arrowp->tail->myevent->payloadprops = 5481414Scindi lut_add(arrowp->tail->myevent->payloadprops, 5491414Scindi (void *)np->u.expr.left->u.quote.s, 5501414Scindi (void *)payloadvalp, NULL); 5511414Scindi 5521414Scindi /* function is always true */ 5531414Scindi valuep->t = UINT64; 5541414Scindi valuep->v = 1; 5551414Scindi return (1); 556*7197Sstephh } else if (funcname == L_setserdn || funcname == L_setserdt || 557*7197Sstephh funcname == L_setserdsuffix || funcname == L_setserdincrement) { 558*7197Sstephh struct evalue *serdvalp; 559*7197Sstephh int alloced = 0; 560*7197Sstephh char *str; 561*7197Sstephh struct event *flt = arrowp->tail->myevent; 562*7197Sstephh 563*7197Sstephh if (arrowp->head->myevent->count == 0) 564*7197Sstephh return (0); 565*7197Sstephh 566*7197Sstephh if (funcname == L_setserdn) 567*7197Sstephh str = "n"; 568*7197Sstephh else if (funcname == L_setserdt) 569*7197Sstephh str = "t"; 570*7197Sstephh else if (funcname == L_setserdsuffix) 571*7197Sstephh str = "suffix"; 572*7197Sstephh else if (funcname == L_setserdincrement) 573*7197Sstephh str = "increment"; 574*7197Sstephh 575*7197Sstephh /* 576*7197Sstephh * allocate a struct evalue to hold the serd property's 577*7197Sstephh * value, unless we've been here already, in which case we 578*7197Sstephh * might calculate a different value, but we'll store it 579*7197Sstephh * in the already-allocated struct evalue. 580*7197Sstephh */ 581*7197Sstephh if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops, 582*7197Sstephh (void *)str, NULL)) == NULL) { 583*7197Sstephh serdvalp = MALLOC(sizeof (*serdvalp)); 584*7197Sstephh alloced = 1; 585*7197Sstephh } 586*7197Sstephh 587*7197Sstephh if (!eval_expr(np, ex, events, globals, croot, arrowp, try, 588*7197Sstephh serdvalp)) { 589*7197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 590*7197Sstephh "setserd%s: %s: ", str, 591*7197Sstephh flt->enode->u.event.ename->u.name.s); 592*7197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 593*7197Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)"); 594*7197Sstephh if (alloced) 595*7197Sstephh FREE(serdvalp); 596*7197Sstephh return (0); 597*7197Sstephh } else if (serdvalp->t == UNDEFINED) { 598*7197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 599*7197Sstephh "setserd%s: %s: ", str, 600*7197Sstephh flt->enode->u.event.ename->u.name.s); 601*7197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 602*7197Sstephh out(O_ALTFP|O_VERB2, " (undefined)"); 603*7197Sstephh } else { 604*7197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 605*7197Sstephh "setserd%s: %s: ", str, 606*7197Sstephh flt->enode->u.event.ename->u.name.s); 607*7197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np); 608*7197Sstephh if ((funcname == L_setserdincrement || 609*7197Sstephh funcname == L_setserdn) && serdvalp->t == STRING) { 610*7197Sstephh serdvalp->t = UINT64; 611*7197Sstephh serdvalp->v = strtoull((char *) 612*7197Sstephh (uintptr_t)serdvalp->v, NULL, 0); 613*7197Sstephh } 614*7197Sstephh if (funcname == L_setserdt && serdvalp->t == UINT64) { 615*7197Sstephh int len = snprintf(NULL, 0, "%lldns", 616*7197Sstephh serdvalp->v); 617*7197Sstephh char *buf = MALLOC(len + 1); 618*7197Sstephh 619*7197Sstephh (void) snprintf(buf, len + 1, "%lldns", 620*7197Sstephh serdvalp->v); 621*7197Sstephh serdvalp->t = STRING; 622*7197Sstephh serdvalp->v = (uintptr_t)stable(buf); 623*7197Sstephh FREE(buf); 624*7197Sstephh } 625*7197Sstephh if (serdvalp->t == UINT64) 626*7197Sstephh out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v); 627*7197Sstephh else 628*7197Sstephh out(O_ALTFP|O_VERB2, " (\"%s\")", 629*7197Sstephh (char *)(uintptr_t)serdvalp->v); 630*7197Sstephh flt->serdprops = lut_add(flt->serdprops, (void *)str, 631*7197Sstephh (void *)serdvalp, NULL); 632*7197Sstephh } 633*7197Sstephh valuep->t = UINT64; 634*7197Sstephh valuep->v = 1; 635*7197Sstephh return (1); 6361414Scindi } else if (funcname == L_payloadprop_defined) { 6371414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6381414Scindi "payloadprop_defined(\"%s\") ", np->u.quote.s); 6391414Scindi 6405204Sstephh if (arrowp->head->myevent->count == 0) { 6415204Sstephh /* 6425204Sstephh * Haven't seen this ereport yet, so must defer 6435204Sstephh */ 6445204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 6455204Sstephh return (0); 6465204Sstephh } else if (platform_payloadprop(np, NULL)) { 6471414Scindi /* platform_payloadprop() returned false */ 6481414Scindi valuep->v = 0; 6495204Sstephh out(O_ALTFP|O_VERB2, "not found."); 6501414Scindi } else { 6511414Scindi valuep->v = 1; 6521414Scindi out(O_ALTFP|O_VERB2, "found."); 6531414Scindi } 6541414Scindi valuep->t = UINT64; 6551414Scindi return (1); 6561414Scindi } else if (funcname == L_payloadprop_contains) { 6571414Scindi int nvals; 6581414Scindi struct evalue *vals; 6591414Scindi struct evalue cmpval; 6601414Scindi 6611414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t)); 6621414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE, 6631414Scindi ptree_nodetype2str(np->u.expr.left->t)); 6641414Scindi 6651414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, 6661414Scindi "payloadprop_contains(\"%s\", ", 6671414Scindi np->u.expr.left->u.quote.s); 6681414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right); 6692869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, ") "); 6701414Scindi 6711414Scindi /* evaluate the expression we're comparing against */ 6724436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 6731414Scindi arrowp, try, &cmpval)) { 6741414Scindi out(O_ALTFP|O_VERB2|O_NONL, 6755204Sstephh "(cannot eval) "); 6765204Sstephh return (0); 6771414Scindi } else { 6782869Sgavinm switch (cmpval.t) { 6792869Sgavinm case UNDEFINED: 6802869Sgavinm out(O_ALTFP|O_VERB2, "(undefined type)"); 6812869Sgavinm break; 6822869Sgavinm 6832869Sgavinm case UINT64: 6841414Scindi out(O_ALTFP|O_VERB2, 6851414Scindi "(%llu) ", cmpval.v); 6862869Sgavinm break; 6872869Sgavinm 6882869Sgavinm case STRING: 6891414Scindi out(O_ALTFP|O_VERB2, 6901717Swesolows "(\"%s\") ", (char *)(uintptr_t)cmpval.v); 6912869Sgavinm break; 6922869Sgavinm 6932869Sgavinm case NODEPTR: 6942869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, "("); 6952869Sgavinm ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, 6962869Sgavinm (struct node *)(uintptr_t)(cmpval.v)); 6972869Sgavinm out(O_ALTFP|O_VERB2, ") "); 6982869Sgavinm break; 6992869Sgavinm } 7001414Scindi } 7011414Scindi 7021414Scindi /* get the payload values and check for a match */ 7031414Scindi vals = platform_payloadprop_values(np->u.expr.left->u.quote.s, 7041414Scindi &nvals); 7051414Scindi valuep->t = UINT64; 7061414Scindi valuep->v = 0; 7075204Sstephh if (arrowp->head->myevent->count == 0) { 7085204Sstephh /* 7095204Sstephh * Haven't seen this ereport yet, so must defer 7105204Sstephh */ 7115204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer."); 7125204Sstephh return (0); 7135204Sstephh } else if (nvals == 0) { 7141414Scindi out(O_ALTFP|O_VERB2, "not found."); 7155204Sstephh return (1); 7161414Scindi } else { 7171414Scindi struct evalue preval; 7181414Scindi int i; 7191414Scindi 7201414Scindi out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals); 7211414Scindi 7221414Scindi for (i = 0; i < nvals; i++) { 7231414Scindi 7241414Scindi preval.t = vals[i].t; 7251414Scindi preval.v = vals[i].v; 7261414Scindi 7271414Scindi if (check_expr_args(&vals[i], &cmpval, 7281414Scindi UNDEFINED, np)) 7291414Scindi continue; 7301414Scindi 7311414Scindi /* 7321414Scindi * If we auto-converted the value to a 7331414Scindi * string, we need to free the 7341414Scindi * original tree value. 7351414Scindi */ 7361414Scindi if (preval.t == NODEPTR && 7371717Swesolows ((struct node *)(uintptr_t)(preval.v))->t == 7381717Swesolows T_NAME) { 7391717Swesolows tree_free((struct node *)(uintptr_t) 7401717Swesolows preval.v); 7411414Scindi } 7421414Scindi 7431414Scindi if (vals[i].v == cmpval.v) { 7441414Scindi valuep->v = 1; 7451414Scindi break; 7461414Scindi } 7471414Scindi } 748186Sdb35262 7491414Scindi if (valuep->v) 7501414Scindi out(O_ALTFP|O_VERB2, "match."); 7511414Scindi else 7521414Scindi out(O_ALTFP|O_VERB2, "no match."); 753186Sdb35262 7541414Scindi for (i = 0; i < nvals; i++) { 7551414Scindi if (vals[i].t == NODEPTR) { 7561717Swesolows tree_free((struct node *)(uintptr_t) 7571717Swesolows vals[i].v); 7581414Scindi break; 7591414Scindi } 760186Sdb35262 } 7611414Scindi FREE(vals); 7621414Scindi } 7631414Scindi return (1); 7641414Scindi } else if (funcname == L_confcall) { 7651414Scindi return (!platform_confcall(np, globals, croot, arrowp, valuep)); 7660Sstevel@tonic-gate } else 7670Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 7680Sstevel@tonic-gate "eval_func: unexpected func: %s", funcname); 7690Sstevel@tonic-gate /*NOTREACHED*/ 7701717Swesolows return (0); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7734436Sstephh /* 7744436Sstephh * defines for u.expr.temp - these are used for T_OR and T_AND so that if 7754436Sstephh * we worked out that part of the expression was true or false during an 7764436Sstephh * earlier eval_expr, then we don't need to dup that part. 7774436Sstephh */ 7780Sstevel@tonic-gate 7794436Sstephh #define EXPR_TEMP_BOTH_UNK 0 7804436Sstephh #define EXPR_TEMP_LHS_UNK 1 7814436Sstephh #define EXPR_TEMP_RHS_UNK 2 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate static struct node * 7844436Sstephh eval_dup(struct node *np, struct lut *ex, struct node *events[]) 7850Sstevel@tonic-gate { 7860Sstevel@tonic-gate struct node *newnp; 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate if (np == NULL) 7890Sstevel@tonic-gate return (NULL); 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate switch (np->t) { 7920Sstevel@tonic-gate case T_GLOBID: 7930Sstevel@tonic-gate return (tree_globid(np->u.globid.s, np->file, np->line)); 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate case T_ASSIGN: 7960Sstevel@tonic-gate case T_CONDIF: 7970Sstevel@tonic-gate case T_CONDELSE: 7980Sstevel@tonic-gate case T_NE: 7990Sstevel@tonic-gate case T_EQ: 8000Sstevel@tonic-gate case T_LT: 8010Sstevel@tonic-gate case T_LE: 8020Sstevel@tonic-gate case T_GT: 8030Sstevel@tonic-gate case T_GE: 8040Sstevel@tonic-gate case T_BITAND: 8050Sstevel@tonic-gate case T_BITOR: 8060Sstevel@tonic-gate case T_BITXOR: 8070Sstevel@tonic-gate case T_BITNOT: 8080Sstevel@tonic-gate case T_LSHIFT: 8090Sstevel@tonic-gate case T_RSHIFT: 8100Sstevel@tonic-gate case T_NOT: 8110Sstevel@tonic-gate case T_ADD: 8120Sstevel@tonic-gate case T_SUB: 8130Sstevel@tonic-gate case T_MUL: 8140Sstevel@tonic-gate case T_DIV: 8150Sstevel@tonic-gate case T_MOD: 8160Sstevel@tonic-gate return (tree_expr(np->t, 8174436Sstephh eval_dup(np->u.expr.left, ex, events), 8184436Sstephh eval_dup(np->u.expr.right, ex, events))); 8194436Sstephh case T_LIST: 8204436Sstephh case T_AND: 8214436Sstephh switch (np->u.expr.temp) { 8224436Sstephh case EXPR_TEMP_LHS_UNK: 8234436Sstephh return (eval_dup(np->u.expr.left, ex, events)); 8244436Sstephh case EXPR_TEMP_RHS_UNK: 8254436Sstephh return (eval_dup(np->u.expr.right, ex, events)); 8264436Sstephh default: 8274436Sstephh return (tree_expr(np->t, 8284436Sstephh eval_dup(np->u.expr.left, ex, events), 8294436Sstephh eval_dup(np->u.expr.right, ex, events))); 8304436Sstephh } 8314436Sstephh 8324436Sstephh case T_OR: 8334436Sstephh switch (np->u.expr.temp) { 8344436Sstephh case EXPR_TEMP_LHS_UNK: 8354436Sstephh return (eval_dup(np->u.expr.left, ex, events)); 8364436Sstephh case EXPR_TEMP_RHS_UNK: 8374436Sstephh return (eval_dup(np->u.expr.right, ex, events)); 8384436Sstephh default: 8394436Sstephh return (tree_expr(T_OR, 8404436Sstephh eval_dup(np->u.expr.left, ex, events), 8414436Sstephh eval_dup(np->u.expr.right, ex, events))); 8424436Sstephh } 8430Sstevel@tonic-gate 8440Sstevel@tonic-gate case T_NAME: { 8450Sstevel@tonic-gate struct iterinfo *iterinfop; 8464436Sstephh int got_matchf = 0; 8474436Sstephh int got_matcht = 0; 8484436Sstephh struct evalue value; 8494436Sstephh struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL; 8504436Sstephh struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest; 8510Sstevel@tonic-gate 8524436Sstephh /* 8534436Sstephh * Check if we already have a match of the nonwildcarded path 8544436Sstephh * in oldepname (check both to and from events). 8554436Sstephh */ 8564436Sstephh for (np1f = np, np2f = events[0]->u.event.oldepname; 8574436Sstephh np1f != NULL && np2f != NULL; 8584436Sstephh np1f = np1f->u.name.next, np2f = np2f->u.name.next) { 8594436Sstephh if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0) 8604436Sstephh break; 8614436Sstephh if (np1f->u.name.child->t != np2f->u.name.child->t) 8624436Sstephh break; 8634436Sstephh if (np1f->u.name.child->t == T_NUM && 8644436Sstephh np1f->u.name.child->u.ull != 8654436Sstephh np2f->u.name.child->u.ull) 8664436Sstephh break; 8674436Sstephh if (np1f->u.name.child->t == T_NAME && 8684436Sstephh strcmp(np1f->u.name.child->u.name.s, 8694436Sstephh np2f->u.name.child->u.name.s) != 0) 8704436Sstephh break; 8714436Sstephh got_matchf++; 8724436Sstephh } 8734436Sstephh for (np1t = np, np2t = events[1]->u.event.oldepname; 8744436Sstephh np1t != NULL && np2t != NULL; 8754436Sstephh np1t = np1t->u.name.next, np2t = np2t->u.name.next) { 8764436Sstephh if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0) 8774436Sstephh break; 8784436Sstephh if (np1t->u.name.child->t != np2t->u.name.child->t) 8794436Sstephh break; 8804436Sstephh if (np1t->u.name.child->t == T_NUM && 8814436Sstephh np1t->u.name.child->u.ull != 8824436Sstephh np2t->u.name.child->u.ull) 8834436Sstephh break; 8844436Sstephh if (np1t->u.name.child->t == T_NAME && 8854436Sstephh strcmp(np1t->u.name.child->u.name.s, 8864436Sstephh np2t->u.name.child->u.name.s) != 0) 8874436Sstephh break; 8884436Sstephh got_matcht++; 8894436Sstephh } 8904436Sstephh nprest = np; 8914436Sstephh if (got_matchf || got_matcht) { 8924436Sstephh /* 8934436Sstephh * so we are wildcarding. Copy ewname in full, plus 8944436Sstephh * matching section of oldepname. Use whichever gives 8954436Sstephh * the closest match. 8964436Sstephh */ 8974436Sstephh if (got_matchf > got_matcht) { 8984436Sstephh npstart = events[0]->u.event.ewname; 8994436Sstephh npcont = events[0]->u.event.oldepname; 9004436Sstephh npend = np2f; 9014436Sstephh nprest = np1f; 9024436Sstephh } else { 9034436Sstephh npstart = events[1]->u.event.ewname; 9044436Sstephh npcont = events[1]->u.event.oldepname; 9054436Sstephh npend = np2t; 9064436Sstephh nprest = np1t; 9074436Sstephh } 9084436Sstephh for (npref = npstart; npref != NULL; 9094436Sstephh npref = npref->u.name.next) { 9104436Sstephh newnp = newnode(T_NAME, np->file, np->line); 9114436Sstephh newnp->u.name.t = npref->u.name.t; 9124436Sstephh newnp->u.name.s = npref->u.name.s; 9134436Sstephh newnp->u.name.last = newnp; 9144436Sstephh newnp->u.name.it = npref->u.name.it; 9154436Sstephh newnp->u.name.cp = npref->u.name.cp; 9164436Sstephh newnp->u.name.child = 9174436Sstephh newnode(T_NUM, np->file, np->line); 9184436Sstephh if (eval_expr(npref->u.name.child, ex, events, 9190Sstevel@tonic-gate NULL, NULL, NULL, 1, &value) == 0 || 9200Sstevel@tonic-gate value.t != UINT64) { 9210Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 9220Sstevel@tonic-gate "eval_dup: could not resolve " 9230Sstevel@tonic-gate "iterator of %s", np->u.name.s); 9240Sstevel@tonic-gate } 9254436Sstephh newnp->u.name.child->u.ull = value.v; 9264436Sstephh if (retp == NULL) { 9274436Sstephh retp = newnp; 9284436Sstephh } else { 9294436Sstephh retp->u.name.last->u.name.next = newnp; 9304436Sstephh retp->u.name.last = newnp; 9314436Sstephh } 9320Sstevel@tonic-gate } 9334436Sstephh for (npref = npcont; npref != NULL && npref != npend; 9344436Sstephh npref = npref->u.name.next) { 9354436Sstephh newnp = newnode(T_NAME, np->file, np->line); 9364436Sstephh newnp->u.name.t = npref->u.name.t; 9374436Sstephh newnp->u.name.s = npref->u.name.s; 9384436Sstephh newnp->u.name.last = newnp; 9394436Sstephh newnp->u.name.it = npref->u.name.it; 9404436Sstephh newnp->u.name.cp = npref->u.name.cp; 9414436Sstephh newnp->u.name.child = 9424436Sstephh newnode(T_NUM, np->file, np->line); 9434436Sstephh if (eval_expr(npref->u.name.child, ex, events, 9444436Sstephh NULL, NULL, NULL, 1, &value) == 0 || 9454436Sstephh value.t != UINT64) { 9464436Sstephh outfl(O_DIE, np->file, np->line, 9474436Sstephh "eval_dup: could not resolve " 9484436Sstephh "iterator of %s", np->u.name.s); 9494436Sstephh } 9504436Sstephh newnp->u.name.child->u.ull = value.v; 9514436Sstephh if (retp == NULL) { 9524436Sstephh retp = newnp; 9534436Sstephh } else { 9544436Sstephh retp->u.name.last->u.name.next = newnp; 9554436Sstephh retp->u.name.last = newnp; 9564436Sstephh } 9574436Sstephh } 9584436Sstephh } else { 9594436Sstephh /* 9604436Sstephh * not wildcarding - check if explicit iterator 9614436Sstephh */ 9624436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL); 9634436Sstephh if (iterinfop != NULL) { 9644436Sstephh /* explicit iterator; not part of pathname */ 9654436Sstephh newnp = newnode(T_NUM, np->file, np->line); 9664436Sstephh newnp->u.ull = iterinfop->num; 9670Sstevel@tonic-gate return (newnp); 9680Sstevel@tonic-gate } 9690Sstevel@tonic-gate } 9704436Sstephh 9714436Sstephh /* 9724436Sstephh * finally, whether wildcarding or not, we need to copy the 9734436Sstephh * remaining part of the path (if any). This must be defined 9744436Sstephh * absolutely (no more expansion/wildcarding). 9754436Sstephh */ 9764436Sstephh for (npref = nprest; npref != NULL; 9774436Sstephh npref = npref->u.name.next) { 9784436Sstephh newnp = newnode(T_NAME, np->file, np->line); 9794436Sstephh newnp->u.name.t = npref->u.name.t; 9804436Sstephh newnp->u.name.s = npref->u.name.s; 9814436Sstephh newnp->u.name.last = newnp; 9824436Sstephh newnp->u.name.it = npref->u.name.it; 9834436Sstephh newnp->u.name.cp = npref->u.name.cp; 9844436Sstephh newnp->u.name.child = 9854436Sstephh newnode(T_NUM, np->file, np->line); 9864436Sstephh if (eval_expr(npref->u.name.child, ex, events, 9874436Sstephh NULL, NULL, NULL, 1, &value) == 0 || 9884436Sstephh value.t != UINT64) { 9894436Sstephh outfl(O_DIE, np->file, np->line, 9904436Sstephh "eval_dup: could not resolve " 9914436Sstephh "iterator of %s", np->u.name.s); 9924436Sstephh } 9934436Sstephh newnp->u.name.child->u.ull = value.v; 9944436Sstephh if (retp == NULL) { 9954436Sstephh retp = newnp; 9964436Sstephh } else { 9974436Sstephh retp->u.name.last->u.name.next = newnp; 9984436Sstephh retp->u.name.last = newnp; 9994436Sstephh } 10004436Sstephh } 10014436Sstephh return (retp); 10020Sstevel@tonic-gate } 10030Sstevel@tonic-gate 10041414Scindi case T_EVENT: 10051414Scindi newnp = newnode(T_NAME, np->file, np->line); 10061414Scindi 10071414Scindi newnp->u.name.t = np->u.event.ename->u.name.t; 10081414Scindi newnp->u.name.s = np->u.event.ename->u.name.s; 10091414Scindi newnp->u.name.it = np->u.event.ename->u.name.it; 10101414Scindi newnp->u.name.last = newnp; 10111414Scindi 10121414Scindi return (tree_event(newnp, 10134436Sstephh eval_dup(np->u.event.epname, ex, events), 10144436Sstephh eval_dup(np->u.event.eexprlist, ex, events))); 10151414Scindi 10160Sstevel@tonic-gate case T_FUNC: 10170Sstevel@tonic-gate return (tree_func(np->u.func.s, 10184436Sstephh eval_dup(np->u.func.arglist, ex, events), 10190Sstevel@tonic-gate np->file, np->line)); 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate case T_QUOTE: 10220Sstevel@tonic-gate newnp = newnode(T_QUOTE, np->file, np->line); 10230Sstevel@tonic-gate newnp->u.quote.s = np->u.quote.s; 10240Sstevel@tonic-gate return (newnp); 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate case T_NUM: 10270Sstevel@tonic-gate newnp = newnode(T_NUM, np->file, np->line); 10280Sstevel@tonic-gate newnp->u.ull = np->u.ull; 10290Sstevel@tonic-gate return (newnp); 10300Sstevel@tonic-gate 1031*7197Sstephh case T_TIMEVAL: 1032*7197Sstephh newnp = newnode(T_TIMEVAL, np->file, np->line); 1033*7197Sstephh newnp->u.ull = np->u.ull; 1034*7197Sstephh return (newnp); 1035*7197Sstephh 10360Sstevel@tonic-gate default: 10370Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 10380Sstevel@tonic-gate "eval_dup: unexpected node type: %s", 10390Sstevel@tonic-gate ptree_nodetype2str(np->t)); 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate /*NOTREACHED*/ 10421717Swesolows return (0); 10430Sstevel@tonic-gate } 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate /* 10460Sstevel@tonic-gate * eval_potential -- see if constraint is potentially true 10470Sstevel@tonic-gate * 10480Sstevel@tonic-gate * this function is used at instance tree creation time to see if 10490Sstevel@tonic-gate * any constraints are already known to be false. if this function 10500Sstevel@tonic-gate * returns false, then the constraint will always be false and there's 10510Sstevel@tonic-gate * no need to include the propagation arrow in the instance tree. 10520Sstevel@tonic-gate * 10530Sstevel@tonic-gate * if this routine returns true, either the constraint is known to 10540Sstevel@tonic-gate * be always true (so there's no point in attaching the constraint 10550Sstevel@tonic-gate * to the propagation arrow in the instance tree), or the constraint 10560Sstevel@tonic-gate * contains "deferred" expressions like global variables or poller calls 10570Sstevel@tonic-gate * and so it must be evaluated during calls to fme_eval(). in this last 10580Sstevel@tonic-gate * case, where a constraint needs to be attached to the propagation arrow 10590Sstevel@tonic-gate * in the instance tree, this routine returns a newly created constraint 10600Sstevel@tonic-gate * in *newc where all the non-deferred things have been filled in. 10610Sstevel@tonic-gate * 10620Sstevel@tonic-gate * so in summary: 10630Sstevel@tonic-gate * 10640Sstevel@tonic-gate * return of false: constraint can never be true, *newc will be NULL. 10650Sstevel@tonic-gate * 10660Sstevel@tonic-gate * return of true with *newc unchanged: constraint will always be true. 10670Sstevel@tonic-gate * 10680Sstevel@tonic-gate * return of true with *newc changed: use new constraint in *newc. 10690Sstevel@tonic-gate * 10700Sstevel@tonic-gate * the lookup table for all explicit iterators, ex, is passed in. 10710Sstevel@tonic-gate * 10720Sstevel@tonic-gate * *newc can either be NULL on entry, or if can contain constraints from 10730Sstevel@tonic-gate * previous calls to eval_potential() (i.e. for building up an instance 10740Sstevel@tonic-gate * tree constraint from several potential constraints). if *newc already 10750Sstevel@tonic-gate * contains constraints, anything added to it will be joined by adding 10760Sstevel@tonic-gate * a T_AND node at the top of *newc. 10770Sstevel@tonic-gate */ 10780Sstevel@tonic-gate int 10794436Sstephh eval_potential(struct node *np, struct lut *ex, struct node *events[], 10802318Sstephh struct node **newc, struct config *croot) 10810Sstevel@tonic-gate { 10820Sstevel@tonic-gate struct node *newnp; 10830Sstevel@tonic-gate struct evalue value; 10840Sstevel@tonic-gate 10854436Sstephh if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) { 10860Sstevel@tonic-gate /* 10870Sstevel@tonic-gate * couldn't eval expression because 10880Sstevel@tonic-gate * it contains deferred items. make 10890Sstevel@tonic-gate * a duplicate expression with all the 10900Sstevel@tonic-gate * non-deferred items expanded. 10910Sstevel@tonic-gate */ 10924436Sstephh newnp = eval_dup(np, ex, events); 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate if (*newc == NULL) { 10950Sstevel@tonic-gate /* 10960Sstevel@tonic-gate * constraint is potentially true if deferred 10970Sstevel@tonic-gate * expression in newnp is true. *newc was NULL 10980Sstevel@tonic-gate * so new constraint is just the one in newnp. 10990Sstevel@tonic-gate */ 11000Sstevel@tonic-gate *newc = newnp; 11010Sstevel@tonic-gate return (1); 11020Sstevel@tonic-gate } else { 11030Sstevel@tonic-gate /* 11040Sstevel@tonic-gate * constraint is potentially true if deferred 11050Sstevel@tonic-gate * expression in newnp is true. *newc already 11060Sstevel@tonic-gate * contained a constraint so add an AND with the 11070Sstevel@tonic-gate * constraint in newnp. 11080Sstevel@tonic-gate */ 11090Sstevel@tonic-gate *newc = tree_expr(T_AND, *newc, newnp); 11100Sstevel@tonic-gate return (1); 11110Sstevel@tonic-gate } 11120Sstevel@tonic-gate } else if (value.t == UNDEFINED) { 11130Sstevel@tonic-gate /* constraint can never be true */ 11140Sstevel@tonic-gate return (0); 11150Sstevel@tonic-gate } else if (value.t == UINT64 && value.v == 0) { 11160Sstevel@tonic-gate /* constraint can never be true */ 11170Sstevel@tonic-gate return (0); 11180Sstevel@tonic-gate } else { 11190Sstevel@tonic-gate /* constraint is always true (nothing deferred to eval) */ 11200Sstevel@tonic-gate return (1); 11210Sstevel@tonic-gate } 11220Sstevel@tonic-gate } 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate static int 11250Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype, 11260Sstevel@tonic-gate struct node *np) 11270Sstevel@tonic-gate { 11281414Scindi /* auto-convert T_NAMES to strings */ 11291717Swesolows if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t == 11301717Swesolows T_NAME) { 11311717Swesolows char *s = ipath2str(NULL, 11321717Swesolows ipath((struct node *)(uintptr_t)lp->v)); 11331414Scindi lp->t = STRING; 11341717Swesolows lp->v = (uintptr_t)stable(s); 11351414Scindi FREE(s); 11361414Scindi out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"", 11371717Swesolows (char *)(uintptr_t)lp->v); 11381414Scindi } 11391414Scindi if (rp != NULL && 11401717Swesolows rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t == 11411717Swesolows T_NAME) { 11421717Swesolows char *s = ipath2str(NULL, 11431717Swesolows ipath((struct node *)(uintptr_t)rp->v)); 11441414Scindi rp->t = STRING; 11451717Swesolows rp->v = (uintptr_t)stable(s); 11461414Scindi FREE(s); 11471414Scindi out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"", 11481717Swesolows (char *)(uintptr_t)rp->v); 11491414Scindi } 11501414Scindi 11511414Scindi /* auto-convert strings to numbers */ 11521414Scindi if (dtype == UINT64) { 11531414Scindi if (lp->t == STRING) { 11541414Scindi lp->t = UINT64; 11551717Swesolows lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0); 11561414Scindi } 11571414Scindi if (rp != NULL && rp->t == STRING) { 11581414Scindi rp->t = UINT64; 11591717Swesolows rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0); 11601414Scindi } 11611414Scindi } 11621414Scindi 11630Sstevel@tonic-gate if (dtype != UNDEFINED && lp->t != dtype) { 11644436Sstephh outfl(O_DIE, np->file, np->line, 11654436Sstephh "invalid datatype of argument for operation %s", 11664436Sstephh ptree_nodetype2str(np->t)); 11674436Sstephh /* NOTREACHED */ 11680Sstevel@tonic-gate return (1); 11690Sstevel@tonic-gate } 11700Sstevel@tonic-gate 11710Sstevel@tonic-gate if (rp != NULL && lp->t != rp->t) { 11724436Sstephh outfl(O_DIE, np->file, np->line, 11734436Sstephh "mismatch in datatype of arguments for operation %s", 11744436Sstephh ptree_nodetype2str(np->t)); 11754436Sstephh /* NOTREACHED */ 11760Sstevel@tonic-gate return (1); 11770Sstevel@tonic-gate } 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate return (0); 11800Sstevel@tonic-gate } 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate /* 11830Sstevel@tonic-gate * eval_expr -- evaluate expression into *valuep 11840Sstevel@tonic-gate * 11850Sstevel@tonic-gate * the meaning of the return value depends on the input value of try. 11860Sstevel@tonic-gate * 11870Sstevel@tonic-gate * for try == 1: if any deferred items are encounted, bail out and return 11880Sstevel@tonic-gate * false. returns true if we made it through entire expression without 11890Sstevel@tonic-gate * hitting any deferred items. 11900Sstevel@tonic-gate * 11910Sstevel@tonic-gate * for try == 0: return true if all operations were performed successfully. 11920Sstevel@tonic-gate * return false if otherwise. for example, any of the following conditions 11930Sstevel@tonic-gate * will result in a false return value: 11940Sstevel@tonic-gate * - attempted use of an uninitialized global variable 11950Sstevel@tonic-gate * - failure in function evaluation 11960Sstevel@tonic-gate * - illegal arithmetic operation (argument out of range) 11970Sstevel@tonic-gate */ 11980Sstevel@tonic-gate int 11994436Sstephh eval_expr(struct node *np, struct lut *ex, struct node *events[], 12000Sstevel@tonic-gate struct lut **globals, struct config *croot, struct arrow *arrowp, 12010Sstevel@tonic-gate int try, struct evalue *valuep) 12020Sstevel@tonic-gate { 12030Sstevel@tonic-gate struct evalue *gval; 12040Sstevel@tonic-gate struct evalue lval; 12050Sstevel@tonic-gate struct evalue rval; 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate if (np == NULL) { 12080Sstevel@tonic-gate valuep->t = UINT64; 12090Sstevel@tonic-gate valuep->v = 1; /* no constraint means "true" */ 12100Sstevel@tonic-gate return (1); 12110Sstevel@tonic-gate } 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate valuep->t = UNDEFINED; 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate switch (np->t) { 12160Sstevel@tonic-gate case T_GLOBID: 12170Sstevel@tonic-gate if (try) 12180Sstevel@tonic-gate return (0); 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate /* 12210Sstevel@tonic-gate * only handle case of getting (and not setting) the value 12220Sstevel@tonic-gate * of a global variable 12230Sstevel@tonic-gate */ 12240Sstevel@tonic-gate gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL); 12250Sstevel@tonic-gate if (gval == NULL) { 12260Sstevel@tonic-gate return (0); 12270Sstevel@tonic-gate } else { 12280Sstevel@tonic-gate valuep->t = gval->t; 12290Sstevel@tonic-gate valuep->v = gval->v; 12300Sstevel@tonic-gate return (1); 12310Sstevel@tonic-gate } 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate case T_ASSIGN: 12340Sstevel@tonic-gate if (try) 12350Sstevel@tonic-gate return (0); 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate /* 12380Sstevel@tonic-gate * first evaluate rhs, then try to store value in lhs which 12390Sstevel@tonic-gate * should be a global variable 12400Sstevel@tonic-gate */ 12414436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 12424436Sstephh arrowp, try, &rval)) 12430Sstevel@tonic-gate return (0); 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate ASSERT(np->u.expr.left->t == T_GLOBID); 12460Sstevel@tonic-gate gval = lut_lookup(*globals, 12474436Sstephh (void *)np->u.expr.left->u.globid.s, NULL); 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate if (gval == NULL) { 12500Sstevel@tonic-gate gval = MALLOC(sizeof (*gval)); 12510Sstevel@tonic-gate *globals = lut_add(*globals, 12524436Sstephh (void *) np->u.expr.left->u.globid.s, gval, NULL); 12530Sstevel@tonic-gate } 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate gval->t = rval.t; 12560Sstevel@tonic-gate gval->v = rval.v; 12571414Scindi 12581414Scindi if (gval->t == UINT64) { 12591414Scindi out(O_ALTFP|O_VERB2, 12601414Scindi "assign $%s=%llu", 12611414Scindi np->u.expr.left->u.globid.s, gval->v); 12621414Scindi } else { 12631414Scindi out(O_ALTFP|O_VERB2, 12641414Scindi "assign $%s=\"%s\"", 12651717Swesolows np->u.expr.left->u.globid.s, 12661717Swesolows (char *)(uintptr_t)gval->v); 12671414Scindi } 12681414Scindi 12691414Scindi /* 12701414Scindi * but always return true -- an assignment should not 12711414Scindi * cause a constraint to be false. 12721414Scindi */ 12731414Scindi valuep->t = UINT64; 12741414Scindi valuep->v = 1; 12750Sstevel@tonic-gate return (1); 12760Sstevel@tonic-gate 12770Sstevel@tonic-gate case T_EQ: 12780Sstevel@tonic-gate #define IMPLICIT_ASSIGN_IN_EQ 12790Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ 12800Sstevel@tonic-gate /* 12810Sstevel@tonic-gate * if lhs is an uninitialized global variable, perform 12820Sstevel@tonic-gate * an assignment. 12830Sstevel@tonic-gate * 12840Sstevel@tonic-gate * one insidious side effect of implicit assignment is 12850Sstevel@tonic-gate * that the "==" operator does not return a Boolean if 12860Sstevel@tonic-gate * implicit assignment was performed. 12870Sstevel@tonic-gate */ 12880Sstevel@tonic-gate if (try == 0 && 12890Sstevel@tonic-gate np->u.expr.left->t == T_GLOBID && 12900Sstevel@tonic-gate (gval = lut_lookup(*globals, 12914436Sstephh (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) { 12924436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 12934436Sstephh croot, arrowp, try, &rval)) 12940Sstevel@tonic-gate return (0); 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate gval = MALLOC(sizeof (*gval)); 12970Sstevel@tonic-gate *globals = lut_add(*globals, 12984436Sstephh (void *) np->u.expr.left->u.globid.s, 12994436Sstephh gval, NULL); 13000Sstevel@tonic-gate 13010Sstevel@tonic-gate gval->t = rval.t; 13020Sstevel@tonic-gate gval->v = rval.v; 13030Sstevel@tonic-gate valuep->t = rval.t; 13040Sstevel@tonic-gate valuep->v = rval.v; 13050Sstevel@tonic-gate return (1); 13060Sstevel@tonic-gate } 13070Sstevel@tonic-gate #endif /* IMPLICIT_ASSIGN_IN_EQ */ 13080Sstevel@tonic-gate 13094436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13104436Sstephh arrowp, try, &lval)) 13114436Sstephh return (0); 13124436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13134436Sstephh arrowp, try, &rval)) 13140Sstevel@tonic-gate return (0); 13154436Sstephh if (rval.t == UINT64 || lval.t == UINT64) { 13164436Sstephh if (check_expr_args(&lval, &rval, UINT64, np)) 13174436Sstephh return (0); 13184436Sstephh } else { 13194436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np)) 13204436Sstephh return (0); 13214436Sstephh } 13220Sstevel@tonic-gate 13230Sstevel@tonic-gate valuep->t = UINT64; 13240Sstevel@tonic-gate valuep->v = (lval.v == rval.v); 13250Sstevel@tonic-gate return (1); 13260Sstevel@tonic-gate 13270Sstevel@tonic-gate case T_LT: 13284436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13294436Sstephh arrowp, try, &lval)) 13300Sstevel@tonic-gate return (0); 13314436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13324436Sstephh arrowp, try, &rval)) 13330Sstevel@tonic-gate return (0); 13341414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 13350Sstevel@tonic-gate return (0); 13360Sstevel@tonic-gate 13370Sstevel@tonic-gate valuep->t = UINT64; 13380Sstevel@tonic-gate valuep->v = (lval.v < rval.v); 13390Sstevel@tonic-gate return (1); 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate case T_LE: 13424436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 13434436Sstephh arrowp, try, &lval)) 13440Sstevel@tonic-gate return (0); 13454436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 13464436Sstephh arrowp, try, &rval)) 13470Sstevel@tonic-gate return (0); 13481414Scindi if (check_expr_args(&lval, &rval, UINT64, np)) 13490Sstevel@tonic-gate return (0); 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_GT: 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_GE: 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_BITAND: 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); 13900Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 13910Sstevel@tonic-gate return (0); 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate valuep->t = lval.t; 13940Sstevel@tonic-gate valuep->v = (lval.v & rval.v); 13950Sstevel@tonic-gate return (1); 13960Sstevel@tonic-gate 13970Sstevel@tonic-gate case T_BITOR: 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); 14040Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14050Sstevel@tonic-gate return (0); 14060Sstevel@tonic-gate 14070Sstevel@tonic-gate valuep->t = lval.t; 14080Sstevel@tonic-gate valuep->v = (lval.v | rval.v); 14090Sstevel@tonic-gate return (1); 14100Sstevel@tonic-gate 14110Sstevel@tonic-gate case T_BITXOR: 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_BITNOT: 14264436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14274436Sstephh arrowp, try, &lval)) 14280Sstevel@tonic-gate return (0); 14290Sstevel@tonic-gate ASSERT(np->u.expr.right == NULL); 14300Sstevel@tonic-gate if (check_expr_args(&lval, NULL, UINT64, np)) 14310Sstevel@tonic-gate return (0); 14320Sstevel@tonic-gate 14330Sstevel@tonic-gate valuep->t = UINT64; 14340Sstevel@tonic-gate valuep->v = ~ lval.v; 14350Sstevel@tonic-gate return (1); 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate case T_LSHIFT: 14384436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14394436Sstephh arrowp, try, &lval)) 14400Sstevel@tonic-gate return (0); 14414436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14424436Sstephh arrowp, try, &rval)) 14430Sstevel@tonic-gate return (0); 14440Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14450Sstevel@tonic-gate return (0); 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate valuep->t = UINT64; 14480Sstevel@tonic-gate valuep->v = (lval.v << rval.v); 14490Sstevel@tonic-gate return (1); 14500Sstevel@tonic-gate 14510Sstevel@tonic-gate case T_RSHIFT: 14524436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14534436Sstephh arrowp, try, &lval)) 14540Sstevel@tonic-gate return (0); 14554436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 14564436Sstephh arrowp, try, &rval)) 14570Sstevel@tonic-gate return (0); 14580Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 14590Sstevel@tonic-gate return (0); 14600Sstevel@tonic-gate 14610Sstevel@tonic-gate valuep->t = UINT64; 14620Sstevel@tonic-gate valuep->v = (lval.v >> rval.v); 14630Sstevel@tonic-gate return (1); 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate case T_CONDIF: { 14660Sstevel@tonic-gate struct node *retnp; 14670Sstevel@tonic-gate int dotrue = 0; 14680Sstevel@tonic-gate 14690Sstevel@tonic-gate /* 14700Sstevel@tonic-gate * evaluate 14710Sstevel@tonic-gate * expression ? stmtA [ : stmtB ] 14720Sstevel@tonic-gate * 14730Sstevel@tonic-gate * first see if expression is true or false, then determine 14740Sstevel@tonic-gate * if stmtA (or stmtB, if it exists) should be evaluated. 14750Sstevel@tonic-gate * 14760Sstevel@tonic-gate * "dotrue = 1" means stmtA should be evaluated. 14770Sstevel@tonic-gate */ 14785204Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 14795204Sstephh arrowp, try, &lval)) 14805204Sstephh return (0); 14815204Sstephh 14825204Sstephh if (lval.t != UNDEFINED && lval.v != 0) 14830Sstevel@tonic-gate dotrue = 1; 14840Sstevel@tonic-gate 14850Sstevel@tonic-gate ASSERT(np->u.expr.right != NULL); 14860Sstevel@tonic-gate if (np->u.expr.right->t == T_CONDELSE) { 14870Sstevel@tonic-gate if (dotrue) 14880Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.left; 14890Sstevel@tonic-gate else 14900Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.right; 14910Sstevel@tonic-gate } else { 14920Sstevel@tonic-gate /* no ELSE clause */ 14930Sstevel@tonic-gate if (dotrue) 14940Sstevel@tonic-gate retnp = np->u.expr.right; 14950Sstevel@tonic-gate else { 14964436Sstephh outfl(O_DIE, np->file, np->line, 14974436Sstephh "eval_expr: missing condelse"); 14980Sstevel@tonic-gate } 14990Sstevel@tonic-gate } 15000Sstevel@tonic-gate 15014436Sstephh if (!eval_expr(retnp, ex, events, globals, croot, 15024436Sstephh arrowp, try, valuep)) 15030Sstevel@tonic-gate return (0); 15040Sstevel@tonic-gate return (1); 15050Sstevel@tonic-gate } 15060Sstevel@tonic-gate 15070Sstevel@tonic-gate case T_CONDELSE: 15080Sstevel@tonic-gate /* 15090Sstevel@tonic-gate * shouldn't get here, since T_CONDELSE is supposed to be 15100Sstevel@tonic-gate * evaluated as part of T_CONDIF 15110Sstevel@tonic-gate */ 15120Sstevel@tonic-gate out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s", 15130Sstevel@tonic-gate ptree_nodetype2str(np->t)); 15144436Sstephh /*NOTREACHED*/ 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate case T_NE: 15174436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15184436Sstephh arrowp, try, &lval)) 15194436Sstephh return (0); 15204436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15214436Sstephh arrowp, try, &rval)) 15220Sstevel@tonic-gate return (0); 15234436Sstephh if (rval.t == UINT64 || lval.t == UINT64) { 15244436Sstephh if (check_expr_args(&lval, &rval, UINT64, np)) 15254436Sstephh return (0); 15264436Sstephh } else { 15274436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np)) 15284436Sstephh return (0); 15294436Sstephh } 15300Sstevel@tonic-gate 15310Sstevel@tonic-gate valuep->t = UINT64; 15320Sstevel@tonic-gate valuep->v = (lval.v != rval.v); 15330Sstevel@tonic-gate return (1); 15340Sstevel@tonic-gate 15350Sstevel@tonic-gate case T_LIST: 15360Sstevel@tonic-gate case T_AND: 15374436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15384436Sstephh arrowp, try, valuep)) { 15393159Sstephh /* 15403159Sstephh * if lhs is unknown, still check rhs. If that 15415204Sstephh * is false we can return false irrespective of lhs 15423159Sstephh */ 15435204Sstephh if (!try) { 15445204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 15455204Sstephh return (0); 15465204Sstephh } 15474436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 15484436Sstephh croot, arrowp, try, valuep)) { 15494436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 15503159Sstephh return (0); 15514436Sstephh } 15524436Sstephh if (valuep->v != 0) { 15534436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK; 15543159Sstephh return (0); 15554436Sstephh } 15563159Sstephh } 15570Sstevel@tonic-gate if (valuep->v == 0) { 15580Sstevel@tonic-gate valuep->t = UINT64; 15590Sstevel@tonic-gate return (1); 15600Sstevel@tonic-gate } 15614436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15624436Sstephh arrowp, try, valuep)) { 15634436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK; 15640Sstevel@tonic-gate return (0); 15654436Sstephh } 15660Sstevel@tonic-gate valuep->t = UINT64; 15670Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1; 15680Sstevel@tonic-gate return (1); 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate case T_OR: 15714436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 15724436Sstephh arrowp, try, valuep)) { 15733159Sstephh /* 15743159Sstephh * if lhs is unknown, still check rhs. If that 15755204Sstephh * is true we can return true irrespective of lhs 15763159Sstephh */ 15775204Sstephh if (!try) { 15785204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 15795204Sstephh return (0); 15805204Sstephh } 15814436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, 15824436Sstephh croot, arrowp, try, valuep)) { 15834436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK; 15843159Sstephh return (0); 15854436Sstephh } 15864436Sstephh if (valuep->v == 0) { 15874436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK; 15883159Sstephh return (0); 15894436Sstephh } 15903159Sstephh } 15910Sstevel@tonic-gate if (valuep->v != 0) { 15920Sstevel@tonic-gate valuep->t = UINT64; 15930Sstevel@tonic-gate valuep->v = 1; 15940Sstevel@tonic-gate return (1); 15950Sstevel@tonic-gate } 15964436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 15974436Sstephh arrowp, try, valuep)) { 15984436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK; 15990Sstevel@tonic-gate return (0); 16004436Sstephh } 16010Sstevel@tonic-gate valuep->t = UINT64; 16020Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1; 16030Sstevel@tonic-gate return (1); 16040Sstevel@tonic-gate 16050Sstevel@tonic-gate case T_NOT: 16064436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16074436Sstephh arrowp, try, valuep)) 16080Sstevel@tonic-gate return (0); 16090Sstevel@tonic-gate valuep->t = UINT64; 16100Sstevel@tonic-gate valuep->v = ! valuep->v; 16110Sstevel@tonic-gate return (1); 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate case T_ADD: 16144436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16154436Sstephh arrowp, try, &lval)) 16160Sstevel@tonic-gate return (0); 16174436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16184436Sstephh arrowp, try, &rval)) 16190Sstevel@tonic-gate return (0); 16200Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16210Sstevel@tonic-gate return (0); 16220Sstevel@tonic-gate 16230Sstevel@tonic-gate valuep->t = lval.t; 16240Sstevel@tonic-gate valuep->v = lval.v + rval.v; 16250Sstevel@tonic-gate return (1); 16260Sstevel@tonic-gate 16270Sstevel@tonic-gate case T_SUB: 16284436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16294436Sstephh arrowp, try, &lval)) 16300Sstevel@tonic-gate return (0); 16314436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16324436Sstephh arrowp, try, &rval)) 16330Sstevel@tonic-gate return (0); 16340Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16350Sstevel@tonic-gate return (0); 16360Sstevel@tonic-gate 16370Sstevel@tonic-gate /* since valuep is unsigned, return false if lval.v < rval.v */ 16380Sstevel@tonic-gate if (lval.v < rval.v) { 16394436Sstephh outfl(O_DIE, np->file, np->line, 16404436Sstephh "eval_expr: T_SUB result is out of range"); 16410Sstevel@tonic-gate } 16420Sstevel@tonic-gate 16430Sstevel@tonic-gate valuep->t = lval.t; 16440Sstevel@tonic-gate valuep->v = lval.v - rval.v; 16450Sstevel@tonic-gate return (1); 16460Sstevel@tonic-gate 16470Sstevel@tonic-gate case T_MUL: 16484436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16494436Sstephh arrowp, try, &lval)) 16500Sstevel@tonic-gate return (0); 16514436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16524436Sstephh arrowp, try, &rval)) 16530Sstevel@tonic-gate return (0); 16540Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16550Sstevel@tonic-gate return (0); 16560Sstevel@tonic-gate 16570Sstevel@tonic-gate valuep->t = lval.t; 16580Sstevel@tonic-gate valuep->v = lval.v * rval.v; 16590Sstevel@tonic-gate return (1); 16600Sstevel@tonic-gate 16610Sstevel@tonic-gate case T_DIV: 16624436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16634436Sstephh arrowp, try, &lval)) 16640Sstevel@tonic-gate return (0); 16654436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16664436Sstephh arrowp, try, &rval)) 16670Sstevel@tonic-gate return (0); 16680Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16690Sstevel@tonic-gate return (0); 16700Sstevel@tonic-gate 16710Sstevel@tonic-gate /* return false if dividing by zero */ 16720Sstevel@tonic-gate if (rval.v == 0) { 16734436Sstephh outfl(O_DIE, np->file, np->line, 16744436Sstephh "eval_expr: T_DIV division by zero"); 16750Sstevel@tonic-gate } 16760Sstevel@tonic-gate 16770Sstevel@tonic-gate valuep->t = lval.t; 16780Sstevel@tonic-gate valuep->v = lval.v / rval.v; 16790Sstevel@tonic-gate return (1); 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate case T_MOD: 16824436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot, 16834436Sstephh arrowp, try, &lval)) 16840Sstevel@tonic-gate return (0); 16854436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot, 16864436Sstephh arrowp, try, &rval)) 16870Sstevel@tonic-gate return (0); 16880Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np)) 16890Sstevel@tonic-gate return (0); 16900Sstevel@tonic-gate 16910Sstevel@tonic-gate /* return false if dividing by zero */ 16920Sstevel@tonic-gate if (rval.v == 0) { 16934436Sstephh outfl(O_DIE, np->file, np->line, 16944436Sstephh "eval_expr: T_MOD division by zero"); 16950Sstevel@tonic-gate } 16960Sstevel@tonic-gate 16970Sstevel@tonic-gate valuep->t = lval.t; 16980Sstevel@tonic-gate valuep->v = lval.v % rval.v; 16990Sstevel@tonic-gate return (1); 17000Sstevel@tonic-gate 17010Sstevel@tonic-gate case T_NAME: 17020Sstevel@tonic-gate if (try) { 17030Sstevel@tonic-gate struct iterinfo *iterinfop; 17044436Sstephh struct node *np1, *np2; 17054436Sstephh int i, gotmatch = 0; 17060Sstevel@tonic-gate 17070Sstevel@tonic-gate /* 17084436Sstephh * Check if we have an exact match of the nonwildcarded 17094436Sstephh * path in oldepname - if so we can just use the 17104436Sstephh * full wildcarded path in epname. 17110Sstevel@tonic-gate */ 17124436Sstephh for (i = 0; i < 1; i++) { 17134436Sstephh for (np1 = np, 17144436Sstephh np2 = events[i]->u.event.oldepname; 17154436Sstephh np1 != NULL && np2 != NULL; 17164436Sstephh np1 = np1->u.name.next, 17174436Sstephh np2 = np2->u.name.next) { 17184436Sstephh if (strcmp(np1->u.name.s, 17194436Sstephh np2->u.name.s) != 0) 17204436Sstephh break; 17214436Sstephh if (np1->u.name.child->t != 17224436Sstephh np2->u.name.child->t) 17234436Sstephh break; 17244436Sstephh if (np1->u.name.child->t == T_NUM && 17254436Sstephh np1->u.name.child->u.ull != 17264436Sstephh np2->u.name.child->u.ull) 17274436Sstephh break; 17284436Sstephh if (np1->u.name.child->t == T_NAME && 17294436Sstephh strcmp(np1->u.name.child->u.name.s, 17304436Sstephh np2->u.name.child->u.name.s) != 0) 17314436Sstephh break; 17324436Sstephh gotmatch++; 17334436Sstephh } 17344436Sstephh if (np1 == NULL && np2 == NULL) { 17354436Sstephh valuep->t = NODEPTR; 17364436Sstephh valuep->v = (uintptr_t) 17374436Sstephh events[i]->u.event.epname; 17384436Sstephh return (1); 17394436Sstephh } 17400Sstevel@tonic-gate } 17414436Sstephh if (!gotmatch) { 17424436Sstephh /* 17434436Sstephh * we're not wildcarding. However at 17444436Sstephh * itree_create() time, we can also expand 17454436Sstephh * simple iterators - so check for those. 17464436Sstephh */ 17474436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, 17484436Sstephh NULL); 17494436Sstephh if (iterinfop != NULL) { 17504436Sstephh valuep->t = UINT64; 17514436Sstephh valuep->v = 17524436Sstephh (unsigned long long)iterinfop->num; 17534436Sstephh return (1); 17544436Sstephh } 17554436Sstephh } 17564436Sstephh /* 17574436Sstephh * For anything else we'll have to wait for eval_dup(). 17584436Sstephh */ 17590Sstevel@tonic-gate return (0); 17600Sstevel@tonic-gate } 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate /* return address of struct node */ 17630Sstevel@tonic-gate valuep->t = NODEPTR; 17641717Swesolows valuep->v = (uintptr_t)np; 17650Sstevel@tonic-gate return (1); 17660Sstevel@tonic-gate 17670Sstevel@tonic-gate case T_QUOTE: 17680Sstevel@tonic-gate valuep->t = STRING; 17691717Swesolows valuep->v = (uintptr_t)np->u.quote.s; 17700Sstevel@tonic-gate return (1); 17710Sstevel@tonic-gate 17720Sstevel@tonic-gate case T_FUNC: 17734436Sstephh return (eval_func(np, ex, events, np->u.func.arglist, 17744436Sstephh globals, croot, arrowp, try, valuep)); 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate case T_NUM: 1777*7197Sstephh case T_TIMEVAL: 17780Sstevel@tonic-gate valuep->t = UINT64; 17790Sstevel@tonic-gate valuep->v = np->u.ull; 17800Sstevel@tonic-gate return (1); 17810Sstevel@tonic-gate 17820Sstevel@tonic-gate default: 17830Sstevel@tonic-gate outfl(O_DIE, np->file, np->line, 17840Sstevel@tonic-gate "eval_expr: unexpected node type: %s", 17850Sstevel@tonic-gate ptree_nodetype2str(np->t)); 17860Sstevel@tonic-gate } 17870Sstevel@tonic-gate /*NOTREACHED*/ 17881717Swesolows return (0); 17890Sstevel@tonic-gate } 17900Sstevel@tonic-gate 17910Sstevel@tonic-gate /* 17920Sstevel@tonic-gate * eval_fru() and eval_asru() don't do much, but are called from a number 17930Sstevel@tonic-gate * of places. 17940Sstevel@tonic-gate */ 17954436Sstephh static struct node * 17960Sstevel@tonic-gate eval_fru(struct node *np) 17970Sstevel@tonic-gate { 17980Sstevel@tonic-gate ASSERT(np->t == T_NAME); 17990Sstevel@tonic-gate return (np); 18000Sstevel@tonic-gate } 18010Sstevel@tonic-gate 18024436Sstephh static struct node * 18030Sstevel@tonic-gate eval_asru(struct node *np) 18040Sstevel@tonic-gate { 18050Sstevel@tonic-gate ASSERT(np->t == T_NAME); 18060Sstevel@tonic-gate return (np); 18070Sstevel@tonic-gate } 1808