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