xref: /titanic_44/usr/src/cmd/fm/modules/common/eversholt/eval.c (revision 705e9f42059a29645037854181bc0bf216398c4c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
580ab886dSwesolows  * Common Development and Distribution License (the "License").
680ab886dSwesolows  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2180ab886dSwesolows 
227c478bd9Sstevel@tonic-gate /*
23*705e9f42SStephen Hanson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * eval.c -- constraint evaluation module
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * this module evaluates constraints.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include "alloc.h"
367c478bd9Sstevel@tonic-gate #include "out.h"
377c478bd9Sstevel@tonic-gate #include "stable.h"
387c478bd9Sstevel@tonic-gate #include "literals.h"
397c478bd9Sstevel@tonic-gate #include "lut.h"
407c478bd9Sstevel@tonic-gate #include "tree.h"
417c478bd9Sstevel@tonic-gate #include "ptree.h"
427c478bd9Sstevel@tonic-gate #include "itree.h"
437aec1d6eScindi #include "ipath.h"
447c478bd9Sstevel@tonic-gate #include "eval.h"
457c478bd9Sstevel@tonic-gate #include "config.h"
467c478bd9Sstevel@tonic-gate #include "platform.h"
477aec1d6eScindi #include "fme.h"
487aec1d6eScindi #include "stats.h"
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate static struct node *eval_dup(struct node *np, struct lut *ex,
51b5016cbbSstephh     struct node *events[]);
527aec1d6eScindi static int check_expr_args(struct evalue *lp, struct evalue *rp,
537aec1d6eScindi     enum datatype dtype, struct node *np);
54b5016cbbSstephh static struct node *eval_fru(struct node *np);
55b5016cbbSstephh static struct node *eval_asru(struct node *np);
567c478bd9Sstevel@tonic-gate 
5725c6ff4bSstephh extern fmd_hdl_t *Hdl;	/* handle from eft.c */
5825c6ff4bSstephh 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * begins_with -- return true if rhs path begins with everything in lhs path
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate static int
begins_with(struct node * lhs,struct node * rhs,struct lut * ex)63b5016cbbSstephh begins_with(struct node *lhs, struct node *rhs, struct lut *ex)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 	int lnum;
667c478bd9Sstevel@tonic-gate 	int rnum;
67b5016cbbSstephh 	struct iterinfo *iterinfop;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	if (lhs == NULL)
707c478bd9Sstevel@tonic-gate 		return (1);	/* yep -- it all matched */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	if (rhs == NULL)
737c478bd9Sstevel@tonic-gate 		return (0);	/* nope, ran out of rhs first */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str);
767c478bd9Sstevel@tonic-gate 	ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	if (lhs->u.name.s != rhs->u.name.s)
797c478bd9Sstevel@tonic-gate 		return (0);	/* nope, different component names */
807c478bd9Sstevel@tonic-gate 
81b5016cbbSstephh 	if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) {
827c478bd9Sstevel@tonic-gate 		lnum = (int)lhs->u.name.child->u.ull;
83b5016cbbSstephh 	} else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) {
84b5016cbbSstephh 		iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s,
85b5016cbbSstephh 		    NULL);
86b5016cbbSstephh 		if (iterinfop != NULL)
87b5016cbbSstephh 			lnum = iterinfop->num;
887c478bd9Sstevel@tonic-gate 		else
897c478bd9Sstevel@tonic-gate 			out(O_DIE, "begins_with: unexpected lhs child");
90b5016cbbSstephh 	} else {
91b5016cbbSstephh 		out(O_DIE, "begins_with: unexpected lhs child");
92b5016cbbSstephh 	}
937c478bd9Sstevel@tonic-gate 
94b5016cbbSstephh 	if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) {
957c478bd9Sstevel@tonic-gate 		rnum = (int)rhs->u.name.child->u.ull;
96b5016cbbSstephh 	} else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) {
97b5016cbbSstephh 		iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s,
98b5016cbbSstephh 		    NULL);
99b5016cbbSstephh 		if (iterinfop != NULL)
100b5016cbbSstephh 			rnum = iterinfop->num;
1017c478bd9Sstevel@tonic-gate 		else
1027c478bd9Sstevel@tonic-gate 			out(O_DIE, "begins_with: unexpected rhs child");
103b5016cbbSstephh 	} else {
104b5016cbbSstephh 		out(O_DIE, "begins_with: unexpected rhs child");
105b5016cbbSstephh 	}
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	if (lnum != rnum)
1087c478bd9Sstevel@tonic-gate 		return (0);	/* nope, instance numbers were different */
1097c478bd9Sstevel@tonic-gate 
110b5016cbbSstephh 	return (begins_with(lhs->u.name.next, rhs->u.name.next, ex));
111b5016cbbSstephh }
112b5016cbbSstephh 
113b5016cbbSstephh /*
114b5016cbbSstephh  * eval_getname - used by eval_func to evaluate a name, preferably without using
115b5016cbbSstephh  * eval_dup (but if it does have to use eval_dup then the *dupedp flag is set).
116b5016cbbSstephh  */
117b5016cbbSstephh static struct node *
eval_getname(struct node * funcnp,struct lut * ex,struct node * events[],struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,int * dupedp)118b5016cbbSstephh eval_getname(struct node *funcnp, struct lut *ex, struct node *events[],
119b5016cbbSstephh     struct node *np, struct lut **globals,
120b5016cbbSstephh     struct config *croot, struct arrow *arrowp, int try, int *dupedp)
121b5016cbbSstephh {
122b5016cbbSstephh 	struct node *nodep;
123b5016cbbSstephh 	const char *funcname = funcnp->u.func.s;
124b5016cbbSstephh 	struct evalue val;
125b5016cbbSstephh 
126b5016cbbSstephh 	if (np->t == T_NAME)
127b5016cbbSstephh 		nodep = np;
128b0daa853SStephen Hanson 	else if (np->t == T_FUNC && np->u.func.s == L_fru)
129b5016cbbSstephh 		nodep = eval_fru(np->u.func.arglist);
130b0daa853SStephen Hanson 	else if (np->t == T_FUNC && np->u.func.s == L_asru)
131b5016cbbSstephh 		nodep = eval_asru(np->u.func.arglist);
132b0daa853SStephen Hanson 	else if (np->t == T_FUNC) {
133b0daa853SStephen Hanson 		if (eval_expr(np, ex, events, globals, croot, arrowp, try,
134b0daa853SStephen Hanson 		    &val) == 0)
135b0daa853SStephen Hanson 			/*
136b0daa853SStephen Hanson 			 * Can't evaluate yet. Return null so constraint is
137b0daa853SStephen Hanson 			 * deferred.
138b0daa853SStephen Hanson 			 */
139b0daa853SStephen Hanson 			return (NULL);
140b0daa853SStephen Hanson 		if (val.t == NODEPTR)
141b0daa853SStephen Hanson 			return ((struct node *)(uintptr_t)val.v);
142b5016cbbSstephh 		else
143b0daa853SStephen Hanson 			/*
144b0daa853SStephen Hanson 			 * just return the T_FUNC - which the caller will
145b0daa853SStephen Hanson 			 * reject.
146b0daa853SStephen Hanson 			 */
147b0daa853SStephen Hanson 			return (np);
148b0daa853SStephen Hanson 	} else
149b5016cbbSstephh 		out(O_DIE, "%s: unexpected type: %s",
150b5016cbbSstephh 		    funcname, ptree_nodetype2str(np->t));
151b5016cbbSstephh 	if (try) {
152b5016cbbSstephh 		if (eval_expr(nodep, ex, events, globals, croot,
153b5016cbbSstephh 		    arrowp, try, &val) && val.t == NODEPTR)
154b5016cbbSstephh 			nodep = (struct node *)(uintptr_t)val.v;
155b5016cbbSstephh 		else {
156b5016cbbSstephh 			*dupedp = 1;
157b5016cbbSstephh 			nodep = eval_dup(nodep, ex, events);
158b5016cbbSstephh 		}
159b5016cbbSstephh 	}
160b5016cbbSstephh 	return (nodep);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
163b0daa853SStephen Hanson /*ARGSUSED*/
164b0daa853SStephen Hanson static int
eval_cat(struct node * np,struct lut * ex,struct node * events[],struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,struct evalue * valuep)165b0daa853SStephen Hanson eval_cat(struct node *np, struct lut *ex, struct node *events[],
166b0daa853SStephen Hanson 	struct lut **globals, struct config *croot, struct arrow *arrowp,
167b0daa853SStephen Hanson 	int try, struct evalue *valuep)
168b0daa853SStephen Hanson {
169b0daa853SStephen Hanson 	if (np->t == T_LIST) {
170b0daa853SStephen Hanson 		struct evalue lval;
171b0daa853SStephen Hanson 		struct evalue rval;
172b0daa853SStephen Hanson 		int len;
173b0daa853SStephen Hanson 		char *s;
174b0daa853SStephen Hanson 
175b0daa853SStephen Hanson 		if (!eval_cat(np->u.expr.left, ex, events, globals, croot,
176b0daa853SStephen Hanson 		    arrowp, try, &lval))
177b0daa853SStephen Hanson 			return (0);
178b0daa853SStephen Hanson 		if (!eval_cat(np->u.expr.right, ex, events, globals, croot,
179b0daa853SStephen Hanson 		    arrowp, try, &rval))
180b0daa853SStephen Hanson 			return (0);
181b0daa853SStephen Hanson 		len = snprintf(NULL, 0, "%s%s", (char *)(uintptr_t)lval.v,
182b0daa853SStephen Hanson 		    (char *)(uintptr_t)rval.v);
183b0daa853SStephen Hanson 		s = MALLOC(len + 1);
184b0daa853SStephen Hanson 
185b0daa853SStephen Hanson 		(void) snprintf(s, len + 1, "%s%s", (char *)(uintptr_t)lval.v,
186b0daa853SStephen Hanson 		    (char *)(uintptr_t)rval.v);
187b0daa853SStephen Hanson 		outfl(O_ALTFP|O_VERB2, np->file, np->line,
188b0daa853SStephen Hanson 		    "eval_cat: %s %s returns %s", (char *)(uintptr_t)lval.v,
189b0daa853SStephen Hanson 		    (char *)(uintptr_t)rval.v, s);
190b0daa853SStephen Hanson 		valuep->t = STRING;
191b0daa853SStephen Hanson 		valuep->v = (uintptr_t)stable(s);
192b0daa853SStephen Hanson 		FREE(s);
193b0daa853SStephen Hanson 	} else {
194b0daa853SStephen Hanson 		if (!eval_expr(np, ex, events, globals, croot,
195b0daa853SStephen Hanson 		    arrowp, try, valuep))
196b0daa853SStephen Hanson 			return (0);
197b0daa853SStephen Hanson 		if (check_expr_args(valuep, NULL, STRING, np))
198b0daa853SStephen Hanson 			return (0);
199b0daa853SStephen Hanson 	}
200b0daa853SStephen Hanson 	return (1);
201b0daa853SStephen Hanson }
202b0daa853SStephen Hanson 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * evaluate a variety of functions and place result in valuep.  return 1 if
2057c478bd9Sstevel@tonic-gate  * function evaluation was successful; 0 if otherwise (e.g., the case of an
2067c478bd9Sstevel@tonic-gate  * invalid argument to the function)
2077c478bd9Sstevel@tonic-gate  */
2087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2097c478bd9Sstevel@tonic-gate static int
eval_func(struct node * funcnp,struct lut * ex,struct node * events[],struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,struct evalue * valuep)210b5016cbbSstephh eval_func(struct node *funcnp, struct lut *ex, struct node *events[],
2117c478bd9Sstevel@tonic-gate     struct node *np, struct lut **globals,
2127c478bd9Sstevel@tonic-gate     struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	const char *funcname = funcnp->u.func.s;
215b5016cbbSstephh 	int duped_lhs = 0, duped_rhs = 0, duped = 0;
216b5016cbbSstephh 	struct node *lhs;
217b5016cbbSstephh 	struct node *rhs;
218b5016cbbSstephh 	struct config *cp;
219b5016cbbSstephh 	struct node *nodep;
220b5016cbbSstephh 	char *path;
221b5016cbbSstephh 	struct evalue val;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	if (funcname == L_within) {
2247c478bd9Sstevel@tonic-gate 		/* within()'s are not really constraints -- always true */
2257c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
2267c478bd9Sstevel@tonic-gate 		valuep->v = 1;
2277c478bd9Sstevel@tonic-gate 		return (1);
2287c478bd9Sstevel@tonic-gate 	} else if (funcname == L_is_under) {
229b5016cbbSstephh 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
230b5016cbbSstephh 		    croot, arrowp, try, &duped_lhs);
231b5016cbbSstephh 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
232b5016cbbSstephh 		    globals, croot, arrowp, try, &duped_rhs);
233b0daa853SStephen Hanson 		if (!rhs || !lhs)
234b0daa853SStephen Hanson 			return (0);
235b0daa853SStephen Hanson 		if (rhs->t != T_NAME || lhs->t != T_NAME) {
236b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
237b0daa853SStephen Hanson 			return (1);
238b0daa853SStephen Hanson 		}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
241b5016cbbSstephh 		valuep->v = begins_with(lhs, rhs, ex);
2427c478bd9Sstevel@tonic-gate 		out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
2437c478bd9Sstevel@tonic-gate 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
2447c478bd9Sstevel@tonic-gate 		out(O_ALTFP|O_VERB2|O_NONL, ",");
2457c478bd9Sstevel@tonic-gate 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
246b5016cbbSstephh 		out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v);
2477c478bd9Sstevel@tonic-gate 
248b5016cbbSstephh 		if (duped_lhs)
2497c478bd9Sstevel@tonic-gate 			tree_free(lhs);
250b5016cbbSstephh 		if (duped_rhs)
2517c478bd9Sstevel@tonic-gate 			tree_free(rhs);
2527c478bd9Sstevel@tonic-gate 		return (1);
2538a40a695Sgavinm 	} else if (funcname == L_confprop || funcname == L_confprop_defined) {
254d96ce684Sstephh 		const char *s;
255d96ce684Sstephh 
256d96ce684Sstephh 		/* for now s will point to a quote [see addconfigprop()] */
257d96ce684Sstephh 		ASSERT(np->u.expr.right->t == T_QUOTE);
258d96ce684Sstephh 
259b5016cbbSstephh 		nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
260b5016cbbSstephh 		    globals, croot, arrowp, try, &duped);
261b0daa853SStephen Hanson 		if (!nodep)
262b0daa853SStephen Hanson 			return (0);
263b0daa853SStephen Hanson 		if (nodep->t != T_NAME) {
264b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
265b0daa853SStephen Hanson 			return (1);
266b0daa853SStephen Hanson 		}
267b0daa853SStephen Hanson 
268b5016cbbSstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
269b5016cbbSstephh 			cp = nodep->u.name.last->u.name.cp;
270b5016cbbSstephh 		} else {
271b5016cbbSstephh 			path = ipath2str(NULL, ipath(nodep));
272d96ce684Sstephh 			cp = config_lookup(croot, path, 0);
273d96ce684Sstephh 			FREE((void *)path);
274b5016cbbSstephh 		}
275b5016cbbSstephh 		if (cp == NULL) {
276b5016cbbSstephh 			if (funcname == L_confprop) {
277b5016cbbSstephh 				out(O_ALTFP|O_VERB3, "%s: path ", funcname);
278b5016cbbSstephh 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
279b5016cbbSstephh 				out(O_ALTFP|O_VERB3, " not found");
280b5016cbbSstephh 				valuep->v = (uintptr_t)stable("");
281b5016cbbSstephh 				valuep->t = STRING;
282b5016cbbSstephh 				if (duped)
283b5016cbbSstephh 					tree_free(nodep);
2848a40a695Sgavinm 				return (1);
2858a40a695Sgavinm 			} else {
286b5016cbbSstephh 				valuep->v = 0;
287b5016cbbSstephh 				valuep->t = UINT64;
288b5016cbbSstephh 				if (duped)
289b5016cbbSstephh 					tree_free(nodep);
290b5016cbbSstephh 				return (1);
2918a40a695Sgavinm 			}
2928a40a695Sgavinm 		}
293d96ce684Sstephh 		s = config_getprop(cp, np->u.expr.right->u.quote.s);
294b5016cbbSstephh 		if (s == NULL && strcmp(np->u.expr.right->u.quote.s,
295b5016cbbSstephh 		    "class-code") == 0)
296b5016cbbSstephh 			s = config_getprop(cp, "CLASS-CODE");
2978a40a695Sgavinm 		if (s == NULL) {
298b5016cbbSstephh 			if (funcname == L_confprop) {
299b5016cbbSstephh 				out(O_ALTFP|O_VERB3|O_NONL,
300b5016cbbSstephh 				    "%s: \"%s\" not found for path ",
301b5016cbbSstephh 				    funcname, np->u.expr.right->u.quote.s);
302b5016cbbSstephh 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
303b5016cbbSstephh 				valuep->v = (uintptr_t)stable("");
304b5016cbbSstephh 				valuep->t = STRING;
305b5016cbbSstephh 				if (duped)
306b5016cbbSstephh 					tree_free(nodep);
3078a40a695Sgavinm 				return (1);
3088a40a695Sgavinm 			} else {
309b5016cbbSstephh 				valuep->v = 0;
310b5016cbbSstephh 				valuep->t = UINT64;
311b5016cbbSstephh 				if (duped)
312b5016cbbSstephh 					tree_free(nodep);
313b5016cbbSstephh 				return (1);
3148a40a695Sgavinm 			}
3158a40a695Sgavinm 		}
3168a40a695Sgavinm 
3178a40a695Sgavinm 		if (funcname == L_confprop) {
318d96ce684Sstephh 			valuep->v = (uintptr_t)stable(s);
319d96ce684Sstephh 			valuep->t = STRING;
320b5016cbbSstephh 			out(O_ALTFP|O_VERB3|O_NONL, "  %s(\"", funcname);
321b5016cbbSstephh 			ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
322b5016cbbSstephh 			out(O_ALTFP|O_VERB3|O_NONL,
323b5016cbbSstephh 			    "\", \"%s\") = \"%s\"  ",
324b5016cbbSstephh 			    np->u.expr.right->u.quote.s,
3258a40a695Sgavinm 			    (char *)(uintptr_t)valuep->v);
3268a40a695Sgavinm 		} else {
3278a40a695Sgavinm 			valuep->v = 1;
3288a40a695Sgavinm 			valuep->t = UINT64;
3298a40a695Sgavinm 		}
330b5016cbbSstephh 		if (duped)
331b5016cbbSstephh 			tree_free(nodep);
332d96ce684Sstephh 		return (1);
333b5016cbbSstephh 	} else if (funcname == L_is_connected) {
334b5016cbbSstephh 		const char *connstrings[] = { "connected", "CONNECTED", NULL };
335b5016cbbSstephh 		struct config *cp[2];
336b5016cbbSstephh 		const char *matchthis[2], *s;
337b5016cbbSstephh 		char *nameslist, *w;
338b5016cbbSstephh 		int i, j;
339b5016cbbSstephh 
340b5016cbbSstephh 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
341b5016cbbSstephh 		    croot, arrowp, try, &duped_lhs);
342b5016cbbSstephh 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
343b5016cbbSstephh 		    globals, croot, arrowp, try, &duped_rhs);
344b0daa853SStephen Hanson 		if (!rhs || !lhs)
345b0daa853SStephen Hanson 			return (0);
346b0daa853SStephen Hanson 		if (rhs->t != T_NAME || lhs->t != T_NAME) {
347b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
348b0daa853SStephen Hanson 			return (1);
349b0daa853SStephen Hanson 		}
350b0daa853SStephen Hanson 
351b5016cbbSstephh 		path = ipath2str(NULL, ipath(lhs));
352b5016cbbSstephh 		matchthis[1] = stable(path);
353b5016cbbSstephh 		if (lhs->u.name.last->u.name.cp != NULL)
354b5016cbbSstephh 			cp[0] = lhs->u.name.last->u.name.cp;
355b5016cbbSstephh 		else
356b5016cbbSstephh 			cp[0] = config_lookup(croot, path, 0);
357b5016cbbSstephh 		FREE((void *)path);
358b5016cbbSstephh 		path = ipath2str(NULL, ipath(rhs));
359b5016cbbSstephh 		matchthis[0] = stable(path);
360b5016cbbSstephh 		if (rhs->u.name.last->u.name.cp != NULL)
361b5016cbbSstephh 			cp[1] = rhs->u.name.last->u.name.cp;
362b5016cbbSstephh 		else
363b5016cbbSstephh 			cp[1] = config_lookup(croot, path, 0);
364b5016cbbSstephh 		FREE((void *)path);
365b5016cbbSstephh 		if (duped_lhs)
366b5016cbbSstephh 			tree_free(lhs);
367b5016cbbSstephh 		if (duped_rhs)
368b5016cbbSstephh 			tree_free(rhs);
369b5016cbbSstephh 
370b5016cbbSstephh 		valuep->t = UINT64;
371b5016cbbSstephh 		valuep->v = 0;
372b5016cbbSstephh 		if (cp[0] == NULL || cp[1] == NULL)
373b5016cbbSstephh 			return (1);
374b5016cbbSstephh 
375b5016cbbSstephh 		/* to thine self always be connected */
376b5016cbbSstephh 		if (cp[0] == cp[1]) {
377b5016cbbSstephh 			valuep->v = 1;
378b5016cbbSstephh 			return (1);
379b5016cbbSstephh 		}
380b5016cbbSstephh 
381b5016cbbSstephh 		/*
382b5016cbbSstephh 		 * Extract "connected" property from each cp. Search this
383b5016cbbSstephh 		 * property for the name associated with the other cp[].
384b5016cbbSstephh 		 */
385b5016cbbSstephh 		for (i = 0; i < 2 && valuep->v == 0; i++) {
386b5016cbbSstephh 			for (j = 0; connstrings[j] != NULL && valuep->v == 0;
387b5016cbbSstephh 			    j++) {
388b5016cbbSstephh 				s = config_getprop(cp[i],
389b5016cbbSstephh 				    stable(connstrings[j]));
390b5016cbbSstephh 				if (s != NULL) {
391b5016cbbSstephh 					nameslist = STRDUP(s);
392b5016cbbSstephh 					w = strtok(nameslist, " ,");
393b5016cbbSstephh 					while (w != NULL) {
394b5016cbbSstephh 						if (stable(w) == matchthis[i]) {
395b5016cbbSstephh 							valuep->v = 1;
396b5016cbbSstephh 							break;
397b5016cbbSstephh 						}
398b5016cbbSstephh 						w = strtok(NULL, " ,");
399b5016cbbSstephh 					}
400b5016cbbSstephh 					FREE(nameslist);
401b5016cbbSstephh 				}
402b5016cbbSstephh 			}
403b5016cbbSstephh 		}
404b5016cbbSstephh 		return (1);
405b5016cbbSstephh 	} else if (funcname == L_is_type) {
406b5016cbbSstephh 		const char *typestrings[] = { "type", "TYPE", NULL };
407b5016cbbSstephh 		const char *s;
408b5016cbbSstephh 		int i;
409b5016cbbSstephh 
410b5016cbbSstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
411b5016cbbSstephh 		    croot, arrowp, try, &duped);
412b0daa853SStephen Hanson 		if (!nodep)
413b0daa853SStephen Hanson 			return (0);
414b0daa853SStephen Hanson 		if (nodep->t != T_NAME) {
415b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
416b0daa853SStephen Hanson 			return (1);
417b0daa853SStephen Hanson 		}
418b0daa853SStephen Hanson 
419b5016cbbSstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
420b5016cbbSstephh 			cp = nodep->u.name.last->u.name.cp;
421b5016cbbSstephh 		} else {
422b5016cbbSstephh 			path = ipath2str(NULL, ipath(nodep));
423b5016cbbSstephh 			cp = config_lookup(croot, path, 0);
424b5016cbbSstephh 			FREE((void *)path);
425b5016cbbSstephh 		}
426b5016cbbSstephh 		if (duped)
427b5016cbbSstephh 			tree_free(nodep);
428b5016cbbSstephh 
429b5016cbbSstephh 		valuep->t = STRING;
430b5016cbbSstephh 		valuep->v = (uintptr_t)stable("");
431b5016cbbSstephh 		if (cp == NULL)
432b5016cbbSstephh 			return (1);
433b5016cbbSstephh 		for (i = 0; typestrings[i] != NULL; i++) {
434b5016cbbSstephh 			s = config_getprop(cp, stable(typestrings[i]));
435b5016cbbSstephh 			if (s != NULL) {
436b5016cbbSstephh 				valuep->v = (uintptr_t)stable(s);
437b5016cbbSstephh 				break;
438b5016cbbSstephh 			}
439b5016cbbSstephh 		}
440b5016cbbSstephh 		return (1);
441b5016cbbSstephh 	} else if (funcname == L_is_on) {
442b5016cbbSstephh 		const char *onstrings[] = { "on", "ON", NULL };
443b5016cbbSstephh 		const char *truestrings[] = { "yes", "YES", "y", "Y",
444b5016cbbSstephh 				    "true", "TRUE", "t", "T", "1", NULL };
445b5016cbbSstephh 		const char *s;
446b5016cbbSstephh 		int i, j;
447b5016cbbSstephh 
448b5016cbbSstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
449b5016cbbSstephh 		    croot, arrowp, try, &duped);
450b0daa853SStephen Hanson 		if (!nodep)
451b0daa853SStephen Hanson 			return (0);
452b0daa853SStephen Hanson 		if (nodep->t != T_NAME) {
453b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
454b0daa853SStephen Hanson 			return (1);
455b0daa853SStephen Hanson 		}
456b0daa853SStephen Hanson 
457b5016cbbSstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
458b5016cbbSstephh 			cp = nodep->u.name.last->u.name.cp;
459b5016cbbSstephh 		} else {
460b5016cbbSstephh 			path = ipath2str(NULL, ipath(nodep));
461b5016cbbSstephh 			cp = config_lookup(croot, path, 0);
462b5016cbbSstephh 			FREE((void *)path);
463b5016cbbSstephh 		}
464b5016cbbSstephh 		if (duped)
465b5016cbbSstephh 			tree_free(nodep);
466b5016cbbSstephh 
467b5016cbbSstephh 		valuep->t = UINT64;
468b5016cbbSstephh 		valuep->v = 0;
469b5016cbbSstephh 		if (cp == NULL)
470b5016cbbSstephh 			return (1);
471b5016cbbSstephh 		for (i = 0; onstrings[i] != NULL; i++) {
472b5016cbbSstephh 			s = config_getprop(cp, stable(onstrings[i]));
473b5016cbbSstephh 			if (s != NULL) {
474b5016cbbSstephh 				s = stable(s);
475b5016cbbSstephh 				for (j = 0; truestrings[j] != NULL; j++) {
476b5016cbbSstephh 					if (s == stable(truestrings[j])) {
477b5016cbbSstephh 						valuep->v = 1;
478b5016cbbSstephh 						return (1);
479b5016cbbSstephh 					}
480b5016cbbSstephh 				}
481b5016cbbSstephh 			}
482b5016cbbSstephh 		}
483b5016cbbSstephh 		return (1);
484b5016cbbSstephh 	} else if (funcname == L_is_present) {
485b5016cbbSstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
486b5016cbbSstephh 		    croot, arrowp, try, &duped);
487b0daa853SStephen Hanson 		if (!nodep)
488b0daa853SStephen Hanson 			return (0);
489b0daa853SStephen Hanson 		if (nodep->t != T_NAME) {
490b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
491b0daa853SStephen Hanson 			return (1);
492b0daa853SStephen Hanson 		}
493b0daa853SStephen Hanson 
494b5016cbbSstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
495b5016cbbSstephh 			cp = nodep->u.name.last->u.name.cp;
496b5016cbbSstephh 		} else {
497b5016cbbSstephh 			path = ipath2str(NULL, ipath(nodep));
498b5016cbbSstephh 			cp = config_lookup(croot, path, 0);
499b5016cbbSstephh 			FREE((void *)path);
500b5016cbbSstephh 		}
501b5016cbbSstephh 		if (duped)
502b5016cbbSstephh 			tree_free(nodep);
503b5016cbbSstephh 
504b5016cbbSstephh 		valuep->t = UINT64;
505b5016cbbSstephh 		valuep->v = 0;
506b5016cbbSstephh 		if (cp != NULL)
507b5016cbbSstephh 			valuep->v = 1;
508b5016cbbSstephh 		return (1);
50925c6ff4bSstephh 	} else if (funcname == L_has_fault) {
51025c6ff4bSstephh 		nvlist_t *asru = NULL, *fru = NULL, *rsrc = NULL;
51125c6ff4bSstephh 
51225c6ff4bSstephh 		nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
51325c6ff4bSstephh 		    globals, croot, arrowp, try, &duped);
514b0daa853SStephen Hanson 		if (!nodep)
515b0daa853SStephen Hanson 			return (0);
516b0daa853SStephen Hanson 		if (nodep->t != T_NAME) {
517b0daa853SStephen Hanson 			valuep->t = UNDEFINED;
518b0daa853SStephen Hanson 			return (1);
519b0daa853SStephen Hanson 		}
520b0daa853SStephen Hanson 
52125c6ff4bSstephh 		path = ipath2str(NULL, ipath(nodep));
52225c6ff4bSstephh 		platform_units_translate(0, croot, &asru, &fru, &rsrc, path);
5238e7248e5SStephen Hanson 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, "has_fault(");
524b0daa853SStephen Hanson 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, nodep);
525b0daa853SStephen Hanson 		out(O_ALTFP|O_VERB2|O_NONL, "(%s), \"%s\") ", path,
5268e7248e5SStephen Hanson 		    np->u.expr.right->u.quote.s);
52725c6ff4bSstephh 		FREE((void *)path);
52825c6ff4bSstephh 		if (duped)
52925c6ff4bSstephh 			tree_free(nodep);
53025c6ff4bSstephh 
5318e7248e5SStephen Hanson 		if (rsrc == NULL) {
53225c6ff4bSstephh 			valuep->v = 0;
5338e7248e5SStephen Hanson 			out(O_ALTFP|O_VERB2, "no path");
5348e7248e5SStephen Hanson 		} else {
53525c6ff4bSstephh 			valuep->v = fmd_nvl_fmri_has_fault(Hdl, rsrc,
53625c6ff4bSstephh 			    FMD_HAS_FAULT_RESOURCE,
53725c6ff4bSstephh 			    strcmp(np->u.expr.right->u.quote.s, "") == 0 ?
53825c6ff4bSstephh 			    NULL : (char *)np->u.expr.right->u.quote.s);
5398e7248e5SStephen Hanson 			out(O_ALTFP|O_VERB2, "returned %lld", valuep->v);
540*705e9f42SStephen Hanson 			nvlist_free(rsrc);
5418e7248e5SStephen Hanson 		}
54225c6ff4bSstephh 		valuep->t = UINT64;
54325c6ff4bSstephh 		return (1);
544b5016cbbSstephh 	} else if (funcname == L_count) {
545b5016cbbSstephh 		struct stats *statp;
546b5016cbbSstephh 		struct istat_entry ent;
547b5016cbbSstephh 
548b5016cbbSstephh 		ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
549b5016cbbSstephh 
550b5016cbbSstephh 		nodep = np->u.event.epname;
551b5016cbbSstephh 		if (try) {
552b5016cbbSstephh 			if (eval_expr(nodep, ex, events, globals,
553b5016cbbSstephh 			    croot, arrowp, try, &val) && val.t == NODEPTR)
554b5016cbbSstephh 				nodep = (struct node *)(uintptr_t)val.v;
555b5016cbbSstephh 			else {
556b5016cbbSstephh 				duped = 1;
557b5016cbbSstephh 				nodep = eval_dup(nodep, ex, events);
558b5016cbbSstephh 			}
559b5016cbbSstephh 		}
560b5016cbbSstephh 		ent.ename = np->u.event.ename->u.name.s;
561b5016cbbSstephh 		ent.ipath = ipath(nodep);
562b5016cbbSstephh 		valuep->t = UINT64;
563b5016cbbSstephh 		if ((statp = (struct stats *)
564b5016cbbSstephh 		    lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
565b5016cbbSstephh 			valuep->v = 0;
566b5016cbbSstephh 		else
567b5016cbbSstephh 			valuep->v = stats_counter_value(statp);
568b5016cbbSstephh 		if (duped)
569b5016cbbSstephh 			tree_free(nodep);
570b5016cbbSstephh 		return (1);
571b5016cbbSstephh 	} else if (funcname == L_envprop) {
572b5016cbbSstephh 		outfl(O_DIE, np->file, np->line,
573b5016cbbSstephh 		    "eval_func: %s not yet supported", funcname);
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	if (try)
5777c478bd9Sstevel@tonic-gate 		return (0);
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	if (funcname == L_fru) {
5807c478bd9Sstevel@tonic-gate 		valuep->t = NODEPTR;
58180ab886dSwesolows 		valuep->v = (uintptr_t)eval_fru(np);
5827c478bd9Sstevel@tonic-gate 		return (1);
5837c478bd9Sstevel@tonic-gate 	} else if (funcname == L_asru) {
5847c478bd9Sstevel@tonic-gate 		valuep->t = NODEPTR;
58580ab886dSwesolows 		valuep->v = (uintptr_t)eval_asru(np);
5867c478bd9Sstevel@tonic-gate 		return (1);
5877aec1d6eScindi 	} else if (funcname == L_defined) {
5887aec1d6eScindi 		ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
5897aec1d6eScindi 		valuep->t = UINT64;
5907aec1d6eScindi 		valuep->v = (lut_lookup(*globals,
5917aec1d6eScindi 		    (void *)np->u.globid.s, NULL) != NULL);
5927aec1d6eScindi 		return (1);
5937c478bd9Sstevel@tonic-gate 	} else if (funcname == L_call) {
5947c478bd9Sstevel@tonic-gate 		return (! platform_call(np, globals, croot, arrowp, valuep));
5957c478bd9Sstevel@tonic-gate 	} else if (funcname == L_payloadprop) {
5967aec1d6eScindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
5977c478bd9Sstevel@tonic-gate 		    "payloadprop(\"%s\") ", np->u.quote.s);
5983e8d8e18Sdb35262 
599e5ba14ffSstephh 		if (arrowp->head->myevent->count == 0) {
600e5ba14ffSstephh 			/*
601e5ba14ffSstephh 			 * Haven't seen this ereport yet, so must defer
602e5ba14ffSstephh 			 */
603e5ba14ffSstephh 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
6047c478bd9Sstevel@tonic-gate 			return (0);
605e5ba14ffSstephh 		} else if (platform_payloadprop(np, valuep)) {
606e5ba14ffSstephh 			/* platform_payloadprop() returned false */
607e5ba14ffSstephh 			out(O_ALTFP|O_VERB, "not found.");
608e5ba14ffSstephh 			valuep->t = UNDEFINED;
609e5ba14ffSstephh 			return (1);
6107c478bd9Sstevel@tonic-gate 		} else {
6113e8d8e18Sdb35262 			switch (valuep->t) {
6123e8d8e18Sdb35262 			case NODEPTR:
613b0daa853SStephen Hanson 				if (((struct node *)(uintptr_t)
614b0daa853SStephen Hanson 				    (valuep->v))->t == T_NAME) {
615b0daa853SStephen Hanson 					char *s = ipath2str(NULL,
616b0daa853SStephen Hanson 					    ipath((struct node *)
617b0daa853SStephen Hanson 					    (uintptr_t)valuep->v));
618b0daa853SStephen Hanson 					out(O_ALTFP|O_VERB2,
619b0daa853SStephen Hanson 					    "found: \"%s\"", s);
620b0daa853SStephen Hanson 					FREE(s);
621b0daa853SStephen Hanson 				} else
622b0daa853SStephen Hanson 					out(O_ALTFP|O_VERB2, "found: %llu",
623b0daa853SStephen Hanson 					    valuep->v);
624b0daa853SStephen Hanson 				break;
625b0daa853SStephen Hanson 			case UINT64:
6267aec1d6eScindi 				out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
6273e8d8e18Sdb35262 				break;
6283e8d8e18Sdb35262 			case STRING:
6297aec1d6eScindi 				out(O_ALTFP|O_VERB2, "found: \"%s\"",
63080ab886dSwesolows 				    (char *)(uintptr_t)valuep->v);
6313e8d8e18Sdb35262 				break;
6323e8d8e18Sdb35262 			default:
6337aec1d6eScindi 				out(O_ALTFP|O_VERB2, "found: undefined");
6343e8d8e18Sdb35262 				break;
6353e8d8e18Sdb35262 			}
6367c478bd9Sstevel@tonic-gate 			return (1);
6377c478bd9Sstevel@tonic-gate 		}
6387aec1d6eScindi 	} else if (funcname == L_setpayloadprop) {
6397aec1d6eScindi 		struct evalue *payloadvalp;
640e5ba14ffSstephh 		int alloced = 0;
6417aec1d6eScindi 
6427aec1d6eScindi 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
6437aec1d6eScindi 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
6447aec1d6eScindi 		    ptree_nodetype2str(np->u.expr.left->t));
6457aec1d6eScindi 
6468cffa125SStephen Hanson 		if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
647b7d3956bSstephh 			return (0);
648b7d3956bSstephh 
6497aec1d6eScindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
6507aec1d6eScindi 		    "setpayloadprop: %s: %s=",
6517aec1d6eScindi 		    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
6527aec1d6eScindi 		    np->u.expr.left->u.quote.s);
6537aec1d6eScindi 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
6547aec1d6eScindi 
6557aec1d6eScindi 		/*
6567aec1d6eScindi 		 * allocate a struct evalue to hold the payload property's
6577aec1d6eScindi 		 * value, unless we've been here already, in which case we
6587aec1d6eScindi 		 * might calculate a different value, but we'll store it
6597aec1d6eScindi 		 * in the already-allocated struct evalue.
6607aec1d6eScindi 		 */
6617aec1d6eScindi 		if ((payloadvalp = (struct evalue *)lut_lookup(
6627aec1d6eScindi 		    arrowp->tail->myevent->payloadprops,
6637aec1d6eScindi 		    (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
6647aec1d6eScindi 			payloadvalp = MALLOC(sizeof (*payloadvalp));
665e5ba14ffSstephh 			alloced = 1;
6667aec1d6eScindi 		}
6677aec1d6eScindi 
668b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
6697aec1d6eScindi 		    arrowp, try, payloadvalp)) {
670e5ba14ffSstephh 			out(O_ALTFP|O_VERB2, " (cannot eval)");
671e5ba14ffSstephh 			if (alloced)
672e5ba14ffSstephh 				FREE(payloadvalp);
673e5ba14ffSstephh 			return (0);
6747aec1d6eScindi 		} else {
675e5ba14ffSstephh 			if (payloadvalp->t == UNDEFINED) {
676e5ba14ffSstephh 				/* function is always true */
677e5ba14ffSstephh 				out(O_ALTFP|O_VERB2, " (undefined)");
678e5ba14ffSstephh 				valuep->t = UINT64;
679e5ba14ffSstephh 				valuep->v = 1;
680e5ba14ffSstephh 				return (1);
681e5ba14ffSstephh 			}
6827aec1d6eScindi 			if (payloadvalp->t == UINT64)
6837aec1d6eScindi 				out(O_ALTFP|O_VERB2,
6847aec1d6eScindi 				    " (%llu)", payloadvalp->v);
6857aec1d6eScindi 			else
68680ab886dSwesolows 				out(O_ALTFP|O_VERB2, " (\"%s\")",
68780ab886dSwesolows 				    (char *)(uintptr_t)payloadvalp->v);
6887aec1d6eScindi 		}
6897aec1d6eScindi 
6907aec1d6eScindi 		/* add to table of payload properties for current problem */
6917aec1d6eScindi 		arrowp->tail->myevent->payloadprops =
6927aec1d6eScindi 		    lut_add(arrowp->tail->myevent->payloadprops,
6937aec1d6eScindi 		    (void *)np->u.expr.left->u.quote.s,
6947aec1d6eScindi 		    (void *)payloadvalp, NULL);
6957aec1d6eScindi 
6967aec1d6eScindi 		/* function is always true */
6977aec1d6eScindi 		valuep->t = UINT64;
6987aec1d6eScindi 		valuep->v = 1;
6997aec1d6eScindi 		return (1);
700b0daa853SStephen Hanson 	} else if (funcname == L_cat) {
701b0daa853SStephen Hanson 		int retval = eval_cat(np, ex, events, globals, croot,
702b0daa853SStephen Hanson 		    arrowp, try, valuep);
703b0daa853SStephen Hanson 
704b0daa853SStephen Hanson 		outfl(O_ALTFP|O_VERB2, np->file, np->line,
705b0daa853SStephen Hanson 		    "cat: returns %s", (char *)(uintptr_t)valuep->v);
706b0daa853SStephen Hanson 		return (retval);
707b7d3956bSstephh 	} else if (funcname == L_setserdn || funcname == L_setserdt ||
708b7d3956bSstephh 	    funcname == L_setserdsuffix || funcname == L_setserdincrement) {
709b7d3956bSstephh 		struct evalue *serdvalp;
710b7d3956bSstephh 		int alloced = 0;
711b7d3956bSstephh 		char *str;
712b7d3956bSstephh 		struct event *flt = arrowp->tail->myevent;
713b7d3956bSstephh 
7148cffa125SStephen Hanson 		if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
715b7d3956bSstephh 			return (0);
716b7d3956bSstephh 
717b7d3956bSstephh 		if (funcname == L_setserdn)
718b7d3956bSstephh 			str = "n";
719b7d3956bSstephh 		else if (funcname == L_setserdt)
720b7d3956bSstephh 			str = "t";
721b7d3956bSstephh 		else if (funcname == L_setserdsuffix)
722b7d3956bSstephh 			str = "suffix";
723b7d3956bSstephh 		else if (funcname == L_setserdincrement)
724b7d3956bSstephh 			str = "increment";
725b7d3956bSstephh 
726b7d3956bSstephh 		/*
727b7d3956bSstephh 		 * allocate a struct evalue to hold the serd property's
728b7d3956bSstephh 		 * value, unless we've been here already, in which case we
729b7d3956bSstephh 		 * might calculate a different value, but we'll store it
730b7d3956bSstephh 		 * in the already-allocated struct evalue.
731b7d3956bSstephh 		 */
732b7d3956bSstephh 		if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops,
73358841c98SScott Davenport 		    (void *)str, (lut_cmp)strcmp)) == NULL) {
734b7d3956bSstephh 			serdvalp = MALLOC(sizeof (*serdvalp));
735b7d3956bSstephh 			alloced = 1;
736b7d3956bSstephh 		}
737b7d3956bSstephh 
738b7d3956bSstephh 		if (!eval_expr(np, ex, events, globals, croot, arrowp, try,
739b7d3956bSstephh 		    serdvalp)) {
740b7d3956bSstephh 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
741b7d3956bSstephh 			    "setserd%s: %s: ", str,
742b7d3956bSstephh 			    flt->enode->u.event.ename->u.name.s);
743b7d3956bSstephh 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
744b7d3956bSstephh 			out(O_ALTFP|O_VERB2, " (cannot eval)");
745b7d3956bSstephh 			if (alloced)
746b7d3956bSstephh 				FREE(serdvalp);
747b7d3956bSstephh 			return (0);
748b7d3956bSstephh 		} else if (serdvalp->t == UNDEFINED) {
749b7d3956bSstephh 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
750b7d3956bSstephh 			    "setserd%s: %s: ", str,
751b7d3956bSstephh 			    flt->enode->u.event.ename->u.name.s);
752b7d3956bSstephh 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
753b7d3956bSstephh 			out(O_ALTFP|O_VERB2, " (undefined)");
754b7d3956bSstephh 		} else {
755b7d3956bSstephh 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
756b7d3956bSstephh 			    "setserd%s: %s: ", str,
757b7d3956bSstephh 			    flt->enode->u.event.ename->u.name.s);
758b7d3956bSstephh 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
759b7d3956bSstephh 			if ((funcname == L_setserdincrement ||
760b7d3956bSstephh 			    funcname == L_setserdn) && serdvalp->t == STRING) {
761b7d3956bSstephh 				serdvalp->t = UINT64;
762b7d3956bSstephh 				serdvalp->v = strtoull((char *)
763b7d3956bSstephh 				    (uintptr_t)serdvalp->v, NULL, 0);
764b7d3956bSstephh 			}
765b7d3956bSstephh 			if (funcname == L_setserdt && serdvalp->t == UINT64) {
766b7d3956bSstephh 				int len = snprintf(NULL, 0, "%lldns",
767b7d3956bSstephh 				    serdvalp->v);
768b7d3956bSstephh 				char *buf = MALLOC(len + 1);
769b7d3956bSstephh 
770b7d3956bSstephh 				(void) snprintf(buf, len + 1, "%lldns",
771b7d3956bSstephh 				    serdvalp->v);
772b7d3956bSstephh 				serdvalp->t = STRING;
773b7d3956bSstephh 				serdvalp->v = (uintptr_t)stable(buf);
774b7d3956bSstephh 				FREE(buf);
775b7d3956bSstephh 			}
7765dc9a986SDavid Zhang 			if (funcname == L_setserdsuffix &&
7775dc9a986SDavid Zhang 			    serdvalp->t == UINT64) {
7785dc9a986SDavid Zhang 				int len = snprintf(NULL, 0, "%lld",
7795dc9a986SDavid Zhang 				    serdvalp->v);
7805dc9a986SDavid Zhang 				char *buf = MALLOC(len + 1);
7815dc9a986SDavid Zhang 
7825dc9a986SDavid Zhang 				(void) snprintf(buf, len + 1, "%lld",
7835dc9a986SDavid Zhang 				    serdvalp->v);
7845dc9a986SDavid Zhang 				serdvalp->t = STRING;
7855dc9a986SDavid Zhang 				serdvalp->v = (uintptr_t)stable(buf);
7865dc9a986SDavid Zhang 				FREE(buf);
7875dc9a986SDavid Zhang 			}
78858841c98SScott Davenport 
789b7d3956bSstephh 			if (serdvalp->t == UINT64)
790b7d3956bSstephh 				out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v);
791b7d3956bSstephh 			else
792b7d3956bSstephh 				out(O_ALTFP|O_VERB2, " (\"%s\")",
793b7d3956bSstephh 				    (char *)(uintptr_t)serdvalp->v);
794b7d3956bSstephh 			flt->serdprops = lut_add(flt->serdprops, (void *)str,
79558841c98SScott Davenport 			    (void *)serdvalp, (lut_cmp)strcmp);
796b7d3956bSstephh 		}
797b7d3956bSstephh 		valuep->t = UINT64;
798b7d3956bSstephh 		valuep->v = 1;
799b7d3956bSstephh 		return (1);
8007aec1d6eScindi 	} else if (funcname == L_payloadprop_defined) {
8017aec1d6eScindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
8027aec1d6eScindi 		    "payloadprop_defined(\"%s\") ", np->u.quote.s);
8037aec1d6eScindi 
804e5ba14ffSstephh 		if (arrowp->head->myevent->count == 0) {
805e5ba14ffSstephh 			/*
806e5ba14ffSstephh 			 * Haven't seen this ereport yet, so must defer
807e5ba14ffSstephh 			 */
808e5ba14ffSstephh 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
809e5ba14ffSstephh 			return (0);
810e5ba14ffSstephh 		} else if (platform_payloadprop(np, NULL)) {
8117aec1d6eScindi 			/* platform_payloadprop() returned false */
8127aec1d6eScindi 			valuep->v = 0;
813e5ba14ffSstephh 			out(O_ALTFP|O_VERB2, "not found.");
8147aec1d6eScindi 		} else {
8157aec1d6eScindi 			valuep->v = 1;
8167aec1d6eScindi 			out(O_ALTFP|O_VERB2, "found.");
8177aec1d6eScindi 		}
8187aec1d6eScindi 		valuep->t = UINT64;
8197aec1d6eScindi 		return (1);
8207aec1d6eScindi 	} else if (funcname == L_payloadprop_contains) {
8217aec1d6eScindi 		int nvals;
8227aec1d6eScindi 		struct evalue *vals;
8237aec1d6eScindi 		struct evalue cmpval;
8247aec1d6eScindi 
8257aec1d6eScindi 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
8267aec1d6eScindi 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
8277aec1d6eScindi 		    ptree_nodetype2str(np->u.expr.left->t));
8287aec1d6eScindi 
8297aec1d6eScindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
8307aec1d6eScindi 		    "payloadprop_contains(\"%s\", ",
8317aec1d6eScindi 		    np->u.expr.left->u.quote.s);
8327aec1d6eScindi 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
8338a40a695Sgavinm 		out(O_ALTFP|O_VERB2|O_NONL, ") ");
8347aec1d6eScindi 
8357aec1d6eScindi 		/* evaluate the expression we're comparing against */
836b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
8377aec1d6eScindi 		    arrowp, try, &cmpval)) {
8387aec1d6eScindi 			out(O_ALTFP|O_VERB2|O_NONL,
839e5ba14ffSstephh 			    "(cannot eval) ");
840e5ba14ffSstephh 			return (0);
8417aec1d6eScindi 		} else {
8428a40a695Sgavinm 			switch (cmpval.t) {
8438a40a695Sgavinm 			case UNDEFINED:
8448a40a695Sgavinm 				out(O_ALTFP|O_VERB2, "(undefined type)");
8458a40a695Sgavinm 				break;
8468a40a695Sgavinm 
8478a40a695Sgavinm 			case UINT64:
8487aec1d6eScindi 				out(O_ALTFP|O_VERB2,
8497aec1d6eScindi 				    "(%llu) ", cmpval.v);
8508a40a695Sgavinm 				break;
8518a40a695Sgavinm 
8528a40a695Sgavinm 			case STRING:
8537aec1d6eScindi 				out(O_ALTFP|O_VERB2,
85480ab886dSwesolows 				    "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
8558a40a695Sgavinm 				break;
8568a40a695Sgavinm 
8578a40a695Sgavinm 			case NODEPTR:
8588a40a695Sgavinm 				out(O_ALTFP|O_VERB2|O_NONL, "(");
8598a40a695Sgavinm 				ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
8608a40a695Sgavinm 				    (struct node *)(uintptr_t)(cmpval.v));
8618a40a695Sgavinm 				out(O_ALTFP|O_VERB2, ") ");
8628a40a695Sgavinm 				break;
8638a40a695Sgavinm 			}
8647aec1d6eScindi 		}
8657aec1d6eScindi 
8667aec1d6eScindi 		/* get the payload values and check for a match */
8677aec1d6eScindi 		vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
8687aec1d6eScindi 		    &nvals);
8697aec1d6eScindi 		valuep->t = UINT64;
8707aec1d6eScindi 		valuep->v = 0;
871e5ba14ffSstephh 		if (arrowp->head->myevent->count == 0) {
872e5ba14ffSstephh 			/*
873e5ba14ffSstephh 			 * Haven't seen this ereport yet, so must defer
874e5ba14ffSstephh 			 */
875e5ba14ffSstephh 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
876b5016cbbSstephh 			return (0);
877e5ba14ffSstephh 		} else if (nvals == 0) {
878e5ba14ffSstephh 			out(O_ALTFP|O_VERB2, "not found.");
879e5ba14ffSstephh 			return (1);
8807aec1d6eScindi 		} else {
8817aec1d6eScindi 			struct evalue preval;
8827aec1d6eScindi 			int i;
8837aec1d6eScindi 
8847aec1d6eScindi 			out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
8857aec1d6eScindi 
8867aec1d6eScindi 			for (i = 0; i < nvals; i++) {
8877aec1d6eScindi 
8887aec1d6eScindi 				preval.t = vals[i].t;
8897aec1d6eScindi 				preval.v = vals[i].v;
8907aec1d6eScindi 
8917aec1d6eScindi 				if (check_expr_args(&vals[i], &cmpval,
8927aec1d6eScindi 				    UNDEFINED, np))
8937aec1d6eScindi 					continue;
8947aec1d6eScindi 
8957aec1d6eScindi 				/*
8967aec1d6eScindi 				 * If we auto-converted the value to a
8977aec1d6eScindi 				 * string, we need to free the
8987aec1d6eScindi 				 * original tree value.
8997aec1d6eScindi 				 */
9007aec1d6eScindi 				if (preval.t == NODEPTR &&
90180ab886dSwesolows 				    ((struct node *)(uintptr_t)(preval.v))->t ==
90280ab886dSwesolows 				    T_NAME) {
90380ab886dSwesolows 					tree_free((struct node *)(uintptr_t)
90480ab886dSwesolows 					    preval.v);
9057aec1d6eScindi 				}
9067aec1d6eScindi 
9077aec1d6eScindi 				if (vals[i].v == cmpval.v) {
9087aec1d6eScindi 					valuep->v = 1;
9097aec1d6eScindi 					break;
9107aec1d6eScindi 				}
9117aec1d6eScindi 			}
9127aec1d6eScindi 
9137aec1d6eScindi 			if (valuep->v)
9147aec1d6eScindi 				out(O_ALTFP|O_VERB2, "match.");
9157aec1d6eScindi 			else
9167aec1d6eScindi 				out(O_ALTFP|O_VERB2, "no match.");
9177aec1d6eScindi 
9187aec1d6eScindi 			for (i = 0; i < nvals; i++) {
9197aec1d6eScindi 				if (vals[i].t == NODEPTR) {
92080ab886dSwesolows 					tree_free((struct node *)(uintptr_t)
92180ab886dSwesolows 					    vals[i].v);
9227aec1d6eScindi 					break;
9237aec1d6eScindi 				}
9247aec1d6eScindi 			}
9257aec1d6eScindi 			FREE(vals);
9267aec1d6eScindi 		}
9277aec1d6eScindi 		return (1);
9287aec1d6eScindi 	} else if (funcname == L_confcall) {
9297aec1d6eScindi 		return (!platform_confcall(np, globals, croot, arrowp, valuep));
9307c478bd9Sstevel@tonic-gate 	} else
9317c478bd9Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
9327c478bd9Sstevel@tonic-gate 		    "eval_func: unexpected func: %s", funcname);
9337c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
93480ab886dSwesolows 	return (0);
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate /*
938b5016cbbSstephh  * defines for u.expr.temp - these are used for T_OR and T_AND so that if
939b5016cbbSstephh  * we worked out that part of the expression was true or false during an
940b5016cbbSstephh  * earlier eval_expr, then we don't need to dup that part.
9417c478bd9Sstevel@tonic-gate  */
9427c478bd9Sstevel@tonic-gate 
943b5016cbbSstephh #define	EXPR_TEMP_BOTH_UNK	0
944b5016cbbSstephh #define	EXPR_TEMP_LHS_UNK	1
945b5016cbbSstephh #define	EXPR_TEMP_RHS_UNK	2
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate static struct node *
eval_dup(struct node * np,struct lut * ex,struct node * events[])948b5016cbbSstephh eval_dup(struct node *np, struct lut *ex, struct node *events[])
9497c478bd9Sstevel@tonic-gate {
9507c478bd9Sstevel@tonic-gate 	struct node *newnp;
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 	if (np == NULL)
9537c478bd9Sstevel@tonic-gate 		return (NULL);
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	switch (np->t) {
9567c478bd9Sstevel@tonic-gate 	case T_GLOBID:
9577c478bd9Sstevel@tonic-gate 		return (tree_globid(np->u.globid.s, np->file, np->line));
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	case T_ASSIGN:
9607c478bd9Sstevel@tonic-gate 	case T_CONDIF:
9617c478bd9Sstevel@tonic-gate 	case T_CONDELSE:
9627c478bd9Sstevel@tonic-gate 	case T_NE:
9637c478bd9Sstevel@tonic-gate 	case T_EQ:
9647c478bd9Sstevel@tonic-gate 	case T_LT:
9657c478bd9Sstevel@tonic-gate 	case T_LE:
9667c478bd9Sstevel@tonic-gate 	case T_GT:
9677c478bd9Sstevel@tonic-gate 	case T_GE:
9687c478bd9Sstevel@tonic-gate 	case T_BITAND:
9697c478bd9Sstevel@tonic-gate 	case T_BITOR:
9707c478bd9Sstevel@tonic-gate 	case T_BITXOR:
9717c478bd9Sstevel@tonic-gate 	case T_BITNOT:
9727c478bd9Sstevel@tonic-gate 	case T_LSHIFT:
9737c478bd9Sstevel@tonic-gate 	case T_RSHIFT:
9747c478bd9Sstevel@tonic-gate 	case T_NOT:
9757c478bd9Sstevel@tonic-gate 	case T_ADD:
9767c478bd9Sstevel@tonic-gate 	case T_SUB:
9777c478bd9Sstevel@tonic-gate 	case T_MUL:
9787c478bd9Sstevel@tonic-gate 	case T_DIV:
9797c478bd9Sstevel@tonic-gate 	case T_MOD:
9807c478bd9Sstevel@tonic-gate 		return (tree_expr(np->t,
981b5016cbbSstephh 		    eval_dup(np->u.expr.left, ex, events),
982b5016cbbSstephh 		    eval_dup(np->u.expr.right, ex, events)));
983b5016cbbSstephh 	case T_LIST:
984b5016cbbSstephh 	case T_AND:
985b5016cbbSstephh 		switch (np->u.expr.temp) {
986b5016cbbSstephh 		case EXPR_TEMP_LHS_UNK:
987b5016cbbSstephh 			return (eval_dup(np->u.expr.left, ex, events));
988b5016cbbSstephh 		case EXPR_TEMP_RHS_UNK:
989b5016cbbSstephh 			return (eval_dup(np->u.expr.right, ex, events));
990b5016cbbSstephh 		default:
991b5016cbbSstephh 			return (tree_expr(np->t,
992b5016cbbSstephh 			    eval_dup(np->u.expr.left, ex, events),
993b5016cbbSstephh 			    eval_dup(np->u.expr.right, ex, events)));
994b5016cbbSstephh 		}
995b5016cbbSstephh 
996b5016cbbSstephh 	case T_OR:
997b5016cbbSstephh 		switch (np->u.expr.temp) {
998b5016cbbSstephh 		case EXPR_TEMP_LHS_UNK:
999b5016cbbSstephh 			return (eval_dup(np->u.expr.left, ex, events));
1000b5016cbbSstephh 		case EXPR_TEMP_RHS_UNK:
1001b5016cbbSstephh 			return (eval_dup(np->u.expr.right, ex, events));
1002b5016cbbSstephh 		default:
1003b5016cbbSstephh 			return (tree_expr(T_OR,
1004b5016cbbSstephh 			    eval_dup(np->u.expr.left, ex, events),
1005b5016cbbSstephh 			    eval_dup(np->u.expr.right, ex, events)));
1006b5016cbbSstephh 		}
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 	case T_NAME: {
10097c478bd9Sstevel@tonic-gate 		struct iterinfo *iterinfop;
1010b5016cbbSstephh 		int got_matchf = 0;
1011b5016cbbSstephh 		int got_matcht = 0;
1012b5016cbbSstephh 		struct evalue value;
1013b5016cbbSstephh 		struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
1014b5016cbbSstephh 		struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
10157c478bd9Sstevel@tonic-gate 
1016b5016cbbSstephh 		/*
1017b5016cbbSstephh 		 * Check if we already have a match of the nonwildcarded path
1018b5016cbbSstephh 		 * in oldepname (check both to and from events).
1019b5016cbbSstephh 		 */
1020b5016cbbSstephh 		for (np1f = np, np2f = events[0]->u.event.oldepname;
1021b5016cbbSstephh 		    np1f != NULL && np2f != NULL;
1022b5016cbbSstephh 		    np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
1023b5016cbbSstephh 			if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
1024b5016cbbSstephh 				break;
1025b5016cbbSstephh 			if (np1f->u.name.child->t != np2f->u.name.child->t)
1026b5016cbbSstephh 				break;
1027b5016cbbSstephh 			if (np1f->u.name.child->t == T_NUM &&
1028b5016cbbSstephh 			    np1f->u.name.child->u.ull !=
1029b5016cbbSstephh 			    np2f->u.name.child->u.ull)
1030b5016cbbSstephh 				break;
1031b5016cbbSstephh 			if (np1f->u.name.child->t == T_NAME &&
1032b5016cbbSstephh 			    strcmp(np1f->u.name.child->u.name.s,
1033b5016cbbSstephh 			    np2f->u.name.child->u.name.s) != 0)
1034b5016cbbSstephh 				break;
1035b5016cbbSstephh 			got_matchf++;
1036b5016cbbSstephh 		}
1037b5016cbbSstephh 		for (np1t = np, np2t = events[1]->u.event.oldepname;
1038b5016cbbSstephh 		    np1t != NULL && np2t != NULL;
1039b5016cbbSstephh 		    np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
1040b5016cbbSstephh 			if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
1041b5016cbbSstephh 				break;
1042b5016cbbSstephh 			if (np1t->u.name.child->t != np2t->u.name.child->t)
1043b5016cbbSstephh 				break;
1044b5016cbbSstephh 			if (np1t->u.name.child->t == T_NUM &&
1045b5016cbbSstephh 			    np1t->u.name.child->u.ull !=
1046b5016cbbSstephh 			    np2t->u.name.child->u.ull)
1047b5016cbbSstephh 				break;
1048b5016cbbSstephh 			if (np1t->u.name.child->t == T_NAME &&
1049b5016cbbSstephh 			    strcmp(np1t->u.name.child->u.name.s,
1050b5016cbbSstephh 			    np2t->u.name.child->u.name.s) != 0)
1051b5016cbbSstephh 				break;
1052b5016cbbSstephh 			got_matcht++;
1053b5016cbbSstephh 		}
1054b5016cbbSstephh 		nprest = np;
1055b5016cbbSstephh 		if (got_matchf || got_matcht) {
1056b5016cbbSstephh 			/*
1057b5016cbbSstephh 			 * so we are wildcarding. Copy ewname in full, plus
1058b5016cbbSstephh 			 * matching section of oldepname. Use whichever gives
1059b5016cbbSstephh 			 * the closest match.
1060b5016cbbSstephh 			 */
1061b5016cbbSstephh 			if (got_matchf > got_matcht) {
1062b5016cbbSstephh 				npstart = events[0]->u.event.ewname;
1063b5016cbbSstephh 				npcont = events[0]->u.event.oldepname;
1064b5016cbbSstephh 				npend = np2f;
1065b5016cbbSstephh 				nprest = np1f;
1066b5016cbbSstephh 			} else {
1067b5016cbbSstephh 				npstart = events[1]->u.event.ewname;
1068b5016cbbSstephh 				npcont = events[1]->u.event.oldepname;
1069b5016cbbSstephh 				npend = np2t;
1070b5016cbbSstephh 				nprest = np1t;
1071b5016cbbSstephh 			}
1072b5016cbbSstephh 			for (npref = npstart; npref != NULL;
1073b5016cbbSstephh 			    npref = npref->u.name.next) {
1074b5016cbbSstephh 				newnp = newnode(T_NAME, np->file, np->line);
1075b5016cbbSstephh 				newnp->u.name.t = npref->u.name.t;
1076b5016cbbSstephh 				newnp->u.name.s = npref->u.name.s;
1077b5016cbbSstephh 				newnp->u.name.last = newnp;
1078b5016cbbSstephh 				newnp->u.name.it = npref->u.name.it;
1079b5016cbbSstephh 				newnp->u.name.cp = npref->u.name.cp;
1080b5016cbbSstephh 				newnp->u.name.child =
1081b5016cbbSstephh 				    newnode(T_NUM, np->file, np->line);
1082b5016cbbSstephh 				if (eval_expr(npref->u.name.child, ex, events,
1083b5016cbbSstephh 				    NULL, NULL, NULL, 1, &value) == 0 ||
1084b5016cbbSstephh 				    value.t != UINT64) {
1085b5016cbbSstephh 					outfl(O_DIE, np->file, np->line,
1086b5016cbbSstephh 					    "eval_dup: could not resolve "
1087b5016cbbSstephh 					    "iterator of %s", np->u.name.s);
1088b5016cbbSstephh 				}
1089b5016cbbSstephh 				newnp->u.name.child->u.ull = value.v;
1090b5016cbbSstephh 				if (retp == NULL) {
1091b5016cbbSstephh 					retp = newnp;
1092b5016cbbSstephh 				} else {
1093b5016cbbSstephh 					retp->u.name.last->u.name.next = newnp;
1094b5016cbbSstephh 					retp->u.name.last = newnp;
1095b5016cbbSstephh 				}
1096b5016cbbSstephh 			}
1097b5016cbbSstephh 			for (npref = npcont; npref != NULL && npref != npend;
1098b5016cbbSstephh 			    npref = npref->u.name.next) {
1099b5016cbbSstephh 				newnp = newnode(T_NAME, np->file, np->line);
1100b5016cbbSstephh 				newnp->u.name.t = npref->u.name.t;
1101b5016cbbSstephh 				newnp->u.name.s = npref->u.name.s;
1102b5016cbbSstephh 				newnp->u.name.last = newnp;
1103b5016cbbSstephh 				newnp->u.name.it = npref->u.name.it;
1104b5016cbbSstephh 				newnp->u.name.cp = npref->u.name.cp;
1105b5016cbbSstephh 				newnp->u.name.child =
1106b5016cbbSstephh 				    newnode(T_NUM, np->file, np->line);
1107b5016cbbSstephh 				if (eval_expr(npref->u.name.child, ex, events,
1108b5016cbbSstephh 				    NULL, NULL, NULL, 1, &value) == 0 ||
1109b5016cbbSstephh 				    value.t != UINT64) {
1110b5016cbbSstephh 					outfl(O_DIE, np->file, np->line,
1111b5016cbbSstephh 					    "eval_dup: could not resolve "
1112b5016cbbSstephh 					    "iterator of %s", np->u.name.s);
1113b5016cbbSstephh 				}
1114b5016cbbSstephh 				newnp->u.name.child->u.ull = value.v;
1115b5016cbbSstephh 				if (retp == NULL) {
1116b5016cbbSstephh 					retp = newnp;
1117b5016cbbSstephh 				} else {
1118b5016cbbSstephh 					retp->u.name.last->u.name.next = newnp;
1119b5016cbbSstephh 					retp->u.name.last = newnp;
1120b5016cbbSstephh 				}
1121b5016cbbSstephh 			}
1122b5016cbbSstephh 		} else {
1123b5016cbbSstephh 			/*
1124b5016cbbSstephh 			 * not wildcarding - check if explicit iterator
1125b5016cbbSstephh 			 */
11267c478bd9Sstevel@tonic-gate 			iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
11277c478bd9Sstevel@tonic-gate 			if (iterinfop != NULL) {
11287c478bd9Sstevel@tonic-gate 				/* explicit iterator; not part of pathname */
11297c478bd9Sstevel@tonic-gate 				newnp = newnode(T_NUM, np->file, np->line);
11307c478bd9Sstevel@tonic-gate 				newnp->u.ull = iterinfop->num;
11317c478bd9Sstevel@tonic-gate 				return (newnp);
11327c478bd9Sstevel@tonic-gate 			}
1133b5016cbbSstephh 		}
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 		/*
1136b5016cbbSstephh 		 * finally, whether wildcarding or not, we need to copy the
1137b5016cbbSstephh 		 * remaining part of the path (if any). This must be defined
1138b5016cbbSstephh 		 * absolutely (no more expansion/wildcarding).
11397c478bd9Sstevel@tonic-gate 		 */
1140b5016cbbSstephh 		for (npref = nprest; npref != NULL;
1141b5016cbbSstephh 		    npref = npref->u.name.next) {
1142b5016cbbSstephh 			newnp = newnode(T_NAME, np->file, np->line);
1143b5016cbbSstephh 			newnp->u.name.t = npref->u.name.t;
1144b5016cbbSstephh 			newnp->u.name.s = npref->u.name.s;
1145b5016cbbSstephh 			newnp->u.name.last = newnp;
1146b5016cbbSstephh 			newnp->u.name.it = npref->u.name.it;
1147b5016cbbSstephh 			newnp->u.name.cp = npref->u.name.cp;
1148b5016cbbSstephh 			newnp->u.name.child =
1149b5016cbbSstephh 			    newnode(T_NUM, np->file, np->line);
1150b5016cbbSstephh 			if (eval_expr(npref->u.name.child, ex, events,
11517c478bd9Sstevel@tonic-gate 			    NULL, NULL, NULL, 1, &value) == 0 ||
11527c478bd9Sstevel@tonic-gate 			    value.t != UINT64) {
11537c478bd9Sstevel@tonic-gate 				outfl(O_DIE, np->file, np->line,
11547c478bd9Sstevel@tonic-gate 				    "eval_dup: could not resolve "
11557c478bd9Sstevel@tonic-gate 				    "iterator of %s", np->u.name.s);
11567c478bd9Sstevel@tonic-gate 			}
1157b5016cbbSstephh 			newnp->u.name.child->u.ull = value.v;
1158b5016cbbSstephh 			if (retp == NULL) {
1159b5016cbbSstephh 				retp = newnp;
11607c478bd9Sstevel@tonic-gate 			} else {
1161b5016cbbSstephh 				retp->u.name.last->u.name.next = newnp;
1162b5016cbbSstephh 				retp->u.name.last = newnp;
11637c478bd9Sstevel@tonic-gate 			}
11647c478bd9Sstevel@tonic-gate 		}
1165b5016cbbSstephh 		return (retp);
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 
11687aec1d6eScindi 	case T_EVENT:
11697aec1d6eScindi 		newnp = newnode(T_NAME, np->file, np->line);
11707aec1d6eScindi 
11717aec1d6eScindi 		newnp->u.name.t = np->u.event.ename->u.name.t;
11727aec1d6eScindi 		newnp->u.name.s = np->u.event.ename->u.name.s;
11737aec1d6eScindi 		newnp->u.name.it = np->u.event.ename->u.name.it;
11747aec1d6eScindi 		newnp->u.name.last = newnp;
11757aec1d6eScindi 
11767aec1d6eScindi 		return (tree_event(newnp,
1177b5016cbbSstephh 		    eval_dup(np->u.event.epname, ex, events),
1178b5016cbbSstephh 		    eval_dup(np->u.event.eexprlist, ex, events)));
11797aec1d6eScindi 
11807c478bd9Sstevel@tonic-gate 	case T_FUNC:
11817c478bd9Sstevel@tonic-gate 		return (tree_func(np->u.func.s,
1182b5016cbbSstephh 		    eval_dup(np->u.func.arglist, ex, events),
11837c478bd9Sstevel@tonic-gate 		    np->file, np->line));
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	case T_QUOTE:
11867c478bd9Sstevel@tonic-gate 		newnp = newnode(T_QUOTE, np->file, np->line);
11877c478bd9Sstevel@tonic-gate 		newnp->u.quote.s = np->u.quote.s;
11887c478bd9Sstevel@tonic-gate 		return (newnp);
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 	case T_NUM:
11917c478bd9Sstevel@tonic-gate 		newnp = newnode(T_NUM, np->file, np->line);
11927c478bd9Sstevel@tonic-gate 		newnp->u.ull = np->u.ull;
11937c478bd9Sstevel@tonic-gate 		return (newnp);
11947c478bd9Sstevel@tonic-gate 
1195b7d3956bSstephh 	case T_TIMEVAL:
1196b7d3956bSstephh 		newnp = newnode(T_TIMEVAL, np->file, np->line);
1197b7d3956bSstephh 		newnp->u.ull = np->u.ull;
1198b7d3956bSstephh 		return (newnp);
1199b7d3956bSstephh 
12007c478bd9Sstevel@tonic-gate 	default:
12017c478bd9Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
12027c478bd9Sstevel@tonic-gate 		    "eval_dup: unexpected node type: %s",
12037c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
12047c478bd9Sstevel@tonic-gate 	}
12057c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
120680ab886dSwesolows 	return (0);
12077c478bd9Sstevel@tonic-gate }
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate /*
12107c478bd9Sstevel@tonic-gate  * eval_potential -- see if constraint is potentially true
12117c478bd9Sstevel@tonic-gate  *
12127c478bd9Sstevel@tonic-gate  * this function is used at instance tree creation time to see if
12137c478bd9Sstevel@tonic-gate  * any constraints are already known to be false.  if this function
12147c478bd9Sstevel@tonic-gate  * returns false, then the constraint will always be false and there's
12157c478bd9Sstevel@tonic-gate  * no need to include the propagation arrow in the instance tree.
12167c478bd9Sstevel@tonic-gate  *
12177c478bd9Sstevel@tonic-gate  * if this routine returns true, either the constraint is known to
12187c478bd9Sstevel@tonic-gate  * be always true (so there's no point in attaching the constraint
12197c478bd9Sstevel@tonic-gate  * to the propagation arrow in the instance tree), or the constraint
12207c478bd9Sstevel@tonic-gate  * contains "deferred" expressions like global variables or poller calls
12217c478bd9Sstevel@tonic-gate  * and so it must be evaluated during calls to fme_eval().  in this last
12227c478bd9Sstevel@tonic-gate  * case, where a constraint needs to be attached to the propagation arrow
12237c478bd9Sstevel@tonic-gate  * in the instance tree, this routine returns a newly created constraint
12247c478bd9Sstevel@tonic-gate  * in *newc where all the non-deferred things have been filled in.
12257c478bd9Sstevel@tonic-gate  *
12267c478bd9Sstevel@tonic-gate  * so in summary:
12277c478bd9Sstevel@tonic-gate  *
12287c478bd9Sstevel@tonic-gate  *	return of false: constraint can never be true, *newc will be NULL.
12297c478bd9Sstevel@tonic-gate  *
12307c478bd9Sstevel@tonic-gate  *	return of true with *newc unchanged: constraint will always be true.
12317c478bd9Sstevel@tonic-gate  *
12327c478bd9Sstevel@tonic-gate  *	return of true with *newc changed: use new constraint in *newc.
12337c478bd9Sstevel@tonic-gate  *
12347c478bd9Sstevel@tonic-gate  * the lookup table for all explicit iterators, ex, is passed in.
12357c478bd9Sstevel@tonic-gate  *
12367c478bd9Sstevel@tonic-gate  * *newc can either be NULL on entry, or if can contain constraints from
12377c478bd9Sstevel@tonic-gate  * previous calls to eval_potential() (i.e. for building up an instance
12387c478bd9Sstevel@tonic-gate  * tree constraint from several potential constraints).  if *newc already
12397c478bd9Sstevel@tonic-gate  * contains constraints, anything added to it will be joined by adding
12407c478bd9Sstevel@tonic-gate  * a T_AND node at the top of *newc.
12417c478bd9Sstevel@tonic-gate  */
12427c478bd9Sstevel@tonic-gate int
eval_potential(struct node * np,struct lut * ex,struct node * events[],struct node ** newc,struct config * croot)1243b5016cbbSstephh eval_potential(struct node *np, struct lut *ex, struct node *events[],
1244d96ce684Sstephh 	    struct node **newc, struct config *croot)
12457c478bd9Sstevel@tonic-gate {
12467c478bd9Sstevel@tonic-gate 	struct node *newnp;
12477c478bd9Sstevel@tonic-gate 	struct evalue value;
12487c478bd9Sstevel@tonic-gate 
1249b5016cbbSstephh 	if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
12507c478bd9Sstevel@tonic-gate 		/*
12517c478bd9Sstevel@tonic-gate 		 * couldn't eval expression because
12527c478bd9Sstevel@tonic-gate 		 * it contains deferred items.  make
12537c478bd9Sstevel@tonic-gate 		 * a duplicate expression with all the
12547c478bd9Sstevel@tonic-gate 		 * non-deferred items expanded.
12557c478bd9Sstevel@tonic-gate 		 */
1256b5016cbbSstephh 		newnp = eval_dup(np, ex, events);
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 		if (*newc == NULL) {
12597c478bd9Sstevel@tonic-gate 			/*
12607c478bd9Sstevel@tonic-gate 			 * constraint is potentially true if deferred
12617c478bd9Sstevel@tonic-gate 			 * expression in newnp is true.  *newc was NULL
12627c478bd9Sstevel@tonic-gate 			 * so new constraint is just the one in newnp.
12637c478bd9Sstevel@tonic-gate 			 */
12647c478bd9Sstevel@tonic-gate 			*newc = newnp;
12657c478bd9Sstevel@tonic-gate 			return (1);
12667c478bd9Sstevel@tonic-gate 		} else {
12677c478bd9Sstevel@tonic-gate 			/*
12687c478bd9Sstevel@tonic-gate 			 * constraint is potentially true if deferred
12697c478bd9Sstevel@tonic-gate 			 * expression in newnp is true.  *newc already
12707c478bd9Sstevel@tonic-gate 			 * contained a constraint so add an AND with the
12717c478bd9Sstevel@tonic-gate 			 * constraint in newnp.
12727c478bd9Sstevel@tonic-gate 			 */
12737c478bd9Sstevel@tonic-gate 			*newc = tree_expr(T_AND, *newc, newnp);
12747c478bd9Sstevel@tonic-gate 			return (1);
12757c478bd9Sstevel@tonic-gate 		}
12767c478bd9Sstevel@tonic-gate 	} else if (value.t == UNDEFINED) {
12777c478bd9Sstevel@tonic-gate 		/* constraint can never be true */
12787c478bd9Sstevel@tonic-gate 		return (0);
12797c478bd9Sstevel@tonic-gate 	} else if (value.t == UINT64 && value.v == 0) {
12807c478bd9Sstevel@tonic-gate 		/* constraint can never be true */
12817c478bd9Sstevel@tonic-gate 		return (0);
12827c478bd9Sstevel@tonic-gate 	} else {
12837c478bd9Sstevel@tonic-gate 		/* constraint is always true (nothing deferred to eval) */
12847c478bd9Sstevel@tonic-gate 		return (1);
12857c478bd9Sstevel@tonic-gate 	}
12867c478bd9Sstevel@tonic-gate }
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate static int
check_expr_args(struct evalue * lp,struct evalue * rp,enum datatype dtype,struct node * np)12897c478bd9Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
12907c478bd9Sstevel@tonic-gate 		struct node *np)
12917c478bd9Sstevel@tonic-gate {
12927aec1d6eScindi 	/* auto-convert T_NAMES to strings */
129380ab886dSwesolows 	if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
129480ab886dSwesolows 	    T_NAME) {
129580ab886dSwesolows 		char *s = ipath2str(NULL,
129680ab886dSwesolows 		    ipath((struct node *)(uintptr_t)lp->v));
12977aec1d6eScindi 		lp->t = STRING;
129880ab886dSwesolows 		lp->v = (uintptr_t)stable(s);
12997aec1d6eScindi 		FREE(s);
13007aec1d6eScindi 		out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
130180ab886dSwesolows 		    (char *)(uintptr_t)lp->v);
13027aec1d6eScindi 	}
13037aec1d6eScindi 	if (rp != NULL &&
130480ab886dSwesolows 	    rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
130580ab886dSwesolows 	    T_NAME) {
130680ab886dSwesolows 		char *s = ipath2str(NULL,
130780ab886dSwesolows 		    ipath((struct node *)(uintptr_t)rp->v));
13087aec1d6eScindi 		rp->t = STRING;
130980ab886dSwesolows 		rp->v = (uintptr_t)stable(s);
13107aec1d6eScindi 		FREE(s);
13117aec1d6eScindi 		out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
131280ab886dSwesolows 		    (char *)(uintptr_t)rp->v);
13137aec1d6eScindi 	}
13147aec1d6eScindi 
1315b0daa853SStephen Hanson 	/* auto-convert numbers to strings */
1316b0daa853SStephen Hanson 	if (dtype == STRING) {
1317b0daa853SStephen Hanson 		if (lp->t == UINT64) {
1318b0daa853SStephen Hanson 			int len = snprintf(NULL, 0, "%llx", lp->v);
1319b0daa853SStephen Hanson 			char *s = MALLOC(len + 1);
1320b0daa853SStephen Hanson 
1321b0daa853SStephen Hanson 			(void) snprintf(s, len + 1, "%llx", lp->v);
1322b0daa853SStephen Hanson 			lp->t = STRING;
1323b0daa853SStephen Hanson 			lp->v = (uintptr_t)stable(s);
1324b0daa853SStephen Hanson 			FREE(s);
1325b0daa853SStephen Hanson 		}
1326b0daa853SStephen Hanson 		if (rp != NULL && rp->t == UINT64) {
1327b0daa853SStephen Hanson 			int len = snprintf(NULL, 0, "%llx", rp->v);
1328b0daa853SStephen Hanson 			char *s = MALLOC(len + 1);
1329b0daa853SStephen Hanson 
1330b0daa853SStephen Hanson 			(void) snprintf(s, len + 1, "%llx", rp->v);
1331b0daa853SStephen Hanson 			rp->t = STRING;
1332b0daa853SStephen Hanson 			rp->v = (uintptr_t)stable(s);
1333b0daa853SStephen Hanson 			FREE(s);
1334b0daa853SStephen Hanson 		}
1335b0daa853SStephen Hanson 	}
1336b0daa853SStephen Hanson 
13377aec1d6eScindi 	/* auto-convert strings to numbers */
13387aec1d6eScindi 	if (dtype == UINT64) {
13397aec1d6eScindi 		if (lp->t == STRING) {
13407aec1d6eScindi 			lp->t = UINT64;
134180ab886dSwesolows 			lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
13427aec1d6eScindi 		}
13437aec1d6eScindi 		if (rp != NULL && rp->t == STRING) {
13447aec1d6eScindi 			rp->t = UINT64;
134580ab886dSwesolows 			rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
13467aec1d6eScindi 		}
13477aec1d6eScindi 	}
13487aec1d6eScindi 
13497c478bd9Sstevel@tonic-gate 	if (dtype != UNDEFINED && lp->t != dtype) {
1350b5016cbbSstephh 		outfl(O_DIE, np->file, np->line,
13517c478bd9Sstevel@tonic-gate 		    "invalid datatype of argument for operation %s",
13527c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
1353b5016cbbSstephh 		/* NOTREACHED */
13547c478bd9Sstevel@tonic-gate 		return (1);
13557c478bd9Sstevel@tonic-gate 	}
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 	if (rp != NULL && lp->t != rp->t) {
1358b5016cbbSstephh 		outfl(O_DIE, np->file, np->line,
13597c478bd9Sstevel@tonic-gate 		    "mismatch in datatype of arguments for operation %s",
13607c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
1361b5016cbbSstephh 		/* NOTREACHED */
13627c478bd9Sstevel@tonic-gate 		return (1);
13637c478bd9Sstevel@tonic-gate 	}
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 	return (0);
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate /*
13697c478bd9Sstevel@tonic-gate  * eval_expr -- evaluate expression into *valuep
13707c478bd9Sstevel@tonic-gate  *
13717c478bd9Sstevel@tonic-gate  * the meaning of the return value depends on the input value of try.
13727c478bd9Sstevel@tonic-gate  *
13737c478bd9Sstevel@tonic-gate  * for try == 1: if any deferred items are encounted, bail out and return
13747c478bd9Sstevel@tonic-gate  * false.  returns true if we made it through entire expression without
13757c478bd9Sstevel@tonic-gate  * hitting any deferred items.
13767c478bd9Sstevel@tonic-gate  *
13777c478bd9Sstevel@tonic-gate  * for try == 0: return true if all operations were performed successfully.
13787c478bd9Sstevel@tonic-gate  * return false if otherwise.  for example, any of the following conditions
13797c478bd9Sstevel@tonic-gate  * will result in a false return value:
13807c478bd9Sstevel@tonic-gate  *   - attempted use of an uninitialized global variable
13817c478bd9Sstevel@tonic-gate  *   - failure in function evaluation
13827c478bd9Sstevel@tonic-gate  *   - illegal arithmetic operation (argument out of range)
13837c478bd9Sstevel@tonic-gate  */
13847c478bd9Sstevel@tonic-gate int
eval_expr(struct node * np,struct lut * ex,struct node * events[],struct lut ** globals,struct config * croot,struct arrow * arrowp,int try,struct evalue * valuep)1385b5016cbbSstephh eval_expr(struct node *np, struct lut *ex, struct node *events[],
13867c478bd9Sstevel@tonic-gate 	struct lut **globals, struct config *croot, struct arrow *arrowp,
13877c478bd9Sstevel@tonic-gate 	int try, struct evalue *valuep)
13887c478bd9Sstevel@tonic-gate {
13897c478bd9Sstevel@tonic-gate 	struct evalue *gval;
13907c478bd9Sstevel@tonic-gate 	struct evalue lval;
13917c478bd9Sstevel@tonic-gate 	struct evalue rval;
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 	if (np == NULL) {
13947c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
13957c478bd9Sstevel@tonic-gate 		valuep->v = 1;	/* no constraint means "true" */
13967c478bd9Sstevel@tonic-gate 		return (1);
13977c478bd9Sstevel@tonic-gate 	}
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 	valuep->t = UNDEFINED;
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 	switch (np->t) {
14027c478bd9Sstevel@tonic-gate 	case T_GLOBID:
14037c478bd9Sstevel@tonic-gate 		if (try)
14047c478bd9Sstevel@tonic-gate 			return (0);
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 		/*
14077c478bd9Sstevel@tonic-gate 		 * only handle case of getting (and not setting) the value
14087c478bd9Sstevel@tonic-gate 		 * of a global variable
14097c478bd9Sstevel@tonic-gate 		 */
14107c478bd9Sstevel@tonic-gate 		gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
14117c478bd9Sstevel@tonic-gate 		if (gval == NULL) {
14127c478bd9Sstevel@tonic-gate 			return (0);
14137c478bd9Sstevel@tonic-gate 		} else {
14147c478bd9Sstevel@tonic-gate 			valuep->t = gval->t;
14157c478bd9Sstevel@tonic-gate 			valuep->v = gval->v;
14167c478bd9Sstevel@tonic-gate 			return (1);
14177c478bd9Sstevel@tonic-gate 		}
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 	case T_ASSIGN:
14207c478bd9Sstevel@tonic-gate 		if (try)
14217c478bd9Sstevel@tonic-gate 			return (0);
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 		/*
14247c478bd9Sstevel@tonic-gate 		 * first evaluate rhs, then try to store value in lhs which
14257c478bd9Sstevel@tonic-gate 		 * should be a global variable
14267c478bd9Sstevel@tonic-gate 		 */
1427b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14287c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
14297c478bd9Sstevel@tonic-gate 			return (0);
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate 		ASSERT(np->u.expr.left->t == T_GLOBID);
14327c478bd9Sstevel@tonic-gate 		gval = lut_lookup(*globals,
14337c478bd9Sstevel@tonic-gate 		    (void *)np->u.expr.left->u.globid.s, NULL);
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 		if (gval == NULL) {
14367c478bd9Sstevel@tonic-gate 			gval = MALLOC(sizeof (*gval));
14377c478bd9Sstevel@tonic-gate 			*globals = lut_add(*globals,
1438b5016cbbSstephh 			    (void *) np->u.expr.left->u.globid.s, gval, NULL);
14397c478bd9Sstevel@tonic-gate 		}
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 		gval->t = rval.t;
14427c478bd9Sstevel@tonic-gate 		gval->v = rval.v;
14437aec1d6eScindi 
14447aec1d6eScindi 		if (gval->t == UINT64) {
14457aec1d6eScindi 			out(O_ALTFP|O_VERB2,
14467aec1d6eScindi 			    "assign $%s=%llu",
14477aec1d6eScindi 			    np->u.expr.left->u.globid.s, gval->v);
14487aec1d6eScindi 		} else {
14497aec1d6eScindi 			out(O_ALTFP|O_VERB2,
14507aec1d6eScindi 			    "assign $%s=\"%s\"",
145180ab886dSwesolows 			    np->u.expr.left->u.globid.s,
145280ab886dSwesolows 			    (char *)(uintptr_t)gval->v);
14537aec1d6eScindi 		}
14547aec1d6eScindi 
14557aec1d6eScindi 		/*
14567aec1d6eScindi 		 * but always return true -- an assignment should not
14577aec1d6eScindi 		 * cause a constraint to be false.
14587aec1d6eScindi 		 */
14597aec1d6eScindi 		valuep->t = UINT64;
14607aec1d6eScindi 		valuep->v = 1;
14617c478bd9Sstevel@tonic-gate 		return (1);
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 	case T_EQ:
14647c478bd9Sstevel@tonic-gate #define	IMPLICIT_ASSIGN_IN_EQ
14657c478bd9Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ
14667c478bd9Sstevel@tonic-gate 		/*
14677c478bd9Sstevel@tonic-gate 		 * if lhs is an uninitialized global variable, perform
14687c478bd9Sstevel@tonic-gate 		 * an assignment.
14697c478bd9Sstevel@tonic-gate 		 *
14707c478bd9Sstevel@tonic-gate 		 * one insidious side effect of implicit assignment is
14717c478bd9Sstevel@tonic-gate 		 * that the "==" operator does not return a Boolean if
14727c478bd9Sstevel@tonic-gate 		 * implicit assignment was performed.
14737c478bd9Sstevel@tonic-gate 		 */
14747c478bd9Sstevel@tonic-gate 		if (try == 0 &&
14757c478bd9Sstevel@tonic-gate 		    np->u.expr.left->t == T_GLOBID &&
14767c478bd9Sstevel@tonic-gate 		    (gval = lut_lookup(*globals,
14777c478bd9Sstevel@tonic-gate 		    (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
1478b5016cbbSstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
14797c478bd9Sstevel@tonic-gate 			    croot, arrowp, try, &rval))
14807c478bd9Sstevel@tonic-gate 				return (0);
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 			gval = MALLOC(sizeof (*gval));
14837c478bd9Sstevel@tonic-gate 			*globals = lut_add(*globals,
14847c478bd9Sstevel@tonic-gate 			    (void *) np->u.expr.left->u.globid.s,
14857c478bd9Sstevel@tonic-gate 			    gval, NULL);
14867c478bd9Sstevel@tonic-gate 
14877c478bd9Sstevel@tonic-gate 			gval->t = rval.t;
14887c478bd9Sstevel@tonic-gate 			gval->v = rval.v;
14897c478bd9Sstevel@tonic-gate 			valuep->t = rval.t;
14907c478bd9Sstevel@tonic-gate 			valuep->v = rval.v;
14917c478bd9Sstevel@tonic-gate 			return (1);
14927c478bd9Sstevel@tonic-gate 		}
14937c478bd9Sstevel@tonic-gate #endif  /* IMPLICIT_ASSIGN_IN_EQ */
14947c478bd9Sstevel@tonic-gate 
1495b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14967c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
14977c478bd9Sstevel@tonic-gate 			return (0);
1498b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14997c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15007c478bd9Sstevel@tonic-gate 			return (0);
1501b5016cbbSstephh 		if (rval.t == UINT64 || lval.t == UINT64) {
1502b5016cbbSstephh 			if (check_expr_args(&lval, &rval, UINT64, np))
1503b5016cbbSstephh 				return (0);
1504b5016cbbSstephh 		} else {
15057c478bd9Sstevel@tonic-gate 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
15067c478bd9Sstevel@tonic-gate 				return (0);
1507b5016cbbSstephh 		}
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
15107c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v == rval.v);
15117c478bd9Sstevel@tonic-gate 		return (1);
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 	case T_LT:
1514b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15157c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
15167c478bd9Sstevel@tonic-gate 			return (0);
1517b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15187c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15197c478bd9Sstevel@tonic-gate 			return (0);
15207aec1d6eScindi 		if (check_expr_args(&lval, &rval, UINT64, np))
15217c478bd9Sstevel@tonic-gate 			return (0);
15227c478bd9Sstevel@tonic-gate 
15237c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
15247c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v < rval.v);
15257c478bd9Sstevel@tonic-gate 		return (1);
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	case T_LE:
1528b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15297c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
15307c478bd9Sstevel@tonic-gate 			return (0);
1531b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15327c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15337c478bd9Sstevel@tonic-gate 			return (0);
15347aec1d6eScindi 		if (check_expr_args(&lval, &rval, UINT64, np))
15357c478bd9Sstevel@tonic-gate 			return (0);
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
15387c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v <= rval.v);
15397c478bd9Sstevel@tonic-gate 		return (1);
15407c478bd9Sstevel@tonic-gate 
15417c478bd9Sstevel@tonic-gate 	case T_GT:
1542b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15437c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
15447c478bd9Sstevel@tonic-gate 			return (0);
1545b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15467c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15477c478bd9Sstevel@tonic-gate 			return (0);
15487aec1d6eScindi 		if (check_expr_args(&lval, &rval, UINT64, np))
15497c478bd9Sstevel@tonic-gate 			return (0);
15507c478bd9Sstevel@tonic-gate 
15517c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
15527c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v > rval.v);
15537c478bd9Sstevel@tonic-gate 		return (1);
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 	case T_GE:
1556b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15577c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
15587c478bd9Sstevel@tonic-gate 			return (0);
1559b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15607c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15617c478bd9Sstevel@tonic-gate 			return (0);
15627aec1d6eScindi 		if (check_expr_args(&lval, &rval, UINT64, np))
15637c478bd9Sstevel@tonic-gate 			return (0);
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
15667c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v >= rval.v);
15677c478bd9Sstevel@tonic-gate 		return (1);
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 	case T_BITAND:
1570b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15717c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
15727c478bd9Sstevel@tonic-gate 			return (0);
1573b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15747c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15757c478bd9Sstevel@tonic-gate 			return (0);
15767c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
15777c478bd9Sstevel@tonic-gate 			return (0);
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
15807c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v & rval.v);
15817c478bd9Sstevel@tonic-gate 		return (1);
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate 	case T_BITOR:
1584b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15857c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
15867c478bd9Sstevel@tonic-gate 			return (0);
1587b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15887c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
15897c478bd9Sstevel@tonic-gate 			return (0);
15907c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
15917c478bd9Sstevel@tonic-gate 			return (0);
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
15947c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v | rval.v);
15957c478bd9Sstevel@tonic-gate 		return (1);
15967c478bd9Sstevel@tonic-gate 
15977c478bd9Sstevel@tonic-gate 	case T_BITXOR:
1598b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15997c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
16007c478bd9Sstevel@tonic-gate 			return (0);
1601b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16027c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
16037c478bd9Sstevel@tonic-gate 			return (0);
16047c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16057c478bd9Sstevel@tonic-gate 			return (0);
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
16087c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v ^ rval.v);
16097c478bd9Sstevel@tonic-gate 		return (1);
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	case T_BITNOT:
1612b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16137c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
16147c478bd9Sstevel@tonic-gate 			return (0);
16157c478bd9Sstevel@tonic-gate 		ASSERT(np->u.expr.right == NULL);
16167c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, NULL, UINT64, np))
16177c478bd9Sstevel@tonic-gate 			return (0);
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16207c478bd9Sstevel@tonic-gate 		valuep->v = ~ lval.v;
16217c478bd9Sstevel@tonic-gate 		return (1);
16227c478bd9Sstevel@tonic-gate 
16237c478bd9Sstevel@tonic-gate 	case T_LSHIFT:
1624b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16257c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
16267c478bd9Sstevel@tonic-gate 			return (0);
1627b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16287c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
16297c478bd9Sstevel@tonic-gate 			return (0);
16307c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16317c478bd9Sstevel@tonic-gate 			return (0);
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16347c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v << rval.v);
16357c478bd9Sstevel@tonic-gate 		return (1);
16367c478bd9Sstevel@tonic-gate 
16377c478bd9Sstevel@tonic-gate 	case T_RSHIFT:
1638b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16397c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
16407c478bd9Sstevel@tonic-gate 			return (0);
1641b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16427c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
16437c478bd9Sstevel@tonic-gate 			return (0);
16447c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16457c478bd9Sstevel@tonic-gate 			return (0);
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16487c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v >> rval.v);
16497c478bd9Sstevel@tonic-gate 		return (1);
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 	case T_CONDIF: {
16527c478bd9Sstevel@tonic-gate 		struct node *retnp;
16537c478bd9Sstevel@tonic-gate 		int dotrue = 0;
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 		/*
16567c478bd9Sstevel@tonic-gate 		 * evaluate
16577c478bd9Sstevel@tonic-gate 		 *	expression ? stmtA [ : stmtB ]
16587c478bd9Sstevel@tonic-gate 		 *
16597c478bd9Sstevel@tonic-gate 		 * first see if expression is true or false, then determine
16607c478bd9Sstevel@tonic-gate 		 * if stmtA (or stmtB, if it exists) should be evaluated.
16617c478bd9Sstevel@tonic-gate 		 *
16627c478bd9Sstevel@tonic-gate 		 * "dotrue = 1" means stmtA should be evaluated.
16637c478bd9Sstevel@tonic-gate 		 */
1664e5ba14ffSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1665e5ba14ffSstephh 		    arrowp, try, &lval))
1666e5ba14ffSstephh 			return (0);
1667e5ba14ffSstephh 
1668e5ba14ffSstephh 		if (lval.t != UNDEFINED && lval.v != 0)
16697c478bd9Sstevel@tonic-gate 			dotrue = 1;
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 		ASSERT(np->u.expr.right != NULL);
16727c478bd9Sstevel@tonic-gate 		if (np->u.expr.right->t == T_CONDELSE) {
16737c478bd9Sstevel@tonic-gate 			if (dotrue)
16747c478bd9Sstevel@tonic-gate 				retnp = np->u.expr.right->u.expr.left;
16757c478bd9Sstevel@tonic-gate 			else
16767c478bd9Sstevel@tonic-gate 				retnp = np->u.expr.right->u.expr.right;
16777c478bd9Sstevel@tonic-gate 		} else {
16787c478bd9Sstevel@tonic-gate 			/* no ELSE clause */
16797c478bd9Sstevel@tonic-gate 			if (dotrue)
16807c478bd9Sstevel@tonic-gate 				retnp = np->u.expr.right;
16817c478bd9Sstevel@tonic-gate 			else {
1682b5016cbbSstephh 				outfl(O_DIE, np->file, np->line,
1683b5016cbbSstephh 				    "eval_expr: missing condelse");
16847c478bd9Sstevel@tonic-gate 			}
16857c478bd9Sstevel@tonic-gate 		}
16867c478bd9Sstevel@tonic-gate 
1687b5016cbbSstephh 		if (!eval_expr(retnp, ex, events, globals, croot,
16887c478bd9Sstevel@tonic-gate 		    arrowp, try, valuep))
16897c478bd9Sstevel@tonic-gate 			return (0);
16907c478bd9Sstevel@tonic-gate 		return (1);
16917c478bd9Sstevel@tonic-gate 	}
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate 	case T_CONDELSE:
16947c478bd9Sstevel@tonic-gate 		/*
16957c478bd9Sstevel@tonic-gate 		 * shouldn't get here, since T_CONDELSE is supposed to be
16967c478bd9Sstevel@tonic-gate 		 * evaluated as part of T_CONDIF
16977c478bd9Sstevel@tonic-gate 		 */
16987c478bd9Sstevel@tonic-gate 		out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
16997c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
1700b5016cbbSstephh 		/*NOTREACHED*/
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 	case T_NE:
1703b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17047c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
17057c478bd9Sstevel@tonic-gate 			return (0);
1706b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
17077c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
17087c478bd9Sstevel@tonic-gate 			return (0);
1709b5016cbbSstephh 		if (rval.t == UINT64 || lval.t == UINT64) {
1710b5016cbbSstephh 			if (check_expr_args(&lval, &rval, UINT64, np))
1711b5016cbbSstephh 				return (0);
1712b5016cbbSstephh 		} else {
17137c478bd9Sstevel@tonic-gate 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
17147c478bd9Sstevel@tonic-gate 				return (0);
1715b5016cbbSstephh 		}
17167c478bd9Sstevel@tonic-gate 
17177c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17187c478bd9Sstevel@tonic-gate 		valuep->v = (lval.v != rval.v);
17197c478bd9Sstevel@tonic-gate 		return (1);
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	case T_LIST:
17227c478bd9Sstevel@tonic-gate 	case T_AND:
1723b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17248aec9182Sstephh 		    arrowp, try, valuep)) {
17258aec9182Sstephh 			/*
17268aec9182Sstephh 			 * if lhs is unknown, still check rhs. If that
1727e5ba14ffSstephh 			 * is false we can return false irrespective of lhs
17288aec9182Sstephh 			 */
1729e5ba14ffSstephh 			if (!try) {
1730e5ba14ffSstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1731e5ba14ffSstephh 				return (0);
1732e5ba14ffSstephh 			}
1733b5016cbbSstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1734b5016cbbSstephh 			    croot, arrowp, try, valuep)) {
1735b5016cbbSstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
17367c478bd9Sstevel@tonic-gate 				return (0);
1737b5016cbbSstephh 			}
1738b5016cbbSstephh 			if (valuep->v != 0) {
1739b5016cbbSstephh 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
17408aec9182Sstephh 				return (0);
17418aec9182Sstephh 			}
1742b5016cbbSstephh 		}
17437c478bd9Sstevel@tonic-gate 		if (valuep->v == 0) {
17447c478bd9Sstevel@tonic-gate 			valuep->t = UINT64;
17457c478bd9Sstevel@tonic-gate 			return (1);
17467c478bd9Sstevel@tonic-gate 		}
1747b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1748b5016cbbSstephh 		    arrowp, try, valuep)) {
1749b5016cbbSstephh 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
17507c478bd9Sstevel@tonic-gate 			return (0);
1751b5016cbbSstephh 		}
17527c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17537c478bd9Sstevel@tonic-gate 		valuep->v = valuep->v == 0 ? 0 : 1;
17547c478bd9Sstevel@tonic-gate 		return (1);
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 	case T_OR:
1757b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17588aec9182Sstephh 		    arrowp, try, valuep)) {
17598aec9182Sstephh 			/*
17608aec9182Sstephh 			 * if lhs is unknown, still check rhs. If that
1761e5ba14ffSstephh 			 * is true we can return true irrespective of lhs
17628aec9182Sstephh 			 */
1763e5ba14ffSstephh 			if (!try) {
1764e5ba14ffSstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1765e5ba14ffSstephh 				return (0);
1766e5ba14ffSstephh 			}
1767b5016cbbSstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1768b5016cbbSstephh 			    croot, arrowp, try, valuep)) {
1769b5016cbbSstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
17707c478bd9Sstevel@tonic-gate 				return (0);
1771b5016cbbSstephh 			}
1772b5016cbbSstephh 			if (valuep->v == 0) {
1773b5016cbbSstephh 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
17748aec9182Sstephh 				return (0);
17758aec9182Sstephh 			}
1776b5016cbbSstephh 		}
17777c478bd9Sstevel@tonic-gate 		if (valuep->v != 0) {
17787c478bd9Sstevel@tonic-gate 			valuep->t = UINT64;
17797c478bd9Sstevel@tonic-gate 			valuep->v = 1;
17807c478bd9Sstevel@tonic-gate 			return (1);
17817c478bd9Sstevel@tonic-gate 		}
1782b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1783b5016cbbSstephh 		    arrowp, try, valuep)) {
1784b5016cbbSstephh 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
17857c478bd9Sstevel@tonic-gate 			return (0);
1786b5016cbbSstephh 		}
17877c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17887c478bd9Sstevel@tonic-gate 		valuep->v = valuep->v == 0 ? 0 : 1;
17897c478bd9Sstevel@tonic-gate 		return (1);
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 	case T_NOT:
1792b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
17937c478bd9Sstevel@tonic-gate 		    arrowp, try, valuep))
17947c478bd9Sstevel@tonic-gate 			return (0);
17957c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17967c478bd9Sstevel@tonic-gate 		valuep->v = ! valuep->v;
17977c478bd9Sstevel@tonic-gate 		return (1);
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 	case T_ADD:
1800b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18017c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
18027c478bd9Sstevel@tonic-gate 			return (0);
1803b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18047c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
18057c478bd9Sstevel@tonic-gate 			return (0);
18067c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
18077c478bd9Sstevel@tonic-gate 			return (0);
18087c478bd9Sstevel@tonic-gate 
18097c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
18107c478bd9Sstevel@tonic-gate 		valuep->v = lval.v + rval.v;
18117c478bd9Sstevel@tonic-gate 		return (1);
18127c478bd9Sstevel@tonic-gate 
18137c478bd9Sstevel@tonic-gate 	case T_SUB:
1814b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18157c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
18167c478bd9Sstevel@tonic-gate 			return (0);
1817b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18187c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
18197c478bd9Sstevel@tonic-gate 			return (0);
18207c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
18217c478bd9Sstevel@tonic-gate 			return (0);
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate 		/* since valuep is unsigned, return false if lval.v < rval.v */
18247c478bd9Sstevel@tonic-gate 		if (lval.v < rval.v) {
1825b5016cbbSstephh 			outfl(O_DIE, np->file, np->line,
1826b5016cbbSstephh 			    "eval_expr: T_SUB result is out of range");
18277c478bd9Sstevel@tonic-gate 		}
18287c478bd9Sstevel@tonic-gate 
18297c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
18307c478bd9Sstevel@tonic-gate 		valuep->v = lval.v - rval.v;
18317c478bd9Sstevel@tonic-gate 		return (1);
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 	case T_MUL:
1834b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18357c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
18367c478bd9Sstevel@tonic-gate 			return (0);
1837b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18387c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
18397c478bd9Sstevel@tonic-gate 			return (0);
18407c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
18417c478bd9Sstevel@tonic-gate 			return (0);
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
18447c478bd9Sstevel@tonic-gate 		valuep->v = lval.v * rval.v;
18457c478bd9Sstevel@tonic-gate 		return (1);
18467c478bd9Sstevel@tonic-gate 
18477c478bd9Sstevel@tonic-gate 	case T_DIV:
1848b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18497c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
18507c478bd9Sstevel@tonic-gate 			return (0);
1851b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18527c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
18537c478bd9Sstevel@tonic-gate 			return (0);
18547c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
18557c478bd9Sstevel@tonic-gate 			return (0);
18567c478bd9Sstevel@tonic-gate 
18577c478bd9Sstevel@tonic-gate 		/* return false if dividing by zero */
18587c478bd9Sstevel@tonic-gate 		if (rval.v == 0) {
1859b5016cbbSstephh 			outfl(O_DIE, np->file, np->line,
1860b5016cbbSstephh 			    "eval_expr: T_DIV division by zero");
18617c478bd9Sstevel@tonic-gate 		}
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
18647c478bd9Sstevel@tonic-gate 		valuep->v = lval.v / rval.v;
18657c478bd9Sstevel@tonic-gate 		return (1);
18667c478bd9Sstevel@tonic-gate 
18677c478bd9Sstevel@tonic-gate 	case T_MOD:
1868b5016cbbSstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
18697c478bd9Sstevel@tonic-gate 		    arrowp, try, &lval))
18707c478bd9Sstevel@tonic-gate 			return (0);
1871b5016cbbSstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
18727c478bd9Sstevel@tonic-gate 		    arrowp, try, &rval))
18737c478bd9Sstevel@tonic-gate 			return (0);
18747c478bd9Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
18757c478bd9Sstevel@tonic-gate 			return (0);
18767c478bd9Sstevel@tonic-gate 
18777c478bd9Sstevel@tonic-gate 		/* return false if dividing by zero */
18787c478bd9Sstevel@tonic-gate 		if (rval.v == 0) {
1879b5016cbbSstephh 			outfl(O_DIE, np->file, np->line,
1880b5016cbbSstephh 			    "eval_expr: T_MOD division by zero");
18817c478bd9Sstevel@tonic-gate 		}
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 		valuep->t = lval.t;
18847c478bd9Sstevel@tonic-gate 		valuep->v = lval.v % rval.v;
18857c478bd9Sstevel@tonic-gate 		return (1);
18867c478bd9Sstevel@tonic-gate 
18877c478bd9Sstevel@tonic-gate 	case T_NAME:
18887c478bd9Sstevel@tonic-gate 		if (try) {
18897c478bd9Sstevel@tonic-gate 			struct iterinfo *iterinfop;
1890b5016cbbSstephh 			struct node *np1, *np2;
1891b5016cbbSstephh 			int i, gotmatch = 0;
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 			/*
1894b5016cbbSstephh 			 * Check if we have an exact match of the nonwildcarded
1895b5016cbbSstephh 			 * path in oldepname - if so we can just use the
1896b5016cbbSstephh 			 * full wildcarded path in epname.
18977c478bd9Sstevel@tonic-gate 			 */
1898b5016cbbSstephh 			for (i = 0; i < 1; i++) {
1899b5016cbbSstephh 				for (np1 = np,
1900b5016cbbSstephh 				    np2 = events[i]->u.event.oldepname;
1901b5016cbbSstephh 				    np1 != NULL && np2 != NULL;
1902b5016cbbSstephh 				    np1 = np1->u.name.next,
1903b5016cbbSstephh 				    np2 = np2->u.name.next) {
1904b5016cbbSstephh 					if (strcmp(np1->u.name.s,
1905b5016cbbSstephh 					    np2->u.name.s) != 0)
1906b5016cbbSstephh 						break;
1907b5016cbbSstephh 					if (np1->u.name.child->t !=
1908b5016cbbSstephh 					    np2->u.name.child->t)
1909b5016cbbSstephh 						break;
1910b5016cbbSstephh 					if (np1->u.name.child->t == T_NUM &&
1911b5016cbbSstephh 					    np1->u.name.child->u.ull !=
1912b5016cbbSstephh 					    np2->u.name.child->u.ull)
1913b5016cbbSstephh 						break;
1914b5016cbbSstephh 					if (np1->u.name.child->t == T_NAME &&
1915b5016cbbSstephh 					    strcmp(np1->u.name.child->u.name.s,
1916b5016cbbSstephh 					    np2->u.name.child->u.name.s) != 0)
1917b5016cbbSstephh 						break;
1918b5016cbbSstephh 					gotmatch++;
1919b5016cbbSstephh 				}
1920b5016cbbSstephh 				if (np1 == NULL && np2 == NULL) {
1921b5016cbbSstephh 					valuep->t = NODEPTR;
1922b5016cbbSstephh 					valuep->v = (uintptr_t)
1923b5016cbbSstephh 					    events[i]->u.event.epname;
19247c478bd9Sstevel@tonic-gate 					return (1);
19257c478bd9Sstevel@tonic-gate 				}
1926b5016cbbSstephh 			}
1927b5016cbbSstephh 			if (!gotmatch) {
1928b5016cbbSstephh 				/*
1929b5016cbbSstephh 				 * we're not wildcarding. However at
1930b5016cbbSstephh 				 * itree_create() time, we can also expand
1931b5016cbbSstephh 				 * simple iterators - so check for those.
1932b5016cbbSstephh 				 */
1933b5016cbbSstephh 				iterinfop = lut_lookup(ex, (void *)np->u.name.s,
1934b5016cbbSstephh 				    NULL);
1935b5016cbbSstephh 				if (iterinfop != NULL) {
1936b5016cbbSstephh 					valuep->t = UINT64;
1937b5016cbbSstephh 					valuep->v =
1938b5016cbbSstephh 					    (unsigned long long)iterinfop->num;
1939b5016cbbSstephh 					return (1);
1940b5016cbbSstephh 				}
1941b5016cbbSstephh 			}
1942b5016cbbSstephh 			/*
1943b5016cbbSstephh 			 * For anything else we'll have to wait for eval_dup().
1944b5016cbbSstephh 			 */
19457c478bd9Sstevel@tonic-gate 			return (0);
19467c478bd9Sstevel@tonic-gate 		}
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 		/* return address of struct node */
19497c478bd9Sstevel@tonic-gate 		valuep->t = NODEPTR;
195080ab886dSwesolows 		valuep->v = (uintptr_t)np;
19517c478bd9Sstevel@tonic-gate 		return (1);
19527c478bd9Sstevel@tonic-gate 
19537c478bd9Sstevel@tonic-gate 	case T_QUOTE:
19547c478bd9Sstevel@tonic-gate 		valuep->t = STRING;
195580ab886dSwesolows 		valuep->v = (uintptr_t)np->u.quote.s;
19567c478bd9Sstevel@tonic-gate 		return (1);
19577c478bd9Sstevel@tonic-gate 
19587c478bd9Sstevel@tonic-gate 	case T_FUNC:
1959b5016cbbSstephh 		return (eval_func(np, ex, events, np->u.func.arglist,
19607c478bd9Sstevel@tonic-gate 		    globals, croot, arrowp, try, valuep));
19617c478bd9Sstevel@tonic-gate 
19627c478bd9Sstevel@tonic-gate 	case T_NUM:
1963b7d3956bSstephh 	case T_TIMEVAL:
19647c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
19657c478bd9Sstevel@tonic-gate 		valuep->v = np->u.ull;
19667c478bd9Sstevel@tonic-gate 		return (1);
19677c478bd9Sstevel@tonic-gate 
19687c478bd9Sstevel@tonic-gate 	default:
19697c478bd9Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
19707c478bd9Sstevel@tonic-gate 		    "eval_expr: unexpected node type: %s",
19717c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
19727c478bd9Sstevel@tonic-gate 	}
19737c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
197480ab886dSwesolows 	return (0);
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate 
19777c478bd9Sstevel@tonic-gate /*
19787c478bd9Sstevel@tonic-gate  * eval_fru() and eval_asru() don't do much, but are called from a number
19797c478bd9Sstevel@tonic-gate  * of places.
19807c478bd9Sstevel@tonic-gate  */
1981b5016cbbSstephh static struct node *
eval_fru(struct node * np)19827c478bd9Sstevel@tonic-gate eval_fru(struct node *np)
19837c478bd9Sstevel@tonic-gate {
19847c478bd9Sstevel@tonic-gate 	ASSERT(np->t == T_NAME);
19857c478bd9Sstevel@tonic-gate 	return (np);
19867c478bd9Sstevel@tonic-gate }
19877c478bd9Sstevel@tonic-gate 
1988b5016cbbSstephh static struct node *
eval_asru(struct node * np)19897c478bd9Sstevel@tonic-gate eval_asru(struct node *np)
19907c478bd9Sstevel@tonic-gate {
19917c478bd9Sstevel@tonic-gate 	ASSERT(np->t == T_NAME);
19927c478bd9Sstevel@tonic-gate 	return (np);
19937c478bd9Sstevel@tonic-gate }
1994