xref: /onnv-gate/usr/src/cmd/fm/modules/common/eversholt/eval.c (revision 7197:6062b005c7ea)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51717Swesolows  * Common Development and Distribution License (the "License").
61717Swesolows  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211717Swesolows 
220Sstevel@tonic-gate /*
23*7197Sstephh  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  *
260Sstevel@tonic-gate  * eval.c -- constraint evaluation module
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * this module evaluates constraints.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <ctype.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include "alloc.h"
380Sstevel@tonic-gate #include "out.h"
390Sstevel@tonic-gate #include "stable.h"
400Sstevel@tonic-gate #include "literals.h"
410Sstevel@tonic-gate #include "lut.h"
420Sstevel@tonic-gate #include "tree.h"
430Sstevel@tonic-gate #include "ptree.h"
440Sstevel@tonic-gate #include "itree.h"
451414Scindi #include "ipath.h"
460Sstevel@tonic-gate #include "eval.h"
470Sstevel@tonic-gate #include "config.h"
480Sstevel@tonic-gate #include "platform.h"
491414Scindi #include "fme.h"
501414Scindi #include "stats.h"
510Sstevel@tonic-gate 
520Sstevel@tonic-gate static struct node *eval_dup(struct node *np, struct lut *ex,
534436Sstephh     struct node *events[]);
541414Scindi static int check_expr_args(struct evalue *lp, struct evalue *rp,
551414Scindi     enum datatype dtype, struct node *np);
564436Sstephh static struct node *eval_fru(struct node *np);
574436Sstephh static struct node *eval_asru(struct node *np);
580Sstevel@tonic-gate 
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate  * begins_with -- return true if rhs path begins with everything in lhs path
610Sstevel@tonic-gate  */
620Sstevel@tonic-gate static int
634436Sstephh begins_with(struct node *lhs, struct node *rhs, struct lut *ex)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate 	int lnum;
660Sstevel@tonic-gate 	int rnum;
674436Sstephh 	struct iterinfo *iterinfop;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	if (lhs == NULL)
700Sstevel@tonic-gate 		return (1);	/* yep -- it all matched */
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	if (rhs == NULL)
730Sstevel@tonic-gate 		return (0);	/* nope, ran out of rhs first */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str);
760Sstevel@tonic-gate 	ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str);
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	if (lhs->u.name.s != rhs->u.name.s)
790Sstevel@tonic-gate 		return (0);	/* nope, different component names */
800Sstevel@tonic-gate 
814436Sstephh 	if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) {
820Sstevel@tonic-gate 		lnum = (int)lhs->u.name.child->u.ull;
834436Sstephh 	} else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) {
844436Sstephh 		iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s,
854436Sstephh 		    NULL);
864436Sstephh 		if (iterinfop != NULL)
874436Sstephh 			lnum = iterinfop->num;
884436Sstephh 		else
894436Sstephh 			out(O_DIE, "begins_with: unexpected lhs child");
904436Sstephh 	} else {
910Sstevel@tonic-gate 		out(O_DIE, "begins_with: unexpected lhs child");
924436Sstephh 	}
930Sstevel@tonic-gate 
944436Sstephh 	if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) {
950Sstevel@tonic-gate 		rnum = (int)rhs->u.name.child->u.ull;
964436Sstephh 	} else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) {
974436Sstephh 		iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s,
984436Sstephh 		    NULL);
994436Sstephh 		if (iterinfop != NULL)
1004436Sstephh 			rnum = iterinfop->num;
1014436Sstephh 		else
1024436Sstephh 			out(O_DIE, "begins_with: unexpected rhs child");
1034436Sstephh 	} else {
1040Sstevel@tonic-gate 		out(O_DIE, "begins_with: unexpected rhs child");
1054436Sstephh 	}
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	if (lnum != rnum)
1080Sstevel@tonic-gate 		return (0);	/* nope, instance numbers were different */
1090Sstevel@tonic-gate 
1104436Sstephh 	return (begins_with(lhs->u.name.next, rhs->u.name.next, ex));
1114436Sstephh }
1124436Sstephh 
1134436Sstephh /*
1144436Sstephh  * eval_getname - used by eval_func to evaluate a name, preferably without using
1154436Sstephh  * eval_dup (but if it does have to use eval_dup then the *dupedp flag is set).
1164436Sstephh  */
1174436Sstephh static struct node *
1184436Sstephh eval_getname(struct node *funcnp, struct lut *ex, struct node *events[],
1194436Sstephh     struct node *np, struct lut **globals,
1204436Sstephh     struct config *croot, struct arrow *arrowp, int try, int *dupedp)
1214436Sstephh {
1224436Sstephh 	struct node *nodep;
1234436Sstephh 	const char *funcname = funcnp->u.func.s;
1244436Sstephh 	struct evalue val;
1254436Sstephh 
1264436Sstephh 	if (np->t == T_NAME)
1274436Sstephh 		nodep = np;
1284436Sstephh 	else if (np->u.func.s == L_fru)
1294436Sstephh 		nodep = eval_fru(np->u.func.arglist);
1304436Sstephh 	else if (np->u.func.s == L_asru)
1314436Sstephh 		nodep = eval_asru(np->u.func.arglist);
1324436Sstephh 	else
1334436Sstephh 		out(O_DIE, "%s: unexpected type: %s",
1344436Sstephh 		    funcname, ptree_nodetype2str(np->t));
1354436Sstephh 	if (try) {
1364436Sstephh 		if (eval_expr(nodep, ex, events, globals, croot,
1374436Sstephh 		    arrowp, try, &val) && val.t == NODEPTR)
1384436Sstephh 			nodep = (struct node *)(uintptr_t)val.v;
1394436Sstephh 		else {
1404436Sstephh 			*dupedp = 1;
1414436Sstephh 			nodep = eval_dup(nodep, ex, events);
1424436Sstephh 		}
1434436Sstephh 	}
1444436Sstephh 	return (nodep);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate /*
1480Sstevel@tonic-gate  * evaluate a variety of functions and place result in valuep.  return 1 if
1490Sstevel@tonic-gate  * function evaluation was successful; 0 if otherwise (e.g., the case of an
1500Sstevel@tonic-gate  * invalid argument to the function)
1510Sstevel@tonic-gate  */
1520Sstevel@tonic-gate /*ARGSUSED*/
1530Sstevel@tonic-gate static int
1544436Sstephh eval_func(struct node *funcnp, struct lut *ex, struct node *events[],
1550Sstevel@tonic-gate     struct node *np, struct lut **globals,
1560Sstevel@tonic-gate     struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 	const char *funcname = funcnp->u.func.s;
1594436Sstephh 	int duped_lhs = 0, duped_rhs = 0, duped = 0;
1604436Sstephh 	struct node *lhs;
1614436Sstephh 	struct node *rhs;
1624436Sstephh 	struct config *cp;
1634436Sstephh 	struct node *nodep;
1644436Sstephh 	char *path;
1654436Sstephh 	struct evalue val;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	if (funcname == L_within) {
1680Sstevel@tonic-gate 		/* within()'s are not really constraints -- always true */
1690Sstevel@tonic-gate 		valuep->t = UINT64;
1700Sstevel@tonic-gate 		valuep->v = 1;
1710Sstevel@tonic-gate 		return (1);
1720Sstevel@tonic-gate 	} else if (funcname == L_is_under) {
1734436Sstephh 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
1744436Sstephh 		    croot, arrowp, try, &duped_lhs);
1754436Sstephh 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
1764436Sstephh 		    globals, croot, arrowp, try, &duped_rhs);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 		valuep->t = UINT64;
1794436Sstephh 		valuep->v = begins_with(lhs, rhs, ex);
1800Sstevel@tonic-gate 		out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
1810Sstevel@tonic-gate 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
1820Sstevel@tonic-gate 		out(O_ALTFP|O_VERB2|O_NONL, ",");
1830Sstevel@tonic-gate 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
1844436Sstephh 		out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v);
1850Sstevel@tonic-gate 
1864436Sstephh 		if (duped_lhs)
1874436Sstephh 			tree_free(lhs);
1884436Sstephh 		if (duped_rhs)
1894436Sstephh 			tree_free(rhs);
1900Sstevel@tonic-gate 		return (1);
1912869Sgavinm 	} else if (funcname == L_confprop || funcname == L_confprop_defined) {
1922318Sstephh 		const char *s;
1932318Sstephh 
1942318Sstephh 		/* for now s will point to a quote [see addconfigprop()] */
1952318Sstephh 		ASSERT(np->u.expr.right->t == T_QUOTE);
1962318Sstephh 
1974436Sstephh 		nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
1984436Sstephh 		    globals, croot, arrowp, try, &duped);
1994436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
2004436Sstephh 			cp = nodep->u.name.last->u.name.cp;
2014436Sstephh 		} else {
2024436Sstephh 			path = ipath2str(NULL, ipath(nodep));
2034436Sstephh 			cp = config_lookup(croot, path, 0);
2044436Sstephh 			FREE((void *)path);
2054436Sstephh 		}
2062869Sgavinm 		if (cp == NULL) {
2074436Sstephh 			if (funcname == L_confprop) {
2084436Sstephh 				out(O_ALTFP|O_VERB3, "%s: path ", funcname);
2094436Sstephh 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
2104436Sstephh 				out(O_ALTFP|O_VERB3, " not found");
2114436Sstephh 				valuep->v = (uintptr_t)stable("");
2124436Sstephh 				valuep->t = STRING;
2134436Sstephh 				if (duped)
2144436Sstephh 					tree_free(nodep);
2154436Sstephh 				return (1);
2164436Sstephh 			} else {
2172869Sgavinm 				valuep->v = 0;
2182869Sgavinm 				valuep->t = UINT64;
2194436Sstephh 				if (duped)
2204436Sstephh 					tree_free(nodep);
2212869Sgavinm 				return (1);
2222869Sgavinm 			}
2232869Sgavinm 		}
2242318Sstephh 		s = config_getprop(cp, np->u.expr.right->u.quote.s);
2254436Sstephh 		if (s == NULL && strcmp(np->u.expr.right->u.quote.s,
2264436Sstephh 		    "class-code") == 0)
2274436Sstephh 			s = config_getprop(cp, "CLASS-CODE");
2282869Sgavinm 		if (s == NULL) {
2294436Sstephh 			if (funcname == L_confprop) {
2304436Sstephh 				out(O_ALTFP|O_VERB3|O_NONL,
2314436Sstephh 				    "%s: \"%s\" not found for path ",
2324436Sstephh 				    funcname, np->u.expr.right->u.quote.s);
2334436Sstephh 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
2344436Sstephh 				valuep->v = (uintptr_t)stable("");
2354436Sstephh 				valuep->t = STRING;
2364436Sstephh 				if (duped)
2374436Sstephh 					tree_free(nodep);
2384436Sstephh 				return (1);
2394436Sstephh 			} else {
2402869Sgavinm 				valuep->v = 0;
2412869Sgavinm 				valuep->t = UINT64;
2424436Sstephh 				if (duped)
2434436Sstephh 					tree_free(nodep);
2442869Sgavinm 				return (1);
2452869Sgavinm 			}
2462869Sgavinm 		}
2472869Sgavinm 
2482869Sgavinm 		if (funcname == L_confprop) {
2492869Sgavinm 			valuep->v = (uintptr_t)stable(s);
2502869Sgavinm 			valuep->t = STRING;
2514436Sstephh 			out(O_ALTFP|O_VERB3|O_NONL, "  %s(\"", funcname);
2524436Sstephh 			ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
2534436Sstephh 			out(O_ALTFP|O_VERB3|O_NONL,
2544436Sstephh 			    "\", \"%s\") = \"%s\"  ",
2554436Sstephh 			    np->u.expr.right->u.quote.s,
2562869Sgavinm 			    (char *)(uintptr_t)valuep->v);
2572869Sgavinm 		} else {
2582869Sgavinm 			valuep->v = 1;
2592869Sgavinm 			valuep->t = UINT64;
2602869Sgavinm 		}
2614436Sstephh 		if (duped)
2624436Sstephh 			tree_free(nodep);
2634436Sstephh 		return (1);
2644436Sstephh 	} else if (funcname == L_is_connected) {
2654436Sstephh 		const char *connstrings[] = { "connected", "CONNECTED", NULL };
2664436Sstephh 		struct config *cp[2];
2674436Sstephh 		const char *matchthis[2], *s;
2684436Sstephh 		char *nameslist, *w;
2694436Sstephh 		int i, j;
2704436Sstephh 
2714436Sstephh 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
2724436Sstephh 		    croot, arrowp, try, &duped_lhs);
2734436Sstephh 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
2744436Sstephh 		    globals, croot, arrowp, try, &duped_rhs);
2754436Sstephh 		path = ipath2str(NULL, ipath(lhs));
2764436Sstephh 		matchthis[1] = stable(path);
2774436Sstephh 		if (lhs->u.name.last->u.name.cp != NULL)
2784436Sstephh 			cp[0] = lhs->u.name.last->u.name.cp;
2794436Sstephh 		else
2804436Sstephh 			cp[0] = config_lookup(croot, path, 0);
2812869Sgavinm 		FREE((void *)path);
2824436Sstephh 		path = ipath2str(NULL, ipath(rhs));
2834436Sstephh 		matchthis[0] = stable(path);
2844436Sstephh 		if (rhs->u.name.last->u.name.cp != NULL)
2854436Sstephh 			cp[1] = rhs->u.name.last->u.name.cp;
2864436Sstephh 		else
2874436Sstephh 			cp[1] = config_lookup(croot, path, 0);
2884436Sstephh 		FREE((void *)path);
2894436Sstephh 		if (duped_lhs)
2904436Sstephh 			tree_free(lhs);
2914436Sstephh 		if (duped_rhs)
2924436Sstephh 			tree_free(rhs);
2934436Sstephh 
2944436Sstephh 		valuep->t = UINT64;
2954436Sstephh 		valuep->v = 0;
2964436Sstephh 		if (cp[0] == NULL || cp[1] == NULL)
2974436Sstephh 			return (1);
2984436Sstephh 
2994436Sstephh 		/* to thine self always be connected */
3004436Sstephh 		if (cp[0] == cp[1]) {
3014436Sstephh 			valuep->v = 1;
3024436Sstephh 			return (1);
3034436Sstephh 		}
3044436Sstephh 
3054436Sstephh 		/*
3064436Sstephh 		 * Extract "connected" property from each cp. Search this
3074436Sstephh 		 * property for the name associated with the other cp[].
3084436Sstephh 		 */
3094436Sstephh 		for (i = 0; i < 2 && valuep->v == 0; i++) {
3104436Sstephh 			for (j = 0; connstrings[j] != NULL && valuep->v == 0;
3114436Sstephh 			    j++) {
3124436Sstephh 				s = config_getprop(cp[i],
3134436Sstephh 				    stable(connstrings[j]));
3144436Sstephh 				if (s != NULL) {
3154436Sstephh 					nameslist = STRDUP(s);
3164436Sstephh 					w = strtok(nameslist, " ,");
3174436Sstephh 					while (w != NULL) {
3184436Sstephh 						if (stable(w) == matchthis[i]) {
3194436Sstephh 							valuep->v = 1;
3204436Sstephh 							break;
3214436Sstephh 						}
3224436Sstephh 						w = strtok(NULL, " ,");
3234436Sstephh 					}
3244436Sstephh 					FREE(nameslist);
3254436Sstephh 				}
3264436Sstephh 			}
3274436Sstephh 		}
3282318Sstephh 		return (1);
3294436Sstephh 	} else if (funcname == L_is_type) {
3304436Sstephh 		const char *typestrings[] = { "type", "TYPE", NULL };
3314436Sstephh 		const char *s;
3324436Sstephh 		int i;
3334436Sstephh 
3344436Sstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
3354436Sstephh 		    croot, arrowp, try, &duped);
3364436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
3374436Sstephh 			cp = nodep->u.name.last->u.name.cp;
3384436Sstephh 		} else {
3394436Sstephh 			path = ipath2str(NULL, ipath(nodep));
3404436Sstephh 			cp = config_lookup(croot, path, 0);
3414436Sstephh 			FREE((void *)path);
3424436Sstephh 		}
3434436Sstephh 		if (duped)
3444436Sstephh 			tree_free(nodep);
3454436Sstephh 
3464436Sstephh 		valuep->t = STRING;
3474436Sstephh 		valuep->v = (uintptr_t)stable("");
3484436Sstephh 		if (cp == NULL)
3494436Sstephh 			return (1);
3504436Sstephh 		for (i = 0; typestrings[i] != NULL; i++) {
3514436Sstephh 			s = config_getprop(cp, stable(typestrings[i]));
3524436Sstephh 			if (s != NULL) {
3534436Sstephh 				valuep->v = (uintptr_t)stable(s);
3544436Sstephh 				break;
3554436Sstephh 			}
3564436Sstephh 		}
3574436Sstephh 		return (1);
3584436Sstephh 	} else if (funcname == L_is_on) {
3594436Sstephh 		const char *onstrings[] = { "on", "ON", NULL };
3604436Sstephh 		const char *truestrings[] = { "yes", "YES", "y", "Y",
3614436Sstephh 				    "true", "TRUE", "t", "T", "1", NULL };
3624436Sstephh 		const char *s;
3634436Sstephh 		int i, j;
3644436Sstephh 
3654436Sstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
3664436Sstephh 		    croot, arrowp, try, &duped);
3674436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
3684436Sstephh 			cp = nodep->u.name.last->u.name.cp;
3694436Sstephh 		} else {
3704436Sstephh 			path = ipath2str(NULL, ipath(nodep));
3714436Sstephh 			cp = config_lookup(croot, path, 0);
3724436Sstephh 			FREE((void *)path);
3734436Sstephh 		}
3744436Sstephh 		if (duped)
3754436Sstephh 			tree_free(nodep);
3764436Sstephh 
3774436Sstephh 		valuep->t = UINT64;
3784436Sstephh 		valuep->v = 0;
3794436Sstephh 		if (cp == NULL)
3804436Sstephh 			return (1);
3814436Sstephh 		for (i = 0; onstrings[i] != NULL; i++) {
3824436Sstephh 			s = config_getprop(cp, stable(onstrings[i]));
3834436Sstephh 			if (s != NULL) {
3844436Sstephh 				s = stable(s);
3854436Sstephh 				for (j = 0; truestrings[j] != NULL; j++) {
3864436Sstephh 					if (s == stable(truestrings[j])) {
3874436Sstephh 						valuep->v = 1;
3884436Sstephh 						return (1);
3894436Sstephh 					}
3904436Sstephh 				}
3914436Sstephh 			}
3924436Sstephh 		}
3934436Sstephh 		return (1);
3944436Sstephh 	} else if (funcname == L_is_present) {
3954436Sstephh 		nodep = eval_getname(funcnp, ex, events, np, globals,
3964436Sstephh 		    croot, arrowp, try, &duped);
3974436Sstephh 		if (nodep->u.name.last->u.name.cp != NULL) {
3984436Sstephh 			cp = nodep->u.name.last->u.name.cp;
3994436Sstephh 		} else {
4004436Sstephh 			path = ipath2str(NULL, ipath(nodep));
4014436Sstephh 			cp = config_lookup(croot, path, 0);
4024436Sstephh 			FREE((void *)path);
4034436Sstephh 		}
4044436Sstephh 		if (duped)
4054436Sstephh 			tree_free(nodep);
4064436Sstephh 
4074436Sstephh 		valuep->t = UINT64;
4084436Sstephh 		valuep->v = 0;
4094436Sstephh 		if (cp != NULL)
4104436Sstephh 			valuep->v = 1;
4114436Sstephh 		return (1);
4124436Sstephh 	} else if (funcname == L_count) {
4134436Sstephh 		struct stats *statp;
4144436Sstephh 		struct istat_entry ent;
4154436Sstephh 
4164436Sstephh 		ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
4174436Sstephh 
4184436Sstephh 		nodep = np->u.event.epname;
4194436Sstephh 		if (try) {
4204436Sstephh 			if (eval_expr(nodep, ex, events, globals,
4214436Sstephh 			    croot, arrowp, try, &val) && val.t == NODEPTR)
4224436Sstephh 				nodep = (struct node *)(uintptr_t)val.v;
4234436Sstephh 			else {
4244436Sstephh 				duped = 1;
4254436Sstephh 				nodep = eval_dup(nodep, ex, events);
4264436Sstephh 			}
4274436Sstephh 		}
4284436Sstephh 		ent.ename = np->u.event.ename->u.name.s;
4294436Sstephh 		ent.ipath = ipath(nodep);
4304436Sstephh 		valuep->t = UINT64;
4314436Sstephh 		if ((statp = (struct stats *)
4324436Sstephh 		    lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
4334436Sstephh 			valuep->v = 0;
4344436Sstephh 		else
4354436Sstephh 			valuep->v = stats_counter_value(statp);
4364436Sstephh 		if (duped)
4374436Sstephh 			tree_free(nodep);
4384436Sstephh 		return (1);
4394436Sstephh 	} else if (funcname == L_envprop) {
4404436Sstephh 		outfl(O_DIE, np->file, np->line,
4414436Sstephh 		    "eval_func: %s not yet supported", funcname);
4420Sstevel@tonic-gate 	}
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (try)
4450Sstevel@tonic-gate 		return (0);
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	if (funcname == L_fru) {
4480Sstevel@tonic-gate 		valuep->t = NODEPTR;
4491717Swesolows 		valuep->v = (uintptr_t)eval_fru(np);
4500Sstevel@tonic-gate 		return (1);
4510Sstevel@tonic-gate 	} else if (funcname == L_asru) {
4520Sstevel@tonic-gate 		valuep->t = NODEPTR;
4531717Swesolows 		valuep->v = (uintptr_t)eval_asru(np);
4540Sstevel@tonic-gate 		return (1);
4551414Scindi 	} else if (funcname == L_defined) {
4561414Scindi 		ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
4571414Scindi 		valuep->t = UINT64;
4581414Scindi 		valuep->v = (lut_lookup(*globals,
4591414Scindi 		    (void *)np->u.globid.s, NULL) != NULL);
4601414Scindi 		return (1);
4610Sstevel@tonic-gate 	} else if (funcname == L_call) {
4620Sstevel@tonic-gate 		return (! platform_call(np, globals, croot, arrowp, valuep));
4630Sstevel@tonic-gate 	} else if (funcname == L_payloadprop) {
4641414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
4650Sstevel@tonic-gate 		    "payloadprop(\"%s\") ", np->u.quote.s);
466186Sdb35262 
4675204Sstephh 		if (arrowp->head->myevent->count == 0) {
4685204Sstephh 			/*
4695204Sstephh 			 * Haven't seen this ereport yet, so must defer
4705204Sstephh 			 */
4715204Sstephh 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
4725204Sstephh 			return (0);
4735204Sstephh 		} else if (platform_payloadprop(np, valuep)) {
4741414Scindi 			/* platform_payloadprop() returned false */
4755204Sstephh 			out(O_ALTFP|O_VERB, "not found.");
4765204Sstephh 			valuep->t = UNDEFINED;
4775204Sstephh 			return (1);
4781414Scindi 		} else {
479186Sdb35262 			switch (valuep->t) {
480186Sdb35262 			case UINT64:
481186Sdb35262 			case NODEPTR:
4821414Scindi 				out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
483186Sdb35262 				break;
484186Sdb35262 			case STRING:
4851414Scindi 				out(O_ALTFP|O_VERB2, "found: \"%s\"",
4861717Swesolows 				    (char *)(uintptr_t)valuep->v);
487186Sdb35262 				break;
488186Sdb35262 			default:
4891414Scindi 				out(O_ALTFP|O_VERB2, "found: undefined");
490186Sdb35262 				break;
491186Sdb35262 			}
4921414Scindi 			return (1);
4931414Scindi 		}
4941414Scindi 	} else if (funcname == L_setpayloadprop) {
4951414Scindi 		struct evalue *payloadvalp;
4965204Sstephh 		int alloced = 0;
4971414Scindi 
4981414Scindi 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
4991414Scindi 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
5001414Scindi 		    ptree_nodetype2str(np->u.expr.left->t));
5011414Scindi 
502*7197Sstephh 		if (arrowp->head->myevent->count == 0)
503*7197Sstephh 			return (0);
504*7197Sstephh 
5051414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
5061414Scindi 		    "setpayloadprop: %s: %s=",
5071414Scindi 		    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
5081414Scindi 		    np->u.expr.left->u.quote.s);
5091414Scindi 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
5101414Scindi 
5111414Scindi 		/*
5121414Scindi 		 * allocate a struct evalue to hold the payload property's
5131414Scindi 		 * value, unless we've been here already, in which case we
5141414Scindi 		 * might calculate a different value, but we'll store it
5151414Scindi 		 * in the already-allocated struct evalue.
5161414Scindi 		 */
5171414Scindi 		if ((payloadvalp = (struct evalue *)lut_lookup(
5181414Scindi 		    arrowp->tail->myevent->payloadprops,
5191414Scindi 		    (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
5201414Scindi 			payloadvalp = MALLOC(sizeof (*payloadvalp));
5215204Sstephh 			alloced = 1;
5221414Scindi 		}
5231414Scindi 
5244436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
5251414Scindi 		    arrowp, try, payloadvalp)) {
5265204Sstephh 			out(O_ALTFP|O_VERB2, " (cannot eval)");
5275204Sstephh 			if (alloced)
5285204Sstephh 				FREE(payloadvalp);
5295204Sstephh 			return (0);
5301414Scindi 		} else {
5315204Sstephh 			if (payloadvalp->t == UNDEFINED) {
5325204Sstephh 				/* function is always true */
5335204Sstephh 				out(O_ALTFP|O_VERB2, " (undefined)");
5345204Sstephh 				valuep->t = UINT64;
5355204Sstephh 				valuep->v = 1;
5365204Sstephh 				return (1);
5375204Sstephh 			}
5381414Scindi 			if (payloadvalp->t == UINT64)
5391414Scindi 				out(O_ALTFP|O_VERB2,
5401414Scindi 				    " (%llu)", payloadvalp->v);
5411414Scindi 			else
5421717Swesolows 				out(O_ALTFP|O_VERB2, " (\"%s\")",
5431717Swesolows 				    (char *)(uintptr_t)payloadvalp->v);
5441414Scindi 		}
5451414Scindi 
5461414Scindi 		/* add to table of payload properties for current problem */
5471414Scindi 		arrowp->tail->myevent->payloadprops =
5481414Scindi 		    lut_add(arrowp->tail->myevent->payloadprops,
5491414Scindi 		    (void *)np->u.expr.left->u.quote.s,
5501414Scindi 		    (void *)payloadvalp, NULL);
5511414Scindi 
5521414Scindi 		/* function is always true */
5531414Scindi 		valuep->t = UINT64;
5541414Scindi 		valuep->v = 1;
5551414Scindi 		return (1);
556*7197Sstephh 	} else if (funcname == L_setserdn || funcname == L_setserdt ||
557*7197Sstephh 	    funcname == L_setserdsuffix || funcname == L_setserdincrement) {
558*7197Sstephh 		struct evalue *serdvalp;
559*7197Sstephh 		int alloced = 0;
560*7197Sstephh 		char *str;
561*7197Sstephh 		struct event *flt = arrowp->tail->myevent;
562*7197Sstephh 
563*7197Sstephh 		if (arrowp->head->myevent->count == 0)
564*7197Sstephh 			return (0);
565*7197Sstephh 
566*7197Sstephh 		if (funcname == L_setserdn)
567*7197Sstephh 			str = "n";
568*7197Sstephh 		else if (funcname == L_setserdt)
569*7197Sstephh 			str = "t";
570*7197Sstephh 		else if (funcname == L_setserdsuffix)
571*7197Sstephh 			str = "suffix";
572*7197Sstephh 		else if (funcname == L_setserdincrement)
573*7197Sstephh 			str = "increment";
574*7197Sstephh 
575*7197Sstephh 		/*
576*7197Sstephh 		 * allocate a struct evalue to hold the serd property's
577*7197Sstephh 		 * value, unless we've been here already, in which case we
578*7197Sstephh 		 * might calculate a different value, but we'll store it
579*7197Sstephh 		 * in the already-allocated struct evalue.
580*7197Sstephh 		 */
581*7197Sstephh 		if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops,
582*7197Sstephh 		    (void *)str, NULL)) == NULL) {
583*7197Sstephh 			serdvalp = MALLOC(sizeof (*serdvalp));
584*7197Sstephh 			alloced = 1;
585*7197Sstephh 		}
586*7197Sstephh 
587*7197Sstephh 		if (!eval_expr(np, ex, events, globals, croot, arrowp, try,
588*7197Sstephh 		    serdvalp)) {
589*7197Sstephh 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
590*7197Sstephh 			    "setserd%s: %s: ", str,
591*7197Sstephh 			    flt->enode->u.event.ename->u.name.s);
592*7197Sstephh 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
593*7197Sstephh 			out(O_ALTFP|O_VERB2, " (cannot eval)");
594*7197Sstephh 			if (alloced)
595*7197Sstephh 				FREE(serdvalp);
596*7197Sstephh 			return (0);
597*7197Sstephh 		} else if (serdvalp->t == UNDEFINED) {
598*7197Sstephh 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
599*7197Sstephh 			    "setserd%s: %s: ", str,
600*7197Sstephh 			    flt->enode->u.event.ename->u.name.s);
601*7197Sstephh 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
602*7197Sstephh 			out(O_ALTFP|O_VERB2, " (undefined)");
603*7197Sstephh 		} else {
604*7197Sstephh 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
605*7197Sstephh 			    "setserd%s: %s: ", str,
606*7197Sstephh 			    flt->enode->u.event.ename->u.name.s);
607*7197Sstephh 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
608*7197Sstephh 			if ((funcname == L_setserdincrement ||
609*7197Sstephh 			    funcname == L_setserdn) && serdvalp->t == STRING) {
610*7197Sstephh 				serdvalp->t = UINT64;
611*7197Sstephh 				serdvalp->v = strtoull((char *)
612*7197Sstephh 				    (uintptr_t)serdvalp->v, NULL, 0);
613*7197Sstephh 			}
614*7197Sstephh 			if (funcname == L_setserdt && serdvalp->t == UINT64) {
615*7197Sstephh 				int len = snprintf(NULL, 0, "%lldns",
616*7197Sstephh 				    serdvalp->v);
617*7197Sstephh 				char *buf = MALLOC(len + 1);
618*7197Sstephh 
619*7197Sstephh 				(void) snprintf(buf, len + 1, "%lldns",
620*7197Sstephh 				    serdvalp->v);
621*7197Sstephh 				serdvalp->t = STRING;
622*7197Sstephh 				serdvalp->v = (uintptr_t)stable(buf);
623*7197Sstephh 				FREE(buf);
624*7197Sstephh 			}
625*7197Sstephh 			if (serdvalp->t == UINT64)
626*7197Sstephh 				out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v);
627*7197Sstephh 			else
628*7197Sstephh 				out(O_ALTFP|O_VERB2, " (\"%s\")",
629*7197Sstephh 				    (char *)(uintptr_t)serdvalp->v);
630*7197Sstephh 			flt->serdprops = lut_add(flt->serdprops, (void *)str,
631*7197Sstephh 			    (void *)serdvalp, NULL);
632*7197Sstephh 		}
633*7197Sstephh 		valuep->t = UINT64;
634*7197Sstephh 		valuep->v = 1;
635*7197Sstephh 		return (1);
6361414Scindi 	} else if (funcname == L_payloadprop_defined) {
6371414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
6381414Scindi 		    "payloadprop_defined(\"%s\") ", np->u.quote.s);
6391414Scindi 
6405204Sstephh 		if (arrowp->head->myevent->count == 0) {
6415204Sstephh 			/*
6425204Sstephh 			 * Haven't seen this ereport yet, so must defer
6435204Sstephh 			 */
6445204Sstephh 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
6455204Sstephh 			return (0);
6465204Sstephh 		} else if (platform_payloadprop(np, NULL)) {
6471414Scindi 			/* platform_payloadprop() returned false */
6481414Scindi 			valuep->v = 0;
6495204Sstephh 			out(O_ALTFP|O_VERB2, "not found.");
6501414Scindi 		} else {
6511414Scindi 			valuep->v = 1;
6521414Scindi 			out(O_ALTFP|O_VERB2, "found.");
6531414Scindi 		}
6541414Scindi 		valuep->t = UINT64;
6551414Scindi 		return (1);
6561414Scindi 	} else if (funcname == L_payloadprop_contains) {
6571414Scindi 		int nvals;
6581414Scindi 		struct evalue *vals;
6591414Scindi 		struct evalue cmpval;
6601414Scindi 
6611414Scindi 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
6621414Scindi 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
6631414Scindi 		    ptree_nodetype2str(np->u.expr.left->t));
6641414Scindi 
6651414Scindi 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
6661414Scindi 		    "payloadprop_contains(\"%s\", ",
6671414Scindi 		    np->u.expr.left->u.quote.s);
6681414Scindi 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
6692869Sgavinm 		out(O_ALTFP|O_VERB2|O_NONL, ") ");
6701414Scindi 
6711414Scindi 		/* evaluate the expression we're comparing against */
6724436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
6731414Scindi 		    arrowp, try, &cmpval)) {
6741414Scindi 			out(O_ALTFP|O_VERB2|O_NONL,
6755204Sstephh 			    "(cannot eval) ");
6765204Sstephh 			return (0);
6771414Scindi 		} else {
6782869Sgavinm 			switch (cmpval.t) {
6792869Sgavinm 			case UNDEFINED:
6802869Sgavinm 				out(O_ALTFP|O_VERB2, "(undefined type)");
6812869Sgavinm 				break;
6822869Sgavinm 
6832869Sgavinm 			case UINT64:
6841414Scindi 				out(O_ALTFP|O_VERB2,
6851414Scindi 				    "(%llu) ", cmpval.v);
6862869Sgavinm 				break;
6872869Sgavinm 
6882869Sgavinm 			case STRING:
6891414Scindi 				out(O_ALTFP|O_VERB2,
6901717Swesolows 				    "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
6912869Sgavinm 				break;
6922869Sgavinm 
6932869Sgavinm 			case NODEPTR:
6942869Sgavinm 				out(O_ALTFP|O_VERB2|O_NONL, "(");
6952869Sgavinm 				ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
6962869Sgavinm 				    (struct node *)(uintptr_t)(cmpval.v));
6972869Sgavinm 				out(O_ALTFP|O_VERB2, ") ");
6982869Sgavinm 				break;
6992869Sgavinm 			}
7001414Scindi 		}
7011414Scindi 
7021414Scindi 		/* get the payload values and check for a match */
7031414Scindi 		vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
7041414Scindi 		    &nvals);
7051414Scindi 		valuep->t = UINT64;
7061414Scindi 		valuep->v = 0;
7075204Sstephh 		if (arrowp->head->myevent->count == 0) {
7085204Sstephh 			/*
7095204Sstephh 			 * Haven't seen this ereport yet, so must defer
7105204Sstephh 			 */
7115204Sstephh 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
7125204Sstephh 			return (0);
7135204Sstephh 		} else if (nvals == 0) {
7141414Scindi 			out(O_ALTFP|O_VERB2, "not found.");
7155204Sstephh 			return (1);
7161414Scindi 		} else {
7171414Scindi 			struct evalue preval;
7181414Scindi 			int i;
7191414Scindi 
7201414Scindi 			out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
7211414Scindi 
7221414Scindi 			for (i = 0; i < nvals; i++) {
7231414Scindi 
7241414Scindi 				preval.t = vals[i].t;
7251414Scindi 				preval.v = vals[i].v;
7261414Scindi 
7271414Scindi 				if (check_expr_args(&vals[i], &cmpval,
7281414Scindi 				    UNDEFINED, np))
7291414Scindi 					continue;
7301414Scindi 
7311414Scindi 				/*
7321414Scindi 				 * If we auto-converted the value to a
7331414Scindi 				 * string, we need to free the
7341414Scindi 				 * original tree value.
7351414Scindi 				 */
7361414Scindi 				if (preval.t == NODEPTR &&
7371717Swesolows 				    ((struct node *)(uintptr_t)(preval.v))->t ==
7381717Swesolows 				    T_NAME) {
7391717Swesolows 					tree_free((struct node *)(uintptr_t)
7401717Swesolows 					    preval.v);
7411414Scindi 				}
7421414Scindi 
7431414Scindi 				if (vals[i].v == cmpval.v) {
7441414Scindi 					valuep->v = 1;
7451414Scindi 					break;
7461414Scindi 				}
7471414Scindi 			}
748186Sdb35262 
7491414Scindi 			if (valuep->v)
7501414Scindi 				out(O_ALTFP|O_VERB2, "match.");
7511414Scindi 			else
7521414Scindi 				out(O_ALTFP|O_VERB2, "no match.");
753186Sdb35262 
7541414Scindi 			for (i = 0; i < nvals; i++) {
7551414Scindi 				if (vals[i].t == NODEPTR) {
7561717Swesolows 					tree_free((struct node *)(uintptr_t)
7571717Swesolows 					    vals[i].v);
7581414Scindi 					break;
7591414Scindi 				}
760186Sdb35262 			}
7611414Scindi 			FREE(vals);
7621414Scindi 		}
7631414Scindi 		return (1);
7641414Scindi 	} else if (funcname == L_confcall) {
7651414Scindi 		return (!platform_confcall(np, globals, croot, arrowp, valuep));
7660Sstevel@tonic-gate 	} else
7670Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
7680Sstevel@tonic-gate 		    "eval_func: unexpected func: %s", funcname);
7690Sstevel@tonic-gate 	/*NOTREACHED*/
7701717Swesolows 	return (0);
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate 
7734436Sstephh /*
7744436Sstephh  * defines for u.expr.temp - these are used for T_OR and T_AND so that if
7754436Sstephh  * we worked out that part of the expression was true or false during an
7764436Sstephh  * earlier eval_expr, then we don't need to dup that part.
7774436Sstephh  */
7780Sstevel@tonic-gate 
7794436Sstephh #define	EXPR_TEMP_BOTH_UNK	0
7804436Sstephh #define	EXPR_TEMP_LHS_UNK	1
7814436Sstephh #define	EXPR_TEMP_RHS_UNK	2
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate static struct node *
7844436Sstephh eval_dup(struct node *np, struct lut *ex, struct node *events[])
7850Sstevel@tonic-gate {
7860Sstevel@tonic-gate 	struct node *newnp;
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	if (np == NULL)
7890Sstevel@tonic-gate 		return (NULL);
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	switch (np->t) {
7920Sstevel@tonic-gate 	case T_GLOBID:
7930Sstevel@tonic-gate 		return (tree_globid(np->u.globid.s, np->file, np->line));
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	case T_ASSIGN:
7960Sstevel@tonic-gate 	case T_CONDIF:
7970Sstevel@tonic-gate 	case T_CONDELSE:
7980Sstevel@tonic-gate 	case T_NE:
7990Sstevel@tonic-gate 	case T_EQ:
8000Sstevel@tonic-gate 	case T_LT:
8010Sstevel@tonic-gate 	case T_LE:
8020Sstevel@tonic-gate 	case T_GT:
8030Sstevel@tonic-gate 	case T_GE:
8040Sstevel@tonic-gate 	case T_BITAND:
8050Sstevel@tonic-gate 	case T_BITOR:
8060Sstevel@tonic-gate 	case T_BITXOR:
8070Sstevel@tonic-gate 	case T_BITNOT:
8080Sstevel@tonic-gate 	case T_LSHIFT:
8090Sstevel@tonic-gate 	case T_RSHIFT:
8100Sstevel@tonic-gate 	case T_NOT:
8110Sstevel@tonic-gate 	case T_ADD:
8120Sstevel@tonic-gate 	case T_SUB:
8130Sstevel@tonic-gate 	case T_MUL:
8140Sstevel@tonic-gate 	case T_DIV:
8150Sstevel@tonic-gate 	case T_MOD:
8160Sstevel@tonic-gate 		return (tree_expr(np->t,
8174436Sstephh 		    eval_dup(np->u.expr.left, ex, events),
8184436Sstephh 		    eval_dup(np->u.expr.right, ex, events)));
8194436Sstephh 	case T_LIST:
8204436Sstephh 	case T_AND:
8214436Sstephh 		switch (np->u.expr.temp) {
8224436Sstephh 		case EXPR_TEMP_LHS_UNK:
8234436Sstephh 			return (eval_dup(np->u.expr.left, ex, events));
8244436Sstephh 		case EXPR_TEMP_RHS_UNK:
8254436Sstephh 			return (eval_dup(np->u.expr.right, ex, events));
8264436Sstephh 		default:
8274436Sstephh 			return (tree_expr(np->t,
8284436Sstephh 			    eval_dup(np->u.expr.left, ex, events),
8294436Sstephh 			    eval_dup(np->u.expr.right, ex, events)));
8304436Sstephh 		}
8314436Sstephh 
8324436Sstephh 	case T_OR:
8334436Sstephh 		switch (np->u.expr.temp) {
8344436Sstephh 		case EXPR_TEMP_LHS_UNK:
8354436Sstephh 			return (eval_dup(np->u.expr.left, ex, events));
8364436Sstephh 		case EXPR_TEMP_RHS_UNK:
8374436Sstephh 			return (eval_dup(np->u.expr.right, ex, events));
8384436Sstephh 		default:
8394436Sstephh 			return (tree_expr(T_OR,
8404436Sstephh 			    eval_dup(np->u.expr.left, ex, events),
8414436Sstephh 			    eval_dup(np->u.expr.right, ex, events)));
8424436Sstephh 		}
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	case T_NAME: {
8450Sstevel@tonic-gate 		struct iterinfo *iterinfop;
8464436Sstephh 		int got_matchf = 0;
8474436Sstephh 		int got_matcht = 0;
8484436Sstephh 		struct evalue value;
8494436Sstephh 		struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
8504436Sstephh 		struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
8510Sstevel@tonic-gate 
8524436Sstephh 		/*
8534436Sstephh 		 * Check if we already have a match of the nonwildcarded path
8544436Sstephh 		 * in oldepname (check both to and from events).
8554436Sstephh 		 */
8564436Sstephh 		for (np1f = np, np2f = events[0]->u.event.oldepname;
8574436Sstephh 		    np1f != NULL && np2f != NULL;
8584436Sstephh 		    np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
8594436Sstephh 			if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
8604436Sstephh 				break;
8614436Sstephh 			if (np1f->u.name.child->t != np2f->u.name.child->t)
8624436Sstephh 				break;
8634436Sstephh 			if (np1f->u.name.child->t == T_NUM &&
8644436Sstephh 			    np1f->u.name.child->u.ull !=
8654436Sstephh 			    np2f->u.name.child->u.ull)
8664436Sstephh 				break;
8674436Sstephh 			if (np1f->u.name.child->t == T_NAME &&
8684436Sstephh 			    strcmp(np1f->u.name.child->u.name.s,
8694436Sstephh 			    np2f->u.name.child->u.name.s) != 0)
8704436Sstephh 				break;
8714436Sstephh 			got_matchf++;
8724436Sstephh 		}
8734436Sstephh 		for (np1t = np, np2t = events[1]->u.event.oldepname;
8744436Sstephh 		    np1t != NULL && np2t != NULL;
8754436Sstephh 		    np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
8764436Sstephh 			if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
8774436Sstephh 				break;
8784436Sstephh 			if (np1t->u.name.child->t != np2t->u.name.child->t)
8794436Sstephh 				break;
8804436Sstephh 			if (np1t->u.name.child->t == T_NUM &&
8814436Sstephh 			    np1t->u.name.child->u.ull !=
8824436Sstephh 			    np2t->u.name.child->u.ull)
8834436Sstephh 				break;
8844436Sstephh 			if (np1t->u.name.child->t == T_NAME &&
8854436Sstephh 			    strcmp(np1t->u.name.child->u.name.s,
8864436Sstephh 			    np2t->u.name.child->u.name.s) != 0)
8874436Sstephh 				break;
8884436Sstephh 			got_matcht++;
8894436Sstephh 		}
8904436Sstephh 		nprest = np;
8914436Sstephh 		if (got_matchf || got_matcht) {
8924436Sstephh 			/*
8934436Sstephh 			 * so we are wildcarding. Copy ewname in full, plus
8944436Sstephh 			 * matching section of oldepname. Use whichever gives
8954436Sstephh 			 * the closest match.
8964436Sstephh 			 */
8974436Sstephh 			if (got_matchf > got_matcht) {
8984436Sstephh 				npstart = events[0]->u.event.ewname;
8994436Sstephh 				npcont = events[0]->u.event.oldepname;
9004436Sstephh 				npend = np2f;
9014436Sstephh 				nprest = np1f;
9024436Sstephh 			} else {
9034436Sstephh 				npstart = events[1]->u.event.ewname;
9044436Sstephh 				npcont = events[1]->u.event.oldepname;
9054436Sstephh 				npend = np2t;
9064436Sstephh 				nprest = np1t;
9074436Sstephh 			}
9084436Sstephh 			for (npref = npstart; npref != NULL;
9094436Sstephh 			    npref = npref->u.name.next) {
9104436Sstephh 				newnp = newnode(T_NAME, np->file, np->line);
9114436Sstephh 				newnp->u.name.t = npref->u.name.t;
9124436Sstephh 				newnp->u.name.s = npref->u.name.s;
9134436Sstephh 				newnp->u.name.last = newnp;
9144436Sstephh 				newnp->u.name.it = npref->u.name.it;
9154436Sstephh 				newnp->u.name.cp = npref->u.name.cp;
9164436Sstephh 				newnp->u.name.child =
9174436Sstephh 				    newnode(T_NUM, np->file, np->line);
9184436Sstephh 				if (eval_expr(npref->u.name.child, ex, events,
9190Sstevel@tonic-gate 				    NULL, NULL, NULL, 1, &value) == 0 ||
9200Sstevel@tonic-gate 				    value.t != UINT64) {
9210Sstevel@tonic-gate 					outfl(O_DIE, np->file, np->line,
9220Sstevel@tonic-gate 					    "eval_dup: could not resolve "
9230Sstevel@tonic-gate 					    "iterator of %s", np->u.name.s);
9240Sstevel@tonic-gate 				}
9254436Sstephh 				newnp->u.name.child->u.ull = value.v;
9264436Sstephh 				if (retp == NULL) {
9274436Sstephh 					retp = newnp;
9284436Sstephh 				} else {
9294436Sstephh 					retp->u.name.last->u.name.next = newnp;
9304436Sstephh 					retp->u.name.last = newnp;
9314436Sstephh 				}
9320Sstevel@tonic-gate 			}
9334436Sstephh 			for (npref = npcont; npref != NULL && npref != npend;
9344436Sstephh 			    npref = npref->u.name.next) {
9354436Sstephh 				newnp = newnode(T_NAME, np->file, np->line);
9364436Sstephh 				newnp->u.name.t = npref->u.name.t;
9374436Sstephh 				newnp->u.name.s = npref->u.name.s;
9384436Sstephh 				newnp->u.name.last = newnp;
9394436Sstephh 				newnp->u.name.it = npref->u.name.it;
9404436Sstephh 				newnp->u.name.cp = npref->u.name.cp;
9414436Sstephh 				newnp->u.name.child =
9424436Sstephh 				    newnode(T_NUM, np->file, np->line);
9434436Sstephh 				if (eval_expr(npref->u.name.child, ex, events,
9444436Sstephh 				    NULL, NULL, NULL, 1, &value) == 0 ||
9454436Sstephh 				    value.t != UINT64) {
9464436Sstephh 					outfl(O_DIE, np->file, np->line,
9474436Sstephh 					    "eval_dup: could not resolve "
9484436Sstephh 					    "iterator of %s", np->u.name.s);
9494436Sstephh 				}
9504436Sstephh 				newnp->u.name.child->u.ull = value.v;
9514436Sstephh 				if (retp == NULL) {
9524436Sstephh 					retp = newnp;
9534436Sstephh 				} else {
9544436Sstephh 					retp->u.name.last->u.name.next = newnp;
9554436Sstephh 					retp->u.name.last = newnp;
9564436Sstephh 				}
9574436Sstephh 			}
9584436Sstephh 		} else {
9594436Sstephh 			/*
9604436Sstephh 			 * not wildcarding - check if explicit iterator
9614436Sstephh 			 */
9624436Sstephh 			iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
9634436Sstephh 			if (iterinfop != NULL) {
9644436Sstephh 				/* explicit iterator; not part of pathname */
9654436Sstephh 				newnp = newnode(T_NUM, np->file, np->line);
9664436Sstephh 				newnp->u.ull = iterinfop->num;
9670Sstevel@tonic-gate 				return (newnp);
9680Sstevel@tonic-gate 			}
9690Sstevel@tonic-gate 		}
9704436Sstephh 
9714436Sstephh 		/*
9724436Sstephh 		 * finally, whether wildcarding or not, we need to copy the
9734436Sstephh 		 * remaining part of the path (if any). This must be defined
9744436Sstephh 		 * absolutely (no more expansion/wildcarding).
9754436Sstephh 		 */
9764436Sstephh 		for (npref = nprest; npref != NULL;
9774436Sstephh 		    npref = npref->u.name.next) {
9784436Sstephh 			newnp = newnode(T_NAME, np->file, np->line);
9794436Sstephh 			newnp->u.name.t = npref->u.name.t;
9804436Sstephh 			newnp->u.name.s = npref->u.name.s;
9814436Sstephh 			newnp->u.name.last = newnp;
9824436Sstephh 			newnp->u.name.it = npref->u.name.it;
9834436Sstephh 			newnp->u.name.cp = npref->u.name.cp;
9844436Sstephh 			newnp->u.name.child =
9854436Sstephh 			    newnode(T_NUM, np->file, np->line);
9864436Sstephh 			if (eval_expr(npref->u.name.child, ex, events,
9874436Sstephh 			    NULL, NULL, NULL, 1, &value) == 0 ||
9884436Sstephh 			    value.t != UINT64) {
9894436Sstephh 				outfl(O_DIE, np->file, np->line,
9904436Sstephh 				    "eval_dup: could not resolve "
9914436Sstephh 				    "iterator of %s", np->u.name.s);
9924436Sstephh 			}
9934436Sstephh 			newnp->u.name.child->u.ull = value.v;
9944436Sstephh 			if (retp == NULL) {
9954436Sstephh 				retp = newnp;
9964436Sstephh 			} else {
9974436Sstephh 				retp->u.name.last->u.name.next = newnp;
9984436Sstephh 				retp->u.name.last = newnp;
9994436Sstephh 			}
10004436Sstephh 		}
10014436Sstephh 		return (retp);
10020Sstevel@tonic-gate 	}
10030Sstevel@tonic-gate 
10041414Scindi 	case T_EVENT:
10051414Scindi 		newnp = newnode(T_NAME, np->file, np->line);
10061414Scindi 
10071414Scindi 		newnp->u.name.t = np->u.event.ename->u.name.t;
10081414Scindi 		newnp->u.name.s = np->u.event.ename->u.name.s;
10091414Scindi 		newnp->u.name.it = np->u.event.ename->u.name.it;
10101414Scindi 		newnp->u.name.last = newnp;
10111414Scindi 
10121414Scindi 		return (tree_event(newnp,
10134436Sstephh 		    eval_dup(np->u.event.epname, ex, events),
10144436Sstephh 		    eval_dup(np->u.event.eexprlist, ex, events)));
10151414Scindi 
10160Sstevel@tonic-gate 	case T_FUNC:
10170Sstevel@tonic-gate 		return (tree_func(np->u.func.s,
10184436Sstephh 		    eval_dup(np->u.func.arglist, ex, events),
10190Sstevel@tonic-gate 		    np->file, np->line));
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	case T_QUOTE:
10220Sstevel@tonic-gate 		newnp = newnode(T_QUOTE, np->file, np->line);
10230Sstevel@tonic-gate 		newnp->u.quote.s = np->u.quote.s;
10240Sstevel@tonic-gate 		return (newnp);
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate 	case T_NUM:
10270Sstevel@tonic-gate 		newnp = newnode(T_NUM, np->file, np->line);
10280Sstevel@tonic-gate 		newnp->u.ull = np->u.ull;
10290Sstevel@tonic-gate 		return (newnp);
10300Sstevel@tonic-gate 
1031*7197Sstephh 	case T_TIMEVAL:
1032*7197Sstephh 		newnp = newnode(T_TIMEVAL, np->file, np->line);
1033*7197Sstephh 		newnp->u.ull = np->u.ull;
1034*7197Sstephh 		return (newnp);
1035*7197Sstephh 
10360Sstevel@tonic-gate 	default:
10370Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
10380Sstevel@tonic-gate 		    "eval_dup: unexpected node type: %s",
10390Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
10400Sstevel@tonic-gate 	}
10410Sstevel@tonic-gate 	/*NOTREACHED*/
10421717Swesolows 	return (0);
10430Sstevel@tonic-gate }
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate /*
10460Sstevel@tonic-gate  * eval_potential -- see if constraint is potentially true
10470Sstevel@tonic-gate  *
10480Sstevel@tonic-gate  * this function is used at instance tree creation time to see if
10490Sstevel@tonic-gate  * any constraints are already known to be false.  if this function
10500Sstevel@tonic-gate  * returns false, then the constraint will always be false and there's
10510Sstevel@tonic-gate  * no need to include the propagation arrow in the instance tree.
10520Sstevel@tonic-gate  *
10530Sstevel@tonic-gate  * if this routine returns true, either the constraint is known to
10540Sstevel@tonic-gate  * be always true (so there's no point in attaching the constraint
10550Sstevel@tonic-gate  * to the propagation arrow in the instance tree), or the constraint
10560Sstevel@tonic-gate  * contains "deferred" expressions like global variables or poller calls
10570Sstevel@tonic-gate  * and so it must be evaluated during calls to fme_eval().  in this last
10580Sstevel@tonic-gate  * case, where a constraint needs to be attached to the propagation arrow
10590Sstevel@tonic-gate  * in the instance tree, this routine returns a newly created constraint
10600Sstevel@tonic-gate  * in *newc where all the non-deferred things have been filled in.
10610Sstevel@tonic-gate  *
10620Sstevel@tonic-gate  * so in summary:
10630Sstevel@tonic-gate  *
10640Sstevel@tonic-gate  *	return of false: constraint can never be true, *newc will be NULL.
10650Sstevel@tonic-gate  *
10660Sstevel@tonic-gate  *	return of true with *newc unchanged: constraint will always be true.
10670Sstevel@tonic-gate  *
10680Sstevel@tonic-gate  *	return of true with *newc changed: use new constraint in *newc.
10690Sstevel@tonic-gate  *
10700Sstevel@tonic-gate  * the lookup table for all explicit iterators, ex, is passed in.
10710Sstevel@tonic-gate  *
10720Sstevel@tonic-gate  * *newc can either be NULL on entry, or if can contain constraints from
10730Sstevel@tonic-gate  * previous calls to eval_potential() (i.e. for building up an instance
10740Sstevel@tonic-gate  * tree constraint from several potential constraints).  if *newc already
10750Sstevel@tonic-gate  * contains constraints, anything added to it will be joined by adding
10760Sstevel@tonic-gate  * a T_AND node at the top of *newc.
10770Sstevel@tonic-gate  */
10780Sstevel@tonic-gate int
10794436Sstephh eval_potential(struct node *np, struct lut *ex, struct node *events[],
10802318Sstephh 	    struct node **newc, struct config *croot)
10810Sstevel@tonic-gate {
10820Sstevel@tonic-gate 	struct node *newnp;
10830Sstevel@tonic-gate 	struct evalue value;
10840Sstevel@tonic-gate 
10854436Sstephh 	if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
10860Sstevel@tonic-gate 		/*
10870Sstevel@tonic-gate 		 * couldn't eval expression because
10880Sstevel@tonic-gate 		 * it contains deferred items.  make
10890Sstevel@tonic-gate 		 * a duplicate expression with all the
10900Sstevel@tonic-gate 		 * non-deferred items expanded.
10910Sstevel@tonic-gate 		 */
10924436Sstephh 		newnp = eval_dup(np, ex, events);
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 		if (*newc == NULL) {
10950Sstevel@tonic-gate 			/*
10960Sstevel@tonic-gate 			 * constraint is potentially true if deferred
10970Sstevel@tonic-gate 			 * expression in newnp is true.  *newc was NULL
10980Sstevel@tonic-gate 			 * so new constraint is just the one in newnp.
10990Sstevel@tonic-gate 			 */
11000Sstevel@tonic-gate 			*newc = newnp;
11010Sstevel@tonic-gate 			return (1);
11020Sstevel@tonic-gate 		} else {
11030Sstevel@tonic-gate 			/*
11040Sstevel@tonic-gate 			 * constraint is potentially true if deferred
11050Sstevel@tonic-gate 			 * expression in newnp is true.  *newc already
11060Sstevel@tonic-gate 			 * contained a constraint so add an AND with the
11070Sstevel@tonic-gate 			 * constraint in newnp.
11080Sstevel@tonic-gate 			 */
11090Sstevel@tonic-gate 			*newc = tree_expr(T_AND, *newc, newnp);
11100Sstevel@tonic-gate 			return (1);
11110Sstevel@tonic-gate 		}
11120Sstevel@tonic-gate 	} else if (value.t == UNDEFINED) {
11130Sstevel@tonic-gate 		/* constraint can never be true */
11140Sstevel@tonic-gate 		return (0);
11150Sstevel@tonic-gate 	} else if (value.t == UINT64 && value.v == 0) {
11160Sstevel@tonic-gate 		/* constraint can never be true */
11170Sstevel@tonic-gate 		return (0);
11180Sstevel@tonic-gate 	} else {
11190Sstevel@tonic-gate 		/* constraint is always true (nothing deferred to eval) */
11200Sstevel@tonic-gate 		return (1);
11210Sstevel@tonic-gate 	}
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate static int
11250Sstevel@tonic-gate check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
11260Sstevel@tonic-gate 		struct node *np)
11270Sstevel@tonic-gate {
11281414Scindi 	/* auto-convert T_NAMES to strings */
11291717Swesolows 	if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
11301717Swesolows 	    T_NAME) {
11311717Swesolows 		char *s = ipath2str(NULL,
11321717Swesolows 		    ipath((struct node *)(uintptr_t)lp->v));
11331414Scindi 		lp->t = STRING;
11341717Swesolows 		lp->v = (uintptr_t)stable(s);
11351414Scindi 		FREE(s);
11361414Scindi 		out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
11371717Swesolows 		    (char *)(uintptr_t)lp->v);
11381414Scindi 	}
11391414Scindi 	if (rp != NULL &&
11401717Swesolows 	    rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
11411717Swesolows 	    T_NAME) {
11421717Swesolows 		char *s = ipath2str(NULL,
11431717Swesolows 		    ipath((struct node *)(uintptr_t)rp->v));
11441414Scindi 		rp->t = STRING;
11451717Swesolows 		rp->v = (uintptr_t)stable(s);
11461414Scindi 		FREE(s);
11471414Scindi 		out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
11481717Swesolows 		    (char *)(uintptr_t)rp->v);
11491414Scindi 	}
11501414Scindi 
11511414Scindi 	/* auto-convert strings to numbers */
11521414Scindi 	if (dtype == UINT64) {
11531414Scindi 		if (lp->t == STRING) {
11541414Scindi 			lp->t = UINT64;
11551717Swesolows 			lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
11561414Scindi 		}
11571414Scindi 		if (rp != NULL && rp->t == STRING) {
11581414Scindi 			rp->t = UINT64;
11591717Swesolows 			rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
11601414Scindi 		}
11611414Scindi 	}
11621414Scindi 
11630Sstevel@tonic-gate 	if (dtype != UNDEFINED && lp->t != dtype) {
11644436Sstephh 		outfl(O_DIE, np->file, np->line,
11654436Sstephh 		    "invalid datatype of argument for operation %s",
11664436Sstephh 		    ptree_nodetype2str(np->t));
11674436Sstephh 		/* NOTREACHED */
11680Sstevel@tonic-gate 		return (1);
11690Sstevel@tonic-gate 	}
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate 	if (rp != NULL && lp->t != rp->t) {
11724436Sstephh 		outfl(O_DIE, np->file, np->line,
11734436Sstephh 		    "mismatch in datatype of arguments for operation %s",
11744436Sstephh 		    ptree_nodetype2str(np->t));
11754436Sstephh 		/* NOTREACHED */
11760Sstevel@tonic-gate 		return (1);
11770Sstevel@tonic-gate 	}
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	return (0);
11800Sstevel@tonic-gate }
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate /*
11830Sstevel@tonic-gate  * eval_expr -- evaluate expression into *valuep
11840Sstevel@tonic-gate  *
11850Sstevel@tonic-gate  * the meaning of the return value depends on the input value of try.
11860Sstevel@tonic-gate  *
11870Sstevel@tonic-gate  * for try == 1: if any deferred items are encounted, bail out and return
11880Sstevel@tonic-gate  * false.  returns true if we made it through entire expression without
11890Sstevel@tonic-gate  * hitting any deferred items.
11900Sstevel@tonic-gate  *
11910Sstevel@tonic-gate  * for try == 0: return true if all operations were performed successfully.
11920Sstevel@tonic-gate  * return false if otherwise.  for example, any of the following conditions
11930Sstevel@tonic-gate  * will result in a false return value:
11940Sstevel@tonic-gate  *   - attempted use of an uninitialized global variable
11950Sstevel@tonic-gate  *   - failure in function evaluation
11960Sstevel@tonic-gate  *   - illegal arithmetic operation (argument out of range)
11970Sstevel@tonic-gate  */
11980Sstevel@tonic-gate int
11994436Sstephh eval_expr(struct node *np, struct lut *ex, struct node *events[],
12000Sstevel@tonic-gate 	struct lut **globals, struct config *croot, struct arrow *arrowp,
12010Sstevel@tonic-gate 	int try, struct evalue *valuep)
12020Sstevel@tonic-gate {
12030Sstevel@tonic-gate 	struct evalue *gval;
12040Sstevel@tonic-gate 	struct evalue lval;
12050Sstevel@tonic-gate 	struct evalue rval;
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	if (np == NULL) {
12080Sstevel@tonic-gate 		valuep->t = UINT64;
12090Sstevel@tonic-gate 		valuep->v = 1;	/* no constraint means "true" */
12100Sstevel@tonic-gate 		return (1);
12110Sstevel@tonic-gate 	}
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 	valuep->t = UNDEFINED;
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 	switch (np->t) {
12160Sstevel@tonic-gate 	case T_GLOBID:
12170Sstevel@tonic-gate 		if (try)
12180Sstevel@tonic-gate 			return (0);
12190Sstevel@tonic-gate 
12200Sstevel@tonic-gate 		/*
12210Sstevel@tonic-gate 		 * only handle case of getting (and not setting) the value
12220Sstevel@tonic-gate 		 * of a global variable
12230Sstevel@tonic-gate 		 */
12240Sstevel@tonic-gate 		gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
12250Sstevel@tonic-gate 		if (gval == NULL) {
12260Sstevel@tonic-gate 			return (0);
12270Sstevel@tonic-gate 		} else {
12280Sstevel@tonic-gate 			valuep->t = gval->t;
12290Sstevel@tonic-gate 			valuep->v = gval->v;
12300Sstevel@tonic-gate 			return (1);
12310Sstevel@tonic-gate 		}
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 	case T_ASSIGN:
12340Sstevel@tonic-gate 		if (try)
12350Sstevel@tonic-gate 			return (0);
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 		/*
12380Sstevel@tonic-gate 		 * first evaluate rhs, then try to store value in lhs which
12390Sstevel@tonic-gate 		 * should be a global variable
12400Sstevel@tonic-gate 		 */
12414436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
12424436Sstephh 		    arrowp, try, &rval))
12430Sstevel@tonic-gate 			return (0);
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 		ASSERT(np->u.expr.left->t == T_GLOBID);
12460Sstevel@tonic-gate 		gval = lut_lookup(*globals,
12474436Sstephh 		    (void *)np->u.expr.left->u.globid.s, NULL);
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 		if (gval == NULL) {
12500Sstevel@tonic-gate 			gval = MALLOC(sizeof (*gval));
12510Sstevel@tonic-gate 			*globals = lut_add(*globals,
12524436Sstephh 			    (void *) np->u.expr.left->u.globid.s, gval, NULL);
12530Sstevel@tonic-gate 		}
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 		gval->t = rval.t;
12560Sstevel@tonic-gate 		gval->v = rval.v;
12571414Scindi 
12581414Scindi 		if (gval->t == UINT64) {
12591414Scindi 			out(O_ALTFP|O_VERB2,
12601414Scindi 			    "assign $%s=%llu",
12611414Scindi 			    np->u.expr.left->u.globid.s, gval->v);
12621414Scindi 		} else {
12631414Scindi 			out(O_ALTFP|O_VERB2,
12641414Scindi 			    "assign $%s=\"%s\"",
12651717Swesolows 			    np->u.expr.left->u.globid.s,
12661717Swesolows 			    (char *)(uintptr_t)gval->v);
12671414Scindi 		}
12681414Scindi 
12691414Scindi 		/*
12701414Scindi 		 * but always return true -- an assignment should not
12711414Scindi 		 * cause a constraint to be false.
12721414Scindi 		 */
12731414Scindi 		valuep->t = UINT64;
12741414Scindi 		valuep->v = 1;
12750Sstevel@tonic-gate 		return (1);
12760Sstevel@tonic-gate 
12770Sstevel@tonic-gate 	case T_EQ:
12780Sstevel@tonic-gate #define	IMPLICIT_ASSIGN_IN_EQ
12790Sstevel@tonic-gate #ifdef IMPLICIT_ASSIGN_IN_EQ
12800Sstevel@tonic-gate 		/*
12810Sstevel@tonic-gate 		 * if lhs is an uninitialized global variable, perform
12820Sstevel@tonic-gate 		 * an assignment.
12830Sstevel@tonic-gate 		 *
12840Sstevel@tonic-gate 		 * one insidious side effect of implicit assignment is
12850Sstevel@tonic-gate 		 * that the "==" operator does not return a Boolean if
12860Sstevel@tonic-gate 		 * implicit assignment was performed.
12870Sstevel@tonic-gate 		 */
12880Sstevel@tonic-gate 		if (try == 0 &&
12890Sstevel@tonic-gate 		    np->u.expr.left->t == T_GLOBID &&
12900Sstevel@tonic-gate 		    (gval = lut_lookup(*globals,
12914436Sstephh 		    (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
12924436Sstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
12934436Sstephh 			    croot, arrowp, try, &rval))
12940Sstevel@tonic-gate 				return (0);
12950Sstevel@tonic-gate 
12960Sstevel@tonic-gate 			gval = MALLOC(sizeof (*gval));
12970Sstevel@tonic-gate 			*globals = lut_add(*globals,
12984436Sstephh 			    (void *) np->u.expr.left->u.globid.s,
12994436Sstephh 			    gval, NULL);
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 			gval->t = rval.t;
13020Sstevel@tonic-gate 			gval->v = rval.v;
13030Sstevel@tonic-gate 			valuep->t = rval.t;
13040Sstevel@tonic-gate 			valuep->v = rval.v;
13050Sstevel@tonic-gate 			return (1);
13060Sstevel@tonic-gate 		}
13070Sstevel@tonic-gate #endif  /* IMPLICIT_ASSIGN_IN_EQ */
13080Sstevel@tonic-gate 
13094436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13104436Sstephh 		    arrowp, try, &lval))
13114436Sstephh 			return (0);
13124436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
13134436Sstephh 		    arrowp, try, &rval))
13140Sstevel@tonic-gate 			return (0);
13154436Sstephh 		if (rval.t == UINT64 || lval.t == UINT64) {
13164436Sstephh 			if (check_expr_args(&lval, &rval, UINT64, np))
13174436Sstephh 				return (0);
13184436Sstephh 		} else {
13194436Sstephh 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
13204436Sstephh 				return (0);
13214436Sstephh 		}
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate 		valuep->t = UINT64;
13240Sstevel@tonic-gate 		valuep->v = (lval.v == rval.v);
13250Sstevel@tonic-gate 		return (1);
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 	case T_LT:
13284436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13294436Sstephh 		    arrowp, try, &lval))
13300Sstevel@tonic-gate 			return (0);
13314436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
13324436Sstephh 		    arrowp, try, &rval))
13330Sstevel@tonic-gate 			return (0);
13341414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
13350Sstevel@tonic-gate 			return (0);
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 		valuep->t = UINT64;
13380Sstevel@tonic-gate 		valuep->v = (lval.v < rval.v);
13390Sstevel@tonic-gate 		return (1);
13400Sstevel@tonic-gate 
13410Sstevel@tonic-gate 	case T_LE:
13424436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13434436Sstephh 		    arrowp, try, &lval))
13440Sstevel@tonic-gate 			return (0);
13454436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
13464436Sstephh 		    arrowp, try, &rval))
13470Sstevel@tonic-gate 			return (0);
13481414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
13490Sstevel@tonic-gate 			return (0);
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 		valuep->t = UINT64;
13520Sstevel@tonic-gate 		valuep->v = (lval.v <= rval.v);
13530Sstevel@tonic-gate 		return (1);
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 	case T_GT:
13564436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13574436Sstephh 		    arrowp, try, &lval))
13580Sstevel@tonic-gate 			return (0);
13594436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
13604436Sstephh 		    arrowp, try, &rval))
13610Sstevel@tonic-gate 			return (0);
13621414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
13630Sstevel@tonic-gate 			return (0);
13640Sstevel@tonic-gate 
13650Sstevel@tonic-gate 		valuep->t = UINT64;
13660Sstevel@tonic-gate 		valuep->v = (lval.v > rval.v);
13670Sstevel@tonic-gate 		return (1);
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	case T_GE:
13704436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13714436Sstephh 		    arrowp, try, &lval))
13720Sstevel@tonic-gate 			return (0);
13734436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
13744436Sstephh 		    arrowp, try, &rval))
13750Sstevel@tonic-gate 			return (0);
13761414Scindi 		if (check_expr_args(&lval, &rval, UINT64, np))
13770Sstevel@tonic-gate 			return (0);
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate 		valuep->t = UINT64;
13800Sstevel@tonic-gate 		valuep->v = (lval.v >= rval.v);
13810Sstevel@tonic-gate 		return (1);
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 	case T_BITAND:
13844436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13854436Sstephh 		    arrowp, try, &lval))
13860Sstevel@tonic-gate 			return (0);
13874436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
13884436Sstephh 		    arrowp, try, &rval))
13890Sstevel@tonic-gate 			return (0);
13900Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
13910Sstevel@tonic-gate 			return (0);
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 		valuep->t = lval.t;
13940Sstevel@tonic-gate 		valuep->v = (lval.v & rval.v);
13950Sstevel@tonic-gate 		return (1);
13960Sstevel@tonic-gate 
13970Sstevel@tonic-gate 	case T_BITOR:
13984436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
13994436Sstephh 		    arrowp, try, &lval))
14000Sstevel@tonic-gate 			return (0);
14014436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14024436Sstephh 		    arrowp, try, &rval))
14030Sstevel@tonic-gate 			return (0);
14040Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
14050Sstevel@tonic-gate 			return (0);
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate 		valuep->t = lval.t;
14080Sstevel@tonic-gate 		valuep->v = (lval.v | rval.v);
14090Sstevel@tonic-gate 		return (1);
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	case T_BITXOR:
14124436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14134436Sstephh 		    arrowp, try, &lval))
14140Sstevel@tonic-gate 			return (0);
14154436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14164436Sstephh 		    arrowp, try, &rval))
14170Sstevel@tonic-gate 			return (0);
14180Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
14190Sstevel@tonic-gate 			return (0);
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 		valuep->t = lval.t;
14220Sstevel@tonic-gate 		valuep->v = (lval.v ^ rval.v);
14230Sstevel@tonic-gate 		return (1);
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate 	case T_BITNOT:
14264436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14274436Sstephh 		    arrowp, try, &lval))
14280Sstevel@tonic-gate 			return (0);
14290Sstevel@tonic-gate 		ASSERT(np->u.expr.right == NULL);
14300Sstevel@tonic-gate 		if (check_expr_args(&lval, NULL, UINT64, np))
14310Sstevel@tonic-gate 			return (0);
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate 		valuep->t = UINT64;
14340Sstevel@tonic-gate 		valuep->v = ~ lval.v;
14350Sstevel@tonic-gate 		return (1);
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate 	case T_LSHIFT:
14384436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14394436Sstephh 		    arrowp, try, &lval))
14400Sstevel@tonic-gate 			return (0);
14414436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14424436Sstephh 		    arrowp, try, &rval))
14430Sstevel@tonic-gate 			return (0);
14440Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
14450Sstevel@tonic-gate 			return (0);
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 		valuep->t = UINT64;
14480Sstevel@tonic-gate 		valuep->v = (lval.v << rval.v);
14490Sstevel@tonic-gate 		return (1);
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	case T_RSHIFT:
14524436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14534436Sstephh 		    arrowp, try, &lval))
14540Sstevel@tonic-gate 			return (0);
14554436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
14564436Sstephh 		    arrowp, try, &rval))
14570Sstevel@tonic-gate 			return (0);
14580Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
14590Sstevel@tonic-gate 			return (0);
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate 		valuep->t = UINT64;
14620Sstevel@tonic-gate 		valuep->v = (lval.v >> rval.v);
14630Sstevel@tonic-gate 		return (1);
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate 	case T_CONDIF: {
14660Sstevel@tonic-gate 		struct node *retnp;
14670Sstevel@tonic-gate 		int dotrue = 0;
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 		/*
14700Sstevel@tonic-gate 		 * evaluate
14710Sstevel@tonic-gate 		 *	expression ? stmtA [ : stmtB ]
14720Sstevel@tonic-gate 		 *
14730Sstevel@tonic-gate 		 * first see if expression is true or false, then determine
14740Sstevel@tonic-gate 		 * if stmtA (or stmtB, if it exists) should be evaluated.
14750Sstevel@tonic-gate 		 *
14760Sstevel@tonic-gate 		 * "dotrue = 1" means stmtA should be evaluated.
14770Sstevel@tonic-gate 		 */
14785204Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
14795204Sstephh 		    arrowp, try, &lval))
14805204Sstephh 			return (0);
14815204Sstephh 
14825204Sstephh 		if (lval.t != UNDEFINED && lval.v != 0)
14830Sstevel@tonic-gate 			dotrue = 1;
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 		ASSERT(np->u.expr.right != NULL);
14860Sstevel@tonic-gate 		if (np->u.expr.right->t == T_CONDELSE) {
14870Sstevel@tonic-gate 			if (dotrue)
14880Sstevel@tonic-gate 				retnp = np->u.expr.right->u.expr.left;
14890Sstevel@tonic-gate 			else
14900Sstevel@tonic-gate 				retnp = np->u.expr.right->u.expr.right;
14910Sstevel@tonic-gate 		} else {
14920Sstevel@tonic-gate 			/* no ELSE clause */
14930Sstevel@tonic-gate 			if (dotrue)
14940Sstevel@tonic-gate 				retnp = np->u.expr.right;
14950Sstevel@tonic-gate 			else {
14964436Sstephh 				outfl(O_DIE, np->file, np->line,
14974436Sstephh 				    "eval_expr: missing condelse");
14980Sstevel@tonic-gate 			}
14990Sstevel@tonic-gate 		}
15000Sstevel@tonic-gate 
15014436Sstephh 		if (!eval_expr(retnp, ex, events, globals, croot,
15024436Sstephh 		    arrowp, try, valuep))
15030Sstevel@tonic-gate 			return (0);
15040Sstevel@tonic-gate 		return (1);
15050Sstevel@tonic-gate 	}
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate 	case T_CONDELSE:
15080Sstevel@tonic-gate 		/*
15090Sstevel@tonic-gate 		 * shouldn't get here, since T_CONDELSE is supposed to be
15100Sstevel@tonic-gate 		 * evaluated as part of T_CONDIF
15110Sstevel@tonic-gate 		 */
15120Sstevel@tonic-gate 		out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
15130Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
15144436Sstephh 		/*NOTREACHED*/
15150Sstevel@tonic-gate 
15160Sstevel@tonic-gate 	case T_NE:
15174436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15184436Sstephh 		    arrowp, try, &lval))
15194436Sstephh 			return (0);
15204436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15214436Sstephh 		    arrowp, try, &rval))
15220Sstevel@tonic-gate 			return (0);
15234436Sstephh 		if (rval.t == UINT64 || lval.t == UINT64) {
15244436Sstephh 			if (check_expr_args(&lval, &rval, UINT64, np))
15254436Sstephh 				return (0);
15264436Sstephh 		} else {
15274436Sstephh 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
15284436Sstephh 				return (0);
15294436Sstephh 		}
15300Sstevel@tonic-gate 
15310Sstevel@tonic-gate 		valuep->t = UINT64;
15320Sstevel@tonic-gate 		valuep->v = (lval.v != rval.v);
15330Sstevel@tonic-gate 		return (1);
15340Sstevel@tonic-gate 
15350Sstevel@tonic-gate 	case T_LIST:
15360Sstevel@tonic-gate 	case T_AND:
15374436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15384436Sstephh 		    arrowp, try, valuep)) {
15393159Sstephh 			/*
15403159Sstephh 			 * if lhs is unknown, still check rhs. If that
15415204Sstephh 			 * is false we can return false irrespective of lhs
15423159Sstephh 			 */
15435204Sstephh 			if (!try) {
15445204Sstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
15455204Sstephh 				return (0);
15465204Sstephh 			}
15474436Sstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
15484436Sstephh 			    croot, arrowp, try, valuep)) {
15494436Sstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
15503159Sstephh 				return (0);
15514436Sstephh 			}
15524436Sstephh 			if (valuep->v != 0) {
15534436Sstephh 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
15543159Sstephh 				return (0);
15554436Sstephh 			}
15563159Sstephh 		}
15570Sstevel@tonic-gate 		if (valuep->v == 0) {
15580Sstevel@tonic-gate 			valuep->t = UINT64;
15590Sstevel@tonic-gate 			return (1);
15600Sstevel@tonic-gate 		}
15614436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15624436Sstephh 		    arrowp, try, valuep)) {
15634436Sstephh 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
15640Sstevel@tonic-gate 			return (0);
15654436Sstephh 		}
15660Sstevel@tonic-gate 		valuep->t = UINT64;
15670Sstevel@tonic-gate 		valuep->v = valuep->v == 0 ? 0 : 1;
15680Sstevel@tonic-gate 		return (1);
15690Sstevel@tonic-gate 
15700Sstevel@tonic-gate 	case T_OR:
15714436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
15724436Sstephh 		    arrowp, try, valuep)) {
15733159Sstephh 			/*
15743159Sstephh 			 * if lhs is unknown, still check rhs. If that
15755204Sstephh 			 * is true we can return true irrespective of lhs
15763159Sstephh 			 */
15775204Sstephh 			if (!try) {
15785204Sstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
15795204Sstephh 				return (0);
15805204Sstephh 			}
15814436Sstephh 			if (!eval_expr(np->u.expr.right, ex, events, globals,
15824436Sstephh 			    croot, arrowp, try, valuep)) {
15834436Sstephh 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
15843159Sstephh 				return (0);
15854436Sstephh 			}
15864436Sstephh 			if (valuep->v == 0) {
15874436Sstephh 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
15883159Sstephh 				return (0);
15894436Sstephh 			}
15903159Sstephh 		}
15910Sstevel@tonic-gate 		if (valuep->v != 0) {
15920Sstevel@tonic-gate 			valuep->t = UINT64;
15930Sstevel@tonic-gate 			valuep->v = 1;
15940Sstevel@tonic-gate 			return (1);
15950Sstevel@tonic-gate 		}
15964436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
15974436Sstephh 		    arrowp, try, valuep)) {
15984436Sstephh 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
15990Sstevel@tonic-gate 			return (0);
16004436Sstephh 		}
16010Sstevel@tonic-gate 		valuep->t = UINT64;
16020Sstevel@tonic-gate 		valuep->v = valuep->v == 0 ? 0 : 1;
16030Sstevel@tonic-gate 		return (1);
16040Sstevel@tonic-gate 
16050Sstevel@tonic-gate 	case T_NOT:
16064436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16074436Sstephh 		    arrowp, try, valuep))
16080Sstevel@tonic-gate 			return (0);
16090Sstevel@tonic-gate 		valuep->t = UINT64;
16100Sstevel@tonic-gate 		valuep->v = ! valuep->v;
16110Sstevel@tonic-gate 		return (1);
16120Sstevel@tonic-gate 
16130Sstevel@tonic-gate 	case T_ADD:
16144436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16154436Sstephh 		    arrowp, try, &lval))
16160Sstevel@tonic-gate 			return (0);
16174436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16184436Sstephh 		    arrowp, try, &rval))
16190Sstevel@tonic-gate 			return (0);
16200Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16210Sstevel@tonic-gate 			return (0);
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 		valuep->t = lval.t;
16240Sstevel@tonic-gate 		valuep->v = lval.v + rval.v;
16250Sstevel@tonic-gate 		return (1);
16260Sstevel@tonic-gate 
16270Sstevel@tonic-gate 	case T_SUB:
16284436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16294436Sstephh 		    arrowp, try, &lval))
16300Sstevel@tonic-gate 			return (0);
16314436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16324436Sstephh 		    arrowp, try, &rval))
16330Sstevel@tonic-gate 			return (0);
16340Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16350Sstevel@tonic-gate 			return (0);
16360Sstevel@tonic-gate 
16370Sstevel@tonic-gate 		/* since valuep is unsigned, return false if lval.v < rval.v */
16380Sstevel@tonic-gate 		if (lval.v < rval.v) {
16394436Sstephh 			outfl(O_DIE, np->file, np->line,
16404436Sstephh 			    "eval_expr: T_SUB result is out of range");
16410Sstevel@tonic-gate 		}
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate 		valuep->t = lval.t;
16440Sstevel@tonic-gate 		valuep->v = lval.v - rval.v;
16450Sstevel@tonic-gate 		return (1);
16460Sstevel@tonic-gate 
16470Sstevel@tonic-gate 	case T_MUL:
16484436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16494436Sstephh 		    arrowp, try, &lval))
16500Sstevel@tonic-gate 			return (0);
16514436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16524436Sstephh 		    arrowp, try, &rval))
16530Sstevel@tonic-gate 			return (0);
16540Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16550Sstevel@tonic-gate 			return (0);
16560Sstevel@tonic-gate 
16570Sstevel@tonic-gate 		valuep->t = lval.t;
16580Sstevel@tonic-gate 		valuep->v = lval.v * rval.v;
16590Sstevel@tonic-gate 		return (1);
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate 	case T_DIV:
16624436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16634436Sstephh 		    arrowp, try, &lval))
16640Sstevel@tonic-gate 			return (0);
16654436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16664436Sstephh 		    arrowp, try, &rval))
16670Sstevel@tonic-gate 			return (0);
16680Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16690Sstevel@tonic-gate 			return (0);
16700Sstevel@tonic-gate 
16710Sstevel@tonic-gate 		/* return false if dividing by zero */
16720Sstevel@tonic-gate 		if (rval.v == 0) {
16734436Sstephh 			outfl(O_DIE, np->file, np->line,
16744436Sstephh 			    "eval_expr: T_DIV division by zero");
16750Sstevel@tonic-gate 		}
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate 		valuep->t = lval.t;
16780Sstevel@tonic-gate 		valuep->v = lval.v / rval.v;
16790Sstevel@tonic-gate 		return (1);
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 	case T_MOD:
16824436Sstephh 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
16834436Sstephh 		    arrowp, try, &lval))
16840Sstevel@tonic-gate 			return (0);
16854436Sstephh 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
16864436Sstephh 		    arrowp, try, &rval))
16870Sstevel@tonic-gate 			return (0);
16880Sstevel@tonic-gate 		if (check_expr_args(&lval, &rval, UINT64, np))
16890Sstevel@tonic-gate 			return (0);
16900Sstevel@tonic-gate 
16910Sstevel@tonic-gate 		/* return false if dividing by zero */
16920Sstevel@tonic-gate 		if (rval.v == 0) {
16934436Sstephh 			outfl(O_DIE, np->file, np->line,
16944436Sstephh 			    "eval_expr: T_MOD division by zero");
16950Sstevel@tonic-gate 		}
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate 		valuep->t = lval.t;
16980Sstevel@tonic-gate 		valuep->v = lval.v % rval.v;
16990Sstevel@tonic-gate 		return (1);
17000Sstevel@tonic-gate 
17010Sstevel@tonic-gate 	case T_NAME:
17020Sstevel@tonic-gate 		if (try) {
17030Sstevel@tonic-gate 			struct iterinfo *iterinfop;
17044436Sstephh 			struct node *np1, *np2;
17054436Sstephh 			int i, gotmatch = 0;
17060Sstevel@tonic-gate 
17070Sstevel@tonic-gate 			/*
17084436Sstephh 			 * Check if we have an exact match of the nonwildcarded
17094436Sstephh 			 * path in oldepname - if so we can just use the
17104436Sstephh 			 * full wildcarded path in epname.
17110Sstevel@tonic-gate 			 */
17124436Sstephh 			for (i = 0; i < 1; i++) {
17134436Sstephh 				for (np1 = np,
17144436Sstephh 				    np2 = events[i]->u.event.oldepname;
17154436Sstephh 				    np1 != NULL && np2 != NULL;
17164436Sstephh 				    np1 = np1->u.name.next,
17174436Sstephh 				    np2 = np2->u.name.next) {
17184436Sstephh 					if (strcmp(np1->u.name.s,
17194436Sstephh 					    np2->u.name.s) != 0)
17204436Sstephh 						break;
17214436Sstephh 					if (np1->u.name.child->t !=
17224436Sstephh 					    np2->u.name.child->t)
17234436Sstephh 						break;
17244436Sstephh 					if (np1->u.name.child->t == T_NUM &&
17254436Sstephh 					    np1->u.name.child->u.ull !=
17264436Sstephh 					    np2->u.name.child->u.ull)
17274436Sstephh 						break;
17284436Sstephh 					if (np1->u.name.child->t == T_NAME &&
17294436Sstephh 					    strcmp(np1->u.name.child->u.name.s,
17304436Sstephh 					    np2->u.name.child->u.name.s) != 0)
17314436Sstephh 						break;
17324436Sstephh 					gotmatch++;
17334436Sstephh 				}
17344436Sstephh 				if (np1 == NULL && np2 == NULL) {
17354436Sstephh 					valuep->t = NODEPTR;
17364436Sstephh 					valuep->v = (uintptr_t)
17374436Sstephh 					    events[i]->u.event.epname;
17384436Sstephh 					return (1);
17394436Sstephh 				}
17400Sstevel@tonic-gate 			}
17414436Sstephh 			if (!gotmatch) {
17424436Sstephh 				/*
17434436Sstephh 				 * we're not wildcarding. However at
17444436Sstephh 				 * itree_create() time, we can also expand
17454436Sstephh 				 * simple iterators - so check for those.
17464436Sstephh 				 */
17474436Sstephh 				iterinfop = lut_lookup(ex, (void *)np->u.name.s,
17484436Sstephh 				    NULL);
17494436Sstephh 				if (iterinfop != NULL) {
17504436Sstephh 					valuep->t = UINT64;
17514436Sstephh 					valuep->v =
17524436Sstephh 					    (unsigned long long)iterinfop->num;
17534436Sstephh 					return (1);
17544436Sstephh 				}
17554436Sstephh 			}
17564436Sstephh 			/*
17574436Sstephh 			 * For anything else we'll have to wait for eval_dup().
17584436Sstephh 			 */
17590Sstevel@tonic-gate 			return (0);
17600Sstevel@tonic-gate 		}
17610Sstevel@tonic-gate 
17620Sstevel@tonic-gate 		/* return address of struct node */
17630Sstevel@tonic-gate 		valuep->t = NODEPTR;
17641717Swesolows 		valuep->v = (uintptr_t)np;
17650Sstevel@tonic-gate 		return (1);
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate 	case T_QUOTE:
17680Sstevel@tonic-gate 		valuep->t = STRING;
17691717Swesolows 		valuep->v = (uintptr_t)np->u.quote.s;
17700Sstevel@tonic-gate 		return (1);
17710Sstevel@tonic-gate 
17720Sstevel@tonic-gate 	case T_FUNC:
17734436Sstephh 		return (eval_func(np, ex, events, np->u.func.arglist,
17744436Sstephh 		    globals, croot, arrowp, try, valuep));
17750Sstevel@tonic-gate 
17760Sstevel@tonic-gate 	case T_NUM:
1777*7197Sstephh 	case T_TIMEVAL:
17780Sstevel@tonic-gate 		valuep->t = UINT64;
17790Sstevel@tonic-gate 		valuep->v = np->u.ull;
17800Sstevel@tonic-gate 		return (1);
17810Sstevel@tonic-gate 
17820Sstevel@tonic-gate 	default:
17830Sstevel@tonic-gate 		outfl(O_DIE, np->file, np->line,
17840Sstevel@tonic-gate 		    "eval_expr: unexpected node type: %s",
17850Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
17860Sstevel@tonic-gate 	}
17870Sstevel@tonic-gate 	/*NOTREACHED*/
17881717Swesolows 	return (0);
17890Sstevel@tonic-gate }
17900Sstevel@tonic-gate 
17910Sstevel@tonic-gate /*
17920Sstevel@tonic-gate  * eval_fru() and eval_asru() don't do much, but are called from a number
17930Sstevel@tonic-gate  * of places.
17940Sstevel@tonic-gate  */
17954436Sstephh static struct node *
17960Sstevel@tonic-gate eval_fru(struct node *np)
17970Sstevel@tonic-gate {
17980Sstevel@tonic-gate 	ASSERT(np->t == T_NAME);
17990Sstevel@tonic-gate 	return (np);
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate 
18024436Sstephh static struct node *
18030Sstevel@tonic-gate eval_asru(struct node *np)
18040Sstevel@tonic-gate {
18050Sstevel@tonic-gate 	ASSERT(np->t == T_NAME);
18060Sstevel@tonic-gate 	return (np);
18070Sstevel@tonic-gate }
1808