xref: /onnv-gate/usr/src/cmd/fm/modules/common/eversholt/eval.c (revision 4436:35b72f77cdd9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51717Swesolows  * Common Development and Distribution License (the "License").
61717Swesolows  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211717Swesolows 
220Sstevel@tonic-gate /*
23*4436Sstephh  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  *
260Sstevel@tonic-gate  * eval.c -- constraint evaluation module
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * this module evaluates constraints.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <ctype.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include "alloc.h"
380Sstevel@tonic-gate #include "out.h"
390Sstevel@tonic-gate #include "stable.h"
400Sstevel@tonic-gate #include "literals.h"
410Sstevel@tonic-gate #include "lut.h"
420Sstevel@tonic-gate #include "tree.h"
430Sstevel@tonic-gate #include "ptree.h"
440Sstevel@tonic-gate #include "itree.h"
451414Scindi #include "ipath.h"
460Sstevel@tonic-gate #include "eval.h"
470Sstevel@tonic-gate #include "config.h"
480Sstevel@tonic-gate #include "platform.h"
491414Scindi #include "fme.h"
501414Scindi #include "stats.h"
510Sstevel@tonic-gate 
520Sstevel@tonic-gate static struct node *eval_dup(struct node *np, struct lut *ex,
53*4436Sstephh     struct node *events[]);
541414Scindi static int check_expr_args(struct evalue *lp, struct evalue *rp,
551414Scindi     enum datatype dtype, struct node *np);
56*4436Sstephh static struct node *eval_fru(struct node *np);
57*4436Sstephh static struct node *eval_asru(struct node *np);
580Sstevel@tonic-gate 
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate  * begins_with -- return true if rhs path begins with everything in lhs path
610Sstevel@tonic-gate  */
620Sstevel@tonic-gate static int
63*4436Sstephh begins_with(struct node *lhs, struct node *rhs, struct lut *ex)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate 	int lnum;
660Sstevel@tonic-gate 	int rnum;
67*4436Sstephh 	struct iterinfo *iterinfop;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	if (lhs == NULL)
700Sstevel@tonic-gate 		return (1);	/* yep -- it all matched */
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	if (rhs == NULL)
730Sstevel@tonic-gate 		return (0);	/* nope, ran out of rhs first */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str);
760Sstevel@tonic-gate 	ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str);
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	if (lhs->u.name.s != rhs->u.name.s)
790Sstevel@tonic-gate 		return (0);	/* nope, different component names */
800Sstevel@tonic-gate 
81*4436Sstephh 	if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) {
820Sstevel@tonic-gate 		lnum = (int)lhs->u.name.child->u.ull;
83*4436Sstephh 	} else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) {
84*4436Sstephh 		iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s,
85*4436Sstephh 		    NULL);
86*4436Sstephh 		if (iterinfop != NULL)
87*4436Sstephh 			lnum = iterinfop->num;
88*4436Sstephh 		else
89*4436Sstephh 			out(O_DIE, "begins_with: unexpected lhs child");
90*4436Sstephh 	} else {
910Sstevel@tonic-gate 		out(O_DIE, "begins_with: unexpected lhs child");
92*4436Sstephh 	}
930Sstevel@tonic-gate 
94*4436Sstephh 	if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) {
950Sstevel@tonic-gate 		rnum = (int)rhs->u.name.child->u.ull;
96*4436Sstephh 	} else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) {
97*4436Sstephh 		iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s,
98*4436Sstephh 		    NULL);
99*4436Sstephh 		if (iterinfop != NULL)
100*4436Sstephh 			rnum = iterinfop->num;
101*4436Sstephh 		else
102*4436Sstephh 			out(O_DIE, "begins_with: unexpected rhs child");
103*4436Sstephh 	} else {
1040Sstevel@tonic-gate 		out(O_DIE, "begins_with: unexpected rhs child");
105*4436Sstephh 	}
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	if (lnum != rnum)
1080Sstevel@tonic-gate 		return (0);	/* nope, instance numbers were different */
1090Sstevel@tonic-gate 
110*4436Sstephh 	return (begins_with(lhs->u.name.next, rhs->u.name.next, ex));
111*4436Sstephh }
112*4436Sstephh 
113*4436Sstephh /*
114*4436Sstephh  * eval_getname - used by eval_func to evaluate a name, preferably without using
115*4436Sstephh  * eval_dup (but if it does have to use eval_dup then the *dupedp flag is set).
116*4436Sstephh  */
117*4436Sstephh static struct node *
118*4436Sstephh eval_getname(struct node *funcnp, struct lut *ex, struct node *events[],
119*4436Sstephh     struct node *np, struct lut **globals,
120*4436Sstephh     struct config *croot, struct arrow *arrowp, int try, int *dupedp)
121*4436Sstephh {
122*4436Sstephh 	struct node *nodep;
123*4436Sstephh 	const char *funcname = funcnp->u.func.s;
124*4436Sstephh 	struct evalue val;
125*4436Sstephh 
126*4436Sstephh 	if (np->t == T_NAME)
127*4436Sstephh 		nodep = np;
128*4436Sstephh 	else if (np->u.func.s == L_fru)
129*4436Sstephh 		nodep = eval_fru(np->u.func.arglist);
130*4436Sstephh 	else if (np->u.func.s == L_asru)
131*4436Sstephh 		nodep = eval_asru(np->u.func.arglist);
132*4436Sstephh 	else
133*4436Sstephh 		out(O_DIE, "%s: unexpected type: %s",
134*4436Sstephh 		    funcname, ptree_nodetype2str(np->t));
135*4436Sstephh 	if (try) {
136*4436Sstephh 		if (eval_expr(nodep, ex, events, globals, croot,
137*4436Sstephh 		    arrowp, try, &val) && val.t == NODEPTR)
138*4436Sstephh 			nodep = (struct node *)(uintptr_t)val.v;
139*4436Sstephh 		else {
140*4436Sstephh 			*dupedp = 1;
141*4436Sstephh 			nodep = eval_dup(nodep, ex, events);
142*4436Sstephh 		}
143*4436Sstephh 	}
144*4436Sstephh 	return (nodep);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate /*
1480Sstevel@tonic-gate  * evaluate a variety of functions and place result in valuep.  return 1 if
1490Sstevel@tonic-gate  * function evaluation was successful; 0 if otherwise (e.g., the case of an
1500Sstevel@tonic-gate  * invalid argument to the function)
1510Sstevel@tonic-gate  */
1520Sstevel@tonic-gate /*ARGSUSED*/
1530Sstevel@tonic-gate static int
154*4436Sstephh eval_func(struct node *funcnp, struct lut *ex, struct node *events[],
1550Sstevel@tonic-gate     struct node *np, struct lut **globals,
1560Sstevel@tonic-gate     struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 	const char *funcname = funcnp->u.func.s;
159*4436Sstephh 	int duped_lhs = 0, duped_rhs = 0, duped = 0;
160*4436Sstephh 	struct node *lhs;
161*4436Sstephh 	struct node *rhs;
162*4436Sstephh 	struct config *cp;
163*4436Sstephh 	struct node *nodep;
164*4436Sstephh 	char *path;
165*4436Sstephh 	struct evalue val;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	if (funcname == L_within) {
1680Sstevel@tonic-gate 		/* within()'s are not really constraints -- always true */
1690Sstevel@tonic-gate 		valuep->t = UINT64;
1700Sstevel@tonic-gate 		valuep->v = 1;
1710Sstevel@tonic-gate 		return (1);
1720Sstevel@tonic-gate 	} else if (funcname == L_is_under) {
173*4436Sstephh 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
174*4436Sstephh 		    croot, arrowp, try, &duped_lhs);
175*4436Sstephh 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
176*4436Sstephh 		    globals, croot, arrowp, try, &duped_rhs);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 		valuep->t = UINT64;
179*4436Sstephh 		valuep->v = begins_with(lhs, rhs, ex);
1800Sstevel@tonic-gate 		out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
1810Sstevel@tonic-gate 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
1820Sstevel@tonic-gate 		out(O_ALTFP|O_VERB2|O_NONL, ",");
1830Sstevel@tonic-gate 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
184*4436Sstephh 		out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v);
1850Sstevel@tonic-gate 
186*4436Sstephh 		if (duped_lhs)
187*4436Sstephh 			tree_free(lhs);
188*4436Sstephh 		if (duped_rhs)
189*4436Sstephh 			tree_free(rhs);
1900Sstevel@tonic-gate 		return (1);
1912869Sgavinm 	} else if (funcname == L_confprop || funcname == L_confprop_defined) {
1922318Sstephh 		const char *s;
1932318Sstephh 
1942318Sstephh 		/* for now s will point to a quote [see addconfigprop()] */
1952318Sstephh 		ASSERT(np->u.expr.right->t == T_QUOTE);
1962318Sstephh 
197*4436Sstephh 		nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
198*4436Sstephh 		    globals, croot, arrowp, try, &duped);
199*4436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
200*4436Sstephh 			cp = nodep->u.name.last->u.name.cp;
201*4436Sstephh 		} else {
202*4436Sstephh 			path = ipath2str(NULL, ipath(nodep));
203*4436Sstephh 			cp = config_lookup(croot, path, 0);
204*4436Sstephh 			FREE((void *)path);
205*4436Sstephh 		}
2062869Sgavinm 		if (cp == NULL) {
207*4436Sstephh 			if (funcname == L_confprop) {
208*4436Sstephh 				out(O_ALTFP|O_VERB3, "%s: path ", funcname);
209*4436Sstephh 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
210*4436Sstephh 				out(O_ALTFP|O_VERB3, " not found");
211*4436Sstephh 				valuep->v = (uintptr_t)stable("");
212*4436Sstephh 				valuep->t = STRING;
213*4436Sstephh 				if (duped)
214*4436Sstephh 					tree_free(nodep);
215*4436Sstephh 				return (1);
216*4436Sstephh 			} else {
2172869Sgavinm 				valuep->v = 0;
2182869Sgavinm 				valuep->t = UINT64;
219*4436Sstephh 				if (duped)
220*4436Sstephh 					tree_free(nodep);
2212869Sgavinm 				return (1);
2222869Sgavinm 			}
2232869Sgavinm 		}
2242318Sstephh 		s = config_getprop(cp, np->u.expr.right->u.quote.s);
225*4436Sstephh 		if (s == NULL && strcmp(np->u.expr.right->u.quote.s,
226*4436Sstephh 		    "class-code") == 0)
227*4436Sstephh 			s = config_getprop(cp, "CLASS-CODE");
2282869Sgavinm 		if (s == NULL) {
229*4436Sstephh 			if (funcname == L_confprop) {
230*4436Sstephh 				out(O_ALTFP|O_VERB3|O_NONL,
231*4436Sstephh 				    "%s: \"%s\" not found for path ",
232*4436Sstephh 				    funcname, np->u.expr.right->u.quote.s);
233*4436Sstephh 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
234*4436Sstephh 				valuep->v = (uintptr_t)stable("");
235*4436Sstephh 				valuep->t = STRING;
236*4436Sstephh 				if (duped)
237*4436Sstephh 					tree_free(nodep);
238*4436Sstephh 				return (1);
239*4436Sstephh 			} else {
2402869Sgavinm 				valuep->v = 0;
2412869Sgavinm 				valuep->t = UINT64;
242*4436Sstephh 				if (duped)
243*4436Sstephh 					tree_free(nodep);
2442869Sgavinm 				return (1);
2452869Sgavinm 			}
2462869Sgavinm 		}
2472869Sgavinm 
2482869Sgavinm 		if (funcname == L_confprop) {
2492869Sgavinm 			valuep->v = (uintptr_t)stable(s);
2502869Sgavinm 			valuep->t = STRING;
251*4436Sstephh 			out(O_ALTFP|O_VERB3|O_NONL, "  %s(\"", funcname);
252*4436Sstephh 			ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
253*4436Sstephh 			out(O_ALTFP|O_VERB3|O_NONL,
254*4436Sstephh 			    "\", \"%s\") = \"%s\"  ",
255*4436Sstephh 			    np->u.expr.right->u.quote.s,
2562869Sgavinm 			    (char *)(uintptr_t)valuep->v);
2572869Sgavinm 		} else {
2582869Sgavinm 			valuep->v = 1;
2592869Sgavinm 			valuep->t = UINT64;
2602869Sgavinm 		}
261*4436Sstephh 		if (duped)
262*4436Sstephh 			tree_free(nodep);
263*4436Sstephh 		return (1);
264*4436Sstephh 	} else if (funcname == L_is_connected) {
265*4436Sstephh 		const char *connstrings[] = { "connected", "CONNECTED", NULL };
266*4436Sstephh 		struct config *cp[2];
267*4436Sstephh 		const char *matchthis[2], *s;
268*4436Sstephh 		char *nameslist, *w;
269*4436Sstephh 		int i, j;
270*4436Sstephh 
271*4436Sstephh 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
272*4436Sstephh 		    croot, arrowp, try, &duped_lhs);
273*4436Sstephh 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
274*4436Sstephh 		    globals, croot, arrowp, try, &duped_rhs);
275*4436Sstephh 		path = ipath2str(NULL, ipath(lhs));
276*4436Sstephh 		matchthis[1] = stable(path);
277*4436Sstephh 		if (lhs->u.name.last->u.name.cp != NULL)
278*4436Sstephh 			cp[0] = lhs->u.name.last->u.name.cp;
279*4436Sstephh 		else
280*4436Sstephh 			cp[0] = config_lookup(croot, path, 0);
2812869Sgavinm 		FREE((void *)path);
282*4436Sstephh 		path = ipath2str(NULL, ipath(rhs));
283*4436Sstephh 		matchthis[0] = stable(path);
284*4436Sstephh 		if (rhs->u.name.last->u.name.cp != NULL)
285*4436Sstephh 			cp[1] = rhs->u.name.last->u.name.cp;
286*4436Sstephh 		else
287*4436Sstephh 			cp[1] = config_lookup(croot, path, 0);
288*4436Sstephh 		FREE((void *)path);
289*4436Sstephh 		if (duped_lhs)
290*4436Sstephh 			tree_free(lhs);
291*4436Sstephh 		if (duped_rhs)
292*4436Sstephh 			tree_free(rhs);
293*4436Sstephh 
294*4436Sstephh 		valuep->t = UINT64;
295*4436Sstephh 		valuep->v = 0;
296*4436Sstephh 		if (cp[0] == NULL || cp[1] == NULL)
297*4436Sstephh 			return (1);
298*4436Sstephh 
299*4436Sstephh 		/* to thine self always be connected */
300*4436Sstephh 		if (cp[0] == cp[1]) {
301*4436Sstephh 			valuep->v = 1;
302*4436Sstephh 			return (1);
303*4436Sstephh 		}
304*4436Sstephh 
305*4436Sstephh 		/*
306*4436Sstephh 		 * Extract "connected" property from each cp. Search this
307*4436Sstephh 		 * property for the name associated with the other cp[].
308*4436Sstephh 		 */
309*4436Sstephh 		for (i = 0; i < 2 && valuep->v == 0; i++) {
310*4436Sstephh 			for (j = 0; connstrings[j] != NULL && valuep->v == 0;
311*4436Sstephh 			    j++) {
312*4436Sstephh 				s = config_getprop(cp[i],
313*4436Sstephh 				    stable(connstrings[j]));
314*4436Sstephh 				if (s != NULL) {
315*4436Sstephh 					nameslist = STRDUP(s);
316*4436Sstephh 					w = strtok(nameslist, " ,");
317*4436Sstephh 					while (w != NULL) {
318*4436Sstephh 						if (stable(w) == matchthis[i]) {
319*4436Sstephh 							valuep->v = 1;
320*4436Sstephh 							break;
321*4436Sstephh 						}
322*4436Sstephh 						w = strtok(NULL, " ,");
323*4436Sstephh 					}
324*4436Sstephh 					FREE(nameslist);
325*4436Sstephh 				}
326*4436Sstephh 			}
327*4436Sstephh 		}
3282318Sstephh 		return (1);
329*4436Sstephh 	} else if (funcname == L_is_type) {
330*4436Sstephh 		const char *typestrings[] = { "type", "TYPE", NULL };
331*4436Sstephh 		const char *s;
332*4436Sstephh 		int i;
333*4436Sstephh 
334*4436Sstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
335*4436Sstephh 		    croot, arrowp, try, &duped);
336*4436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
337*4436Sstephh 			cp = nodep->u.name.last->u.name.cp;
338*4436Sstephh 		} else {
339*4436Sstephh 			path = ipath2str(NULL, ipath(nodep));
340*4436Sstephh 			cp = config_lookup(croot, path, 0);
341*4436Sstephh 			FREE((void *)path);
342*4436Sstephh 		}
343*4436Sstephh 		if (duped)
344*4436Sstephh 			tree_free(nodep);
345*4436Sstephh 
346*4436Sstephh 		valuep->t = STRING;
347*4436Sstephh 		valuep->v = (uintptr_t)stable("");
348*4436Sstephh 		if (cp == NULL)
349*4436Sstephh 			return (1);
350*4436Sstephh 		for (i = 0; typestrings[i] != NULL; i++) {
351*4436Sstephh 			s = config_getprop(cp, stable(typestrings[i]));
352*4436Sstephh 			if (s != NULL) {
353*4436Sstephh 				valuep->v = (uintptr_t)stable(s);
354*4436Sstephh 				break;
355*4436Sstephh 			}
356*4436Sstephh 		}
357*4436Sstephh 		return (1);
358*4436Sstephh 	} else if (funcname == L_is_on) {
359*4436Sstephh 		const char *onstrings[] = { "on", "ON", NULL };
360*4436Sstephh 		const char *truestrings[] = { "yes", "YES", "y", "Y",
361*4436Sstephh 				    "true", "TRUE", "t", "T", "1", NULL };
362*4436Sstephh 		const char *s;
363*4436Sstephh 		int i, j;
364*4436Sstephh 
365*4436Sstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
366*4436Sstephh 		    croot, arrowp, try, &duped);
367*4436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
368*4436Sstephh 			cp = nodep->u.name.last->u.name.cp;
369*4436Sstephh 		} else {
370*4436Sstephh 			path = ipath2str(NULL, ipath(nodep));
371*4436Sstephh 			cp = config_lookup(croot, path, 0);
372*4436Sstephh 			FREE((void *)path);
373*4436Sstephh 		}
374*4436Sstephh 		if (duped)
375*4436Sstephh 			tree_free(nodep);
376*4436Sstephh 
377*4436Sstephh 		valuep->t = UINT64;
378*4436Sstephh 		valuep->v = 0;
379*4436Sstephh 		if (cp == NULL)
380*4436Sstephh 			return (1);
381*4436Sstephh 		for (i = 0; onstrings[i] != NULL; i++) {
382*4436Sstephh 			s = config_getprop(cp, stable(onstrings[i]));
383*4436Sstephh 			if (s != NULL) {
384*4436Sstephh 				s = stable(s);
385*4436Sstephh 				for (j = 0; truestrings[j] != NULL; j++) {
386*4436Sstephh 					if (s == stable(truestrings[j])) {
387*4436Sstephh 						valuep->v = 1;
388*4436Sstephh 						return (1);
389*4436Sstephh 					}
390*4436Sstephh 				}
391*4436Sstephh 			}
392*4436Sstephh 		}
393*4436Sstephh 		return (1);
394*4436Sstephh 	} else if (funcname == L_is_present) {
395*4436Sstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
396*4436Sstephh 		    croot, arrowp, try, &duped);
397*4436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
398*4436Sstephh 			cp = nodep->u.name.last->u.name.cp;
399*4436Sstephh 		} else {
400*4436Sstephh 			path = ipath2str(NULL, ipath(nodep));
401*4436Sstephh 			cp = config_lookup(croot, path, 0);
402*4436Sstephh 			FREE((void *)path);
403*4436Sstephh 		}
404*4436Sstephh 		if (duped)
405*4436Sstephh 			tree_free(nodep);
406*4436Sstephh 
407*4436Sstephh 		valuep->t = UINT64;
408*4436Sstephh 		valuep->v = 0;
409*4436Sstephh 		if (cp != NULL)
410*4436Sstephh 			valuep->v = 1;
411*4436Sstephh 		return (1);
412*4436Sstephh 	} else if (funcname == L_count) {
413*4436Sstephh 		struct stats *statp;
414*4436Sstephh 		struct istat_entry ent;
415*4436Sstephh 
416*4436Sstephh 		ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
417*4436Sstephh 
418*4436Sstephh 		nodep = np->u.event.epname;
419*4436Sstephh 		if (try) {
420*4436Sstephh 			if (eval_expr(nodep, ex, events, globals,
421*4436Sstephh 			    croot, arrowp, try, &val) && val.t == NODEPTR)
422*4436Sstephh 				nodep = (struct node *)(uintptr_t)val.v;
423*4436Sstephh 			else {
424*4436Sstephh 				duped = 1;
425*4436Sstephh 				nodep = eval_dup(nodep, ex, events);
426*4436Sstephh 			}
427*4436Sstephh 		}
428*4436Sstephh 		ent.ename = np->u.event.ename->u.name.s;
429*4436Sstephh 		ent.ipath = ipath(nodep);
430*4436Sstephh 		valuep->t = UINT64;
431*4436Sstephh 		if ((statp = (struct stats *)
432*4436Sstephh 		    lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
433*4436Sstephh 			valuep->v = 0;
434*4436Sstephh 		else
435*4436Sstephh 			valuep->v = stats_counter_value(statp);
436*4436Sstephh 		if (duped)
437*4436Sstephh 			tree_free(nodep);
438*4436Sstephh 		return (1);
439*4436Sstephh 	} else if (funcname == L_envprop) {
440*4436Sstephh 		outfl(O_DIE, np->file, np->line,
441*4436Sstephh 		    "eval_func: %s not yet supported", funcname);
4420Sstevel@tonic-gate 	}
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (try)
4450Sstevel@tonic-gate 		return (0);
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	if (funcname == L_fru) {
4480Sstevel@tonic-gate 		valuep->t = NODEPTR;
4491717Swesolows 		valuep->v = (uintptr_t)eval_fru(np);
4500Sstevel@tonic-gate 		return (1);
4510Sstevel@tonic-gate 	} else if (funcname == L_asru) {
4520Sstevel@tonic-gate 		valuep->t = NODEPTR;
4531717Swesolows 		valuep->v = (uintptr_t)eval_asru(np);
4540Sstevel@tonic-gate 		return (1);
4551414Scindi 	} else if (funcname == L_defined) {
4561414Scindi 		ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
4571414Scindi 		valuep->t = UINT64;
4581414Scindi 		valuep->v = (lut_lookup(*globals,
4591414Scindi 		    (void *)np->u.globid.s, NULL) != NULL);
4601414Scindi 		return (1);
4610Sstevel@tonic-gate 	} else if (funcname == L_call) {
4620Sstevel@tonic-gate 		return (! platform_call(np, globals, croot, arrowp, valuep));
4630Sstevel@tonic-gate 	} else if (funcname == L_payloadprop) {
4641414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
4650Sstevel@tonic-gate 		    "payloadprop(\"%s\") ", np->u.quote.s);
466186Sdb35262 
4671414Scindi 		if (platform_payloadprop(np, valuep)) {
4681414Scindi 			/* platform_payloadprop() returned false */
4692869Sgavinm 			out(O_ALTFP|O_VERB, "payloadprop \"%s\" not found.",
4702869Sgavinm 			    np->u.quote.s);
4711414Scindi 			return (0);
4721414Scindi 		} else {
473186Sdb35262 			switch (valuep->t) {
474186Sdb35262 			case UINT64:
475186Sdb35262 			case NODEPTR:
4761414Scindi 				out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
477186Sdb35262 				break;
478186Sdb35262 			case STRING:
4791414Scindi 				out(O_ALTFP|O_VERB2, "found: \"%s\"",
4801717Swesolows 				    (char *)(uintptr_t)valuep->v);
481186Sdb35262 				break;
482186Sdb35262 			default:
4831414Scindi 				out(O_ALTFP|O_VERB2, "found: undefined");
484186Sdb35262 				break;
485186Sdb35262 			}
4861414Scindi 			return (1);
4871414Scindi 		}
4881414Scindi 	} else if (funcname == L_setpayloadprop) {
4891414Scindi 		struct evalue *payloadvalp;
4901414Scindi 
4911414Scindi 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
4921414Scindi 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
4931414Scindi 		    ptree_nodetype2str(np->u.expr.left->t));
4941414Scindi 
4951414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
4961414Scindi 		    "setpayloadprop: %s: %s=",
4971414Scindi 		    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
4981414Scindi 		    np->u.expr.left->u.quote.s);
4991414Scindi 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
5001414Scindi 
5011414Scindi 		/*
5021414Scindi 		 * allocate a struct evalue to hold the payload property's
5031414Scindi 		 * value, unless we've been here already, in which case we
5041414Scindi 		 * might calculate a different value, but we'll store it
5051414Scindi 		 * in the already-allocated struct evalue.
5061414Scindi 		 */
5071414Scindi 		if ((payloadvalp = (struct evalue *)lut_lookup(
5081414Scindi 		    arrowp->tail->myevent->payloadprops,
5091414Scindi 		    (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
5101414Scindi 			payloadvalp = MALLOC(sizeof (*payloadvalp));
5111414Scindi 		}
5121414Scindi 
513*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
5141414Scindi 		    arrowp, try, payloadvalp)) {
5151414Scindi 			out(O_ALTFP|O_VERB2, " (cannot eval, using zero)");
5161414Scindi 			payloadvalp->t = UINT64;
5171414Scindi 			payloadvalp->v = 0;
5181414Scindi 		} else {
5191414Scindi 			if (payloadvalp->t == UINT64)
5201414Scindi 				out(O_ALTFP|O_VERB2,
5211414Scindi 				    " (%llu)", payloadvalp->v);
5221414Scindi 			else
5231717Swesolows 				out(O_ALTFP|O_VERB2, " (\"%s\")",
5241717Swesolows 				    (char *)(uintptr_t)payloadvalp->v);
5251414Scindi 		}
5261414Scindi 
5271414Scindi 		/* add to table of payload properties for current problem */
5281414Scindi 		arrowp->tail->myevent->payloadprops =
5291414Scindi 		    lut_add(arrowp->tail->myevent->payloadprops,
5301414Scindi 		    (void *)np->u.expr.left->u.quote.s,
5311414Scindi 		    (void *)payloadvalp, NULL);
5321414Scindi 
5331414Scindi 		/* function is always true */
5341414Scindi 		valuep->t = UINT64;
5351414Scindi 		valuep->v = 1;
5361414Scindi 		return (1);
5371414Scindi 	} else if (funcname == L_payloadprop_defined) {
5381414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
5391414Scindi 		    "payloadprop_defined(\"%s\") ", np->u.quote.s);
5401414Scindi 
5411414Scindi 		if (platform_payloadprop(np, NULL)) {
5421414Scindi 			/* platform_payloadprop() returned false */
5431414Scindi 			valuep->v = 0;
5442869Sgavinm 			out(O_ALTFP|O_VERB2, "payloadprop_defined: \"%s\" "
5452869Sgavinm 			    "not defined.", np->u.quote.s);
5461414Scindi 		} else {
5471414Scindi 			valuep->v = 1;
5481414Scindi 			out(O_ALTFP|O_VERB2, "found.");
5491414Scindi 		}
5501414Scindi 		valuep->t = UINT64;
5511414Scindi 		return (1);
5521414Scindi 	} else if (funcname == L_payloadprop_contains) {
5531414Scindi 		int nvals;
5541414Scindi 		struct evalue *vals;
5551414Scindi 		struct evalue cmpval;
5561414Scindi 
5571414Scindi 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
5581414Scindi 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
5591414Scindi 		    ptree_nodetype2str(np->u.expr.left->t));
5601414Scindi 
5611414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
5621414Scindi 		    "payloadprop_contains(\"%s\", ",
5631414Scindi 		    np->u.expr.left->u.quote.s);
5641414Scindi 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
5652869Sgavinm 		out(O_ALTFP|O_VERB2|O_NONL, ") ");
5661414Scindi 
5671414Scindi 		/* evaluate the expression we're comparing against */
568*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
5691414Scindi 		    arrowp, try, &cmpval)) {
5701414Scindi 			out(O_ALTFP|O_VERB2|O_NONL,
5711414Scindi 			    "(cannot eval, using zero) ");
5721414Scindi 			cmpval.t = UINT64;
5731414Scindi 			cmpval.v = 0;
5741414Scindi 		} else {
5752869Sgavinm 			switch (cmpval.t) {
5762869Sgavinm 			case UNDEFINED:
5772869Sgavinm 				out(O_ALTFP|O_VERB2, "(undefined type)");
5782869Sgavinm 				break;
5792869Sgavinm 
5802869Sgavinm 			case UINT64:
5811414Scindi 				out(O_ALTFP|O_VERB2,
5821414Scindi 				    "(%llu) ", cmpval.v);
5832869Sgavinm 				break;
5842869Sgavinm 
5852869Sgavinm 			case STRING:
5861414Scindi 				out(O_ALTFP|O_VERB2,
5871717Swesolows 				    "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
5882869Sgavinm 				break;
5892869Sgavinm 
5902869Sgavinm 			case NODEPTR:
5912869Sgavinm 				out(O_ALTFP|O_VERB2|O_NONL, "(");
5922869Sgavinm 				ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
5932869Sgavinm 				    (struct node *)(uintptr_t)(cmpval.v));
5942869Sgavinm 				out(O_ALTFP|O_VERB2, ") ");
5952869Sgavinm 				break;
5962869Sgavinm 			}
5971414Scindi 		}
5981414Scindi 
5991414Scindi 		/* get the payload values and check for a match */
6001414Scindi 		vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
6011414Scindi 		    &nvals);
6021414Scindi 		valuep->t = UINT64;
6031414Scindi 		valuep->v = 0;
6041414Scindi 		if (nvals == 0) {
6051414Scindi 			out(O_ALTFP|O_VERB2, "not found.");
606*4436Sstephh 			return (0);
6071414Scindi 		} else {
6081414Scindi 			struct evalue preval;
6091414Scindi 			int i;
6101414Scindi 
6111414Scindi 			out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
6121414Scindi 
6131414Scindi 			for (i = 0; i < nvals; i++) {
6141414Scindi 
6151414Scindi 				preval.t = vals[i].t;
6161414Scindi 				preval.v = vals[i].v;
6171414Scindi 
6181414Scindi 				if (check_expr_args(&vals[i], &cmpval,
6191414Scindi 				    UNDEFINED, np))
6201414Scindi 					continue;
6211414Scindi 
6221414Scindi 				/*
6231414Scindi 				 * If we auto-converted the value to a
6241414Scindi 				 * string, we need to free the
6251414Scindi 				 * original tree value.
6261414Scindi 				 */
6271414Scindi 				if (preval.t == NODEPTR &&
6281717Swesolows 				    ((struct node *)(uintptr_t)(preval.v))->t ==
6291717Swesolows 				    T_NAME) {
6301717Swesolows 					tree_free((struct node *)(uintptr_t)
6311717Swesolows 					    preval.v);
6321414Scindi 				}
6331414Scindi 
6341414Scindi 				if (vals[i].v == cmpval.v) {
6351414Scindi 					valuep->v = 1;
6361414Scindi 					break;
6371414Scindi 				}
6381414Scindi 			}
639186Sdb35262 
6401414Scindi 			if (valuep->v)
6411414Scindi 				out(O_ALTFP|O_VERB2, "match.");
6421414Scindi 			else
6431414Scindi 				out(O_ALTFP|O_VERB2, "no match.");
644186Sdb35262 
6451414Scindi 			for (i = 0; i < nvals; i++) {
6461414Scindi 				if (vals[i].t == NODEPTR) {
6471717Swesolows 					tree_free((struct node *)(uintptr_t)
6481717Swesolows 					    vals[i].v);
6491414Scindi 					break;
6501414Scindi 				}
651186Sdb35262 			}
6521414Scindi 			FREE(vals);
6531414Scindi 		}
6541414Scindi 		return (1);
6551414Scindi 	} else if (funcname == L_confcall) {
6561414Scindi 		return (!platform_confcall(np, globals, croot, arrowp, valuep));
6570Sstevel@tonic-gate 	} else
6580Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
6590Sstevel@tonic-gate 		    "eval_func: unexpected func: %s", funcname);
6600Sstevel@tonic-gate 	/*NOTREACHED*/
6611717Swesolows 	return (0);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate 
664*4436Sstephh /*
665*4436Sstephh  * defines for u.expr.temp - these are used for T_OR and T_AND so that if
666*4436Sstephh  * we worked out that part of the expression was true or false during an
667*4436Sstephh  * earlier eval_expr, then we don't need to dup that part.
668*4436Sstephh  */
6690Sstevel@tonic-gate 
670*4436Sstephh #define	EXPR_TEMP_BOTH_UNK	0
671*4436Sstephh #define	EXPR_TEMP_LHS_UNK	1
672*4436Sstephh #define	EXPR_TEMP_RHS_UNK	2
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate static struct node *
675*4436Sstephh eval_dup(struct node *np, struct lut *ex, struct node *events[])
6760Sstevel@tonic-gate {
6770Sstevel@tonic-gate 	struct node *newnp;
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	if (np == NULL)
6800Sstevel@tonic-gate 		return (NULL);
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	switch (np->t) {
6830Sstevel@tonic-gate 	case T_GLOBID:
6840Sstevel@tonic-gate 		return (tree_globid(np->u.globid.s, np->file, np->line));
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	case T_ASSIGN:
6870Sstevel@tonic-gate 	case T_CONDIF:
6880Sstevel@tonic-gate 	case T_CONDELSE:
6890Sstevel@tonic-gate 	case T_NE:
6900Sstevel@tonic-gate 	case T_EQ:
6910Sstevel@tonic-gate 	case T_LT:
6920Sstevel@tonic-gate 	case T_LE:
6930Sstevel@tonic-gate 	case T_GT:
6940Sstevel@tonic-gate 	case T_GE:
6950Sstevel@tonic-gate 	case T_BITAND:
6960Sstevel@tonic-gate 	case T_BITOR:
6970Sstevel@tonic-gate 	case T_BITXOR:
6980Sstevel@tonic-gate 	case T_BITNOT:
6990Sstevel@tonic-gate 	case T_LSHIFT:
7000Sstevel@tonic-gate 	case T_RSHIFT:
7010Sstevel@tonic-gate 	case T_NOT:
7020Sstevel@tonic-gate 	case T_ADD:
7030Sstevel@tonic-gate 	case T_SUB:
7040Sstevel@tonic-gate 	case T_MUL:
7050Sstevel@tonic-gate 	case T_DIV:
7060Sstevel@tonic-gate 	case T_MOD:
7070Sstevel@tonic-gate 		return (tree_expr(np->t,
708*4436Sstephh 		    eval_dup(np->u.expr.left, ex, events),
709*4436Sstephh 		    eval_dup(np->u.expr.right, ex, events)));
710*4436Sstephh 	case T_LIST:
711*4436Sstephh 	case T_AND:
712*4436Sstephh 		switch (np->u.expr.temp) {
713*4436Sstephh 		case EXPR_TEMP_LHS_UNK:
714*4436Sstephh 			return (eval_dup(np->u.expr.left, ex, events));
715*4436Sstephh 		case EXPR_TEMP_RHS_UNK:
716*4436Sstephh 			return (eval_dup(np->u.expr.right, ex, events));
717*4436Sstephh 		default:
718*4436Sstephh 			return (tree_expr(np->t,
719*4436Sstephh 			    eval_dup(np->u.expr.left, ex, events),
720*4436Sstephh 			    eval_dup(np->u.expr.right, ex, events)));
721*4436Sstephh 		}
722*4436Sstephh 
723*4436Sstephh 	case T_OR:
724*4436Sstephh 		switch (np->u.expr.temp) {
725*4436Sstephh 		case EXPR_TEMP_LHS_UNK:
726*4436Sstephh 			return (eval_dup(np->u.expr.left, ex, events));
727*4436Sstephh 		case EXPR_TEMP_RHS_UNK:
728*4436Sstephh 			return (eval_dup(np->u.expr.right, ex, events));
729*4436Sstephh 		default:
730*4436Sstephh 			return (tree_expr(T_OR,
731*4436Sstephh 			    eval_dup(np->u.expr.left, ex, events),
732*4436Sstephh 			    eval_dup(np->u.expr.right, ex, events)));
733*4436Sstephh 		}
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 	case T_NAME: {
7360Sstevel@tonic-gate 		struct iterinfo *iterinfop;
737*4436Sstephh 		int got_matchf = 0;
738*4436Sstephh 		int got_matcht = 0;
739*4436Sstephh 		struct evalue value;
740*4436Sstephh 		struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
741*4436Sstephh 		struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
7420Sstevel@tonic-gate 
743*4436Sstephh 		/*
744*4436Sstephh 		 * Check if we already have a match of the nonwildcarded path
745*4436Sstephh 		 * in oldepname (check both to and from events).
746*4436Sstephh 		 */
747*4436Sstephh 		for (np1f = np, np2f = events[0]->u.event.oldepname;
748*4436Sstephh 		    np1f != NULL && np2f != NULL;
749*4436Sstephh 		    np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
750*4436Sstephh 			if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
751*4436Sstephh 				break;
752*4436Sstephh 			if (np1f->u.name.child->t != np2f->u.name.child->t)
753*4436Sstephh 				break;
754*4436Sstephh 			if (np1f->u.name.child->t == T_NUM &&
755*4436Sstephh 			    np1f->u.name.child->u.ull !=
756*4436Sstephh 			    np2f->u.name.child->u.ull)
757*4436Sstephh 				break;
758*4436Sstephh 			if (np1f->u.name.child->t == T_NAME &&
759*4436Sstephh 			    strcmp(np1f->u.name.child->u.name.s,
760*4436Sstephh 			    np2f->u.name.child->u.name.s) != 0)
761*4436Sstephh 				break;
762*4436Sstephh 			got_matchf++;
763*4436Sstephh 		}
764*4436Sstephh 		for (np1t = np, np2t = events[1]->u.event.oldepname;
765*4436Sstephh 		    np1t != NULL && np2t != NULL;
766*4436Sstephh 		    np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
767*4436Sstephh 			if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
768*4436Sstephh 				break;
769*4436Sstephh 			if (np1t->u.name.child->t != np2t->u.name.child->t)
770*4436Sstephh 				break;
771*4436Sstephh 			if (np1t->u.name.child->t == T_NUM &&
772*4436Sstephh 			    np1t->u.name.child->u.ull !=
773*4436Sstephh 			    np2t->u.name.child->u.ull)
774*4436Sstephh 				break;
775*4436Sstephh 			if (np1t->u.name.child->t == T_NAME &&
776*4436Sstephh 			    strcmp(np1t->u.name.child->u.name.s,
777*4436Sstephh 			    np2t->u.name.child->u.name.s) != 0)
778*4436Sstephh 				break;
779*4436Sstephh 			got_matcht++;
780*4436Sstephh 		}
781*4436Sstephh 		nprest = np;
782*4436Sstephh 		if (got_matchf || got_matcht) {
783*4436Sstephh 			/*
784*4436Sstephh 			 * so we are wildcarding. Copy ewname in full, plus
785*4436Sstephh 			 * matching section of oldepname. Use whichever gives
786*4436Sstephh 			 * the closest match.
787*4436Sstephh 			 */
788*4436Sstephh 			if (got_matchf > got_matcht) {
789*4436Sstephh 				npstart = events[0]->u.event.ewname;
790*4436Sstephh 				npcont = events[0]->u.event.oldepname;
791*4436Sstephh 				npend = np2f;
792*4436Sstephh 				nprest = np1f;
793*4436Sstephh 			} else {
794*4436Sstephh 				npstart = events[1]->u.event.ewname;
795*4436Sstephh 				npcont = events[1]->u.event.oldepname;
796*4436Sstephh 				npend = np2t;
797*4436Sstephh 				nprest = np1t;
798*4436Sstephh 			}
799*4436Sstephh 			for (npref = npstart; npref != NULL;
800*4436Sstephh 			    npref = npref->u.name.next) {
801*4436Sstephh 				newnp = newnode(T_NAME, np->file, np->line);
802*4436Sstephh 				newnp->u.name.t = npref->u.name.t;
803*4436Sstephh 				newnp->u.name.s = npref->u.name.s;
804*4436Sstephh 				newnp->u.name.last = newnp;
805*4436Sstephh 				newnp->u.name.it = npref->u.name.it;
806*4436Sstephh 				newnp->u.name.cp = npref->u.name.cp;
807*4436Sstephh 				newnp->u.name.child =
808*4436Sstephh 				    newnode(T_NUM, np->file, np->line);
809*4436Sstephh 				if (eval_expr(npref->u.name.child, ex, events,
8100Sstevel@tonic-gate 				    NULL, NULL, NULL, 1, &value) == 0 ||
8110Sstevel@tonic-gate 				    value.t != UINT64) {
8120Sstevel@tonic-gate 					outfl(O_DIE, np->file, np->line,
8130Sstevel@tonic-gate 					    "eval_dup: could not resolve "
8140Sstevel@tonic-gate 					    "iterator of %s", np->u.name.s);
8150Sstevel@tonic-gate 				}
816*4436Sstephh 				newnp->u.name.child->u.ull = value.v;
817*4436Sstephh 				if (retp == NULL) {
818*4436Sstephh 					retp = newnp;
819*4436Sstephh 				} else {
820*4436Sstephh 					retp->u.name.last->u.name.next = newnp;
821*4436Sstephh 					retp->u.name.last = newnp;
822*4436Sstephh 				}
8230Sstevel@tonic-gate 			}
824*4436Sstephh 			for (npref = npcont; npref != NULL && npref != npend;
825*4436Sstephh 			    npref = npref->u.name.next) {
826*4436Sstephh 				newnp = newnode(T_NAME, np->file, np->line);
827*4436Sstephh 				newnp->u.name.t = npref->u.name.t;
828*4436Sstephh 				newnp->u.name.s = npref->u.name.s;
829*4436Sstephh 				newnp->u.name.last = newnp;
830*4436Sstephh 				newnp->u.name.it = npref->u.name.it;
831*4436Sstephh 				newnp->u.name.cp = npref->u.name.cp;
832*4436Sstephh 				newnp->u.name.child =
833*4436Sstephh 				    newnode(T_NUM, np->file, np->line);
834*4436Sstephh 				if (eval_expr(npref->u.name.child, ex, events,
835*4436Sstephh 				    NULL, NULL, NULL, 1, &value) == 0 ||
836*4436Sstephh 				    value.t != UINT64) {
837*4436Sstephh 					outfl(O_DIE, np->file, np->line,
838*4436Sstephh 					    "eval_dup: could not resolve "
839*4436Sstephh 					    "iterator of %s", np->u.name.s);
840*4436Sstephh 				}
841*4436Sstephh 				newnp->u.name.child->u.ull = value.v;
842*4436Sstephh 				if (retp == NULL) {
843*4436Sstephh 					retp = newnp;
844*4436Sstephh 				} else {
845*4436Sstephh 					retp->u.name.last->u.name.next = newnp;
846*4436Sstephh 					retp->u.name.last = newnp;
847*4436Sstephh 				}
848*4436Sstephh 			}
849*4436Sstephh 		} else {
850*4436Sstephh 			/*
851*4436Sstephh 			 * not wildcarding - check if explicit iterator
852*4436Sstephh 			 */
853*4436Sstephh 			iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
854*4436Sstephh 			if (iterinfop != NULL) {
855*4436Sstephh 				/* explicit iterator; not part of pathname */
856*4436Sstephh 				newnp = newnode(T_NUM, np->file, np->line);
857*4436Sstephh 				newnp->u.ull = iterinfop->num;
8580Sstevel@tonic-gate 				return (newnp);
8590Sstevel@tonic-gate 			}
8600Sstevel@tonic-gate 		}
861*4436Sstephh 
862*4436Sstephh 		/*
863*4436Sstephh 		 * finally, whether wildcarding or not, we need to copy the
864*4436Sstephh 		 * remaining part of the path (if any). This must be defined
865*4436Sstephh 		 * absolutely (no more expansion/wildcarding).
866*4436Sstephh 		 */
867*4436Sstephh 		for (npref = nprest; npref != NULL;
868*4436Sstephh 		    npref = npref->u.name.next) {
869*4436Sstephh 			newnp = newnode(T_NAME, np->file, np->line);
870*4436Sstephh 			newnp->u.name.t = npref->u.name.t;
871*4436Sstephh 			newnp->u.name.s = npref->u.name.s;
872*4436Sstephh 			newnp->u.name.last = newnp;
873*4436Sstephh 			newnp->u.name.it = npref->u.name.it;
874*4436Sstephh 			newnp->u.name.cp = npref->u.name.cp;
875*4436Sstephh 			newnp->u.name.child =
876*4436Sstephh 			    newnode(T_NUM, np->file, np->line);
877*4436Sstephh 			if (eval_expr(npref->u.name.child, ex, events,
878*4436Sstephh 			    NULL, NULL, NULL, 1, &value) == 0 ||
879*4436Sstephh 			    value.t != UINT64) {
880*4436Sstephh 				outfl(O_DIE, np->file, np->line,
881*4436Sstephh 				    "eval_dup: could not resolve "
882*4436Sstephh 				    "iterator of %s", np->u.name.s);
883*4436Sstephh 			}
884*4436Sstephh 			newnp->u.name.child->u.ull = value.v;
885*4436Sstephh 			if (retp == NULL) {
886*4436Sstephh 				retp = newnp;
887*4436Sstephh 			} else {
888*4436Sstephh 				retp->u.name.last->u.name.next = newnp;
889*4436Sstephh 				retp->u.name.last = newnp;
890*4436Sstephh 			}
891*4436Sstephh 		}
892*4436Sstephh 		return (retp);
8930Sstevel@tonic-gate 	}
8940Sstevel@tonic-gate 
8951414Scindi 	case T_EVENT:
8961414Scindi 		newnp = newnode(T_NAME, np->file, np->line);
8971414Scindi 
8981414Scindi 		newnp->u.name.t = np->u.event.ename->u.name.t;
8991414Scindi 		newnp->u.name.s = np->u.event.ename->u.name.s;
9001414Scindi 		newnp->u.name.it = np->u.event.ename->u.name.it;
9011414Scindi 		newnp->u.name.last = newnp;
9021414Scindi 
9031414Scindi 		return (tree_event(newnp,
904*4436Sstephh 		    eval_dup(np->u.event.epname, ex, events),
905*4436Sstephh 		    eval_dup(np->u.event.eexprlist, ex, events)));
9061414Scindi 
9070Sstevel@tonic-gate 	case T_FUNC:
9080Sstevel@tonic-gate 		return (tree_func(np->u.func.s,
909*4436Sstephh 		    eval_dup(np->u.func.arglist, ex, events),
9100Sstevel@tonic-gate 		    np->file, np->line));
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	case T_QUOTE:
9130Sstevel@tonic-gate 		newnp = newnode(T_QUOTE, np->file, np->line);
9140Sstevel@tonic-gate 		newnp->u.quote.s = np->u.quote.s;
9150Sstevel@tonic-gate 		return (newnp);
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	case T_NUM:
9180Sstevel@tonic-gate 		newnp = newnode(T_NUM, np->file, np->line);
9190Sstevel@tonic-gate 		newnp->u.ull = np->u.ull;
9200Sstevel@tonic-gate 		return (newnp);
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	default:
9230Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
9240Sstevel@tonic-gate 		    "eval_dup: unexpected node type: %s",
9250Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 	/*NOTREACHED*/
9281717Swesolows 	return (0);
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate /*
9320Sstevel@tonic-gate  * eval_potential -- see if constraint is potentially true
9330Sstevel@tonic-gate  *
9340Sstevel@tonic-gate  * this function is used at instance tree creation time to see if
9350Sstevel@tonic-gate  * any constraints are already known to be false.  if this function
9360Sstevel@tonic-gate  * returns false, then the constraint will always be false and there's
9370Sstevel@tonic-gate  * no need to include the propagation arrow in the instance tree.
9380Sstevel@tonic-gate  *
9390Sstevel@tonic-gate  * if this routine returns true, either the constraint is known to
9400Sstevel@tonic-gate  * be always true (so there's no point in attaching the constraint
9410Sstevel@tonic-gate  * to the propagation arrow in the instance tree), or the constraint
9420Sstevel@tonic-gate  * contains "deferred" expressions like global variables or poller calls
9430Sstevel@tonic-gate  * and so it must be evaluated during calls to fme_eval().  in this last
9440Sstevel@tonic-gate  * case, where a constraint needs to be attached to the propagation arrow
9450Sstevel@tonic-gate  * in the instance tree, this routine returns a newly created constraint
9460Sstevel@tonic-gate  * in *newc where all the non-deferred things have been filled in.
9470Sstevel@tonic-gate  *
9480Sstevel@tonic-gate  * so in summary:
9490Sstevel@tonic-gate  *
9500Sstevel@tonic-gate  *	return of false: constraint can never be true, *newc will be NULL.
9510Sstevel@tonic-gate  *
9520Sstevel@tonic-gate  *	return of true with *newc unchanged: constraint will always be true.
9530Sstevel@tonic-gate  *
9540Sstevel@tonic-gate  *	return of true with *newc changed: use new constraint in *newc.
9550Sstevel@tonic-gate  *
9560Sstevel@tonic-gate  * the lookup table for all explicit iterators, ex, is passed in.
9570Sstevel@tonic-gate  *
9580Sstevel@tonic-gate  * *newc can either be NULL on entry, or if can contain constraints from
9590Sstevel@tonic-gate  * previous calls to eval_potential() (i.e. for building up an instance
9600Sstevel@tonic-gate  * tree constraint from several potential constraints).  if *newc already
9610Sstevel@tonic-gate  * contains constraints, anything added to it will be joined by adding
9620Sstevel@tonic-gate  * a T_AND node at the top of *newc.
9630Sstevel@tonic-gate  */
9640Sstevel@tonic-gate int
965*4436Sstephh eval_potential(struct node *np, struct lut *ex, struct node *events[],
9662318Sstephh 	    struct node **newc, struct config *croot)
9670Sstevel@tonic-gate {
9680Sstevel@tonic-gate 	struct node *newnp;
9690Sstevel@tonic-gate 	struct evalue value;
9700Sstevel@tonic-gate 
971*4436Sstephh 	if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
9720Sstevel@tonic-gate 		/*
9730Sstevel@tonic-gate 		 * couldn't eval expression because
9740Sstevel@tonic-gate 		 * it contains deferred items.  make
9750Sstevel@tonic-gate 		 * a duplicate expression with all the
9760Sstevel@tonic-gate 		 * non-deferred items expanded.
9770Sstevel@tonic-gate 		 */
978*4436Sstephh 		newnp = eval_dup(np, ex, events);
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 		if (*newc == NULL) {
9810Sstevel@tonic-gate 			/*
9820Sstevel@tonic-gate 			 * constraint is potentially true if deferred
9830Sstevel@tonic-gate 			 * expression in newnp is true.  *newc was NULL
9840Sstevel@tonic-gate 			 * so new constraint is just the one in newnp.
9850Sstevel@tonic-gate 			 */
9860Sstevel@tonic-gate 			*newc = newnp;
9870Sstevel@tonic-gate 			return (1);
9880Sstevel@tonic-gate 		} else {
9890Sstevel@tonic-gate 			/*
9900Sstevel@tonic-gate 			 * constraint is potentially true if deferred
9910Sstevel@tonic-gate 			 * expression in newnp is true.  *newc already
9920Sstevel@tonic-gate 			 * contained a constraint so add an AND with the
9930Sstevel@tonic-gate 			 * constraint in newnp.
9940Sstevel@tonic-gate 			 */
9950Sstevel@tonic-gate 			*newc = tree_expr(T_AND, *newc, newnp);
9960Sstevel@tonic-gate 			return (1);
9970Sstevel@tonic-gate 		}
9980Sstevel@tonic-gate 	} else if (value.t == UNDEFINED) {
9990Sstevel@tonic-gate 		/* constraint can never be true */
10000Sstevel@tonic-gate 		return (0);
10010Sstevel@tonic-gate 	} else if (value.t == UINT64 && value.v == 0) {
10020Sstevel@tonic-gate 		/* constraint can never be true */
10030Sstevel@tonic-gate 		return (0);
10040Sstevel@tonic-gate 	} else {
10050Sstevel@tonic-gate 		/* constraint is always true (nothing deferred to eval) */
10060Sstevel@tonic-gate 		return (1);
10070Sstevel@tonic-gate 	}
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate static int
10110Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
10120Sstevel@tonic-gate 		struct node *np)
10130Sstevel@tonic-gate {
10141414Scindi 	/* auto-convert T_NAMES to strings */
10151717Swesolows 	if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
10161717Swesolows 	    T_NAME) {
10171717Swesolows 		char *s = ipath2str(NULL,
10181717Swesolows 		    ipath((struct node *)(uintptr_t)lp->v));
10191414Scindi 		lp->t = STRING;
10201717Swesolows 		lp->v = (uintptr_t)stable(s);
10211414Scindi 		FREE(s);
10221414Scindi 		out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
10231717Swesolows 		    (char *)(uintptr_t)lp->v);
10241414Scindi 	}
10251414Scindi 	if (rp != NULL &&
10261717Swesolows 	    rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
10271717Swesolows 	    T_NAME) {
10281717Swesolows 		char *s = ipath2str(NULL,
10291717Swesolows 		    ipath((struct node *)(uintptr_t)rp->v));
10301414Scindi 		rp->t = STRING;
10311717Swesolows 		rp->v = (uintptr_t)stable(s);
10321414Scindi 		FREE(s);
10331414Scindi 		out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
10341717Swesolows 		    (char *)(uintptr_t)rp->v);
10351414Scindi 	}
10361414Scindi 
10371414Scindi 	/* auto-convert strings to numbers */
10381414Scindi 	if (dtype == UINT64) {
10391414Scindi 		if (lp->t == STRING) {
10401414Scindi 			lp->t = UINT64;
10411717Swesolows 			lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
10421414Scindi 		}
10431414Scindi 		if (rp != NULL && rp->t == STRING) {
10441414Scindi 			rp->t = UINT64;
10451717Swesolows 			rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
10461414Scindi 		}
10471414Scindi 	}
10481414Scindi 
10490Sstevel@tonic-gate 	if (dtype != UNDEFINED && lp->t != dtype) {
1050*4436Sstephh 		outfl(O_DIE, np->file, np->line,
1051*4436Sstephh 		    "invalid datatype of argument for operation %s",
1052*4436Sstephh 		    ptree_nodetype2str(np->t));
1053*4436Sstephh 		/* NOTREACHED */
10540Sstevel@tonic-gate 		return (1);
10550Sstevel@tonic-gate 	}
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 	if (rp != NULL && lp->t != rp->t) {
1058*4436Sstephh 		outfl(O_DIE, np->file, np->line,
1059*4436Sstephh 		    "mismatch in datatype of arguments for operation %s",
1060*4436Sstephh 		    ptree_nodetype2str(np->t));
1061*4436Sstephh 		/* NOTREACHED */
10620Sstevel@tonic-gate 		return (1);
10630Sstevel@tonic-gate 	}
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	return (0);
10660Sstevel@tonic-gate }
10670Sstevel@tonic-gate 
10680Sstevel@tonic-gate /*
10690Sstevel@tonic-gate  * eval_expr -- evaluate expression into *valuep
10700Sstevel@tonic-gate  *
10710Sstevel@tonic-gate  * the meaning of the return value depends on the input value of try.
10720Sstevel@tonic-gate  *
10730Sstevel@tonic-gate  * for try == 1: if any deferred items are encounted, bail out and return
10740Sstevel@tonic-gate  * false.  returns true if we made it through entire expression without
10750Sstevel@tonic-gate  * hitting any deferred items.
10760Sstevel@tonic-gate  *
10770Sstevel@tonic-gate  * for try == 0: return true if all operations were performed successfully.
10780Sstevel@tonic-gate  * return false if otherwise.  for example, any of the following conditions
10790Sstevel@tonic-gate  * will result in a false return value:
10800Sstevel@tonic-gate  *   - attempted use of an uninitialized global variable
10810Sstevel@tonic-gate  *   - failure in function evaluation
10820Sstevel@tonic-gate  *   - illegal arithmetic operation (argument out of range)
10830Sstevel@tonic-gate  */
10840Sstevel@tonic-gate int
1085*4436Sstephh eval_expr(struct node *np, struct lut *ex, struct node *events[],
10860Sstevel@tonic-gate 	struct lut **globals, struct config *croot, struct arrow *arrowp,
10870Sstevel@tonic-gate 	int try, struct evalue *valuep)
10880Sstevel@tonic-gate {
10890Sstevel@tonic-gate 	struct evalue *gval;
10900Sstevel@tonic-gate 	struct evalue lval;
10910Sstevel@tonic-gate 	struct evalue rval;
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	if (np == NULL) {
10940Sstevel@tonic-gate 		valuep->t = UINT64;
10950Sstevel@tonic-gate 		valuep->v = 1;	/* no constraint means "true" */
10960Sstevel@tonic-gate 		return (1);
10970Sstevel@tonic-gate 	}
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	valuep->t = UNDEFINED;
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	switch (np->t) {
11020Sstevel@tonic-gate 	case T_GLOBID:
11030Sstevel@tonic-gate 		if (try)
11040Sstevel@tonic-gate 			return (0);
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 		/*
11070Sstevel@tonic-gate 		 * only handle case of getting (and not setting) the value
11080Sstevel@tonic-gate 		 * of a global variable
11090Sstevel@tonic-gate 		 */
11100Sstevel@tonic-gate 		gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
11110Sstevel@tonic-gate 		if (gval == NULL) {
11120Sstevel@tonic-gate 			return (0);
11130Sstevel@tonic-gate 		} else {
11140Sstevel@tonic-gate 			valuep->t = gval->t;
11150Sstevel@tonic-gate 			valuep->v = gval->v;
11160Sstevel@tonic-gate 			return (1);
11170Sstevel@tonic-gate 		}
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	case T_ASSIGN:
11200Sstevel@tonic-gate 		if (try)
11210Sstevel@tonic-gate 			return (0);
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 		/*
11240Sstevel@tonic-gate 		 * first evaluate rhs, then try to store value in lhs which
11250Sstevel@tonic-gate 		 * should be a global variable
11260Sstevel@tonic-gate 		 */
1127*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1128*4436Sstephh 		    arrowp, try, &rval))
11290Sstevel@tonic-gate 			return (0);
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 		ASSERT(np->u.expr.left->t == T_GLOBID);
11320Sstevel@tonic-gate 		gval = lut_lookup(*globals,
1133*4436Sstephh 		    (void *)np->u.expr.left->u.globid.s, NULL);
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate 		if (gval == NULL) {
11360Sstevel@tonic-gate 			gval = MALLOC(sizeof (*gval));
11370Sstevel@tonic-gate 			*globals = lut_add(*globals,
1138*4436Sstephh 			    (void *) np->u.expr.left->u.globid.s, gval, NULL);
11390Sstevel@tonic-gate 		}
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 		gval->t = rval.t;
11420Sstevel@tonic-gate 		gval->v = rval.v;
11431414Scindi 
11441414Scindi 		if (gval->t == UINT64) {
11451414Scindi 			out(O_ALTFP|O_VERB2,
11461414Scindi 			    "assign $%s=%llu",
11471414Scindi 			    np->u.expr.left->u.globid.s, gval->v);
11481414Scindi 		} else {
11491414Scindi 			out(O_ALTFP|O_VERB2,
11501414Scindi 			    "assign $%s=\"%s\"",
11511717Swesolows 			    np->u.expr.left->u.globid.s,
11521717Swesolows 			    (char *)(uintptr_t)gval->v);
11531414Scindi 		}
11541414Scindi 
11551414Scindi 		/*
11561414Scindi 		 * but always return true -- an assignment should not
11571414Scindi 		 * cause a constraint to be false.
11581414Scindi 		 */
11591414Scindi 		valuep->t = UINT64;
11601414Scindi 		valuep->v = 1;
11610Sstevel@tonic-gate 		return (1);
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 	case T_EQ:
11640Sstevel@tonic-gate #define	IMPLICIT_ASSIGN_IN_EQ
11650Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ
11660Sstevel@tonic-gate 		/*
11670Sstevel@tonic-gate 		 * if lhs is an uninitialized global variable, perform
11680Sstevel@tonic-gate 		 * an assignment.
11690Sstevel@tonic-gate 		 *
11700Sstevel@tonic-gate 		 * one insidious side effect of implicit assignment is
11710Sstevel@tonic-gate 		 * that the "==" operator does not return a Boolean if
11720Sstevel@tonic-gate 		 * implicit assignment was performed.
11730Sstevel@tonic-gate 		 */
11740Sstevel@tonic-gate 		if (try == 0 &&
11750Sstevel@tonic-gate 		    np->u.expr.left->t == T_GLOBID &&
11760Sstevel@tonic-gate 		    (gval = lut_lookup(*globals,
1177*4436Sstephh 		    (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
1178*4436Sstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1179*4436Sstephh 			    croot, arrowp, try, &rval))
11800Sstevel@tonic-gate 				return (0);
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate 			gval = MALLOC(sizeof (*gval));
11830Sstevel@tonic-gate 			*globals = lut_add(*globals,
1184*4436Sstephh 			    (void *) np->u.expr.left->u.globid.s,
1185*4436Sstephh 			    gval, NULL);
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate 			gval->t = rval.t;
11880Sstevel@tonic-gate 			gval->v = rval.v;
11890Sstevel@tonic-gate 			valuep->t = rval.t;
11900Sstevel@tonic-gate 			valuep->v = rval.v;
11910Sstevel@tonic-gate 			return (1);
11920Sstevel@tonic-gate 		}
11930Sstevel@tonic-gate #endif  /* IMPLICIT_ASSIGN_IN_EQ */
11940Sstevel@tonic-gate 
1195*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1196*4436Sstephh 		    arrowp, try, &lval))
1197*4436Sstephh 			return (0);
1198*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1199*4436Sstephh 		    arrowp, try, &rval))
12000Sstevel@tonic-gate 			return (0);
1201*4436Sstephh 		if (rval.t == UINT64 || lval.t == UINT64) {
1202*4436Sstephh 			if (check_expr_args(&lval, &rval, UINT64, np))
1203*4436Sstephh 				return (0);
1204*4436Sstephh 		} else {
1205*4436Sstephh 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
1206*4436Sstephh 				return (0);
1207*4436Sstephh 		}
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 		valuep->t = UINT64;
12100Sstevel@tonic-gate 		valuep->v = (lval.v == rval.v);
12110Sstevel@tonic-gate 		return (1);
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 	case T_LT:
1214*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1215*4436Sstephh 		    arrowp, try, &lval))
12160Sstevel@tonic-gate 			return (0);
1217*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1218*4436Sstephh 		    arrowp, try, &rval))
12190Sstevel@tonic-gate 			return (0);
12201414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
12210Sstevel@tonic-gate 			return (0);
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 		valuep->t = UINT64;
12240Sstevel@tonic-gate 		valuep->v = (lval.v < rval.v);
12250Sstevel@tonic-gate 		return (1);
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 	case T_LE:
1228*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1229*4436Sstephh 		    arrowp, try, &lval))
12300Sstevel@tonic-gate 			return (0);
1231*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1232*4436Sstephh 		    arrowp, try, &rval))
12330Sstevel@tonic-gate 			return (0);
12341414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
12350Sstevel@tonic-gate 			return (0);
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 		valuep->t = UINT64;
12380Sstevel@tonic-gate 		valuep->v = (lval.v <= rval.v);
12390Sstevel@tonic-gate 		return (1);
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 	case T_GT:
1242*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1243*4436Sstephh 		    arrowp, try, &lval))
12440Sstevel@tonic-gate 			return (0);
1245*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1246*4436Sstephh 		    arrowp, try, &rval))
12470Sstevel@tonic-gate 			return (0);
12481414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
12490Sstevel@tonic-gate 			return (0);
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 		valuep->t = UINT64;
12520Sstevel@tonic-gate 		valuep->v = (lval.v > rval.v);
12530Sstevel@tonic-gate 		return (1);
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 	case T_GE:
1256*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1257*4436Sstephh 		    arrowp, try, &lval))
12580Sstevel@tonic-gate 			return (0);
1259*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1260*4436Sstephh 		    arrowp, try, &rval))
12610Sstevel@tonic-gate 			return (0);
12621414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
12630Sstevel@tonic-gate 			return (0);
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 		valuep->t = UINT64;
12660Sstevel@tonic-gate 		valuep->v = (lval.v >= rval.v);
12670Sstevel@tonic-gate 		return (1);
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	case T_BITAND:
1270*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1271*4436Sstephh 		    arrowp, try, &lval))
12720Sstevel@tonic-gate 			return (0);
1273*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1274*4436Sstephh 		    arrowp, try, &rval))
12750Sstevel@tonic-gate 			return (0);
12760Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
12770Sstevel@tonic-gate 			return (0);
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 		valuep->t = lval.t;
12800Sstevel@tonic-gate 		valuep->v = (lval.v & rval.v);
12810Sstevel@tonic-gate 		return (1);
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate 	case T_BITOR:
1284*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1285*4436Sstephh 		    arrowp, try, &lval))
12860Sstevel@tonic-gate 			return (0);
1287*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1288*4436Sstephh 		    arrowp, try, &rval))
12890Sstevel@tonic-gate 			return (0);
12900Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
12910Sstevel@tonic-gate 			return (0);
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate 		valuep->t = lval.t;
12940Sstevel@tonic-gate 		valuep->v = (lval.v | rval.v);
12950Sstevel@tonic-gate 		return (1);
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate 	case T_BITXOR:
1298*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1299*4436Sstephh 		    arrowp, try, &lval))
13000Sstevel@tonic-gate 			return (0);
1301*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1302*4436Sstephh 		    arrowp, try, &rval))
13030Sstevel@tonic-gate 			return (0);
13040Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
13050Sstevel@tonic-gate 			return (0);
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 		valuep->t = lval.t;
13080Sstevel@tonic-gate 		valuep->v = (lval.v ^ rval.v);
13090Sstevel@tonic-gate 		return (1);
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 	case T_BITNOT:
1312*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1313*4436Sstephh 		    arrowp, try, &lval))
13140Sstevel@tonic-gate 			return (0);
13150Sstevel@tonic-gate 		ASSERT(np->u.expr.right == NULL);
13160Sstevel@tonic-gate 		if (check_expr_args(&lval, NULL, UINT64, np))
13170Sstevel@tonic-gate 			return (0);
13180Sstevel@tonic-gate 
13190Sstevel@tonic-gate 		valuep->t = UINT64;
13200Sstevel@tonic-gate 		valuep->v = ~ lval.v;
13210Sstevel@tonic-gate 		return (1);
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate 	case T_LSHIFT:
1324*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1325*4436Sstephh 		    arrowp, try, &lval))
13260Sstevel@tonic-gate 			return (0);
1327*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1328*4436Sstephh 		    arrowp, try, &rval))
13290Sstevel@tonic-gate 			return (0);
13300Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
13310Sstevel@tonic-gate 			return (0);
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 		valuep->t = UINT64;
13340Sstevel@tonic-gate 		valuep->v = (lval.v << rval.v);
13350Sstevel@tonic-gate 		return (1);
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 	case T_RSHIFT:
1338*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1339*4436Sstephh 		    arrowp, try, &lval))
13400Sstevel@tonic-gate 			return (0);
1341*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1342*4436Sstephh 		    arrowp, try, &rval))
13430Sstevel@tonic-gate 			return (0);
13440Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
13450Sstevel@tonic-gate 			return (0);
13460Sstevel@tonic-gate 
13470Sstevel@tonic-gate 		valuep->t = UINT64;
13480Sstevel@tonic-gate 		valuep->v = (lval.v >> rval.v);
13490Sstevel@tonic-gate 		return (1);
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	case T_CONDIF: {
13520Sstevel@tonic-gate 		struct node *retnp;
13530Sstevel@tonic-gate 		int dotrue = 0;
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 		/*
13560Sstevel@tonic-gate 		 * evaluate
13570Sstevel@tonic-gate 		 *	expression ? stmtA [ : stmtB ]
13580Sstevel@tonic-gate 		 *
13590Sstevel@tonic-gate 		 * first see if expression is true or false, then determine
13600Sstevel@tonic-gate 		 * if stmtA (or stmtB, if it exists) should be evaluated.
13610Sstevel@tonic-gate 		 *
13620Sstevel@tonic-gate 		 * "dotrue = 1" means stmtA should be evaluated.
13630Sstevel@tonic-gate 		 */
1364*4436Sstephh 		if (eval_expr(np->u.expr.left, ex, events, globals, croot,
1365*4436Sstephh 		    arrowp, try, &lval) &&
13660Sstevel@tonic-gate 		    lval.t != UNDEFINED && lval.v != 0)
13670Sstevel@tonic-gate 			dotrue = 1;
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 		ASSERT(np->u.expr.right != NULL);
13700Sstevel@tonic-gate 		if (np->u.expr.right->t == T_CONDELSE) {
13710Sstevel@tonic-gate 			if (dotrue)
13720Sstevel@tonic-gate 				retnp = np->u.expr.right->u.expr.left;
13730Sstevel@tonic-gate 			else
13740Sstevel@tonic-gate 				retnp = np->u.expr.right->u.expr.right;
13750Sstevel@tonic-gate 		} else {
13760Sstevel@tonic-gate 			/* no ELSE clause */
13770Sstevel@tonic-gate 			if (dotrue)
13780Sstevel@tonic-gate 				retnp = np->u.expr.right;
13790Sstevel@tonic-gate 			else {
1380*4436Sstephh 				outfl(O_DIE, np->file, np->line,
1381*4436Sstephh 				    "eval_expr: missing condelse");
13820Sstevel@tonic-gate 			}
13830Sstevel@tonic-gate 		}
13840Sstevel@tonic-gate 
1385*4436Sstephh 		if (!eval_expr(retnp, ex, events, globals, croot,
1386*4436Sstephh 		    arrowp, try, valuep))
13870Sstevel@tonic-gate 			return (0);
13880Sstevel@tonic-gate 		return (1);
13890Sstevel@tonic-gate 	}
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	case T_CONDELSE:
13920Sstevel@tonic-gate 		/*
13930Sstevel@tonic-gate 		 * shouldn't get here, since T_CONDELSE is supposed to be
13940Sstevel@tonic-gate 		 * evaluated as part of T_CONDIF
13950Sstevel@tonic-gate 		 */
13960Sstevel@tonic-gate 		out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
13970Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
1398*4436Sstephh 		/*NOTREACHED*/
13990Sstevel@tonic-gate 
14000Sstevel@tonic-gate 	case T_NE:
1401*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1402*4436Sstephh 		    arrowp, try, &lval))
1403*4436Sstephh 			return (0);
1404*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1405*4436Sstephh 		    arrowp, try, &rval))
14060Sstevel@tonic-gate 			return (0);
1407*4436Sstephh 		if (rval.t == UINT64 || lval.t == UINT64) {
1408*4436Sstephh 			if (check_expr_args(&lval, &rval, UINT64, np))
1409*4436Sstephh 				return (0);
1410*4436Sstephh 		} else {
1411*4436Sstephh 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
1412*4436Sstephh 				return (0);
1413*4436Sstephh 		}
14140Sstevel@tonic-gate 
14150Sstevel@tonic-gate 		valuep->t = UINT64;
14160Sstevel@tonic-gate 		valuep->v = (lval.v != rval.v);
14170Sstevel@tonic-gate 		return (1);
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate 	case T_LIST:
14200Sstevel@tonic-gate 	case T_AND:
1421*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1422*4436Sstephh 		    arrowp, try, valuep)) {
14233159Sstephh 			/*
14243159Sstephh 			 * if lhs is unknown, still check rhs. If that
14253159Sstephh 			 * is false we can return false irrespectice of lhs
14263159Sstephh 			 */
1427*4436Sstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1428*4436Sstephh 			    croot, arrowp, try, valuep)) {
1429*4436Sstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
14303159Sstephh 				return (0);
1431*4436Sstephh 			}
1432*4436Sstephh 			if (valuep->v != 0) {
1433*4436Sstephh 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
14343159Sstephh 				return (0);
1435*4436Sstephh 			}
14363159Sstephh 		}
14370Sstevel@tonic-gate 		if (valuep->v == 0) {
14380Sstevel@tonic-gate 			valuep->t = UINT64;
14390Sstevel@tonic-gate 			return (1);
14400Sstevel@tonic-gate 		}
1441*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1442*4436Sstephh 		    arrowp, try, valuep)) {
1443*4436Sstephh 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
14440Sstevel@tonic-gate 			return (0);
1445*4436Sstephh 		}
14460Sstevel@tonic-gate 		valuep->t = UINT64;
14470Sstevel@tonic-gate 		valuep->v = valuep->v == 0 ? 0 : 1;
14480Sstevel@tonic-gate 		return (1);
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 	case T_OR:
1451*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1452*4436Sstephh 		    arrowp, try, valuep)) {
14533159Sstephh 			/*
14543159Sstephh 			 * if lhs is unknown, still check rhs. If that
14553159Sstephh 			 * is true we can return true irrespectice of lhs
14563159Sstephh 			 */
1457*4436Sstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1458*4436Sstephh 			    croot, arrowp, try, valuep)) {
1459*4436Sstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
14603159Sstephh 				return (0);
1461*4436Sstephh 			}
1462*4436Sstephh 			if (valuep->v == 0) {
1463*4436Sstephh 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
14643159Sstephh 				return (0);
1465*4436Sstephh 			}
14663159Sstephh 		}
14670Sstevel@tonic-gate 		if (valuep->v != 0) {
14680Sstevel@tonic-gate 			valuep->t = UINT64;
14690Sstevel@tonic-gate 			valuep->v = 1;
14700Sstevel@tonic-gate 			return (1);
14710Sstevel@tonic-gate 		}
1472*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1473*4436Sstephh 		    arrowp, try, valuep)) {
1474*4436Sstephh 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
14750Sstevel@tonic-gate 			return (0);
1476*4436Sstephh 		}
14770Sstevel@tonic-gate 		valuep->t = UINT64;
14780Sstevel@tonic-gate 		valuep->v = valuep->v == 0 ? 0 : 1;
14790Sstevel@tonic-gate 		return (1);
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 	case T_NOT:
1482*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1483*4436Sstephh 		    arrowp, try, valuep))
14840Sstevel@tonic-gate 			return (0);
14850Sstevel@tonic-gate 		valuep->t = UINT64;
14860Sstevel@tonic-gate 		valuep->v = ! valuep->v;
14870Sstevel@tonic-gate 		return (1);
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 	case T_ADD:
1490*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1491*4436Sstephh 		    arrowp, try, &lval))
14920Sstevel@tonic-gate 			return (0);
1493*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1494*4436Sstephh 		    arrowp, try, &rval))
14950Sstevel@tonic-gate 			return (0);
14960Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
14970Sstevel@tonic-gate 			return (0);
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate 		valuep->t = lval.t;
15000Sstevel@tonic-gate 		valuep->v = lval.v + rval.v;
15010Sstevel@tonic-gate 		return (1);
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate 	case T_SUB:
1504*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1505*4436Sstephh 		    arrowp, try, &lval))
15060Sstevel@tonic-gate 			return (0);
1507*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1508*4436Sstephh 		    arrowp, try, &rval))
15090Sstevel@tonic-gate 			return (0);
15100Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
15110Sstevel@tonic-gate 			return (0);
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate 		/* since valuep is unsigned, return false if lval.v < rval.v */
15140Sstevel@tonic-gate 		if (lval.v < rval.v) {
1515*4436Sstephh 			outfl(O_DIE, np->file, np->line,
1516*4436Sstephh 			    "eval_expr: T_SUB result is out of range");
15170Sstevel@tonic-gate 		}
15180Sstevel@tonic-gate 
15190Sstevel@tonic-gate 		valuep->t = lval.t;
15200Sstevel@tonic-gate 		valuep->v = lval.v - rval.v;
15210Sstevel@tonic-gate 		return (1);
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate 	case T_MUL:
1524*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1525*4436Sstephh 		    arrowp, try, &lval))
15260Sstevel@tonic-gate 			return (0);
1527*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1528*4436Sstephh 		    arrowp, try, &rval))
15290Sstevel@tonic-gate 			return (0);
15300Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
15310Sstevel@tonic-gate 			return (0);
15320Sstevel@tonic-gate 
15330Sstevel@tonic-gate 		valuep->t = lval.t;
15340Sstevel@tonic-gate 		valuep->v = lval.v * rval.v;
15350Sstevel@tonic-gate 		return (1);
15360Sstevel@tonic-gate 
15370Sstevel@tonic-gate 	case T_DIV:
1538*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1539*4436Sstephh 		    arrowp, try, &lval))
15400Sstevel@tonic-gate 			return (0);
1541*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1542*4436Sstephh 		    arrowp, try, &rval))
15430Sstevel@tonic-gate 			return (0);
15440Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
15450Sstevel@tonic-gate 			return (0);
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate 		/* return false if dividing by zero */
15480Sstevel@tonic-gate 		if (rval.v == 0) {
1549*4436Sstephh 			outfl(O_DIE, np->file, np->line,
1550*4436Sstephh 			    "eval_expr: T_DIV division by zero");
15510Sstevel@tonic-gate 		}
15520Sstevel@tonic-gate 
15530Sstevel@tonic-gate 		valuep->t = lval.t;
15540Sstevel@tonic-gate 		valuep->v = lval.v / rval.v;
15550Sstevel@tonic-gate 		return (1);
15560Sstevel@tonic-gate 
15570Sstevel@tonic-gate 	case T_MOD:
1558*4436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1559*4436Sstephh 		    arrowp, try, &lval))
15600Sstevel@tonic-gate 			return (0);
1561*4436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1562*4436Sstephh 		    arrowp, try, &rval))
15630Sstevel@tonic-gate 			return (0);
15640Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
15650Sstevel@tonic-gate 			return (0);
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 		/* return false if dividing by zero */
15680Sstevel@tonic-gate 		if (rval.v == 0) {
1569*4436Sstephh 			outfl(O_DIE, np->file, np->line,
1570*4436Sstephh 			    "eval_expr: T_MOD division by zero");
15710Sstevel@tonic-gate 		}
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 		valuep->t = lval.t;
15740Sstevel@tonic-gate 		valuep->v = lval.v % rval.v;
15750Sstevel@tonic-gate 		return (1);
15760Sstevel@tonic-gate 
15770Sstevel@tonic-gate 	case T_NAME:
15780Sstevel@tonic-gate 		if (try) {
15790Sstevel@tonic-gate 			struct iterinfo *iterinfop;
1580*4436Sstephh 			struct node *np1, *np2;
1581*4436Sstephh 			int i, gotmatch = 0;
15820Sstevel@tonic-gate 
15830Sstevel@tonic-gate 			/*
1584*4436Sstephh 			 * Check if we have an exact match of the nonwildcarded
1585*4436Sstephh 			 * path in oldepname - if so we can just use the
1586*4436Sstephh 			 * full wildcarded path in epname.
15870Sstevel@tonic-gate 			 */
1588*4436Sstephh 			for (i = 0; i < 1; i++) {
1589*4436Sstephh 				for (np1 = np,
1590*4436Sstephh 				    np2 = events[i]->u.event.oldepname;
1591*4436Sstephh 				    np1 != NULL && np2 != NULL;
1592*4436Sstephh 				    np1 = np1->u.name.next,
1593*4436Sstephh 				    np2 = np2->u.name.next) {
1594*4436Sstephh 					if (strcmp(np1->u.name.s,
1595*4436Sstephh 					    np2->u.name.s) != 0)
1596*4436Sstephh 						break;
1597*4436Sstephh 					if (np1->u.name.child->t !=
1598*4436Sstephh 					    np2->u.name.child->t)
1599*4436Sstephh 						break;
1600*4436Sstephh 					if (np1->u.name.child->t == T_NUM &&
1601*4436Sstephh 					    np1->u.name.child->u.ull !=
1602*4436Sstephh 					    np2->u.name.child->u.ull)
1603*4436Sstephh 						break;
1604*4436Sstephh 					if (np1->u.name.child->t == T_NAME &&
1605*4436Sstephh 					    strcmp(np1->u.name.child->u.name.s,
1606*4436Sstephh 					    np2->u.name.child->u.name.s) != 0)
1607*4436Sstephh 						break;
1608*4436Sstephh 					gotmatch++;
1609*4436Sstephh 				}
1610*4436Sstephh 				if (np1 == NULL && np2 == NULL) {
1611*4436Sstephh 					valuep->t = NODEPTR;
1612*4436Sstephh 					valuep->v = (uintptr_t)
1613*4436Sstephh 					    events[i]->u.event.epname;
1614*4436Sstephh 					return (1);
1615*4436Sstephh 				}
16160Sstevel@tonic-gate 			}
1617*4436Sstephh 			if (!gotmatch) {
1618*4436Sstephh 				/*
1619*4436Sstephh 				 * we're not wildcarding. However at
1620*4436Sstephh 				 * itree_create() time, we can also expand
1621*4436Sstephh 				 * simple iterators - so check for those.
1622*4436Sstephh 				 */
1623*4436Sstephh 				iterinfop = lut_lookup(ex, (void *)np->u.name.s,
1624*4436Sstephh 				    NULL);
1625*4436Sstephh 				if (iterinfop != NULL) {
1626*4436Sstephh 					valuep->t = UINT64;
1627*4436Sstephh 					valuep->v =
1628*4436Sstephh 					    (unsigned long long)iterinfop->num;
1629*4436Sstephh 					return (1);
1630*4436Sstephh 				}
1631*4436Sstephh 			}
1632*4436Sstephh 			/*
1633*4436Sstephh 			 * For anything else we'll have to wait for eval_dup().
1634*4436Sstephh 			 */
16350Sstevel@tonic-gate 			return (0);
16360Sstevel@tonic-gate 		}
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate 		/* return address of struct node */
16390Sstevel@tonic-gate 		valuep->t = NODEPTR;
16401717Swesolows 		valuep->v = (uintptr_t)np;
16410Sstevel@tonic-gate 		return (1);
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate 	case T_QUOTE:
16440Sstevel@tonic-gate 		valuep->t = STRING;
16451717Swesolows 		valuep->v = (uintptr_t)np->u.quote.s;
16460Sstevel@tonic-gate 		return (1);
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 	case T_FUNC:
1649*4436Sstephh 		return (eval_func(np, ex, events, np->u.func.arglist,
1650*4436Sstephh 		    globals, croot, arrowp, try, valuep));
16510Sstevel@tonic-gate 
16520Sstevel@tonic-gate 	case T_NUM:
16530Sstevel@tonic-gate 		valuep->t = UINT64;
16540Sstevel@tonic-gate 		valuep->v = np->u.ull;
16550Sstevel@tonic-gate 		return (1);
16560Sstevel@tonic-gate 
16570Sstevel@tonic-gate 	default:
16580Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
16590Sstevel@tonic-gate 		    "eval_expr: unexpected node type: %s",
16600Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
16610Sstevel@tonic-gate 	}
16620Sstevel@tonic-gate 	/*NOTREACHED*/
16631717Swesolows 	return (0);
16640Sstevel@tonic-gate }
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate /*
16670Sstevel@tonic-gate  * eval_fru() and eval_asru() don't do much, but are called from a number
16680Sstevel@tonic-gate  * of places.
16690Sstevel@tonic-gate  */
1670*4436Sstephh static struct node *
16710Sstevel@tonic-gate eval_fru(struct node *np)
16720Sstevel@tonic-gate {
16730Sstevel@tonic-gate 	ASSERT(np->t == T_NAME);
16740Sstevel@tonic-gate 	return (np);
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate 
1677*4436Sstephh static struct node *
16780Sstevel@tonic-gate eval_asru(struct node *np)
16790Sstevel@tonic-gate {
16800Sstevel@tonic-gate 	ASSERT(np->t == T_NAME);
16810Sstevel@tonic-gate 	return (np);
16820Sstevel@tonic-gate }
1683