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