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*11416SStephen.Hanson@Sun.COM * Copyright 2010 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
begins_with(struct node * lhs,struct node * rhs,struct lut * ex)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 *
eval_getname(struct node * funcnp,struct lut * ex,struct node * events[],struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,int * dupedp)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;
12811202SStephen.Hanson@Sun.COM else if (np->t == T_FUNC && np->u.func.s == L_fru)
1294436Sstephh nodep = eval_fru(np->u.func.arglist);
13011202SStephen.Hanson@Sun.COM else if (np->t == T_FUNC && np->u.func.s == L_asru)
1314436Sstephh nodep = eval_asru(np->u.func.arglist);
13211202SStephen.Hanson@Sun.COM else if (np->t == T_FUNC) {
13311202SStephen.Hanson@Sun.COM if (eval_expr(np, ex, events, globals, croot, arrowp, try,
13411202SStephen.Hanson@Sun.COM &val) == 0)
13511202SStephen.Hanson@Sun.COM /*
13611202SStephen.Hanson@Sun.COM * Can't evaluate yet. Return null so constraint is
13711202SStephen.Hanson@Sun.COM * deferred.
13811202SStephen.Hanson@Sun.COM */
13911202SStephen.Hanson@Sun.COM return (NULL);
14011202SStephen.Hanson@Sun.COM if (val.t == NODEPTR)
14111202SStephen.Hanson@Sun.COM return ((struct node *)(uintptr_t)val.v);
14211202SStephen.Hanson@Sun.COM else
14311202SStephen.Hanson@Sun.COM /*
14411202SStephen.Hanson@Sun.COM * just return the T_FUNC - which the caller will
14511202SStephen.Hanson@Sun.COM * reject.
14611202SStephen.Hanson@Sun.COM */
14711202SStephen.Hanson@Sun.COM return (np);
14811202SStephen.Hanson@Sun.COM } else
1494436Sstephh out(O_DIE, "%s: unexpected type: %s",
1504436Sstephh funcname, ptree_nodetype2str(np->t));
1514436Sstephh if (try) {
1524436Sstephh if (eval_expr(nodep, ex, events, globals, croot,
1534436Sstephh arrowp, try, &val) && val.t == NODEPTR)
1544436Sstephh nodep = (struct node *)(uintptr_t)val.v;
1554436Sstephh else {
1564436Sstephh *dupedp = 1;
1574436Sstephh nodep = eval_dup(nodep, ex, events);
1584436Sstephh }
1594436Sstephh }
1604436Sstephh return (nodep);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate
16311202SStephen.Hanson@Sun.COM /*ARGSUSED*/
16411202SStephen.Hanson@Sun.COM static int
eval_cat(struct node * np,struct lut * ex,struct node * events[],struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,struct evalue * valuep)16511202SStephen.Hanson@Sun.COM eval_cat(struct node *np, struct lut *ex, struct node *events[],
16611202SStephen.Hanson@Sun.COM struct lut **globals, struct config *croot, struct arrow *arrowp,
16711202SStephen.Hanson@Sun.COM int try, struct evalue *valuep)
16811202SStephen.Hanson@Sun.COM {
16911202SStephen.Hanson@Sun.COM if (np->t == T_LIST) {
17011202SStephen.Hanson@Sun.COM struct evalue lval;
17111202SStephen.Hanson@Sun.COM struct evalue rval;
17211202SStephen.Hanson@Sun.COM int len;
17311202SStephen.Hanson@Sun.COM char *s;
17411202SStephen.Hanson@Sun.COM
17511202SStephen.Hanson@Sun.COM if (!eval_cat(np->u.expr.left, ex, events, globals, croot,
17611202SStephen.Hanson@Sun.COM arrowp, try, &lval))
17711202SStephen.Hanson@Sun.COM return (0);
17811202SStephen.Hanson@Sun.COM if (!eval_cat(np->u.expr.right, ex, events, globals, croot,
17911202SStephen.Hanson@Sun.COM arrowp, try, &rval))
18011202SStephen.Hanson@Sun.COM return (0);
18111202SStephen.Hanson@Sun.COM len = snprintf(NULL, 0, "%s%s", (char *)(uintptr_t)lval.v,
18211202SStephen.Hanson@Sun.COM (char *)(uintptr_t)rval.v);
18311202SStephen.Hanson@Sun.COM s = MALLOC(len + 1);
18411202SStephen.Hanson@Sun.COM
18511202SStephen.Hanson@Sun.COM (void) snprintf(s, len + 1, "%s%s", (char *)(uintptr_t)lval.v,
18611202SStephen.Hanson@Sun.COM (char *)(uintptr_t)rval.v);
18711202SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2, np->file, np->line,
18811202SStephen.Hanson@Sun.COM "eval_cat: %s %s returns %s", (char *)(uintptr_t)lval.v,
18911202SStephen.Hanson@Sun.COM (char *)(uintptr_t)rval.v, s);
19011202SStephen.Hanson@Sun.COM valuep->t = STRING;
19111202SStephen.Hanson@Sun.COM valuep->v = (uintptr_t)stable(s);
19211202SStephen.Hanson@Sun.COM FREE(s);
19311202SStephen.Hanson@Sun.COM } else {
19411202SStephen.Hanson@Sun.COM if (!eval_expr(np, ex, events, globals, croot,
19511202SStephen.Hanson@Sun.COM arrowp, try, valuep))
19611202SStephen.Hanson@Sun.COM return (0);
19711202SStephen.Hanson@Sun.COM if (check_expr_args(valuep, NULL, STRING, np))
19811202SStephen.Hanson@Sun.COM return (0);
19911202SStephen.Hanson@Sun.COM }
20011202SStephen.Hanson@Sun.COM return (1);
20111202SStephen.Hanson@Sun.COM }
20211202SStephen.Hanson@Sun.COM
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate * evaluate a variety of functions and place result in valuep. return 1 if
2050Sstevel@tonic-gate * function evaluation was successful; 0 if otherwise (e.g., the case of an
2060Sstevel@tonic-gate * invalid argument to the function)
2070Sstevel@tonic-gate */
2080Sstevel@tonic-gate /*ARGSUSED*/
2090Sstevel@tonic-gate static int
eval_func(struct node * funcnp,struct lut * ex,struct node * events[],struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,struct evalue * valuep)2104436Sstephh eval_func(struct node *funcnp, struct lut *ex, struct node *events[],
2110Sstevel@tonic-gate struct node *np, struct lut **globals,
2120Sstevel@tonic-gate struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate const char *funcname = funcnp->u.func.s;
2154436Sstephh int duped_lhs = 0, duped_rhs = 0, duped = 0;
2164436Sstephh struct node *lhs;
2174436Sstephh struct node *rhs;
2184436Sstephh struct config *cp;
2194436Sstephh struct node *nodep;
2204436Sstephh char *path;
2214436Sstephh struct evalue val;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate if (funcname == L_within) {
2240Sstevel@tonic-gate /* within()'s are not really constraints -- always true */
2250Sstevel@tonic-gate valuep->t = UINT64;
2260Sstevel@tonic-gate valuep->v = 1;
2270Sstevel@tonic-gate return (1);
2280Sstevel@tonic-gate } else if (funcname == L_is_under) {
2294436Sstephh lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
2304436Sstephh croot, arrowp, try, &duped_lhs);
2314436Sstephh rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
2324436Sstephh globals, croot, arrowp, try, &duped_rhs);
23311202SStephen.Hanson@Sun.COM if (!rhs || !lhs)
23411202SStephen.Hanson@Sun.COM return (0);
23511202SStephen.Hanson@Sun.COM if (rhs->t != T_NAME || lhs->t != T_NAME) {
23611202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
23711202SStephen.Hanson@Sun.COM return (1);
23811202SStephen.Hanson@Sun.COM }
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate valuep->t = UINT64;
2414436Sstephh valuep->v = begins_with(lhs, rhs, ex);
2420Sstevel@tonic-gate out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
2430Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
2440Sstevel@tonic-gate out(O_ALTFP|O_VERB2|O_NONL, ",");
2450Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
2464436Sstephh out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v);
2470Sstevel@tonic-gate
2484436Sstephh if (duped_lhs)
2494436Sstephh tree_free(lhs);
2504436Sstephh if (duped_rhs)
2514436Sstephh tree_free(rhs);
2520Sstevel@tonic-gate return (1);
2532869Sgavinm } else if (funcname == L_confprop || funcname == L_confprop_defined) {
2542318Sstephh const char *s;
2552318Sstephh
2562318Sstephh /* for now s will point to a quote [see addconfigprop()] */
2572318Sstephh ASSERT(np->u.expr.right->t == T_QUOTE);
2582318Sstephh
2594436Sstephh nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
2604436Sstephh globals, croot, arrowp, try, &duped);
26111202SStephen.Hanson@Sun.COM if (!nodep)
26211202SStephen.Hanson@Sun.COM return (0);
26311202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) {
26411202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
26511202SStephen.Hanson@Sun.COM return (1);
26611202SStephen.Hanson@Sun.COM }
26711202SStephen.Hanson@Sun.COM
2684436Sstephh if (nodep->u.name.last->u.name.cp != NULL) {
2694436Sstephh cp = nodep->u.name.last->u.name.cp;
2704436Sstephh } else {
2714436Sstephh path = ipath2str(NULL, ipath(nodep));
2724436Sstephh cp = config_lookup(croot, path, 0);
2734436Sstephh FREE((void *)path);
2744436Sstephh }
2752869Sgavinm if (cp == NULL) {
2764436Sstephh if (funcname == L_confprop) {
2774436Sstephh out(O_ALTFP|O_VERB3, "%s: path ", funcname);
2784436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
2794436Sstephh out(O_ALTFP|O_VERB3, " not found");
2804436Sstephh valuep->v = (uintptr_t)stable("");
2814436Sstephh valuep->t = STRING;
2824436Sstephh if (duped)
2834436Sstephh tree_free(nodep);
2844436Sstephh return (1);
2854436Sstephh } else {
2862869Sgavinm valuep->v = 0;
2872869Sgavinm valuep->t = UINT64;
2884436Sstephh if (duped)
2894436Sstephh tree_free(nodep);
2902869Sgavinm return (1);
2912869Sgavinm }
2922869Sgavinm }
2932318Sstephh s = config_getprop(cp, np->u.expr.right->u.quote.s);
2944436Sstephh if (s == NULL && strcmp(np->u.expr.right->u.quote.s,
2954436Sstephh "class-code") == 0)
2964436Sstephh s = config_getprop(cp, "CLASS-CODE");
2972869Sgavinm if (s == NULL) {
2984436Sstephh if (funcname == L_confprop) {
2994436Sstephh out(O_ALTFP|O_VERB3|O_NONL,
3004436Sstephh "%s: \"%s\" not found for path ",
3014436Sstephh funcname, np->u.expr.right->u.quote.s);
3024436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
3034436Sstephh valuep->v = (uintptr_t)stable("");
3044436Sstephh valuep->t = STRING;
3054436Sstephh if (duped)
3064436Sstephh tree_free(nodep);
3074436Sstephh return (1);
3084436Sstephh } else {
3092869Sgavinm valuep->v = 0;
3102869Sgavinm valuep->t = UINT64;
3114436Sstephh if (duped)
3124436Sstephh tree_free(nodep);
3132869Sgavinm return (1);
3142869Sgavinm }
3152869Sgavinm }
3162869Sgavinm
3172869Sgavinm if (funcname == L_confprop) {
3182869Sgavinm valuep->v = (uintptr_t)stable(s);
3192869Sgavinm valuep->t = STRING;
3204436Sstephh out(O_ALTFP|O_VERB3|O_NONL, " %s(\"", funcname);
3214436Sstephh ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
3224436Sstephh out(O_ALTFP|O_VERB3|O_NONL,
3234436Sstephh "\", \"%s\") = \"%s\" ",
3244436Sstephh np->u.expr.right->u.quote.s,
3252869Sgavinm (char *)(uintptr_t)valuep->v);
3262869Sgavinm } else {
3272869Sgavinm valuep->v = 1;
3282869Sgavinm valuep->t = UINT64;
3292869Sgavinm }
3304436Sstephh if (duped)
3314436Sstephh tree_free(nodep);
3324436Sstephh return (1);
3334436Sstephh } else if (funcname == L_is_connected) {
3344436Sstephh const char *connstrings[] = { "connected", "CONNECTED", NULL };
3354436Sstephh struct config *cp[2];
3364436Sstephh const char *matchthis[2], *s;
3374436Sstephh char *nameslist, *w;
3384436Sstephh int i, j;
3394436Sstephh
3404436Sstephh lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
3414436Sstephh croot, arrowp, try, &duped_lhs);
3424436Sstephh rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
3434436Sstephh globals, croot, arrowp, try, &duped_rhs);
34411202SStephen.Hanson@Sun.COM if (!rhs || !lhs)
34511202SStephen.Hanson@Sun.COM return (0);
34611202SStephen.Hanson@Sun.COM if (rhs->t != T_NAME || lhs->t != T_NAME) {
34711202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
34811202SStephen.Hanson@Sun.COM return (1);
34911202SStephen.Hanson@Sun.COM }
35011202SStephen.Hanson@Sun.COM
3514436Sstephh path = ipath2str(NULL, ipath(lhs));
3524436Sstephh matchthis[1] = stable(path);
3534436Sstephh if (lhs->u.name.last->u.name.cp != NULL)
3544436Sstephh cp[0] = lhs->u.name.last->u.name.cp;
3554436Sstephh else
3564436Sstephh cp[0] = config_lookup(croot, path, 0);
3572869Sgavinm FREE((void *)path);
3584436Sstephh path = ipath2str(NULL, ipath(rhs));
3594436Sstephh matchthis[0] = stable(path);
3604436Sstephh if (rhs->u.name.last->u.name.cp != NULL)
3614436Sstephh cp[1] = rhs->u.name.last->u.name.cp;
3624436Sstephh else
3634436Sstephh cp[1] = config_lookup(croot, path, 0);
3644436Sstephh FREE((void *)path);
3654436Sstephh if (duped_lhs)
3664436Sstephh tree_free(lhs);
3674436Sstephh if (duped_rhs)
3684436Sstephh tree_free(rhs);
3694436Sstephh
3704436Sstephh valuep->t = UINT64;
3714436Sstephh valuep->v = 0;
3724436Sstephh if (cp[0] == NULL || cp[1] == NULL)
3734436Sstephh return (1);
3744436Sstephh
3754436Sstephh /* to thine self always be connected */
3764436Sstephh if (cp[0] == cp[1]) {
3774436Sstephh valuep->v = 1;
3784436Sstephh return (1);
3794436Sstephh }
3804436Sstephh
3814436Sstephh /*
3824436Sstephh * Extract "connected" property from each cp. Search this
3834436Sstephh * property for the name associated with the other cp[].
3844436Sstephh */
3854436Sstephh for (i = 0; i < 2 && valuep->v == 0; i++) {
3864436Sstephh for (j = 0; connstrings[j] != NULL && valuep->v == 0;
3874436Sstephh j++) {
3884436Sstephh s = config_getprop(cp[i],
3894436Sstephh stable(connstrings[j]));
3904436Sstephh if (s != NULL) {
3914436Sstephh nameslist = STRDUP(s);
3924436Sstephh w = strtok(nameslist, " ,");
3934436Sstephh while (w != NULL) {
3944436Sstephh if (stable(w) == matchthis[i]) {
3954436Sstephh valuep->v = 1;
3964436Sstephh break;
3974436Sstephh }
3984436Sstephh w = strtok(NULL, " ,");
3994436Sstephh }
4004436Sstephh FREE(nameslist);
4014436Sstephh }
4024436Sstephh }
4034436Sstephh }
4042318Sstephh return (1);
4054436Sstephh } else if (funcname == L_is_type) {
4064436Sstephh const char *typestrings[] = { "type", "TYPE", NULL };
4074436Sstephh const char *s;
4084436Sstephh int i;
4094436Sstephh
4104436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals,
4114436Sstephh croot, arrowp, try, &duped);
41211202SStephen.Hanson@Sun.COM if (!nodep)
41311202SStephen.Hanson@Sun.COM return (0);
41411202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) {
41511202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
41611202SStephen.Hanson@Sun.COM return (1);
41711202SStephen.Hanson@Sun.COM }
41811202SStephen.Hanson@Sun.COM
4194436Sstephh if (nodep->u.name.last->u.name.cp != NULL) {
4204436Sstephh cp = nodep->u.name.last->u.name.cp;
4214436Sstephh } else {
4224436Sstephh path = ipath2str(NULL, ipath(nodep));
4234436Sstephh cp = config_lookup(croot, path, 0);
4244436Sstephh FREE((void *)path);
4254436Sstephh }
4264436Sstephh if (duped)
4274436Sstephh tree_free(nodep);
4284436Sstephh
4294436Sstephh valuep->t = STRING;
4304436Sstephh valuep->v = (uintptr_t)stable("");
4314436Sstephh if (cp == NULL)
4324436Sstephh return (1);
4334436Sstephh for (i = 0; typestrings[i] != NULL; i++) {
4344436Sstephh s = config_getprop(cp, stable(typestrings[i]));
4354436Sstephh if (s != NULL) {
4364436Sstephh valuep->v = (uintptr_t)stable(s);
4374436Sstephh break;
4384436Sstephh }
4394436Sstephh }
4404436Sstephh return (1);
4414436Sstephh } else if (funcname == L_is_on) {
4424436Sstephh const char *onstrings[] = { "on", "ON", NULL };
4434436Sstephh const char *truestrings[] = { "yes", "YES", "y", "Y",
4444436Sstephh "true", "TRUE", "t", "T", "1", NULL };
4454436Sstephh const char *s;
4464436Sstephh int i, j;
4474436Sstephh
4484436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals,
4494436Sstephh croot, arrowp, try, &duped);
45011202SStephen.Hanson@Sun.COM if (!nodep)
45111202SStephen.Hanson@Sun.COM return (0);
45211202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) {
45311202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
45411202SStephen.Hanson@Sun.COM return (1);
45511202SStephen.Hanson@Sun.COM }
45611202SStephen.Hanson@Sun.COM
4574436Sstephh if (nodep->u.name.last->u.name.cp != NULL) {
4584436Sstephh cp = nodep->u.name.last->u.name.cp;
4594436Sstephh } else {
4604436Sstephh path = ipath2str(NULL, ipath(nodep));
4614436Sstephh cp = config_lookup(croot, path, 0);
4624436Sstephh FREE((void *)path);
4634436Sstephh }
4644436Sstephh if (duped)
4654436Sstephh tree_free(nodep);
4664436Sstephh
4674436Sstephh valuep->t = UINT64;
4684436Sstephh valuep->v = 0;
4694436Sstephh if (cp == NULL)
4704436Sstephh return (1);
4714436Sstephh for (i = 0; onstrings[i] != NULL; i++) {
4724436Sstephh s = config_getprop(cp, stable(onstrings[i]));
4734436Sstephh if (s != NULL) {
4744436Sstephh s = stable(s);
4754436Sstephh for (j = 0; truestrings[j] != NULL; j++) {
4764436Sstephh if (s == stable(truestrings[j])) {
4774436Sstephh valuep->v = 1;
4784436Sstephh return (1);
4794436Sstephh }
4804436Sstephh }
4814436Sstephh }
4824436Sstephh }
4834436Sstephh return (1);
4844436Sstephh } else if (funcname == L_is_present) {
4854436Sstephh nodep = eval_getname(funcnp, ex, events, np, globals,
4864436Sstephh croot, arrowp, try, &duped);
48711202SStephen.Hanson@Sun.COM if (!nodep)
48811202SStephen.Hanson@Sun.COM return (0);
48911202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) {
49011202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
49111202SStephen.Hanson@Sun.COM return (1);
49211202SStephen.Hanson@Sun.COM }
49311202SStephen.Hanson@Sun.COM
4944436Sstephh if (nodep->u.name.last->u.name.cp != NULL) {
4954436Sstephh cp = nodep->u.name.last->u.name.cp;
4964436Sstephh } else {
4974436Sstephh path = ipath2str(NULL, ipath(nodep));
4984436Sstephh cp = config_lookup(croot, path, 0);
4994436Sstephh FREE((void *)path);
5004436Sstephh }
5014436Sstephh if (duped)
5024436Sstephh tree_free(nodep);
5034436Sstephh
5044436Sstephh valuep->t = UINT64;
5054436Sstephh valuep->v = 0;
5064436Sstephh if (cp != NULL)
5074436Sstephh valuep->v = 1;
5084436Sstephh return (1);
5097275Sstephh } else if (funcname == L_has_fault) {
5107275Sstephh nvlist_t *asru = NULL, *fru = NULL, *rsrc = NULL;
5117275Sstephh
5127275Sstephh nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
5137275Sstephh globals, croot, arrowp, try, &duped);
51411202SStephen.Hanson@Sun.COM if (!nodep)
51511202SStephen.Hanson@Sun.COM return (0);
51611202SStephen.Hanson@Sun.COM if (nodep->t != T_NAME) {
51711202SStephen.Hanson@Sun.COM valuep->t = UNDEFINED;
51811202SStephen.Hanson@Sun.COM return (1);
51911202SStephen.Hanson@Sun.COM }
52011202SStephen.Hanson@Sun.COM
5217275Sstephh path = ipath2str(NULL, ipath(nodep));
5227275Sstephh platform_units_translate(0, croot, &asru, &fru, &rsrc, path);
5238245SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, "has_fault(");
52411202SStephen.Hanson@Sun.COM ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, nodep);
52511202SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2|O_NONL, "(%s), \"%s\") ", path,
5268245SStephen.Hanson@Sun.COM np->u.expr.right->u.quote.s);
5277275Sstephh FREE((void *)path);
5287275Sstephh if (duped)
5297275Sstephh tree_free(nodep);
5307275Sstephh
5318245SStephen.Hanson@Sun.COM if (rsrc == NULL) {
5327275Sstephh valuep->v = 0;
5338245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "no path");
5348245SStephen.Hanson@Sun.COM } else {
5357275Sstephh valuep->v = fmd_nvl_fmri_has_fault(Hdl, rsrc,
5367275Sstephh FMD_HAS_FAULT_RESOURCE,
5377275Sstephh strcmp(np->u.expr.right->u.quote.s, "") == 0 ?
5387275Sstephh NULL : (char *)np->u.expr.right->u.quote.s);
5398245SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "returned %lld", valuep->v);
540*11416SStephen.Hanson@Sun.COM nvlist_free(rsrc);
5418245SStephen.Hanson@Sun.COM }
5427275Sstephh valuep->t = UINT64;
5437275Sstephh return (1);
5444436Sstephh } else if (funcname == L_count) {
5454436Sstephh struct stats *statp;
5464436Sstephh struct istat_entry ent;
5474436Sstephh
5484436Sstephh ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
5494436Sstephh
5504436Sstephh nodep = np->u.event.epname;
5514436Sstephh if (try) {
5524436Sstephh if (eval_expr(nodep, ex, events, globals,
5534436Sstephh croot, arrowp, try, &val) && val.t == NODEPTR)
5544436Sstephh nodep = (struct node *)(uintptr_t)val.v;
5554436Sstephh else {
5564436Sstephh duped = 1;
5574436Sstephh nodep = eval_dup(nodep, ex, events);
5584436Sstephh }
5594436Sstephh }
5604436Sstephh ent.ename = np->u.event.ename->u.name.s;
5614436Sstephh ent.ipath = ipath(nodep);
5624436Sstephh valuep->t = UINT64;
5634436Sstephh if ((statp = (struct stats *)
5644436Sstephh lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
5654436Sstephh valuep->v = 0;
5664436Sstephh else
5674436Sstephh valuep->v = stats_counter_value(statp);
5684436Sstephh if (duped)
5694436Sstephh tree_free(nodep);
5704436Sstephh return (1);
5714436Sstephh } else if (funcname == L_envprop) {
5724436Sstephh outfl(O_DIE, np->file, np->line,
5734436Sstephh "eval_func: %s not yet supported", funcname);
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate if (try)
5770Sstevel@tonic-gate return (0);
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate if (funcname == L_fru) {
5800Sstevel@tonic-gate valuep->t = NODEPTR;
5811717Swesolows valuep->v = (uintptr_t)eval_fru(np);
5820Sstevel@tonic-gate return (1);
5830Sstevel@tonic-gate } else if (funcname == L_asru) {
5840Sstevel@tonic-gate valuep->t = NODEPTR;
5851717Swesolows valuep->v = (uintptr_t)eval_asru(np);
5860Sstevel@tonic-gate return (1);
5871414Scindi } else if (funcname == L_defined) {
5881414Scindi ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
5891414Scindi valuep->t = UINT64;
5901414Scindi valuep->v = (lut_lookup(*globals,
5911414Scindi (void *)np->u.globid.s, NULL) != NULL);
5921414Scindi return (1);
5930Sstevel@tonic-gate } else if (funcname == L_call) {
5940Sstevel@tonic-gate return (! platform_call(np, globals, croot, arrowp, valuep));
5950Sstevel@tonic-gate } else if (funcname == L_payloadprop) {
5961414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
5970Sstevel@tonic-gate "payloadprop(\"%s\") ", np->u.quote.s);
598186Sdb35262
5995204Sstephh if (arrowp->head->myevent->count == 0) {
6005204Sstephh /*
6015204Sstephh * Haven't seen this ereport yet, so must defer
6025204Sstephh */
6035204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
6045204Sstephh return (0);
6055204Sstephh } else if (platform_payloadprop(np, valuep)) {
6061414Scindi /* platform_payloadprop() returned false */
6075204Sstephh out(O_ALTFP|O_VERB, "not found.");
6085204Sstephh valuep->t = UNDEFINED;
6095204Sstephh return (1);
6101414Scindi } else {
611186Sdb35262 switch (valuep->t) {
61211202SStephen.Hanson@Sun.COM case NODEPTR:
61311202SStephen.Hanson@Sun.COM if (((struct node *)(uintptr_t)
61411202SStephen.Hanson@Sun.COM (valuep->v))->t == T_NAME) {
61511202SStephen.Hanson@Sun.COM char *s = ipath2str(NULL,
61611202SStephen.Hanson@Sun.COM ipath((struct node *)
61711202SStephen.Hanson@Sun.COM (uintptr_t)valuep->v));
61811202SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2,
61911202SStephen.Hanson@Sun.COM "found: \"%s\"", s);
62011202SStephen.Hanson@Sun.COM FREE(s);
62111202SStephen.Hanson@Sun.COM } else
62211202SStephen.Hanson@Sun.COM out(O_ALTFP|O_VERB2, "found: %llu",
62311202SStephen.Hanson@Sun.COM valuep->v);
62411202SStephen.Hanson@Sun.COM break;
625186Sdb35262 case UINT64:
6261414Scindi out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
627186Sdb35262 break;
628186Sdb35262 case STRING:
6291414Scindi out(O_ALTFP|O_VERB2, "found: \"%s\"",
6301717Swesolows (char *)(uintptr_t)valuep->v);
631186Sdb35262 break;
632186Sdb35262 default:
6331414Scindi out(O_ALTFP|O_VERB2, "found: undefined");
634186Sdb35262 break;
635186Sdb35262 }
6361414Scindi return (1);
6371414Scindi }
6381414Scindi } else if (funcname == L_setpayloadprop) {
6391414Scindi struct evalue *payloadvalp;
6405204Sstephh int alloced = 0;
6411414Scindi
6421414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
6431414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE,
6441414Scindi ptree_nodetype2str(np->u.expr.left->t));
6451414Scindi
6469078SStephen.Hanson@Sun.COM if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
6477197Sstephh return (0);
6487197Sstephh
6491414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
6501414Scindi "setpayloadprop: %s: %s=",
6511414Scindi arrowp->tail->myevent->enode->u.event.ename->u.name.s,
6521414Scindi np->u.expr.left->u.quote.s);
6531414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
6541414Scindi
6551414Scindi /*
6561414Scindi * allocate a struct evalue to hold the payload property's
6571414Scindi * value, unless we've been here already, in which case we
6581414Scindi * might calculate a different value, but we'll store it
6591414Scindi * in the already-allocated struct evalue.
6601414Scindi */
6611414Scindi if ((payloadvalp = (struct evalue *)lut_lookup(
6621414Scindi arrowp->tail->myevent->payloadprops,
6631414Scindi (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
6641414Scindi payloadvalp = MALLOC(sizeof (*payloadvalp));
6655204Sstephh alloced = 1;
6661414Scindi }
6671414Scindi
6684436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
6691414Scindi arrowp, try, payloadvalp)) {
6705204Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)");
6715204Sstephh if (alloced)
6725204Sstephh FREE(payloadvalp);
6735204Sstephh return (0);
6741414Scindi } else {
6755204Sstephh if (payloadvalp->t == UNDEFINED) {
6765204Sstephh /* function is always true */
6775204Sstephh out(O_ALTFP|O_VERB2, " (undefined)");
6785204Sstephh valuep->t = UINT64;
6795204Sstephh valuep->v = 1;
6805204Sstephh return (1);
6815204Sstephh }
6821414Scindi if (payloadvalp->t == UINT64)
6831414Scindi out(O_ALTFP|O_VERB2,
6841414Scindi " (%llu)", payloadvalp->v);
6851414Scindi else
6861717Swesolows out(O_ALTFP|O_VERB2, " (\"%s\")",
6871717Swesolows (char *)(uintptr_t)payloadvalp->v);
6881414Scindi }
6891414Scindi
6901414Scindi /* add to table of payload properties for current problem */
6911414Scindi arrowp->tail->myevent->payloadprops =
6921414Scindi lut_add(arrowp->tail->myevent->payloadprops,
6931414Scindi (void *)np->u.expr.left->u.quote.s,
6941414Scindi (void *)payloadvalp, NULL);
6951414Scindi
6961414Scindi /* function is always true */
6971414Scindi valuep->t = UINT64;
6981414Scindi valuep->v = 1;
6991414Scindi return (1);
70011202SStephen.Hanson@Sun.COM } else if (funcname == L_cat) {
70111202SStephen.Hanson@Sun.COM int retval = eval_cat(np, ex, events, globals, croot,
70211202SStephen.Hanson@Sun.COM arrowp, try, valuep);
70311202SStephen.Hanson@Sun.COM
70411202SStephen.Hanson@Sun.COM outfl(O_ALTFP|O_VERB2, np->file, np->line,
70511202SStephen.Hanson@Sun.COM "cat: returns %s", (char *)(uintptr_t)valuep->v);
70611202SStephen.Hanson@Sun.COM return (retval);
7077197Sstephh } else if (funcname == L_setserdn || funcname == L_setserdt ||
7087197Sstephh funcname == L_setserdsuffix || funcname == L_setserdincrement) {
7097197Sstephh struct evalue *serdvalp;
7107197Sstephh int alloced = 0;
7117197Sstephh char *str;
7127197Sstephh struct event *flt = arrowp->tail->myevent;
7137197Sstephh
7149078SStephen.Hanson@Sun.COM if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
7157197Sstephh return (0);
7167197Sstephh
7177197Sstephh if (funcname == L_setserdn)
7187197Sstephh str = "n";
7197197Sstephh else if (funcname == L_setserdt)
7207197Sstephh str = "t";
7217197Sstephh else if (funcname == L_setserdsuffix)
7227197Sstephh str = "suffix";
7237197Sstephh else if (funcname == L_setserdincrement)
7247197Sstephh str = "increment";
7257197Sstephh
7267197Sstephh /*
7277197Sstephh * allocate a struct evalue to hold the serd property's
7287197Sstephh * value, unless we've been here already, in which case we
7297197Sstephh * might calculate a different value, but we'll store it
7307197Sstephh * in the already-allocated struct evalue.
7317197Sstephh */
7327197Sstephh if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops,
7337392SScott.Davenport@Sun.COM (void *)str, (lut_cmp)strcmp)) == NULL) {
7347197Sstephh serdvalp = MALLOC(sizeof (*serdvalp));
7357197Sstephh alloced = 1;
7367197Sstephh }
7377197Sstephh
7387197Sstephh if (!eval_expr(np, ex, events, globals, croot, arrowp, try,
7397197Sstephh serdvalp)) {
7407197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
7417197Sstephh "setserd%s: %s: ", str,
7427197Sstephh flt->enode->u.event.ename->u.name.s);
7437197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
7447197Sstephh out(O_ALTFP|O_VERB2, " (cannot eval)");
7457197Sstephh if (alloced)
7467197Sstephh FREE(serdvalp);
7477197Sstephh return (0);
7487197Sstephh } else if (serdvalp->t == UNDEFINED) {
7497197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
7507197Sstephh "setserd%s: %s: ", str,
7517197Sstephh flt->enode->u.event.ename->u.name.s);
7527197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
7537197Sstephh out(O_ALTFP|O_VERB2, " (undefined)");
7547197Sstephh } else {
7557197Sstephh outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
7567197Sstephh "setserd%s: %s: ", str,
7577197Sstephh flt->enode->u.event.ename->u.name.s);
7587197Sstephh ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
7597197Sstephh if ((funcname == L_setserdincrement ||
7607197Sstephh funcname == L_setserdn) && serdvalp->t == STRING) {
7617197Sstephh serdvalp->t = UINT64;
7627197Sstephh serdvalp->v = strtoull((char *)
7637197Sstephh (uintptr_t)serdvalp->v, NULL, 0);
7647197Sstephh }
7657197Sstephh if (funcname == L_setserdt && serdvalp->t == UINT64) {
7667197Sstephh int len = snprintf(NULL, 0, "%lldns",
7677197Sstephh serdvalp->v);
7687197Sstephh char *buf = MALLOC(len + 1);
7697197Sstephh
7707197Sstephh (void) snprintf(buf, len + 1, "%lldns",
7717197Sstephh serdvalp->v);
7727197Sstephh serdvalp->t = STRING;
7737197Sstephh serdvalp->v = (uintptr_t)stable(buf);
7747197Sstephh FREE(buf);
7757197Sstephh }
77611031SDavid.Zhang@Sun.COM if (funcname == L_setserdsuffix &&
77711031SDavid.Zhang@Sun.COM serdvalp->t == UINT64) {
77811031SDavid.Zhang@Sun.COM int len = snprintf(NULL, 0, "%lld",
77911031SDavid.Zhang@Sun.COM serdvalp->v);
78011031SDavid.Zhang@Sun.COM char *buf = MALLOC(len + 1);
78111031SDavid.Zhang@Sun.COM
78211031SDavid.Zhang@Sun.COM (void) snprintf(buf, len + 1, "%lld",
78311031SDavid.Zhang@Sun.COM serdvalp->v);
78411031SDavid.Zhang@Sun.COM serdvalp->t = STRING;
78511031SDavid.Zhang@Sun.COM serdvalp->v = (uintptr_t)stable(buf);
78611031SDavid.Zhang@Sun.COM FREE(buf);
78711031SDavid.Zhang@Sun.COM }
7887392SScott.Davenport@Sun.COM
7897197Sstephh if (serdvalp->t == UINT64)
7907197Sstephh out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v);
7917197Sstephh else
7927197Sstephh out(O_ALTFP|O_VERB2, " (\"%s\")",
7937197Sstephh (char *)(uintptr_t)serdvalp->v);
7947197Sstephh flt->serdprops = lut_add(flt->serdprops, (void *)str,
7957392SScott.Davenport@Sun.COM (void *)serdvalp, (lut_cmp)strcmp);
7967197Sstephh }
7977197Sstephh valuep->t = UINT64;
7987197Sstephh valuep->v = 1;
7997197Sstephh return (1);
8001414Scindi } else if (funcname == L_payloadprop_defined) {
8011414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
8021414Scindi "payloadprop_defined(\"%s\") ", np->u.quote.s);
8031414Scindi
8045204Sstephh if (arrowp->head->myevent->count == 0) {
8055204Sstephh /*
8065204Sstephh * Haven't seen this ereport yet, so must defer
8075204Sstephh */
8085204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
8095204Sstephh return (0);
8105204Sstephh } else if (platform_payloadprop(np, NULL)) {
8111414Scindi /* platform_payloadprop() returned false */
8121414Scindi valuep->v = 0;
8135204Sstephh out(O_ALTFP|O_VERB2, "not found.");
8141414Scindi } else {
8151414Scindi valuep->v = 1;
8161414Scindi out(O_ALTFP|O_VERB2, "found.");
8171414Scindi }
8181414Scindi valuep->t = UINT64;
8191414Scindi return (1);
8201414Scindi } else if (funcname == L_payloadprop_contains) {
8211414Scindi int nvals;
8221414Scindi struct evalue *vals;
8231414Scindi struct evalue cmpval;
8241414Scindi
8251414Scindi ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
8261414Scindi ASSERTinfo(np->u.expr.left->t == T_QUOTE,
8271414Scindi ptree_nodetype2str(np->u.expr.left->t));
8281414Scindi
8291414Scindi outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
8301414Scindi "payloadprop_contains(\"%s\", ",
8311414Scindi np->u.expr.left->u.quote.s);
8321414Scindi ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
8332869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, ") ");
8341414Scindi
8351414Scindi /* evaluate the expression we're comparing against */
8364436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
8371414Scindi arrowp, try, &cmpval)) {
8381414Scindi out(O_ALTFP|O_VERB2|O_NONL,
8395204Sstephh "(cannot eval) ");
8405204Sstephh return (0);
8411414Scindi } else {
8422869Sgavinm switch (cmpval.t) {
8432869Sgavinm case UNDEFINED:
8442869Sgavinm out(O_ALTFP|O_VERB2, "(undefined type)");
8452869Sgavinm break;
8462869Sgavinm
8472869Sgavinm case UINT64:
8481414Scindi out(O_ALTFP|O_VERB2,
8491414Scindi "(%llu) ", cmpval.v);
8502869Sgavinm break;
8512869Sgavinm
8522869Sgavinm case STRING:
8531414Scindi out(O_ALTFP|O_VERB2,
8541717Swesolows "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
8552869Sgavinm break;
8562869Sgavinm
8572869Sgavinm case NODEPTR:
8582869Sgavinm out(O_ALTFP|O_VERB2|O_NONL, "(");
8592869Sgavinm ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
8602869Sgavinm (struct node *)(uintptr_t)(cmpval.v));
8612869Sgavinm out(O_ALTFP|O_VERB2, ") ");
8622869Sgavinm break;
8632869Sgavinm }
8641414Scindi }
8651414Scindi
8661414Scindi /* get the payload values and check for a match */
8671414Scindi vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
8681414Scindi &nvals);
8691414Scindi valuep->t = UINT64;
8701414Scindi valuep->v = 0;
8715204Sstephh if (arrowp->head->myevent->count == 0) {
8725204Sstephh /*
8735204Sstephh * Haven't seen this ereport yet, so must defer
8745204Sstephh */
8755204Sstephh out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
8765204Sstephh return (0);
8775204Sstephh } else if (nvals == 0) {
8781414Scindi out(O_ALTFP|O_VERB2, "not found.");
8795204Sstephh return (1);
8801414Scindi } else {
8811414Scindi struct evalue preval;
8821414Scindi int i;
8831414Scindi
8841414Scindi out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
8851414Scindi
8861414Scindi for (i = 0; i < nvals; i++) {
8871414Scindi
8881414Scindi preval.t = vals[i].t;
8891414Scindi preval.v = vals[i].v;
8901414Scindi
8911414Scindi if (check_expr_args(&vals[i], &cmpval,
8921414Scindi UNDEFINED, np))
8931414Scindi continue;
8941414Scindi
8951414Scindi /*
8961414Scindi * If we auto-converted the value to a
8971414Scindi * string, we need to free the
8981414Scindi * original tree value.
8991414Scindi */
9001414Scindi if (preval.t == NODEPTR &&
9011717Swesolows ((struct node *)(uintptr_t)(preval.v))->t ==
9021717Swesolows T_NAME) {
9031717Swesolows tree_free((struct node *)(uintptr_t)
9041717Swesolows preval.v);
9051414Scindi }
9061414Scindi
9071414Scindi if (vals[i].v == cmpval.v) {
9081414Scindi valuep->v = 1;
9091414Scindi break;
9101414Scindi }
9111414Scindi }
912186Sdb35262
9131414Scindi if (valuep->v)
9141414Scindi out(O_ALTFP|O_VERB2, "match.");
9151414Scindi else
9161414Scindi out(O_ALTFP|O_VERB2, "no match.");
917186Sdb35262
9181414Scindi for (i = 0; i < nvals; i++) {
9191414Scindi if (vals[i].t == NODEPTR) {
9201717Swesolows tree_free((struct node *)(uintptr_t)
9211717Swesolows vals[i].v);
9221414Scindi break;
9231414Scindi }
924186Sdb35262 }
9251414Scindi FREE(vals);
9261414Scindi }
9271414Scindi return (1);
9281414Scindi } else if (funcname == L_confcall) {
9291414Scindi return (!platform_confcall(np, globals, croot, arrowp, valuep));
9300Sstevel@tonic-gate } else
9310Sstevel@tonic-gate outfl(O_DIE, np->file, np->line,
9320Sstevel@tonic-gate "eval_func: unexpected func: %s", funcname);
9330Sstevel@tonic-gate /*NOTREACHED*/
9341717Swesolows return (0);
9350Sstevel@tonic-gate }
9360Sstevel@tonic-gate
9374436Sstephh /*
9384436Sstephh * defines for u.expr.temp - these are used for T_OR and T_AND so that if
9394436Sstephh * we worked out that part of the expression was true or false during an
9404436Sstephh * earlier eval_expr, then we don't need to dup that part.
9414436Sstephh */
9420Sstevel@tonic-gate
9434436Sstephh #define EXPR_TEMP_BOTH_UNK 0
9444436Sstephh #define EXPR_TEMP_LHS_UNK 1
9454436Sstephh #define EXPR_TEMP_RHS_UNK 2
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate static struct node *
eval_dup(struct node * np,struct lut * ex,struct node * events[])9484436Sstephh eval_dup(struct node *np, struct lut *ex, struct node *events[])
9490Sstevel@tonic-gate {
9500Sstevel@tonic-gate struct node *newnp;
9510Sstevel@tonic-gate
9520Sstevel@tonic-gate if (np == NULL)
9530Sstevel@tonic-gate return (NULL);
9540Sstevel@tonic-gate
9550Sstevel@tonic-gate switch (np->t) {
9560Sstevel@tonic-gate case T_GLOBID:
9570Sstevel@tonic-gate return (tree_globid(np->u.globid.s, np->file, np->line));
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate case T_ASSIGN:
9600Sstevel@tonic-gate case T_CONDIF:
9610Sstevel@tonic-gate case T_CONDELSE:
9620Sstevel@tonic-gate case T_NE:
9630Sstevel@tonic-gate case T_EQ:
9640Sstevel@tonic-gate case T_LT:
9650Sstevel@tonic-gate case T_LE:
9660Sstevel@tonic-gate case T_GT:
9670Sstevel@tonic-gate case T_GE:
9680Sstevel@tonic-gate case T_BITAND:
9690Sstevel@tonic-gate case T_BITOR:
9700Sstevel@tonic-gate case T_BITXOR:
9710Sstevel@tonic-gate case T_BITNOT:
9720Sstevel@tonic-gate case T_LSHIFT:
9730Sstevel@tonic-gate case T_RSHIFT:
9740Sstevel@tonic-gate case T_NOT:
9750Sstevel@tonic-gate case T_ADD:
9760Sstevel@tonic-gate case T_SUB:
9770Sstevel@tonic-gate case T_MUL:
9780Sstevel@tonic-gate case T_DIV:
9790Sstevel@tonic-gate case T_MOD:
9800Sstevel@tonic-gate return (tree_expr(np->t,
9814436Sstephh eval_dup(np->u.expr.left, ex, events),
9824436Sstephh eval_dup(np->u.expr.right, ex, events)));
9834436Sstephh case T_LIST:
9844436Sstephh case T_AND:
9854436Sstephh switch (np->u.expr.temp) {
9864436Sstephh case EXPR_TEMP_LHS_UNK:
9874436Sstephh return (eval_dup(np->u.expr.left, ex, events));
9884436Sstephh case EXPR_TEMP_RHS_UNK:
9894436Sstephh return (eval_dup(np->u.expr.right, ex, events));
9904436Sstephh default:
9914436Sstephh return (tree_expr(np->t,
9924436Sstephh eval_dup(np->u.expr.left, ex, events),
9934436Sstephh eval_dup(np->u.expr.right, ex, events)));
9944436Sstephh }
9954436Sstephh
9964436Sstephh case T_OR:
9974436Sstephh switch (np->u.expr.temp) {
9984436Sstephh case EXPR_TEMP_LHS_UNK:
9994436Sstephh return (eval_dup(np->u.expr.left, ex, events));
10004436Sstephh case EXPR_TEMP_RHS_UNK:
10014436Sstephh return (eval_dup(np->u.expr.right, ex, events));
10024436Sstephh default:
10034436Sstephh return (tree_expr(T_OR,
10044436Sstephh eval_dup(np->u.expr.left, ex, events),
10054436Sstephh eval_dup(np->u.expr.right, ex, events)));
10064436Sstephh }
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate case T_NAME: {
10090Sstevel@tonic-gate struct iterinfo *iterinfop;
10104436Sstephh int got_matchf = 0;
10114436Sstephh int got_matcht = 0;
10124436Sstephh struct evalue value;
10134436Sstephh struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
10144436Sstephh struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
10150Sstevel@tonic-gate
10164436Sstephh /*
10174436Sstephh * Check if we already have a match of the nonwildcarded path
10184436Sstephh * in oldepname (check both to and from events).
10194436Sstephh */
10204436Sstephh for (np1f = np, np2f = events[0]->u.event.oldepname;
10214436Sstephh np1f != NULL && np2f != NULL;
10224436Sstephh np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
10234436Sstephh if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
10244436Sstephh break;
10254436Sstephh if (np1f->u.name.child->t != np2f->u.name.child->t)
10264436Sstephh break;
10274436Sstephh if (np1f->u.name.child->t == T_NUM &&
10284436Sstephh np1f->u.name.child->u.ull !=
10294436Sstephh np2f->u.name.child->u.ull)
10304436Sstephh break;
10314436Sstephh if (np1f->u.name.child->t == T_NAME &&
10324436Sstephh strcmp(np1f->u.name.child->u.name.s,
10334436Sstephh np2f->u.name.child->u.name.s) != 0)
10344436Sstephh break;
10354436Sstephh got_matchf++;
10364436Sstephh }
10374436Sstephh for (np1t = np, np2t = events[1]->u.event.oldepname;
10384436Sstephh np1t != NULL && np2t != NULL;
10394436Sstephh np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
10404436Sstephh if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
10414436Sstephh break;
10424436Sstephh if (np1t->u.name.child->t != np2t->u.name.child->t)
10434436Sstephh break;
10444436Sstephh if (np1t->u.name.child->t == T_NUM &&
10454436Sstephh np1t->u.name.child->u.ull !=
10464436Sstephh np2t->u.name.child->u.ull)
10474436Sstephh break;
10484436Sstephh if (np1t->u.name.child->t == T_NAME &&
10494436Sstephh strcmp(np1t->u.name.child->u.name.s,
10504436Sstephh np2t->u.name.child->u.name.s) != 0)
10514436Sstephh break;
10524436Sstephh got_matcht++;
10534436Sstephh }
10544436Sstephh nprest = np;
10554436Sstephh if (got_matchf || got_matcht) {
10564436Sstephh /*
10574436Sstephh * so we are wildcarding. Copy ewname in full, plus
10584436Sstephh * matching section of oldepname. Use whichever gives
10594436Sstephh * the closest match.
10604436Sstephh */
10614436Sstephh if (got_matchf > got_matcht) {
10624436Sstephh npstart = events[0]->u.event.ewname;
10634436Sstephh npcont = events[0]->u.event.oldepname;
10644436Sstephh npend = np2f;
10654436Sstephh nprest = np1f;
10664436Sstephh } else {
10674436Sstephh npstart = events[1]->u.event.ewname;
10684436Sstephh npcont = events[1]->u.event.oldepname;
10694436Sstephh npend = np2t;
10704436Sstephh nprest = np1t;
10714436Sstephh }
10724436Sstephh for (npref = npstart; npref != NULL;
10734436Sstephh npref = npref->u.name.next) {
10744436Sstephh newnp = newnode(T_NAME, np->file, np->line);
10754436Sstephh newnp->u.name.t = npref->u.name.t;
10764436Sstephh newnp->u.name.s = npref->u.name.s;
10774436Sstephh newnp->u.name.last = newnp;
10784436Sstephh newnp->u.name.it = npref->u.name.it;
10794436Sstephh newnp->u.name.cp = npref->u.name.cp;
10804436Sstephh newnp->u.name.child =
10814436Sstephh newnode(T_NUM, np->file, np->line);
10824436Sstephh if (eval_expr(npref->u.name.child, ex, events,
10830Sstevel@tonic-gate NULL, NULL, NULL, 1, &value) == 0 ||
10840Sstevel@tonic-gate value.t != UINT64) {
10850Sstevel@tonic-gate outfl(O_DIE, np->file, np->line,
10860Sstevel@tonic-gate "eval_dup: could not resolve "
10870Sstevel@tonic-gate "iterator of %s", np->u.name.s);
10880Sstevel@tonic-gate }
10894436Sstephh newnp->u.name.child->u.ull = value.v;
10904436Sstephh if (retp == NULL) {
10914436Sstephh retp = newnp;
10924436Sstephh } else {
10934436Sstephh retp->u.name.last->u.name.next = newnp;
10944436Sstephh retp->u.name.last = newnp;
10954436Sstephh }
10960Sstevel@tonic-gate }
10974436Sstephh for (npref = npcont; npref != NULL && npref != npend;
10984436Sstephh npref = npref->u.name.next) {
10994436Sstephh newnp = newnode(T_NAME, np->file, np->line);
11004436Sstephh newnp->u.name.t = npref->u.name.t;
11014436Sstephh newnp->u.name.s = npref->u.name.s;
11024436Sstephh newnp->u.name.last = newnp;
11034436Sstephh newnp->u.name.it = npref->u.name.it;
11044436Sstephh newnp->u.name.cp = npref->u.name.cp;
11054436Sstephh newnp->u.name.child =
11064436Sstephh newnode(T_NUM, np->file, np->line);
11074436Sstephh if (eval_expr(npref->u.name.child, ex, events,
11084436Sstephh NULL, NULL, NULL, 1, &value) == 0 ||
11094436Sstephh value.t != UINT64) {
11104436Sstephh outfl(O_DIE, np->file, np->line,
11114436Sstephh "eval_dup: could not resolve "
11124436Sstephh "iterator of %s", np->u.name.s);
11134436Sstephh }
11144436Sstephh newnp->u.name.child->u.ull = value.v;
11154436Sstephh if (retp == NULL) {
11164436Sstephh retp = newnp;
11174436Sstephh } else {
11184436Sstephh retp->u.name.last->u.name.next = newnp;
11194436Sstephh retp->u.name.last = newnp;
11204436Sstephh }
11214436Sstephh }
11224436Sstephh } else {
11234436Sstephh /*
11244436Sstephh * not wildcarding - check if explicit iterator
11254436Sstephh */
11264436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
11274436Sstephh if (iterinfop != NULL) {
11284436Sstephh /* explicit iterator; not part of pathname */
11294436Sstephh newnp = newnode(T_NUM, np->file, np->line);
11304436Sstephh newnp->u.ull = iterinfop->num;
11310Sstevel@tonic-gate return (newnp);
11320Sstevel@tonic-gate }
11330Sstevel@tonic-gate }
11344436Sstephh
11354436Sstephh /*
11364436Sstephh * finally, whether wildcarding or not, we need to copy the
11374436Sstephh * remaining part of the path (if any). This must be defined
11384436Sstephh * absolutely (no more expansion/wildcarding).
11394436Sstephh */
11404436Sstephh for (npref = nprest; npref != NULL;
11414436Sstephh npref = npref->u.name.next) {
11424436Sstephh newnp = newnode(T_NAME, np->file, np->line);
11434436Sstephh newnp->u.name.t = npref->u.name.t;
11444436Sstephh newnp->u.name.s = npref->u.name.s;
11454436Sstephh newnp->u.name.last = newnp;
11464436Sstephh newnp->u.name.it = npref->u.name.it;
11474436Sstephh newnp->u.name.cp = npref->u.name.cp;
11484436Sstephh newnp->u.name.child =
11494436Sstephh newnode(T_NUM, np->file, np->line);
11504436Sstephh if (eval_expr(npref->u.name.child, ex, events,
11514436Sstephh NULL, NULL, NULL, 1, &value) == 0 ||
11524436Sstephh value.t != UINT64) {
11534436Sstephh outfl(O_DIE, np->file, np->line,
11544436Sstephh "eval_dup: could not resolve "
11554436Sstephh "iterator of %s", np->u.name.s);
11564436Sstephh }
11574436Sstephh newnp->u.name.child->u.ull = value.v;
11584436Sstephh if (retp == NULL) {
11594436Sstephh retp = newnp;
11604436Sstephh } else {
11614436Sstephh retp->u.name.last->u.name.next = newnp;
11624436Sstephh retp->u.name.last = newnp;
11634436Sstephh }
11644436Sstephh }
11654436Sstephh return (retp);
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate
11681414Scindi case T_EVENT:
11691414Scindi newnp = newnode(T_NAME, np->file, np->line);
11701414Scindi
11711414Scindi newnp->u.name.t = np->u.event.ename->u.name.t;
11721414Scindi newnp->u.name.s = np->u.event.ename->u.name.s;
11731414Scindi newnp->u.name.it = np->u.event.ename->u.name.it;
11741414Scindi newnp->u.name.last = newnp;
11751414Scindi
11761414Scindi return (tree_event(newnp,
11774436Sstephh eval_dup(np->u.event.epname, ex, events),
11784436Sstephh eval_dup(np->u.event.eexprlist, ex, events)));
11791414Scindi
11800Sstevel@tonic-gate case T_FUNC:
11810Sstevel@tonic-gate return (tree_func(np->u.func.s,
11824436Sstephh eval_dup(np->u.func.arglist, ex, events),
11830Sstevel@tonic-gate np->file, np->line));
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate case T_QUOTE:
11860Sstevel@tonic-gate newnp = newnode(T_QUOTE, np->file, np->line);
11870Sstevel@tonic-gate newnp->u.quote.s = np->u.quote.s;
11880Sstevel@tonic-gate return (newnp);
11890Sstevel@tonic-gate
11900Sstevel@tonic-gate case T_NUM:
11910Sstevel@tonic-gate newnp = newnode(T_NUM, np->file, np->line);
11920Sstevel@tonic-gate newnp->u.ull = np->u.ull;
11930Sstevel@tonic-gate return (newnp);
11940Sstevel@tonic-gate
11957197Sstephh case T_TIMEVAL:
11967197Sstephh newnp = newnode(T_TIMEVAL, np->file, np->line);
11977197Sstephh newnp->u.ull = np->u.ull;
11987197Sstephh return (newnp);
11997197Sstephh
12000Sstevel@tonic-gate default:
12010Sstevel@tonic-gate outfl(O_DIE, np->file, np->line,
12020Sstevel@tonic-gate "eval_dup: unexpected node type: %s",
12030Sstevel@tonic-gate ptree_nodetype2str(np->t));
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate /*NOTREACHED*/
12061717Swesolows return (0);
12070Sstevel@tonic-gate }
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate /*
12100Sstevel@tonic-gate * eval_potential -- see if constraint is potentially true
12110Sstevel@tonic-gate *
12120Sstevel@tonic-gate * this function is used at instance tree creation time to see if
12130Sstevel@tonic-gate * any constraints are already known to be false. if this function
12140Sstevel@tonic-gate * returns false, then the constraint will always be false and there's
12150Sstevel@tonic-gate * no need to include the propagation arrow in the instance tree.
12160Sstevel@tonic-gate *
12170Sstevel@tonic-gate * if this routine returns true, either the constraint is known to
12180Sstevel@tonic-gate * be always true (so there's no point in attaching the constraint
12190Sstevel@tonic-gate * to the propagation arrow in the instance tree), or the constraint
12200Sstevel@tonic-gate * contains "deferred" expressions like global variables or poller calls
12210Sstevel@tonic-gate * and so it must be evaluated during calls to fme_eval(). in this last
12220Sstevel@tonic-gate * case, where a constraint needs to be attached to the propagation arrow
12230Sstevel@tonic-gate * in the instance tree, this routine returns a newly created constraint
12240Sstevel@tonic-gate * in *newc where all the non-deferred things have been filled in.
12250Sstevel@tonic-gate *
12260Sstevel@tonic-gate * so in summary:
12270Sstevel@tonic-gate *
12280Sstevel@tonic-gate * return of false: constraint can never be true, *newc will be NULL.
12290Sstevel@tonic-gate *
12300Sstevel@tonic-gate * return of true with *newc unchanged: constraint will always be true.
12310Sstevel@tonic-gate *
12320Sstevel@tonic-gate * return of true with *newc changed: use new constraint in *newc.
12330Sstevel@tonic-gate *
12340Sstevel@tonic-gate * the lookup table for all explicit iterators, ex, is passed in.
12350Sstevel@tonic-gate *
12360Sstevel@tonic-gate * *newc can either be NULL on entry, or if can contain constraints from
12370Sstevel@tonic-gate * previous calls to eval_potential() (i.e. for building up an instance
12380Sstevel@tonic-gate * tree constraint from several potential constraints). if *newc already
12390Sstevel@tonic-gate * contains constraints, anything added to it will be joined by adding
12400Sstevel@tonic-gate * a T_AND node at the top of *newc.
12410Sstevel@tonic-gate */
12420Sstevel@tonic-gate int
eval_potential(struct node * np,struct lut * ex,struct node * events[],struct node ** newc,struct config * croot)12434436Sstephh eval_potential(struct node *np, struct lut *ex, struct node *events[],
12442318Sstephh struct node **newc, struct config *croot)
12450Sstevel@tonic-gate {
12460Sstevel@tonic-gate struct node *newnp;
12470Sstevel@tonic-gate struct evalue value;
12480Sstevel@tonic-gate
12494436Sstephh if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
12500Sstevel@tonic-gate /*
12510Sstevel@tonic-gate * couldn't eval expression because
12520Sstevel@tonic-gate * it contains deferred items. make
12530Sstevel@tonic-gate * a duplicate expression with all the
12540Sstevel@tonic-gate * non-deferred items expanded.
12550Sstevel@tonic-gate */
12564436Sstephh newnp = eval_dup(np, ex, events);
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate if (*newc == NULL) {
12590Sstevel@tonic-gate /*
12600Sstevel@tonic-gate * constraint is potentially true if deferred
12610Sstevel@tonic-gate * expression in newnp is true. *newc was NULL
12620Sstevel@tonic-gate * so new constraint is just the one in newnp.
12630Sstevel@tonic-gate */
12640Sstevel@tonic-gate *newc = newnp;
12650Sstevel@tonic-gate return (1);
12660Sstevel@tonic-gate } else {
12670Sstevel@tonic-gate /*
12680Sstevel@tonic-gate * constraint is potentially true if deferred
12690Sstevel@tonic-gate * expression in newnp is true. *newc already
12700Sstevel@tonic-gate * contained a constraint so add an AND with the
12710Sstevel@tonic-gate * constraint in newnp.
12720Sstevel@tonic-gate */
12730Sstevel@tonic-gate *newc = tree_expr(T_AND, *newc, newnp);
12740Sstevel@tonic-gate return (1);
12750Sstevel@tonic-gate }
12760Sstevel@tonic-gate } else if (value.t == UNDEFINED) {
12770Sstevel@tonic-gate /* constraint can never be true */
12780Sstevel@tonic-gate return (0);
12790Sstevel@tonic-gate } else if (value.t == UINT64 && value.v == 0) {
12800Sstevel@tonic-gate /* constraint can never be true */
12810Sstevel@tonic-gate return (0);
12820Sstevel@tonic-gate } else {
12830Sstevel@tonic-gate /* constraint is always true (nothing deferred to eval) */
12840Sstevel@tonic-gate return (1);
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate static int
check_expr_args(struct evalue * lp,struct evalue * rp,enum datatype dtype,struct node * np)12890Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
12900Sstevel@tonic-gate struct node *np)
12910Sstevel@tonic-gate {
12921414Scindi /* auto-convert T_NAMES to strings */
12931717Swesolows if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
12941717Swesolows T_NAME) {
12951717Swesolows char *s = ipath2str(NULL,
12961717Swesolows ipath((struct node *)(uintptr_t)lp->v));
12971414Scindi lp->t = STRING;
12981717Swesolows lp->v = (uintptr_t)stable(s);
12991414Scindi FREE(s);
13001414Scindi out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
13011717Swesolows (char *)(uintptr_t)lp->v);
13021414Scindi }
13031414Scindi if (rp != NULL &&
13041717Swesolows rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
13051717Swesolows T_NAME) {
13061717Swesolows char *s = ipath2str(NULL,
13071717Swesolows ipath((struct node *)(uintptr_t)rp->v));
13081414Scindi rp->t = STRING;
13091717Swesolows rp->v = (uintptr_t)stable(s);
13101414Scindi FREE(s);
13111414Scindi out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
13121717Swesolows (char *)(uintptr_t)rp->v);
13131414Scindi }
13141414Scindi
131511202SStephen.Hanson@Sun.COM /* auto-convert numbers to strings */
131611202SStephen.Hanson@Sun.COM if (dtype == STRING) {
131711202SStephen.Hanson@Sun.COM if (lp->t == UINT64) {
131811202SStephen.Hanson@Sun.COM int len = snprintf(NULL, 0, "%llx", lp->v);
131911202SStephen.Hanson@Sun.COM char *s = MALLOC(len + 1);
132011202SStephen.Hanson@Sun.COM
132111202SStephen.Hanson@Sun.COM (void) snprintf(s, len + 1, "%llx", lp->v);
132211202SStephen.Hanson@Sun.COM lp->t = STRING;
132311202SStephen.Hanson@Sun.COM lp->v = (uintptr_t)stable(s);
132411202SStephen.Hanson@Sun.COM FREE(s);
132511202SStephen.Hanson@Sun.COM }
132611202SStephen.Hanson@Sun.COM if (rp != NULL && rp->t == UINT64) {
132711202SStephen.Hanson@Sun.COM int len = snprintf(NULL, 0, "%llx", rp->v);
132811202SStephen.Hanson@Sun.COM char *s = MALLOC(len + 1);
132911202SStephen.Hanson@Sun.COM
133011202SStephen.Hanson@Sun.COM (void) snprintf(s, len + 1, "%llx", rp->v);
133111202SStephen.Hanson@Sun.COM rp->t = STRING;
133211202SStephen.Hanson@Sun.COM rp->v = (uintptr_t)stable(s);
133311202SStephen.Hanson@Sun.COM FREE(s);
133411202SStephen.Hanson@Sun.COM }
133511202SStephen.Hanson@Sun.COM }
133611202SStephen.Hanson@Sun.COM
13371414Scindi /* auto-convert strings to numbers */
13381414Scindi if (dtype == UINT64) {
13391414Scindi if (lp->t == STRING) {
13401414Scindi lp->t = UINT64;
13411717Swesolows lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
13421414Scindi }
13431414Scindi if (rp != NULL && rp->t == STRING) {
13441414Scindi rp->t = UINT64;
13451717Swesolows rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
13461414Scindi }
13471414Scindi }
13481414Scindi
13490Sstevel@tonic-gate if (dtype != UNDEFINED && lp->t != dtype) {
13504436Sstephh outfl(O_DIE, np->file, np->line,
13514436Sstephh "invalid datatype of argument for operation %s",
13524436Sstephh ptree_nodetype2str(np->t));
13534436Sstephh /* NOTREACHED */
13540Sstevel@tonic-gate return (1);
13550Sstevel@tonic-gate }
13560Sstevel@tonic-gate
13570Sstevel@tonic-gate if (rp != NULL && lp->t != rp->t) {
13584436Sstephh outfl(O_DIE, np->file, np->line,
13594436Sstephh "mismatch in datatype of arguments for operation %s",
13604436Sstephh ptree_nodetype2str(np->t));
13614436Sstephh /* NOTREACHED */
13620Sstevel@tonic-gate return (1);
13630Sstevel@tonic-gate }
13640Sstevel@tonic-gate
13650Sstevel@tonic-gate return (0);
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate
13680Sstevel@tonic-gate /*
13690Sstevel@tonic-gate * eval_expr -- evaluate expression into *valuep
13700Sstevel@tonic-gate *
13710Sstevel@tonic-gate * the meaning of the return value depends on the input value of try.
13720Sstevel@tonic-gate *
13730Sstevel@tonic-gate * for try == 1: if any deferred items are encounted, bail out and return
13740Sstevel@tonic-gate * false. returns true if we made it through entire expression without
13750Sstevel@tonic-gate * hitting any deferred items.
13760Sstevel@tonic-gate *
13770Sstevel@tonic-gate * for try == 0: return true if all operations were performed successfully.
13780Sstevel@tonic-gate * return false if otherwise. for example, any of the following conditions
13790Sstevel@tonic-gate * will result in a false return value:
13800Sstevel@tonic-gate * - attempted use of an uninitialized global variable
13810Sstevel@tonic-gate * - failure in function evaluation
13820Sstevel@tonic-gate * - illegal arithmetic operation (argument out of range)
13830Sstevel@tonic-gate */
13840Sstevel@tonic-gate int
eval_expr(struct node * np,struct lut * ex,struct node * events[],struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,struct evalue * valuep)13854436Sstephh eval_expr(struct node *np, struct lut *ex, struct node *events[],
13860Sstevel@tonic-gate struct lut **globals, struct config *croot, struct arrow *arrowp,
13870Sstevel@tonic-gate int try, struct evalue *valuep)
13880Sstevel@tonic-gate {
13890Sstevel@tonic-gate struct evalue *gval;
13900Sstevel@tonic-gate struct evalue lval;
13910Sstevel@tonic-gate struct evalue rval;
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate if (np == NULL) {
13940Sstevel@tonic-gate valuep->t = UINT64;
13950Sstevel@tonic-gate valuep->v = 1; /* no constraint means "true" */
13960Sstevel@tonic-gate return (1);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate valuep->t = UNDEFINED;
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate switch (np->t) {
14020Sstevel@tonic-gate case T_GLOBID:
14030Sstevel@tonic-gate if (try)
14040Sstevel@tonic-gate return (0);
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate /*
14070Sstevel@tonic-gate * only handle case of getting (and not setting) the value
14080Sstevel@tonic-gate * of a global variable
14090Sstevel@tonic-gate */
14100Sstevel@tonic-gate gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
14110Sstevel@tonic-gate if (gval == NULL) {
14120Sstevel@tonic-gate return (0);
14130Sstevel@tonic-gate } else {
14140Sstevel@tonic-gate valuep->t = gval->t;
14150Sstevel@tonic-gate valuep->v = gval->v;
14160Sstevel@tonic-gate return (1);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate
14190Sstevel@tonic-gate case T_ASSIGN:
14200Sstevel@tonic-gate if (try)
14210Sstevel@tonic-gate return (0);
14220Sstevel@tonic-gate
14230Sstevel@tonic-gate /*
14240Sstevel@tonic-gate * first evaluate rhs, then try to store value in lhs which
14250Sstevel@tonic-gate * should be a global variable
14260Sstevel@tonic-gate */
14274436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14284436Sstephh arrowp, try, &rval))
14290Sstevel@tonic-gate return (0);
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate ASSERT(np->u.expr.left->t == T_GLOBID);
14320Sstevel@tonic-gate gval = lut_lookup(*globals,
14334436Sstephh (void *)np->u.expr.left->u.globid.s, NULL);
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate if (gval == NULL) {
14360Sstevel@tonic-gate gval = MALLOC(sizeof (*gval));
14370Sstevel@tonic-gate *globals = lut_add(*globals,
14384436Sstephh (void *) np->u.expr.left->u.globid.s, gval, NULL);
14390Sstevel@tonic-gate }
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate gval->t = rval.t;
14420Sstevel@tonic-gate gval->v = rval.v;
14431414Scindi
14441414Scindi if (gval->t == UINT64) {
14451414Scindi out(O_ALTFP|O_VERB2,
14461414Scindi "assign $%s=%llu",
14471414Scindi np->u.expr.left->u.globid.s, gval->v);
14481414Scindi } else {
14491414Scindi out(O_ALTFP|O_VERB2,
14501414Scindi "assign $%s=\"%s\"",
14511717Swesolows np->u.expr.left->u.globid.s,
14521717Swesolows (char *)(uintptr_t)gval->v);
14531414Scindi }
14541414Scindi
14551414Scindi /*
14561414Scindi * but always return true -- an assignment should not
14571414Scindi * cause a constraint to be false.
14581414Scindi */
14591414Scindi valuep->t = UINT64;
14601414Scindi valuep->v = 1;
14610Sstevel@tonic-gate return (1);
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate case T_EQ:
14640Sstevel@tonic-gate #define IMPLICIT_ASSIGN_IN_EQ
14650Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ
14660Sstevel@tonic-gate /*
14670Sstevel@tonic-gate * if lhs is an uninitialized global variable, perform
14680Sstevel@tonic-gate * an assignment.
14690Sstevel@tonic-gate *
14700Sstevel@tonic-gate * one insidious side effect of implicit assignment is
14710Sstevel@tonic-gate * that the "==" operator does not return a Boolean if
14720Sstevel@tonic-gate * implicit assignment was performed.
14730Sstevel@tonic-gate */
14740Sstevel@tonic-gate if (try == 0 &&
14750Sstevel@tonic-gate np->u.expr.left->t == T_GLOBID &&
14760Sstevel@tonic-gate (gval = lut_lookup(*globals,
14774436Sstephh (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
14784436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals,
14794436Sstephh croot, arrowp, try, &rval))
14800Sstevel@tonic-gate return (0);
14810Sstevel@tonic-gate
14820Sstevel@tonic-gate gval = MALLOC(sizeof (*gval));
14830Sstevel@tonic-gate *globals = lut_add(*globals,
14844436Sstephh (void *) np->u.expr.left->u.globid.s,
14854436Sstephh gval, NULL);
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate gval->t = rval.t;
14880Sstevel@tonic-gate gval->v = rval.v;
14890Sstevel@tonic-gate valuep->t = rval.t;
14900Sstevel@tonic-gate valuep->v = rval.v;
14910Sstevel@tonic-gate return (1);
14920Sstevel@tonic-gate }
14930Sstevel@tonic-gate #endif /* IMPLICIT_ASSIGN_IN_EQ */
14940Sstevel@tonic-gate
14954436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14964436Sstephh arrowp, try, &lval))
14974436Sstephh return (0);
14984436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14994436Sstephh arrowp, try, &rval))
15000Sstevel@tonic-gate return (0);
15014436Sstephh if (rval.t == UINT64 || lval.t == UINT64) {
15024436Sstephh if (check_expr_args(&lval, &rval, UINT64, np))
15034436Sstephh return (0);
15044436Sstephh } else {
15054436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np))
15064436Sstephh return (0);
15074436Sstephh }
15080Sstevel@tonic-gate
15090Sstevel@tonic-gate valuep->t = UINT64;
15100Sstevel@tonic-gate valuep->v = (lval.v == rval.v);
15110Sstevel@tonic-gate return (1);
15120Sstevel@tonic-gate
15130Sstevel@tonic-gate case T_LT:
15144436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15154436Sstephh arrowp, try, &lval))
15160Sstevel@tonic-gate return (0);
15174436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15184436Sstephh arrowp, try, &rval))
15190Sstevel@tonic-gate return (0);
15201414Scindi if (check_expr_args(&lval, &rval, UINT64, np))
15210Sstevel@tonic-gate return (0);
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate valuep->t = UINT64;
15240Sstevel@tonic-gate valuep->v = (lval.v < rval.v);
15250Sstevel@tonic-gate return (1);
15260Sstevel@tonic-gate
15270Sstevel@tonic-gate case T_LE:
15284436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15294436Sstephh arrowp, try, &lval))
15300Sstevel@tonic-gate return (0);
15314436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15324436Sstephh arrowp, try, &rval))
15330Sstevel@tonic-gate return (0);
15341414Scindi if (check_expr_args(&lval, &rval, UINT64, np))
15350Sstevel@tonic-gate return (0);
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate valuep->t = UINT64;
15380Sstevel@tonic-gate valuep->v = (lval.v <= rval.v);
15390Sstevel@tonic-gate return (1);
15400Sstevel@tonic-gate
15410Sstevel@tonic-gate case T_GT:
15424436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15434436Sstephh arrowp, try, &lval))
15440Sstevel@tonic-gate return (0);
15454436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15464436Sstephh arrowp, try, &rval))
15470Sstevel@tonic-gate return (0);
15481414Scindi if (check_expr_args(&lval, &rval, UINT64, np))
15490Sstevel@tonic-gate return (0);
15500Sstevel@tonic-gate
15510Sstevel@tonic-gate valuep->t = UINT64;
15520Sstevel@tonic-gate valuep->v = (lval.v > rval.v);
15530Sstevel@tonic-gate return (1);
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate case T_GE:
15564436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15574436Sstephh arrowp, try, &lval))
15580Sstevel@tonic-gate return (0);
15594436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15604436Sstephh arrowp, try, &rval))
15610Sstevel@tonic-gate return (0);
15621414Scindi if (check_expr_args(&lval, &rval, UINT64, np))
15630Sstevel@tonic-gate return (0);
15640Sstevel@tonic-gate
15650Sstevel@tonic-gate valuep->t = UINT64;
15660Sstevel@tonic-gate valuep->v = (lval.v >= rval.v);
15670Sstevel@tonic-gate return (1);
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate case T_BITAND:
15704436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15714436Sstephh arrowp, try, &lval))
15720Sstevel@tonic-gate return (0);
15734436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15744436Sstephh arrowp, try, &rval))
15750Sstevel@tonic-gate return (0);
15760Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
15770Sstevel@tonic-gate return (0);
15780Sstevel@tonic-gate
15790Sstevel@tonic-gate valuep->t = lval.t;
15800Sstevel@tonic-gate valuep->v = (lval.v & rval.v);
15810Sstevel@tonic-gate return (1);
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate case T_BITOR:
15844436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15854436Sstephh arrowp, try, &lval))
15860Sstevel@tonic-gate return (0);
15874436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15884436Sstephh arrowp, try, &rval))
15890Sstevel@tonic-gate return (0);
15900Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
15910Sstevel@tonic-gate return (0);
15920Sstevel@tonic-gate
15930Sstevel@tonic-gate valuep->t = lval.t;
15940Sstevel@tonic-gate valuep->v = (lval.v | rval.v);
15950Sstevel@tonic-gate return (1);
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate case T_BITXOR:
15984436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15994436Sstephh arrowp, try, &lval))
16000Sstevel@tonic-gate return (0);
16014436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16024436Sstephh arrowp, try, &rval))
16030Sstevel@tonic-gate return (0);
16040Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
16050Sstevel@tonic-gate return (0);
16060Sstevel@tonic-gate
16070Sstevel@tonic-gate valuep->t = lval.t;
16080Sstevel@tonic-gate valuep->v = (lval.v ^ rval.v);
16090Sstevel@tonic-gate return (1);
16100Sstevel@tonic-gate
16110Sstevel@tonic-gate case T_BITNOT:
16124436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16134436Sstephh arrowp, try, &lval))
16140Sstevel@tonic-gate return (0);
16150Sstevel@tonic-gate ASSERT(np->u.expr.right == NULL);
16160Sstevel@tonic-gate if (check_expr_args(&lval, NULL, UINT64, np))
16170Sstevel@tonic-gate return (0);
16180Sstevel@tonic-gate
16190Sstevel@tonic-gate valuep->t = UINT64;
16200Sstevel@tonic-gate valuep->v = ~ lval.v;
16210Sstevel@tonic-gate return (1);
16220Sstevel@tonic-gate
16230Sstevel@tonic-gate case T_LSHIFT:
16244436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16254436Sstephh arrowp, try, &lval))
16260Sstevel@tonic-gate return (0);
16274436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16284436Sstephh arrowp, try, &rval))
16290Sstevel@tonic-gate return (0);
16300Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
16310Sstevel@tonic-gate return (0);
16320Sstevel@tonic-gate
16330Sstevel@tonic-gate valuep->t = UINT64;
16340Sstevel@tonic-gate valuep->v = (lval.v << rval.v);
16350Sstevel@tonic-gate return (1);
16360Sstevel@tonic-gate
16370Sstevel@tonic-gate case T_RSHIFT:
16384436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16394436Sstephh arrowp, try, &lval))
16400Sstevel@tonic-gate return (0);
16414436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16424436Sstephh arrowp, try, &rval))
16430Sstevel@tonic-gate return (0);
16440Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
16450Sstevel@tonic-gate return (0);
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate valuep->t = UINT64;
16480Sstevel@tonic-gate valuep->v = (lval.v >> rval.v);
16490Sstevel@tonic-gate return (1);
16500Sstevel@tonic-gate
16510Sstevel@tonic-gate case T_CONDIF: {
16520Sstevel@tonic-gate struct node *retnp;
16530Sstevel@tonic-gate int dotrue = 0;
16540Sstevel@tonic-gate
16550Sstevel@tonic-gate /*
16560Sstevel@tonic-gate * evaluate
16570Sstevel@tonic-gate * expression ? stmtA [ : stmtB ]
16580Sstevel@tonic-gate *
16590Sstevel@tonic-gate * first see if expression is true or false, then determine
16600Sstevel@tonic-gate * if stmtA (or stmtB, if it exists) should be evaluated.
16610Sstevel@tonic-gate *
16620Sstevel@tonic-gate * "dotrue = 1" means stmtA should be evaluated.
16630Sstevel@tonic-gate */
16645204Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16655204Sstephh arrowp, try, &lval))
16665204Sstephh return (0);
16675204Sstephh
16685204Sstephh if (lval.t != UNDEFINED && lval.v != 0)
16690Sstevel@tonic-gate dotrue = 1;
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate ASSERT(np->u.expr.right != NULL);
16720Sstevel@tonic-gate if (np->u.expr.right->t == T_CONDELSE) {
16730Sstevel@tonic-gate if (dotrue)
16740Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.left;
16750Sstevel@tonic-gate else
16760Sstevel@tonic-gate retnp = np->u.expr.right->u.expr.right;
16770Sstevel@tonic-gate } else {
16780Sstevel@tonic-gate /* no ELSE clause */
16790Sstevel@tonic-gate if (dotrue)
16800Sstevel@tonic-gate retnp = np->u.expr.right;
16810Sstevel@tonic-gate else {
16824436Sstephh outfl(O_DIE, np->file, np->line,
16834436Sstephh "eval_expr: missing condelse");
16840Sstevel@tonic-gate }
16850Sstevel@tonic-gate }
16860Sstevel@tonic-gate
16874436Sstephh if (!eval_expr(retnp, ex, events, globals, croot,
16884436Sstephh arrowp, try, valuep))
16890Sstevel@tonic-gate return (0);
16900Sstevel@tonic-gate return (1);
16910Sstevel@tonic-gate }
16920Sstevel@tonic-gate
16930Sstevel@tonic-gate case T_CONDELSE:
16940Sstevel@tonic-gate /*
16950Sstevel@tonic-gate * shouldn't get here, since T_CONDELSE is supposed to be
16960Sstevel@tonic-gate * evaluated as part of T_CONDIF
16970Sstevel@tonic-gate */
16980Sstevel@tonic-gate out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
16990Sstevel@tonic-gate ptree_nodetype2str(np->t));
17004436Sstephh /*NOTREACHED*/
17010Sstevel@tonic-gate
17020Sstevel@tonic-gate case T_NE:
17034436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17044436Sstephh arrowp, try, &lval))
17054436Sstephh return (0);
17064436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
17074436Sstephh arrowp, try, &rval))
17080Sstevel@tonic-gate return (0);
17094436Sstephh if (rval.t == UINT64 || lval.t == UINT64) {
17104436Sstephh if (check_expr_args(&lval, &rval, UINT64, np))
17114436Sstephh return (0);
17124436Sstephh } else {
17134436Sstephh if (check_expr_args(&lval, &rval, UNDEFINED, np))
17144436Sstephh return (0);
17154436Sstephh }
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate valuep->t = UINT64;
17180Sstevel@tonic-gate valuep->v = (lval.v != rval.v);
17190Sstevel@tonic-gate return (1);
17200Sstevel@tonic-gate
17210Sstevel@tonic-gate case T_LIST:
17220Sstevel@tonic-gate case T_AND:
17234436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17244436Sstephh arrowp, try, valuep)) {
17253159Sstephh /*
17263159Sstephh * if lhs is unknown, still check rhs. If that
17275204Sstephh * is false we can return false irrespective of lhs
17283159Sstephh */
17295204Sstephh if (!try) {
17305204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
17315204Sstephh return (0);
17325204Sstephh }
17334436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals,
17344436Sstephh croot, arrowp, try, valuep)) {
17354436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
17363159Sstephh return (0);
17374436Sstephh }
17384436Sstephh if (valuep->v != 0) {
17394436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK;
17403159Sstephh return (0);
17414436Sstephh }
17423159Sstephh }
17430Sstevel@tonic-gate if (valuep->v == 0) {
17440Sstevel@tonic-gate valuep->t = UINT64;
17450Sstevel@tonic-gate return (1);
17460Sstevel@tonic-gate }
17474436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
17484436Sstephh arrowp, try, valuep)) {
17494436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK;
17500Sstevel@tonic-gate return (0);
17514436Sstephh }
17520Sstevel@tonic-gate valuep->t = UINT64;
17530Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1;
17540Sstevel@tonic-gate return (1);
17550Sstevel@tonic-gate
17560Sstevel@tonic-gate case T_OR:
17574436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17584436Sstephh arrowp, try, valuep)) {
17593159Sstephh /*
17603159Sstephh * if lhs is unknown, still check rhs. If that
17615204Sstephh * is true we can return true irrespective of lhs
17623159Sstephh */
17635204Sstephh if (!try) {
17645204Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
17655204Sstephh return (0);
17665204Sstephh }
17674436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals,
17684436Sstephh croot, arrowp, try, valuep)) {
17694436Sstephh np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
17703159Sstephh return (0);
17714436Sstephh }
17724436Sstephh if (valuep->v == 0) {
17734436Sstephh np->u.expr.temp = EXPR_TEMP_LHS_UNK;
17743159Sstephh return (0);
17754436Sstephh }
17763159Sstephh }
17770Sstevel@tonic-gate if (valuep->v != 0) {
17780Sstevel@tonic-gate valuep->t = UINT64;
17790Sstevel@tonic-gate valuep->v = 1;
17800Sstevel@tonic-gate return (1);
17810Sstevel@tonic-gate }
17824436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
17834436Sstephh arrowp, try, valuep)) {
17844436Sstephh np->u.expr.temp = EXPR_TEMP_RHS_UNK;
17850Sstevel@tonic-gate return (0);
17864436Sstephh }
17870Sstevel@tonic-gate valuep->t = UINT64;
17880Sstevel@tonic-gate valuep->v = valuep->v == 0 ? 0 : 1;
17890Sstevel@tonic-gate return (1);
17900Sstevel@tonic-gate
17910Sstevel@tonic-gate case T_NOT:
17924436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17934436Sstephh arrowp, try, valuep))
17940Sstevel@tonic-gate return (0);
17950Sstevel@tonic-gate valuep->t = UINT64;
17960Sstevel@tonic-gate valuep->v = ! valuep->v;
17970Sstevel@tonic-gate return (1);
17980Sstevel@tonic-gate
17990Sstevel@tonic-gate case T_ADD:
18004436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18014436Sstephh arrowp, try, &lval))
18020Sstevel@tonic-gate return (0);
18034436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18044436Sstephh arrowp, try, &rval))
18050Sstevel@tonic-gate return (0);
18060Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
18070Sstevel@tonic-gate return (0);
18080Sstevel@tonic-gate
18090Sstevel@tonic-gate valuep->t = lval.t;
18100Sstevel@tonic-gate valuep->v = lval.v + rval.v;
18110Sstevel@tonic-gate return (1);
18120Sstevel@tonic-gate
18130Sstevel@tonic-gate case T_SUB:
18144436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18154436Sstephh arrowp, try, &lval))
18160Sstevel@tonic-gate return (0);
18174436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18184436Sstephh arrowp, try, &rval))
18190Sstevel@tonic-gate return (0);
18200Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
18210Sstevel@tonic-gate return (0);
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate /* since valuep is unsigned, return false if lval.v < rval.v */
18240Sstevel@tonic-gate if (lval.v < rval.v) {
18254436Sstephh outfl(O_DIE, np->file, np->line,
18264436Sstephh "eval_expr: T_SUB result is out of range");
18270Sstevel@tonic-gate }
18280Sstevel@tonic-gate
18290Sstevel@tonic-gate valuep->t = lval.t;
18300Sstevel@tonic-gate valuep->v = lval.v - rval.v;
18310Sstevel@tonic-gate return (1);
18320Sstevel@tonic-gate
18330Sstevel@tonic-gate case T_MUL:
18344436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18354436Sstephh arrowp, try, &lval))
18360Sstevel@tonic-gate return (0);
18374436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18384436Sstephh arrowp, try, &rval))
18390Sstevel@tonic-gate return (0);
18400Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
18410Sstevel@tonic-gate return (0);
18420Sstevel@tonic-gate
18430Sstevel@tonic-gate valuep->t = lval.t;
18440Sstevel@tonic-gate valuep->v = lval.v * rval.v;
18450Sstevel@tonic-gate return (1);
18460Sstevel@tonic-gate
18470Sstevel@tonic-gate case T_DIV:
18484436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18494436Sstephh arrowp, try, &lval))
18500Sstevel@tonic-gate return (0);
18514436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18524436Sstephh arrowp, try, &rval))
18530Sstevel@tonic-gate return (0);
18540Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
18550Sstevel@tonic-gate return (0);
18560Sstevel@tonic-gate
18570Sstevel@tonic-gate /* return false if dividing by zero */
18580Sstevel@tonic-gate if (rval.v == 0) {
18594436Sstephh outfl(O_DIE, np->file, np->line,
18604436Sstephh "eval_expr: T_DIV division by zero");
18610Sstevel@tonic-gate }
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate valuep->t = lval.t;
18640Sstevel@tonic-gate valuep->v = lval.v / rval.v;
18650Sstevel@tonic-gate return (1);
18660Sstevel@tonic-gate
18670Sstevel@tonic-gate case T_MOD:
18684436Sstephh if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18694436Sstephh arrowp, try, &lval))
18700Sstevel@tonic-gate return (0);
18714436Sstephh if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18724436Sstephh arrowp, try, &rval))
18730Sstevel@tonic-gate return (0);
18740Sstevel@tonic-gate if (check_expr_args(&lval, &rval, UINT64, np))
18750Sstevel@tonic-gate return (0);
18760Sstevel@tonic-gate
18770Sstevel@tonic-gate /* return false if dividing by zero */
18780Sstevel@tonic-gate if (rval.v == 0) {
18794436Sstephh outfl(O_DIE, np->file, np->line,
18804436Sstephh "eval_expr: T_MOD division by zero");
18810Sstevel@tonic-gate }
18820Sstevel@tonic-gate
18830Sstevel@tonic-gate valuep->t = lval.t;
18840Sstevel@tonic-gate valuep->v = lval.v % rval.v;
18850Sstevel@tonic-gate return (1);
18860Sstevel@tonic-gate
18870Sstevel@tonic-gate case T_NAME:
18880Sstevel@tonic-gate if (try) {
18890Sstevel@tonic-gate struct iterinfo *iterinfop;
18904436Sstephh struct node *np1, *np2;
18914436Sstephh int i, gotmatch = 0;
18920Sstevel@tonic-gate
18930Sstevel@tonic-gate /*
18944436Sstephh * Check if we have an exact match of the nonwildcarded
18954436Sstephh * path in oldepname - if so we can just use the
18964436Sstephh * full wildcarded path in epname.
18970Sstevel@tonic-gate */
18984436Sstephh for (i = 0; i < 1; i++) {
18994436Sstephh for (np1 = np,
19004436Sstephh np2 = events[i]->u.event.oldepname;
19014436Sstephh np1 != NULL && np2 != NULL;
19024436Sstephh np1 = np1->u.name.next,
19034436Sstephh np2 = np2->u.name.next) {
19044436Sstephh if (strcmp(np1->u.name.s,
19054436Sstephh np2->u.name.s) != 0)
19064436Sstephh break;
19074436Sstephh if (np1->u.name.child->t !=
19084436Sstephh np2->u.name.child->t)
19094436Sstephh break;
19104436Sstephh if (np1->u.name.child->t == T_NUM &&
19114436Sstephh np1->u.name.child->u.ull !=
19124436Sstephh np2->u.name.child->u.ull)
19134436Sstephh break;
19144436Sstephh if (np1->u.name.child->t == T_NAME &&
19154436Sstephh strcmp(np1->u.name.child->u.name.s,
19164436Sstephh np2->u.name.child->u.name.s) != 0)
19174436Sstephh break;
19184436Sstephh gotmatch++;
19194436Sstephh }
19204436Sstephh if (np1 == NULL && np2 == NULL) {
19214436Sstephh valuep->t = NODEPTR;
19224436Sstephh valuep->v = (uintptr_t)
19234436Sstephh events[i]->u.event.epname;
19244436Sstephh return (1);
19254436Sstephh }
19260Sstevel@tonic-gate }
19274436Sstephh if (!gotmatch) {
19284436Sstephh /*
19294436Sstephh * we're not wildcarding. However at
19304436Sstephh * itree_create() time, we can also expand
19314436Sstephh * simple iterators - so check for those.
19324436Sstephh */
19334436Sstephh iterinfop = lut_lookup(ex, (void *)np->u.name.s,
19344436Sstephh NULL);
19354436Sstephh if (iterinfop != NULL) {
19364436Sstephh valuep->t = UINT64;
19374436Sstephh valuep->v =
19384436Sstephh (unsigned long long)iterinfop->num;
19394436Sstephh return (1);
19404436Sstephh }
19414436Sstephh }
19424436Sstephh /*
19434436Sstephh * For anything else we'll have to wait for eval_dup().
19444436Sstephh */
19450Sstevel@tonic-gate return (0);
19460Sstevel@tonic-gate }
19470Sstevel@tonic-gate
19480Sstevel@tonic-gate /* return address of struct node */
19490Sstevel@tonic-gate valuep->t = NODEPTR;
19501717Swesolows valuep->v = (uintptr_t)np;
19510Sstevel@tonic-gate return (1);
19520Sstevel@tonic-gate
19530Sstevel@tonic-gate case T_QUOTE:
19540Sstevel@tonic-gate valuep->t = STRING;
19551717Swesolows valuep->v = (uintptr_t)np->u.quote.s;
19560Sstevel@tonic-gate return (1);
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate case T_FUNC:
19594436Sstephh return (eval_func(np, ex, events, np->u.func.arglist,
19604436Sstephh globals, croot, arrowp, try, valuep));
19610Sstevel@tonic-gate
19620Sstevel@tonic-gate case T_NUM:
19637197Sstephh case T_TIMEVAL:
19640Sstevel@tonic-gate valuep->t = UINT64;
19650Sstevel@tonic-gate valuep->v = np->u.ull;
19660Sstevel@tonic-gate return (1);
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate default:
19690Sstevel@tonic-gate outfl(O_DIE, np->file, np->line,
19700Sstevel@tonic-gate "eval_expr: unexpected node type: %s",
19710Sstevel@tonic-gate ptree_nodetype2str(np->t));
19720Sstevel@tonic-gate }
19730Sstevel@tonic-gate /*NOTREACHED*/
19741717Swesolows return (0);
19750Sstevel@tonic-gate }
19760Sstevel@tonic-gate
19770Sstevel@tonic-gate /*
19780Sstevel@tonic-gate * eval_fru() and eval_asru() don't do much, but are called from a number
19790Sstevel@tonic-gate * of places.
19800Sstevel@tonic-gate */
19814436Sstephh static struct node *
eval_fru(struct node * np)19820Sstevel@tonic-gate eval_fru(struct node *np)
19830Sstevel@tonic-gate {
19840Sstevel@tonic-gate ASSERT(np->t == T_NAME);
19850Sstevel@tonic-gate return (np);
19860Sstevel@tonic-gate }
19870Sstevel@tonic-gate
19884436Sstephh static struct node *
eval_asru(struct node * np)19890Sstevel@tonic-gate eval_asru(struct node *np)
19900Sstevel@tonic-gate {
19910Sstevel@tonic-gate ASSERT(np->t == T_NAME);
19920Sstevel@tonic-gate return (np);
19930Sstevel@tonic-gate }
1994