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