1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * eval.c -- constraint evaluation module
27  *
28  * this module evaluates constraints.
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <string.h>
35 #include "alloc.h"
36 #include "out.h"
37 #include "stable.h"
38 #include "literals.h"
39 #include "lut.h"
40 #include "tree.h"
41 #include "ptree.h"
42 #include "itree.h"
43 #include "ipath.h"
44 #include "eval.h"
45 #include "config.h"
46 #include "platform.h"
47 #include "fme.h"
48 #include "stats.h"
49 
50 static struct node *eval_dup(struct node *np, struct lut *ex,
51     struct node *events[]);
52 static int check_expr_args(struct evalue *lp, struct evalue *rp,
53     enum datatype dtype, struct node *np);
54 static struct node *eval_fru(struct node *np);
55 static struct node *eval_asru(struct node *np);
56 
57 extern fmd_hdl_t *Hdl;	/* handle from eft.c */
58 
59 /*
60  * begins_with -- return true if rhs path begins with everything in lhs path
61  */
62 static int
63 begins_with(struct node *lhs, struct node *rhs, struct lut *ex)
64 {
65 	int lnum;
66 	int rnum;
67 	struct iterinfo *iterinfop;
68 
69 	if (lhs == NULL)
70 		return (1);	/* yep -- it all matched */
71 
72 	if (rhs == NULL)
73 		return (0);	/* nope, ran out of rhs first */
74 
75 	ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str);
76 	ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str);
77 
78 	if (lhs->u.name.s != rhs->u.name.s)
79 		return (0);	/* nope, different component names */
80 
81 	if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) {
82 		lnum = (int)lhs->u.name.child->u.ull;
83 	} else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) {
84 		iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s,
85 		    NULL);
86 		if (iterinfop != NULL)
87 			lnum = iterinfop->num;
88 		else
89 			out(O_DIE, "begins_with: unexpected lhs child");
90 	} else {
91 		out(O_DIE, "begins_with: unexpected lhs child");
92 	}
93 
94 	if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) {
95 		rnum = (int)rhs->u.name.child->u.ull;
96 	} else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) {
97 		iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s,
98 		    NULL);
99 		if (iterinfop != NULL)
100 			rnum = iterinfop->num;
101 		else
102 			out(O_DIE, "begins_with: unexpected rhs child");
103 	} else {
104 		out(O_DIE, "begins_with: unexpected rhs child");
105 	}
106 
107 	if (lnum != rnum)
108 		return (0);	/* nope, instance numbers were different */
109 
110 	return (begins_with(lhs->u.name.next, rhs->u.name.next, ex));
111 }
112 
113 /*
114  * eval_getname - used by eval_func to evaluate a name, preferably without using
115  * eval_dup (but if it does have to use eval_dup then the *dupedp flag is set).
116  */
117 static struct node *
118 eval_getname(struct node *funcnp, struct lut *ex, struct node *events[],
119     struct node *np, struct lut **globals,
120     struct config *croot, struct arrow *arrowp, int try, int *dupedp)
121 {
122 	struct node *nodep;
123 	const char *funcname = funcnp->u.func.s;
124 	struct evalue val;
125 
126 	if (np->t == T_NAME)
127 		nodep = np;
128 	else if (np->t == T_FUNC && np->u.func.s == L_fru)
129 		nodep = eval_fru(np->u.func.arglist);
130 	else if (np->t == T_FUNC && np->u.func.s == L_asru)
131 		nodep = eval_asru(np->u.func.arglist);
132 	else if (np->t == T_FUNC) {
133 		if (eval_expr(np, ex, events, globals, croot, arrowp, try,
134 		    &val) == 0)
135 			/*
136 			 * Can't evaluate yet. Return null so constraint is
137 			 * deferred.
138 			 */
139 			return (NULL);
140 		if (val.t == NODEPTR)
141 			return ((struct node *)(uintptr_t)val.v);
142 		else
143 			/*
144 			 * just return the T_FUNC - which the caller will
145 			 * reject.
146 			 */
147 			return (np);
148 	} else
149 		out(O_DIE, "%s: unexpected type: %s",
150 		    funcname, ptree_nodetype2str(np->t));
151 	if (try) {
152 		if (eval_expr(nodep, ex, events, globals, croot,
153 		    arrowp, try, &val) && val.t == NODEPTR)
154 			nodep = (struct node *)(uintptr_t)val.v;
155 		else {
156 			*dupedp = 1;
157 			nodep = eval_dup(nodep, ex, events);
158 		}
159 	}
160 	return (nodep);
161 }
162 
163 /*ARGSUSED*/
164 static int
165 eval_cat(struct node *np, struct lut *ex, struct node *events[],
166 	struct lut **globals, struct config *croot, struct arrow *arrowp,
167 	int try, struct evalue *valuep)
168 {
169 	if (np->t == T_LIST) {
170 		struct evalue lval;
171 		struct evalue rval;
172 		int len;
173 		char *s;
174 
175 		if (!eval_cat(np->u.expr.left, ex, events, globals, croot,
176 		    arrowp, try, &lval))
177 			return (0);
178 		if (!eval_cat(np->u.expr.right, ex, events, globals, croot,
179 		    arrowp, try, &rval))
180 			return (0);
181 		len = snprintf(NULL, 0, "%s%s", (char *)(uintptr_t)lval.v,
182 		    (char *)(uintptr_t)rval.v);
183 		s = MALLOC(len + 1);
184 
185 		(void) snprintf(s, len + 1, "%s%s", (char *)(uintptr_t)lval.v,
186 		    (char *)(uintptr_t)rval.v);
187 		outfl(O_ALTFP|O_VERB2, np->file, np->line,
188 		    "eval_cat: %s %s returns %s", (char *)(uintptr_t)lval.v,
189 		    (char *)(uintptr_t)rval.v, s);
190 		valuep->t = STRING;
191 		valuep->v = (uintptr_t)stable(s);
192 		FREE(s);
193 	} else {
194 		if (!eval_expr(np, ex, events, globals, croot,
195 		    arrowp, try, valuep))
196 			return (0);
197 		if (check_expr_args(valuep, NULL, STRING, np))
198 			return (0);
199 	}
200 	return (1);
201 }
202 
203 /*
204  * evaluate a variety of functions and place result in valuep.  return 1 if
205  * function evaluation was successful; 0 if otherwise (e.g., the case of an
206  * invalid argument to the function)
207  */
208 /*ARGSUSED*/
209 static int
210 eval_func(struct node *funcnp, struct lut *ex, struct node *events[],
211     struct node *np, struct lut **globals,
212     struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
213 {
214 	const char *funcname = funcnp->u.func.s;
215 	int duped_lhs = 0, duped_rhs = 0, duped = 0;
216 	struct node *lhs;
217 	struct node *rhs;
218 	struct config *cp;
219 	struct node *nodep;
220 	char *path;
221 	struct evalue val;
222 
223 	if (funcname == L_within) {
224 		/* within()'s are not really constraints -- always true */
225 		valuep->t = UINT64;
226 		valuep->v = 1;
227 		return (1);
228 	} else if (funcname == L_is_under) {
229 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
230 		    croot, arrowp, try, &duped_lhs);
231 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
232 		    globals, croot, arrowp, try, &duped_rhs);
233 		if (!rhs || !lhs)
234 			return (0);
235 		if (rhs->t != T_NAME || lhs->t != T_NAME) {
236 			valuep->t = UNDEFINED;
237 			return (1);
238 		}
239 
240 		valuep->t = UINT64;
241 		valuep->v = begins_with(lhs, rhs, ex);
242 		out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
243 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
244 		out(O_ALTFP|O_VERB2|O_NONL, ",");
245 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
246 		out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v);
247 
248 		if (duped_lhs)
249 			tree_free(lhs);
250 		if (duped_rhs)
251 			tree_free(rhs);
252 		return (1);
253 	} else if (funcname == L_confprop || funcname == L_confprop_defined) {
254 		const char *s;
255 
256 		/* for now s will point to a quote [see addconfigprop()] */
257 		ASSERT(np->u.expr.right->t == T_QUOTE);
258 
259 		nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
260 		    globals, croot, arrowp, try, &duped);
261 		if (!nodep)
262 			return (0);
263 		if (nodep->t != T_NAME) {
264 			valuep->t = UNDEFINED;
265 			return (1);
266 		}
267 
268 		if (nodep->u.name.last->u.name.cp != NULL) {
269 			cp = nodep->u.name.last->u.name.cp;
270 		} else {
271 			path = ipath2str(NULL, ipath(nodep));
272 			cp = config_lookup(croot, path, 0);
273 			FREE((void *)path);
274 		}
275 		if (cp == NULL) {
276 			if (funcname == L_confprop) {
277 				out(O_ALTFP|O_VERB3, "%s: path ", funcname);
278 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
279 				out(O_ALTFP|O_VERB3, " not found");
280 				valuep->v = (uintptr_t)stable("");
281 				valuep->t = STRING;
282 				if (duped)
283 					tree_free(nodep);
284 				return (1);
285 			} else {
286 				valuep->v = 0;
287 				valuep->t = UINT64;
288 				if (duped)
289 					tree_free(nodep);
290 				return (1);
291 			}
292 		}
293 		s = config_getprop(cp, np->u.expr.right->u.quote.s);
294 		if (s == NULL && strcmp(np->u.expr.right->u.quote.s,
295 		    "class-code") == 0)
296 			s = config_getprop(cp, "CLASS-CODE");
297 		if (s == NULL) {
298 			if (funcname == L_confprop) {
299 				out(O_ALTFP|O_VERB3|O_NONL,
300 				    "%s: \"%s\" not found for path ",
301 				    funcname, np->u.expr.right->u.quote.s);
302 				ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
303 				valuep->v = (uintptr_t)stable("");
304 				valuep->t = STRING;
305 				if (duped)
306 					tree_free(nodep);
307 				return (1);
308 			} else {
309 				valuep->v = 0;
310 				valuep->t = UINT64;
311 				if (duped)
312 					tree_free(nodep);
313 				return (1);
314 			}
315 		}
316 
317 		if (funcname == L_confprop) {
318 			valuep->v = (uintptr_t)stable(s);
319 			valuep->t = STRING;
320 			out(O_ALTFP|O_VERB3|O_NONL, "  %s(\"", funcname);
321 			ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
322 			out(O_ALTFP|O_VERB3|O_NONL,
323 			    "\", \"%s\") = \"%s\"  ",
324 			    np->u.expr.right->u.quote.s,
325 			    (char *)(uintptr_t)valuep->v);
326 		} else {
327 			valuep->v = 1;
328 			valuep->t = UINT64;
329 		}
330 		if (duped)
331 			tree_free(nodep);
332 		return (1);
333 	} else if (funcname == L_is_connected) {
334 		const char *connstrings[] = { "connected", "CONNECTED", NULL };
335 		struct config *cp[2];
336 		const char *matchthis[2], *s;
337 		char *nameslist, *w;
338 		int i, j;
339 
340 		lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
341 		    croot, arrowp, try, &duped_lhs);
342 		rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
343 		    globals, croot, arrowp, try, &duped_rhs);
344 		if (!rhs || !lhs)
345 			return (0);
346 		if (rhs->t != T_NAME || lhs->t != T_NAME) {
347 			valuep->t = UNDEFINED;
348 			return (1);
349 		}
350 
351 		path = ipath2str(NULL, ipath(lhs));
352 		matchthis[1] = stable(path);
353 		if (lhs->u.name.last->u.name.cp != NULL)
354 			cp[0] = lhs->u.name.last->u.name.cp;
355 		else
356 			cp[0] = config_lookup(croot, path, 0);
357 		FREE((void *)path);
358 		path = ipath2str(NULL, ipath(rhs));
359 		matchthis[0] = stable(path);
360 		if (rhs->u.name.last->u.name.cp != NULL)
361 			cp[1] = rhs->u.name.last->u.name.cp;
362 		else
363 			cp[1] = config_lookup(croot, path, 0);
364 		FREE((void *)path);
365 		if (duped_lhs)
366 			tree_free(lhs);
367 		if (duped_rhs)
368 			tree_free(rhs);
369 
370 		valuep->t = UINT64;
371 		valuep->v = 0;
372 		if (cp[0] == NULL || cp[1] == NULL)
373 			return (1);
374 
375 		/* to thine self always be connected */
376 		if (cp[0] == cp[1]) {
377 			valuep->v = 1;
378 			return (1);
379 		}
380 
381 		/*
382 		 * Extract "connected" property from each cp. Search this
383 		 * property for the name associated with the other cp[].
384 		 */
385 		for (i = 0; i < 2 && valuep->v == 0; i++) {
386 			for (j = 0; connstrings[j] != NULL && valuep->v == 0;
387 			    j++) {
388 				s = config_getprop(cp[i],
389 				    stable(connstrings[j]));
390 				if (s != NULL) {
391 					nameslist = STRDUP(s);
392 					w = strtok(nameslist, " ,");
393 					while (w != NULL) {
394 						if (stable(w) == matchthis[i]) {
395 							valuep->v = 1;
396 							break;
397 						}
398 						w = strtok(NULL, " ,");
399 					}
400 					FREE(nameslist);
401 				}
402 			}
403 		}
404 		return (1);
405 	} else if (funcname == L_is_type) {
406 		const char *typestrings[] = { "type", "TYPE", NULL };
407 		const char *s;
408 		int i;
409 
410 		nodep = eval_getname(funcnp, ex, events, np, globals,
411 		    croot, arrowp, try, &duped);
412 		if (!nodep)
413 			return (0);
414 		if (nodep->t != T_NAME) {
415 			valuep->t = UNDEFINED;
416 			return (1);
417 		}
418 
419 		if (nodep->u.name.last->u.name.cp != NULL) {
420 			cp = nodep->u.name.last->u.name.cp;
421 		} else {
422 			path = ipath2str(NULL, ipath(nodep));
423 			cp = config_lookup(croot, path, 0);
424 			FREE((void *)path);
425 		}
426 		if (duped)
427 			tree_free(nodep);
428 
429 		valuep->t = STRING;
430 		valuep->v = (uintptr_t)stable("");
431 		if (cp == NULL)
432 			return (1);
433 		for (i = 0; typestrings[i] != NULL; i++) {
434 			s = config_getprop(cp, stable(typestrings[i]));
435 			if (s != NULL) {
436 				valuep->v = (uintptr_t)stable(s);
437 				break;
438 			}
439 		}
440 		return (1);
441 	} else if (funcname == L_is_on) {
442 		const char *onstrings[] = { "on", "ON", NULL };
443 		const char *truestrings[] = { "yes", "YES", "y", "Y",
444 				    "true", "TRUE", "t", "T", "1", NULL };
445 		const char *s;
446 		int i, j;
447 
448 		nodep = eval_getname(funcnp, ex, events, np, globals,
449 		    croot, arrowp, try, &duped);
450 		if (!nodep)
451 			return (0);
452 		if (nodep->t != T_NAME) {
453 			valuep->t = UNDEFINED;
454 			return (1);
455 		}
456 
457 		if (nodep->u.name.last->u.name.cp != NULL) {
458 			cp = nodep->u.name.last->u.name.cp;
459 		} else {
460 			path = ipath2str(NULL, ipath(nodep));
461 			cp = config_lookup(croot, path, 0);
462 			FREE((void *)path);
463 		}
464 		if (duped)
465 			tree_free(nodep);
466 
467 		valuep->t = UINT64;
468 		valuep->v = 0;
469 		if (cp == NULL)
470 			return (1);
471 		for (i = 0; onstrings[i] != NULL; i++) {
472 			s = config_getprop(cp, stable(onstrings[i]));
473 			if (s != NULL) {
474 				s = stable(s);
475 				for (j = 0; truestrings[j] != NULL; j++) {
476 					if (s == stable(truestrings[j])) {
477 						valuep->v = 1;
478 						return (1);
479 					}
480 				}
481 			}
482 		}
483 		return (1);
484 	} else if (funcname == L_is_present) {
485 		nodep = eval_getname(funcnp, ex, events, np, globals,
486 		    croot, arrowp, try, &duped);
487 		if (!nodep)
488 			return (0);
489 		if (nodep->t != T_NAME) {
490 			valuep->t = UNDEFINED;
491 			return (1);
492 		}
493 
494 		if (nodep->u.name.last->u.name.cp != NULL) {
495 			cp = nodep->u.name.last->u.name.cp;
496 		} else {
497 			path = ipath2str(NULL, ipath(nodep));
498 			cp = config_lookup(croot, path, 0);
499 			FREE((void *)path);
500 		}
501 		if (duped)
502 			tree_free(nodep);
503 
504 		valuep->t = UINT64;
505 		valuep->v = 0;
506 		if (cp != NULL)
507 			valuep->v = 1;
508 		return (1);
509 	} else if (funcname == L_has_fault) {
510 		nvlist_t *asru = NULL, *fru = NULL, *rsrc = NULL;
511 
512 		nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
513 		    globals, croot, arrowp, try, &duped);
514 		if (!nodep)
515 			return (0);
516 		if (nodep->t != T_NAME) {
517 			valuep->t = UNDEFINED;
518 			return (1);
519 		}
520 
521 		path = ipath2str(NULL, ipath(nodep));
522 		platform_units_translate(0, croot, &asru, &fru, &rsrc, path);
523 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, "has_fault(");
524 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, nodep);
525 		out(O_ALTFP|O_VERB2|O_NONL, "(%s), \"%s\") ", path,
526 		    np->u.expr.right->u.quote.s);
527 		FREE((void *)path);
528 		if (duped)
529 			tree_free(nodep);
530 
531 		if (rsrc == NULL) {
532 			valuep->v = 0;
533 			out(O_ALTFP|O_VERB2, "no path");
534 		} else {
535 			valuep->v = fmd_nvl_fmri_has_fault(Hdl, rsrc,
536 			    FMD_HAS_FAULT_RESOURCE,
537 			    strcmp(np->u.expr.right->u.quote.s, "") == 0 ?
538 			    NULL : (char *)np->u.expr.right->u.quote.s);
539 			out(O_ALTFP|O_VERB2, "returned %lld", valuep->v);
540 		}
541 		valuep->t = UINT64;
542 		return (1);
543 	} else if (funcname == L_count) {
544 		struct stats *statp;
545 		struct istat_entry ent;
546 
547 		ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
548 
549 		nodep = np->u.event.epname;
550 		if (try) {
551 			if (eval_expr(nodep, ex, events, globals,
552 			    croot, arrowp, try, &val) && val.t == NODEPTR)
553 				nodep = (struct node *)(uintptr_t)val.v;
554 			else {
555 				duped = 1;
556 				nodep = eval_dup(nodep, ex, events);
557 			}
558 		}
559 		ent.ename = np->u.event.ename->u.name.s;
560 		ent.ipath = ipath(nodep);
561 		valuep->t = UINT64;
562 		if ((statp = (struct stats *)
563 		    lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
564 			valuep->v = 0;
565 		else
566 			valuep->v = stats_counter_value(statp);
567 		if (duped)
568 			tree_free(nodep);
569 		return (1);
570 	} else if (funcname == L_envprop) {
571 		outfl(O_DIE, np->file, np->line,
572 		    "eval_func: %s not yet supported", funcname);
573 	}
574 
575 	if (try)
576 		return (0);
577 
578 	if (funcname == L_fru) {
579 		valuep->t = NODEPTR;
580 		valuep->v = (uintptr_t)eval_fru(np);
581 		return (1);
582 	} else if (funcname == L_asru) {
583 		valuep->t = NODEPTR;
584 		valuep->v = (uintptr_t)eval_asru(np);
585 		return (1);
586 	} else if (funcname == L_defined) {
587 		ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
588 		valuep->t = UINT64;
589 		valuep->v = (lut_lookup(*globals,
590 		    (void *)np->u.globid.s, NULL) != NULL);
591 		return (1);
592 	} else if (funcname == L_call) {
593 		return (! platform_call(np, globals, croot, arrowp, valuep));
594 	} else if (funcname == L_payloadprop) {
595 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
596 		    "payloadprop(\"%s\") ", np->u.quote.s);
597 
598 		if (arrowp->head->myevent->count == 0) {
599 			/*
600 			 * Haven't seen this ereport yet, so must defer
601 			 */
602 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
603 			return (0);
604 		} else if (platform_payloadprop(np, valuep)) {
605 			/* platform_payloadprop() returned false */
606 			out(O_ALTFP|O_VERB, "not found.");
607 			valuep->t = UNDEFINED;
608 			return (1);
609 		} else {
610 			switch (valuep->t) {
611 			case NODEPTR:
612 				if (((struct node *)(uintptr_t)
613 				    (valuep->v))->t == T_NAME) {
614 					char *s = ipath2str(NULL,
615 					    ipath((struct node *)
616 					    (uintptr_t)valuep->v));
617 					out(O_ALTFP|O_VERB2,
618 					    "found: \"%s\"", s);
619 					FREE(s);
620 				} else
621 					out(O_ALTFP|O_VERB2, "found: %llu",
622 					    valuep->v);
623 				break;
624 			case UINT64:
625 				out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
626 				break;
627 			case STRING:
628 				out(O_ALTFP|O_VERB2, "found: \"%s\"",
629 				    (char *)(uintptr_t)valuep->v);
630 				break;
631 			default:
632 				out(O_ALTFP|O_VERB2, "found: undefined");
633 				break;
634 			}
635 			return (1);
636 		}
637 	} else if (funcname == L_setpayloadprop) {
638 		struct evalue *payloadvalp;
639 		int alloced = 0;
640 
641 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
642 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
643 		    ptree_nodetype2str(np->u.expr.left->t));
644 
645 		if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
646 			return (0);
647 
648 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
649 		    "setpayloadprop: %s: %s=",
650 		    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
651 		    np->u.expr.left->u.quote.s);
652 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
653 
654 		/*
655 		 * allocate a struct evalue to hold the payload property's
656 		 * value, unless we've been here already, in which case we
657 		 * might calculate a different value, but we'll store it
658 		 * in the already-allocated struct evalue.
659 		 */
660 		if ((payloadvalp = (struct evalue *)lut_lookup(
661 		    arrowp->tail->myevent->payloadprops,
662 		    (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
663 			payloadvalp = MALLOC(sizeof (*payloadvalp));
664 			alloced = 1;
665 		}
666 
667 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
668 		    arrowp, try, payloadvalp)) {
669 			out(O_ALTFP|O_VERB2, " (cannot eval)");
670 			if (alloced)
671 				FREE(payloadvalp);
672 			return (0);
673 		} else {
674 			if (payloadvalp->t == UNDEFINED) {
675 				/* function is always true */
676 				out(O_ALTFP|O_VERB2, " (undefined)");
677 				valuep->t = UINT64;
678 				valuep->v = 1;
679 				return (1);
680 			}
681 			if (payloadvalp->t == UINT64)
682 				out(O_ALTFP|O_VERB2,
683 				    " (%llu)", payloadvalp->v);
684 			else
685 				out(O_ALTFP|O_VERB2, " (\"%s\")",
686 				    (char *)(uintptr_t)payloadvalp->v);
687 		}
688 
689 		/* add to table of payload properties for current problem */
690 		arrowp->tail->myevent->payloadprops =
691 		    lut_add(arrowp->tail->myevent->payloadprops,
692 		    (void *)np->u.expr.left->u.quote.s,
693 		    (void *)payloadvalp, NULL);
694 
695 		/* function is always true */
696 		valuep->t = UINT64;
697 		valuep->v = 1;
698 		return (1);
699 	} else if (funcname == L_cat) {
700 		int retval = eval_cat(np, ex, events, globals, croot,
701 		    arrowp, try, valuep);
702 
703 		outfl(O_ALTFP|O_VERB2, np->file, np->line,
704 		    "cat: returns %s", (char *)(uintptr_t)valuep->v);
705 		return (retval);
706 	} else if (funcname == L_setserdn || funcname == L_setserdt ||
707 	    funcname == L_setserdsuffix || funcname == L_setserdincrement) {
708 		struct evalue *serdvalp;
709 		int alloced = 0;
710 		char *str;
711 		struct event *flt = arrowp->tail->myevent;
712 
713 		if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
714 			return (0);
715 
716 		if (funcname == L_setserdn)
717 			str = "n";
718 		else if (funcname == L_setserdt)
719 			str = "t";
720 		else if (funcname == L_setserdsuffix)
721 			str = "suffix";
722 		else if (funcname == L_setserdincrement)
723 			str = "increment";
724 
725 		/*
726 		 * allocate a struct evalue to hold the serd property's
727 		 * value, unless we've been here already, in which case we
728 		 * might calculate a different value, but we'll store it
729 		 * in the already-allocated struct evalue.
730 		 */
731 		if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops,
732 		    (void *)str, (lut_cmp)strcmp)) == NULL) {
733 			serdvalp = MALLOC(sizeof (*serdvalp));
734 			alloced = 1;
735 		}
736 
737 		if (!eval_expr(np, ex, events, globals, croot, arrowp, try,
738 		    serdvalp)) {
739 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
740 			    "setserd%s: %s: ", str,
741 			    flt->enode->u.event.ename->u.name.s);
742 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
743 			out(O_ALTFP|O_VERB2, " (cannot eval)");
744 			if (alloced)
745 				FREE(serdvalp);
746 			return (0);
747 		} else if (serdvalp->t == UNDEFINED) {
748 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
749 			    "setserd%s: %s: ", str,
750 			    flt->enode->u.event.ename->u.name.s);
751 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
752 			out(O_ALTFP|O_VERB2, " (undefined)");
753 		} else {
754 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
755 			    "setserd%s: %s: ", str,
756 			    flt->enode->u.event.ename->u.name.s);
757 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
758 			if ((funcname == L_setserdincrement ||
759 			    funcname == L_setserdn) && serdvalp->t == STRING) {
760 				serdvalp->t = UINT64;
761 				serdvalp->v = strtoull((char *)
762 				    (uintptr_t)serdvalp->v, NULL, 0);
763 			}
764 			if (funcname == L_setserdt && serdvalp->t == UINT64) {
765 				int len = snprintf(NULL, 0, "%lldns",
766 				    serdvalp->v);
767 				char *buf = MALLOC(len + 1);
768 
769 				(void) snprintf(buf, len + 1, "%lldns",
770 				    serdvalp->v);
771 				serdvalp->t = STRING;
772 				serdvalp->v = (uintptr_t)stable(buf);
773 				FREE(buf);
774 			}
775 			if (funcname == L_setserdsuffix &&
776 			    serdvalp->t == UINT64) {
777 				int len = snprintf(NULL, 0, "%lld",
778 				    serdvalp->v);
779 				char *buf = MALLOC(len + 1);
780 
781 				(void) snprintf(buf, len + 1, "%lld",
782 				    serdvalp->v);
783 				serdvalp->t = STRING;
784 				serdvalp->v = (uintptr_t)stable(buf);
785 				FREE(buf);
786 			}
787 
788 			if (serdvalp->t == UINT64)
789 				out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v);
790 			else
791 				out(O_ALTFP|O_VERB2, " (\"%s\")",
792 				    (char *)(uintptr_t)serdvalp->v);
793 			flt->serdprops = lut_add(flt->serdprops, (void *)str,
794 			    (void *)serdvalp, (lut_cmp)strcmp);
795 		}
796 		valuep->t = UINT64;
797 		valuep->v = 1;
798 		return (1);
799 	} else if (funcname == L_payloadprop_defined) {
800 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
801 		    "payloadprop_defined(\"%s\") ", np->u.quote.s);
802 
803 		if (arrowp->head->myevent->count == 0) {
804 			/*
805 			 * Haven't seen this ereport yet, so must defer
806 			 */
807 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
808 			return (0);
809 		} else if (platform_payloadprop(np, NULL)) {
810 			/* platform_payloadprop() returned false */
811 			valuep->v = 0;
812 			out(O_ALTFP|O_VERB2, "not found.");
813 		} else {
814 			valuep->v = 1;
815 			out(O_ALTFP|O_VERB2, "found.");
816 		}
817 		valuep->t = UINT64;
818 		return (1);
819 	} else if (funcname == L_payloadprop_contains) {
820 		int nvals;
821 		struct evalue *vals;
822 		struct evalue cmpval;
823 
824 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
825 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
826 		    ptree_nodetype2str(np->u.expr.left->t));
827 
828 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
829 		    "payloadprop_contains(\"%s\", ",
830 		    np->u.expr.left->u.quote.s);
831 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
832 		out(O_ALTFP|O_VERB2|O_NONL, ") ");
833 
834 		/* evaluate the expression we're comparing against */
835 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
836 		    arrowp, try, &cmpval)) {
837 			out(O_ALTFP|O_VERB2|O_NONL,
838 			    "(cannot eval) ");
839 			return (0);
840 		} else {
841 			switch (cmpval.t) {
842 			case UNDEFINED:
843 				out(O_ALTFP|O_VERB2, "(undefined type)");
844 				break;
845 
846 			case UINT64:
847 				out(O_ALTFP|O_VERB2,
848 				    "(%llu) ", cmpval.v);
849 				break;
850 
851 			case STRING:
852 				out(O_ALTFP|O_VERB2,
853 				    "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
854 				break;
855 
856 			case NODEPTR:
857 				out(O_ALTFP|O_VERB2|O_NONL, "(");
858 				ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
859 				    (struct node *)(uintptr_t)(cmpval.v));
860 				out(O_ALTFP|O_VERB2, ") ");
861 				break;
862 			}
863 		}
864 
865 		/* get the payload values and check for a match */
866 		vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
867 		    &nvals);
868 		valuep->t = UINT64;
869 		valuep->v = 0;
870 		if (arrowp->head->myevent->count == 0) {
871 			/*
872 			 * Haven't seen this ereport yet, so must defer
873 			 */
874 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
875 			return (0);
876 		} else if (nvals == 0) {
877 			out(O_ALTFP|O_VERB2, "not found.");
878 			return (1);
879 		} else {
880 			struct evalue preval;
881 			int i;
882 
883 			out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
884 
885 			for (i = 0; i < nvals; i++) {
886 
887 				preval.t = vals[i].t;
888 				preval.v = vals[i].v;
889 
890 				if (check_expr_args(&vals[i], &cmpval,
891 				    UNDEFINED, np))
892 					continue;
893 
894 				/*
895 				 * If we auto-converted the value to a
896 				 * string, we need to free the
897 				 * original tree value.
898 				 */
899 				if (preval.t == NODEPTR &&
900 				    ((struct node *)(uintptr_t)(preval.v))->t ==
901 				    T_NAME) {
902 					tree_free((struct node *)(uintptr_t)
903 					    preval.v);
904 				}
905 
906 				if (vals[i].v == cmpval.v) {
907 					valuep->v = 1;
908 					break;
909 				}
910 			}
911 
912 			if (valuep->v)
913 				out(O_ALTFP|O_VERB2, "match.");
914 			else
915 				out(O_ALTFP|O_VERB2, "no match.");
916 
917 			for (i = 0; i < nvals; i++) {
918 				if (vals[i].t == NODEPTR) {
919 					tree_free((struct node *)(uintptr_t)
920 					    vals[i].v);
921 					break;
922 				}
923 			}
924 			FREE(vals);
925 		}
926 		return (1);
927 	} else if (funcname == L_confcall) {
928 		return (!platform_confcall(np, globals, croot, arrowp, valuep));
929 	} else
930 		outfl(O_DIE, np->file, np->line,
931 		    "eval_func: unexpected func: %s", funcname);
932 	/*NOTREACHED*/
933 	return (0);
934 }
935 
936 /*
937  * defines for u.expr.temp - these are used for T_OR and T_AND so that if
938  * we worked out that part of the expression was true or false during an
939  * earlier eval_expr, then we don't need to dup that part.
940  */
941 
942 #define	EXPR_TEMP_BOTH_UNK	0
943 #define	EXPR_TEMP_LHS_UNK	1
944 #define	EXPR_TEMP_RHS_UNK	2
945 
946 static struct node *
947 eval_dup(struct node *np, struct lut *ex, struct node *events[])
948 {
949 	struct node *newnp;
950 
951 	if (np == NULL)
952 		return (NULL);
953 
954 	switch (np->t) {
955 	case T_GLOBID:
956 		return (tree_globid(np->u.globid.s, np->file, np->line));
957 
958 	case T_ASSIGN:
959 	case T_CONDIF:
960 	case T_CONDELSE:
961 	case T_NE:
962 	case T_EQ:
963 	case T_LT:
964 	case T_LE:
965 	case T_GT:
966 	case T_GE:
967 	case T_BITAND:
968 	case T_BITOR:
969 	case T_BITXOR:
970 	case T_BITNOT:
971 	case T_LSHIFT:
972 	case T_RSHIFT:
973 	case T_NOT:
974 	case T_ADD:
975 	case T_SUB:
976 	case T_MUL:
977 	case T_DIV:
978 	case T_MOD:
979 		return (tree_expr(np->t,
980 		    eval_dup(np->u.expr.left, ex, events),
981 		    eval_dup(np->u.expr.right, ex, events)));
982 	case T_LIST:
983 	case T_AND:
984 		switch (np->u.expr.temp) {
985 		case EXPR_TEMP_LHS_UNK:
986 			return (eval_dup(np->u.expr.left, ex, events));
987 		case EXPR_TEMP_RHS_UNK:
988 			return (eval_dup(np->u.expr.right, ex, events));
989 		default:
990 			return (tree_expr(np->t,
991 			    eval_dup(np->u.expr.left, ex, events),
992 			    eval_dup(np->u.expr.right, ex, events)));
993 		}
994 
995 	case T_OR:
996 		switch (np->u.expr.temp) {
997 		case EXPR_TEMP_LHS_UNK:
998 			return (eval_dup(np->u.expr.left, ex, events));
999 		case EXPR_TEMP_RHS_UNK:
1000 			return (eval_dup(np->u.expr.right, ex, events));
1001 		default:
1002 			return (tree_expr(T_OR,
1003 			    eval_dup(np->u.expr.left, ex, events),
1004 			    eval_dup(np->u.expr.right, ex, events)));
1005 		}
1006 
1007 	case T_NAME: {
1008 		struct iterinfo *iterinfop;
1009 		int got_matchf = 0;
1010 		int got_matcht = 0;
1011 		struct evalue value;
1012 		struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
1013 		struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
1014 
1015 		/*
1016 		 * Check if we already have a match of the nonwildcarded path
1017 		 * in oldepname (check both to and from events).
1018 		 */
1019 		for (np1f = np, np2f = events[0]->u.event.oldepname;
1020 		    np1f != NULL && np2f != NULL;
1021 		    np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
1022 			if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
1023 				break;
1024 			if (np1f->u.name.child->t != np2f->u.name.child->t)
1025 				break;
1026 			if (np1f->u.name.child->t == T_NUM &&
1027 			    np1f->u.name.child->u.ull !=
1028 			    np2f->u.name.child->u.ull)
1029 				break;
1030 			if (np1f->u.name.child->t == T_NAME &&
1031 			    strcmp(np1f->u.name.child->u.name.s,
1032 			    np2f->u.name.child->u.name.s) != 0)
1033 				break;
1034 			got_matchf++;
1035 		}
1036 		for (np1t = np, np2t = events[1]->u.event.oldepname;
1037 		    np1t != NULL && np2t != NULL;
1038 		    np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
1039 			if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
1040 				break;
1041 			if (np1t->u.name.child->t != np2t->u.name.child->t)
1042 				break;
1043 			if (np1t->u.name.child->t == T_NUM &&
1044 			    np1t->u.name.child->u.ull !=
1045 			    np2t->u.name.child->u.ull)
1046 				break;
1047 			if (np1t->u.name.child->t == T_NAME &&
1048 			    strcmp(np1t->u.name.child->u.name.s,
1049 			    np2t->u.name.child->u.name.s) != 0)
1050 				break;
1051 			got_matcht++;
1052 		}
1053 		nprest = np;
1054 		if (got_matchf || got_matcht) {
1055 			/*
1056 			 * so we are wildcarding. Copy ewname in full, plus
1057 			 * matching section of oldepname. Use whichever gives
1058 			 * the closest match.
1059 			 */
1060 			if (got_matchf > got_matcht) {
1061 				npstart = events[0]->u.event.ewname;
1062 				npcont = events[0]->u.event.oldepname;
1063 				npend = np2f;
1064 				nprest = np1f;
1065 			} else {
1066 				npstart = events[1]->u.event.ewname;
1067 				npcont = events[1]->u.event.oldepname;
1068 				npend = np2t;
1069 				nprest = np1t;
1070 			}
1071 			for (npref = npstart; npref != NULL;
1072 			    npref = npref->u.name.next) {
1073 				newnp = newnode(T_NAME, np->file, np->line);
1074 				newnp->u.name.t = npref->u.name.t;
1075 				newnp->u.name.s = npref->u.name.s;
1076 				newnp->u.name.last = newnp;
1077 				newnp->u.name.it = npref->u.name.it;
1078 				newnp->u.name.cp = npref->u.name.cp;
1079 				newnp->u.name.child =
1080 				    newnode(T_NUM, np->file, np->line);
1081 				if (eval_expr(npref->u.name.child, ex, events,
1082 				    NULL, NULL, NULL, 1, &value) == 0 ||
1083 				    value.t != UINT64) {
1084 					outfl(O_DIE, np->file, np->line,
1085 					    "eval_dup: could not resolve "
1086 					    "iterator of %s", np->u.name.s);
1087 				}
1088 				newnp->u.name.child->u.ull = value.v;
1089 				if (retp == NULL) {
1090 					retp = newnp;
1091 				} else {
1092 					retp->u.name.last->u.name.next = newnp;
1093 					retp->u.name.last = newnp;
1094 				}
1095 			}
1096 			for (npref = npcont; npref != NULL && npref != npend;
1097 			    npref = npref->u.name.next) {
1098 				newnp = newnode(T_NAME, np->file, np->line);
1099 				newnp->u.name.t = npref->u.name.t;
1100 				newnp->u.name.s = npref->u.name.s;
1101 				newnp->u.name.last = newnp;
1102 				newnp->u.name.it = npref->u.name.it;
1103 				newnp->u.name.cp = npref->u.name.cp;
1104 				newnp->u.name.child =
1105 				    newnode(T_NUM, np->file, np->line);
1106 				if (eval_expr(npref->u.name.child, ex, events,
1107 				    NULL, NULL, NULL, 1, &value) == 0 ||
1108 				    value.t != UINT64) {
1109 					outfl(O_DIE, np->file, np->line,
1110 					    "eval_dup: could not resolve "
1111 					    "iterator of %s", np->u.name.s);
1112 				}
1113 				newnp->u.name.child->u.ull = value.v;
1114 				if (retp == NULL) {
1115 					retp = newnp;
1116 				} else {
1117 					retp->u.name.last->u.name.next = newnp;
1118 					retp->u.name.last = newnp;
1119 				}
1120 			}
1121 		} else {
1122 			/*
1123 			 * not wildcarding - check if explicit iterator
1124 			 */
1125 			iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
1126 			if (iterinfop != NULL) {
1127 				/* explicit iterator; not part of pathname */
1128 				newnp = newnode(T_NUM, np->file, np->line);
1129 				newnp->u.ull = iterinfop->num;
1130 				return (newnp);
1131 			}
1132 		}
1133 
1134 		/*
1135 		 * finally, whether wildcarding or not, we need to copy the
1136 		 * remaining part of the path (if any). This must be defined
1137 		 * absolutely (no more expansion/wildcarding).
1138 		 */
1139 		for (npref = nprest; npref != NULL;
1140 		    npref = npref->u.name.next) {
1141 			newnp = newnode(T_NAME, np->file, np->line);
1142 			newnp->u.name.t = npref->u.name.t;
1143 			newnp->u.name.s = npref->u.name.s;
1144 			newnp->u.name.last = newnp;
1145 			newnp->u.name.it = npref->u.name.it;
1146 			newnp->u.name.cp = npref->u.name.cp;
1147 			newnp->u.name.child =
1148 			    newnode(T_NUM, np->file, np->line);
1149 			if (eval_expr(npref->u.name.child, ex, events,
1150 			    NULL, NULL, NULL, 1, &value) == 0 ||
1151 			    value.t != UINT64) {
1152 				outfl(O_DIE, np->file, np->line,
1153 				    "eval_dup: could not resolve "
1154 				    "iterator of %s", np->u.name.s);
1155 			}
1156 			newnp->u.name.child->u.ull = value.v;
1157 			if (retp == NULL) {
1158 				retp = newnp;
1159 			} else {
1160 				retp->u.name.last->u.name.next = newnp;
1161 				retp->u.name.last = newnp;
1162 			}
1163 		}
1164 		return (retp);
1165 	}
1166 
1167 	case T_EVENT:
1168 		newnp = newnode(T_NAME, np->file, np->line);
1169 
1170 		newnp->u.name.t = np->u.event.ename->u.name.t;
1171 		newnp->u.name.s = np->u.event.ename->u.name.s;
1172 		newnp->u.name.it = np->u.event.ename->u.name.it;
1173 		newnp->u.name.last = newnp;
1174 
1175 		return (tree_event(newnp,
1176 		    eval_dup(np->u.event.epname, ex, events),
1177 		    eval_dup(np->u.event.eexprlist, ex, events)));
1178 
1179 	case T_FUNC:
1180 		return (tree_func(np->u.func.s,
1181 		    eval_dup(np->u.func.arglist, ex, events),
1182 		    np->file, np->line));
1183 
1184 	case T_QUOTE:
1185 		newnp = newnode(T_QUOTE, np->file, np->line);
1186 		newnp->u.quote.s = np->u.quote.s;
1187 		return (newnp);
1188 
1189 	case T_NUM:
1190 		newnp = newnode(T_NUM, np->file, np->line);
1191 		newnp->u.ull = np->u.ull;
1192 		return (newnp);
1193 
1194 	case T_TIMEVAL:
1195 		newnp = newnode(T_TIMEVAL, np->file, np->line);
1196 		newnp->u.ull = np->u.ull;
1197 		return (newnp);
1198 
1199 	default:
1200 		outfl(O_DIE, np->file, np->line,
1201 		    "eval_dup: unexpected node type: %s",
1202 		    ptree_nodetype2str(np->t));
1203 	}
1204 	/*NOTREACHED*/
1205 	return (0);
1206 }
1207 
1208 /*
1209  * eval_potential -- see if constraint is potentially true
1210  *
1211  * this function is used at instance tree creation time to see if
1212  * any constraints are already known to be false.  if this function
1213  * returns false, then the constraint will always be false and there's
1214  * no need to include the propagation arrow in the instance tree.
1215  *
1216  * if this routine returns true, either the constraint is known to
1217  * be always true (so there's no point in attaching the constraint
1218  * to the propagation arrow in the instance tree), or the constraint
1219  * contains "deferred" expressions like global variables or poller calls
1220  * and so it must be evaluated during calls to fme_eval().  in this last
1221  * case, where a constraint needs to be attached to the propagation arrow
1222  * in the instance tree, this routine returns a newly created constraint
1223  * in *newc where all the non-deferred things have been filled in.
1224  *
1225  * so in summary:
1226  *
1227  *	return of false: constraint can never be true, *newc will be NULL.
1228  *
1229  *	return of true with *newc unchanged: constraint will always be true.
1230  *
1231  *	return of true with *newc changed: use new constraint in *newc.
1232  *
1233  * the lookup table for all explicit iterators, ex, is passed in.
1234  *
1235  * *newc can either be NULL on entry, or if can contain constraints from
1236  * previous calls to eval_potential() (i.e. for building up an instance
1237  * tree constraint from several potential constraints).  if *newc already
1238  * contains constraints, anything added to it will be joined by adding
1239  * a T_AND node at the top of *newc.
1240  */
1241 int
1242 eval_potential(struct node *np, struct lut *ex, struct node *events[],
1243 	    struct node **newc, struct config *croot)
1244 {
1245 	struct node *newnp;
1246 	struct evalue value;
1247 
1248 	if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
1249 		/*
1250 		 * couldn't eval expression because
1251 		 * it contains deferred items.  make
1252 		 * a duplicate expression with all the
1253 		 * non-deferred items expanded.
1254 		 */
1255 		newnp = eval_dup(np, ex, events);
1256 
1257 		if (*newc == NULL) {
1258 			/*
1259 			 * constraint is potentially true if deferred
1260 			 * expression in newnp is true.  *newc was NULL
1261 			 * so new constraint is just the one in newnp.
1262 			 */
1263 			*newc = newnp;
1264 			return (1);
1265 		} else {
1266 			/*
1267 			 * constraint is potentially true if deferred
1268 			 * expression in newnp is true.  *newc already
1269 			 * contained a constraint so add an AND with the
1270 			 * constraint in newnp.
1271 			 */
1272 			*newc = tree_expr(T_AND, *newc, newnp);
1273 			return (1);
1274 		}
1275 	} else if (value.t == UNDEFINED) {
1276 		/* constraint can never be true */
1277 		return (0);
1278 	} else if (value.t == UINT64 && value.v == 0) {
1279 		/* constraint can never be true */
1280 		return (0);
1281 	} else {
1282 		/* constraint is always true (nothing deferred to eval) */
1283 		return (1);
1284 	}
1285 }
1286 
1287 static int
1288 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
1289 		struct node *np)
1290 {
1291 	/* auto-convert T_NAMES to strings */
1292 	if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
1293 	    T_NAME) {
1294 		char *s = ipath2str(NULL,
1295 		    ipath((struct node *)(uintptr_t)lp->v));
1296 		lp->t = STRING;
1297 		lp->v = (uintptr_t)stable(s);
1298 		FREE(s);
1299 		out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
1300 		    (char *)(uintptr_t)lp->v);
1301 	}
1302 	if (rp != NULL &&
1303 	    rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
1304 	    T_NAME) {
1305 		char *s = ipath2str(NULL,
1306 		    ipath((struct node *)(uintptr_t)rp->v));
1307 		rp->t = STRING;
1308 		rp->v = (uintptr_t)stable(s);
1309 		FREE(s);
1310 		out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
1311 		    (char *)(uintptr_t)rp->v);
1312 	}
1313 
1314 	/* auto-convert numbers to strings */
1315 	if (dtype == STRING) {
1316 		if (lp->t == UINT64) {
1317 			int len = snprintf(NULL, 0, "%llx", lp->v);
1318 			char *s = MALLOC(len + 1);
1319 
1320 			(void) snprintf(s, len + 1, "%llx", lp->v);
1321 			lp->t = STRING;
1322 			lp->v = (uintptr_t)stable(s);
1323 			FREE(s);
1324 		}
1325 		if (rp != NULL && rp->t == UINT64) {
1326 			int len = snprintf(NULL, 0, "%llx", rp->v);
1327 			char *s = MALLOC(len + 1);
1328 
1329 			(void) snprintf(s, len + 1, "%llx", rp->v);
1330 			rp->t = STRING;
1331 			rp->v = (uintptr_t)stable(s);
1332 			FREE(s);
1333 		}
1334 	}
1335 
1336 	/* auto-convert strings to numbers */
1337 	if (dtype == UINT64) {
1338 		if (lp->t == STRING) {
1339 			lp->t = UINT64;
1340 			lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
1341 		}
1342 		if (rp != NULL && rp->t == STRING) {
1343 			rp->t = UINT64;
1344 			rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
1345 		}
1346 	}
1347 
1348 	if (dtype != UNDEFINED && lp->t != dtype) {
1349 		outfl(O_DIE, np->file, np->line,
1350 		    "invalid datatype of argument for operation %s",
1351 		    ptree_nodetype2str(np->t));
1352 		/* NOTREACHED */
1353 		return (1);
1354 	}
1355 
1356 	if (rp != NULL && lp->t != rp->t) {
1357 		outfl(O_DIE, np->file, np->line,
1358 		    "mismatch in datatype of arguments for operation %s",
1359 		    ptree_nodetype2str(np->t));
1360 		/* NOTREACHED */
1361 		return (1);
1362 	}
1363 
1364 	return (0);
1365 }
1366 
1367 /*
1368  * eval_expr -- evaluate expression into *valuep
1369  *
1370  * the meaning of the return value depends on the input value of try.
1371  *
1372  * for try == 1: if any deferred items are encounted, bail out and return
1373  * false.  returns true if we made it through entire expression without
1374  * hitting any deferred items.
1375  *
1376  * for try == 0: return true if all operations were performed successfully.
1377  * return false if otherwise.  for example, any of the following conditions
1378  * will result in a false return value:
1379  *   - attempted use of an uninitialized global variable
1380  *   - failure in function evaluation
1381  *   - illegal arithmetic operation (argument out of range)
1382  */
1383 int
1384 eval_expr(struct node *np, struct lut *ex, struct node *events[],
1385 	struct lut **globals, struct config *croot, struct arrow *arrowp,
1386 	int try, struct evalue *valuep)
1387 {
1388 	struct evalue *gval;
1389 	struct evalue lval;
1390 	struct evalue rval;
1391 
1392 	if (np == NULL) {
1393 		valuep->t = UINT64;
1394 		valuep->v = 1;	/* no constraint means "true" */
1395 		return (1);
1396 	}
1397 
1398 	valuep->t = UNDEFINED;
1399 
1400 	switch (np->t) {
1401 	case T_GLOBID:
1402 		if (try)
1403 			return (0);
1404 
1405 		/*
1406 		 * only handle case of getting (and not setting) the value
1407 		 * of a global variable
1408 		 */
1409 		gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
1410 		if (gval == NULL) {
1411 			return (0);
1412 		} else {
1413 			valuep->t = gval->t;
1414 			valuep->v = gval->v;
1415 			return (1);
1416 		}
1417 
1418 	case T_ASSIGN:
1419 		if (try)
1420 			return (0);
1421 
1422 		/*
1423 		 * first evaluate rhs, then try to store value in lhs which
1424 		 * should be a global variable
1425 		 */
1426 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1427 		    arrowp, try, &rval))
1428 			return (0);
1429 
1430 		ASSERT(np->u.expr.left->t == T_GLOBID);
1431 		gval = lut_lookup(*globals,
1432 		    (void *)np->u.expr.left->u.globid.s, NULL);
1433 
1434 		if (gval == NULL) {
1435 			gval = MALLOC(sizeof (*gval));
1436 			*globals = lut_add(*globals,
1437 			    (void *) np->u.expr.left->u.globid.s, gval, NULL);
1438 		}
1439 
1440 		gval->t = rval.t;
1441 		gval->v = rval.v;
1442 
1443 		if (gval->t == UINT64) {
1444 			out(O_ALTFP|O_VERB2,
1445 			    "assign $%s=%llu",
1446 			    np->u.expr.left->u.globid.s, gval->v);
1447 		} else {
1448 			out(O_ALTFP|O_VERB2,
1449 			    "assign $%s=\"%s\"",
1450 			    np->u.expr.left->u.globid.s,
1451 			    (char *)(uintptr_t)gval->v);
1452 		}
1453 
1454 		/*
1455 		 * but always return true -- an assignment should not
1456 		 * cause a constraint to be false.
1457 		 */
1458 		valuep->t = UINT64;
1459 		valuep->v = 1;
1460 		return (1);
1461 
1462 	case T_EQ:
1463 #define	IMPLICIT_ASSIGN_IN_EQ
1464 #ifdef IMPLICIT_ASSIGN_IN_EQ
1465 		/*
1466 		 * if lhs is an uninitialized global variable, perform
1467 		 * an assignment.
1468 		 *
1469 		 * one insidious side effect of implicit assignment is
1470 		 * that the "==" operator does not return a Boolean if
1471 		 * implicit assignment was performed.
1472 		 */
1473 		if (try == 0 &&
1474 		    np->u.expr.left->t == T_GLOBID &&
1475 		    (gval = lut_lookup(*globals,
1476 		    (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
1477 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1478 			    croot, arrowp, try, &rval))
1479 				return (0);
1480 
1481 			gval = MALLOC(sizeof (*gval));
1482 			*globals = lut_add(*globals,
1483 			    (void *) np->u.expr.left->u.globid.s,
1484 			    gval, NULL);
1485 
1486 			gval->t = rval.t;
1487 			gval->v = rval.v;
1488 			valuep->t = rval.t;
1489 			valuep->v = rval.v;
1490 			return (1);
1491 		}
1492 #endif  /* IMPLICIT_ASSIGN_IN_EQ */
1493 
1494 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1495 		    arrowp, try, &lval))
1496 			return (0);
1497 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1498 		    arrowp, try, &rval))
1499 			return (0);
1500 		if (rval.t == UINT64 || lval.t == UINT64) {
1501 			if (check_expr_args(&lval, &rval, UINT64, np))
1502 				return (0);
1503 		} else {
1504 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
1505 				return (0);
1506 		}
1507 
1508 		valuep->t = UINT64;
1509 		valuep->v = (lval.v == rval.v);
1510 		return (1);
1511 
1512 	case T_LT:
1513 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1514 		    arrowp, try, &lval))
1515 			return (0);
1516 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1517 		    arrowp, try, &rval))
1518 			return (0);
1519 		if (check_expr_args(&lval, &rval, UINT64, np))
1520 			return (0);
1521 
1522 		valuep->t = UINT64;
1523 		valuep->v = (lval.v < rval.v);
1524 		return (1);
1525 
1526 	case T_LE:
1527 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1528 		    arrowp, try, &lval))
1529 			return (0);
1530 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1531 		    arrowp, try, &rval))
1532 			return (0);
1533 		if (check_expr_args(&lval, &rval, UINT64, np))
1534 			return (0);
1535 
1536 		valuep->t = UINT64;
1537 		valuep->v = (lval.v <= rval.v);
1538 		return (1);
1539 
1540 	case T_GT:
1541 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1542 		    arrowp, try, &lval))
1543 			return (0);
1544 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1545 		    arrowp, try, &rval))
1546 			return (0);
1547 		if (check_expr_args(&lval, &rval, UINT64, np))
1548 			return (0);
1549 
1550 		valuep->t = UINT64;
1551 		valuep->v = (lval.v > rval.v);
1552 		return (1);
1553 
1554 	case T_GE:
1555 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1556 		    arrowp, try, &lval))
1557 			return (0);
1558 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1559 		    arrowp, try, &rval))
1560 			return (0);
1561 		if (check_expr_args(&lval, &rval, UINT64, np))
1562 			return (0);
1563 
1564 		valuep->t = UINT64;
1565 		valuep->v = (lval.v >= rval.v);
1566 		return (1);
1567 
1568 	case T_BITAND:
1569 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1570 		    arrowp, try, &lval))
1571 			return (0);
1572 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1573 		    arrowp, try, &rval))
1574 			return (0);
1575 		if (check_expr_args(&lval, &rval, UINT64, np))
1576 			return (0);
1577 
1578 		valuep->t = lval.t;
1579 		valuep->v = (lval.v & rval.v);
1580 		return (1);
1581 
1582 	case T_BITOR:
1583 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1584 		    arrowp, try, &lval))
1585 			return (0);
1586 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1587 		    arrowp, try, &rval))
1588 			return (0);
1589 		if (check_expr_args(&lval, &rval, UINT64, np))
1590 			return (0);
1591 
1592 		valuep->t = lval.t;
1593 		valuep->v = (lval.v | rval.v);
1594 		return (1);
1595 
1596 	case T_BITXOR:
1597 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1598 		    arrowp, try, &lval))
1599 			return (0);
1600 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1601 		    arrowp, try, &rval))
1602 			return (0);
1603 		if (check_expr_args(&lval, &rval, UINT64, np))
1604 			return (0);
1605 
1606 		valuep->t = lval.t;
1607 		valuep->v = (lval.v ^ rval.v);
1608 		return (1);
1609 
1610 	case T_BITNOT:
1611 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1612 		    arrowp, try, &lval))
1613 			return (0);
1614 		ASSERT(np->u.expr.right == NULL);
1615 		if (check_expr_args(&lval, NULL, UINT64, np))
1616 			return (0);
1617 
1618 		valuep->t = UINT64;
1619 		valuep->v = ~ lval.v;
1620 		return (1);
1621 
1622 	case T_LSHIFT:
1623 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1624 		    arrowp, try, &lval))
1625 			return (0);
1626 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1627 		    arrowp, try, &rval))
1628 			return (0);
1629 		if (check_expr_args(&lval, &rval, UINT64, np))
1630 			return (0);
1631 
1632 		valuep->t = UINT64;
1633 		valuep->v = (lval.v << rval.v);
1634 		return (1);
1635 
1636 	case T_RSHIFT:
1637 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1638 		    arrowp, try, &lval))
1639 			return (0);
1640 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1641 		    arrowp, try, &rval))
1642 			return (0);
1643 		if (check_expr_args(&lval, &rval, UINT64, np))
1644 			return (0);
1645 
1646 		valuep->t = UINT64;
1647 		valuep->v = (lval.v >> rval.v);
1648 		return (1);
1649 
1650 	case T_CONDIF: {
1651 		struct node *retnp;
1652 		int dotrue = 0;
1653 
1654 		/*
1655 		 * evaluate
1656 		 *	expression ? stmtA [ : stmtB ]
1657 		 *
1658 		 * first see if expression is true or false, then determine
1659 		 * if stmtA (or stmtB, if it exists) should be evaluated.
1660 		 *
1661 		 * "dotrue = 1" means stmtA should be evaluated.
1662 		 */
1663 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1664 		    arrowp, try, &lval))
1665 			return (0);
1666 
1667 		if (lval.t != UNDEFINED && lval.v != 0)
1668 			dotrue = 1;
1669 
1670 		ASSERT(np->u.expr.right != NULL);
1671 		if (np->u.expr.right->t == T_CONDELSE) {
1672 			if (dotrue)
1673 				retnp = np->u.expr.right->u.expr.left;
1674 			else
1675 				retnp = np->u.expr.right->u.expr.right;
1676 		} else {
1677 			/* no ELSE clause */
1678 			if (dotrue)
1679 				retnp = np->u.expr.right;
1680 			else {
1681 				outfl(O_DIE, np->file, np->line,
1682 				    "eval_expr: missing condelse");
1683 			}
1684 		}
1685 
1686 		if (!eval_expr(retnp, ex, events, globals, croot,
1687 		    arrowp, try, valuep))
1688 			return (0);
1689 		return (1);
1690 	}
1691 
1692 	case T_CONDELSE:
1693 		/*
1694 		 * shouldn't get here, since T_CONDELSE is supposed to be
1695 		 * evaluated as part of T_CONDIF
1696 		 */
1697 		out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
1698 		    ptree_nodetype2str(np->t));
1699 		/*NOTREACHED*/
1700 
1701 	case T_NE:
1702 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1703 		    arrowp, try, &lval))
1704 			return (0);
1705 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1706 		    arrowp, try, &rval))
1707 			return (0);
1708 		if (rval.t == UINT64 || lval.t == UINT64) {
1709 			if (check_expr_args(&lval, &rval, UINT64, np))
1710 				return (0);
1711 		} else {
1712 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
1713 				return (0);
1714 		}
1715 
1716 		valuep->t = UINT64;
1717 		valuep->v = (lval.v != rval.v);
1718 		return (1);
1719 
1720 	case T_LIST:
1721 	case T_AND:
1722 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1723 		    arrowp, try, valuep)) {
1724 			/*
1725 			 * if lhs is unknown, still check rhs. If that
1726 			 * is false we can return false irrespective of lhs
1727 			 */
1728 			if (!try) {
1729 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1730 				return (0);
1731 			}
1732 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1733 			    croot, arrowp, try, valuep)) {
1734 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1735 				return (0);
1736 			}
1737 			if (valuep->v != 0) {
1738 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
1739 				return (0);
1740 			}
1741 		}
1742 		if (valuep->v == 0) {
1743 			valuep->t = UINT64;
1744 			return (1);
1745 		}
1746 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1747 		    arrowp, try, valuep)) {
1748 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
1749 			return (0);
1750 		}
1751 		valuep->t = UINT64;
1752 		valuep->v = valuep->v == 0 ? 0 : 1;
1753 		return (1);
1754 
1755 	case T_OR:
1756 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1757 		    arrowp, try, valuep)) {
1758 			/*
1759 			 * if lhs is unknown, still check rhs. If that
1760 			 * is true we can return true irrespective of lhs
1761 			 */
1762 			if (!try) {
1763 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1764 				return (0);
1765 			}
1766 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1767 			    croot, arrowp, try, valuep)) {
1768 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1769 				return (0);
1770 			}
1771 			if (valuep->v == 0) {
1772 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
1773 				return (0);
1774 			}
1775 		}
1776 		if (valuep->v != 0) {
1777 			valuep->t = UINT64;
1778 			valuep->v = 1;
1779 			return (1);
1780 		}
1781 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1782 		    arrowp, try, valuep)) {
1783 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
1784 			return (0);
1785 		}
1786 		valuep->t = UINT64;
1787 		valuep->v = valuep->v == 0 ? 0 : 1;
1788 		return (1);
1789 
1790 	case T_NOT:
1791 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1792 		    arrowp, try, valuep))
1793 			return (0);
1794 		valuep->t = UINT64;
1795 		valuep->v = ! valuep->v;
1796 		return (1);
1797 
1798 	case T_ADD:
1799 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1800 		    arrowp, try, &lval))
1801 			return (0);
1802 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1803 		    arrowp, try, &rval))
1804 			return (0);
1805 		if (check_expr_args(&lval, &rval, UINT64, np))
1806 			return (0);
1807 
1808 		valuep->t = lval.t;
1809 		valuep->v = lval.v + rval.v;
1810 		return (1);
1811 
1812 	case T_SUB:
1813 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1814 		    arrowp, try, &lval))
1815 			return (0);
1816 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1817 		    arrowp, try, &rval))
1818 			return (0);
1819 		if (check_expr_args(&lval, &rval, UINT64, np))
1820 			return (0);
1821 
1822 		/* since valuep is unsigned, return false if lval.v < rval.v */
1823 		if (lval.v < rval.v) {
1824 			outfl(O_DIE, np->file, np->line,
1825 			    "eval_expr: T_SUB result is out of range");
1826 		}
1827 
1828 		valuep->t = lval.t;
1829 		valuep->v = lval.v - rval.v;
1830 		return (1);
1831 
1832 	case T_MUL:
1833 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1834 		    arrowp, try, &lval))
1835 			return (0);
1836 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1837 		    arrowp, try, &rval))
1838 			return (0);
1839 		if (check_expr_args(&lval, &rval, UINT64, np))
1840 			return (0);
1841 
1842 		valuep->t = lval.t;
1843 		valuep->v = lval.v * rval.v;
1844 		return (1);
1845 
1846 	case T_DIV:
1847 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1848 		    arrowp, try, &lval))
1849 			return (0);
1850 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1851 		    arrowp, try, &rval))
1852 			return (0);
1853 		if (check_expr_args(&lval, &rval, UINT64, np))
1854 			return (0);
1855 
1856 		/* return false if dividing by zero */
1857 		if (rval.v == 0) {
1858 			outfl(O_DIE, np->file, np->line,
1859 			    "eval_expr: T_DIV division by zero");
1860 		}
1861 
1862 		valuep->t = lval.t;
1863 		valuep->v = lval.v / rval.v;
1864 		return (1);
1865 
1866 	case T_MOD:
1867 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1868 		    arrowp, try, &lval))
1869 			return (0);
1870 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1871 		    arrowp, try, &rval))
1872 			return (0);
1873 		if (check_expr_args(&lval, &rval, UINT64, np))
1874 			return (0);
1875 
1876 		/* return false if dividing by zero */
1877 		if (rval.v == 0) {
1878 			outfl(O_DIE, np->file, np->line,
1879 			    "eval_expr: T_MOD division by zero");
1880 		}
1881 
1882 		valuep->t = lval.t;
1883 		valuep->v = lval.v % rval.v;
1884 		return (1);
1885 
1886 	case T_NAME:
1887 		if (try) {
1888 			struct iterinfo *iterinfop;
1889 			struct node *np1, *np2;
1890 			int i, gotmatch = 0;
1891 
1892 			/*
1893 			 * Check if we have an exact match of the nonwildcarded
1894 			 * path in oldepname - if so we can just use the
1895 			 * full wildcarded path in epname.
1896 			 */
1897 			for (i = 0; i < 1; i++) {
1898 				for (np1 = np,
1899 				    np2 = events[i]->u.event.oldepname;
1900 				    np1 != NULL && np2 != NULL;
1901 				    np1 = np1->u.name.next,
1902 				    np2 = np2->u.name.next) {
1903 					if (strcmp(np1->u.name.s,
1904 					    np2->u.name.s) != 0)
1905 						break;
1906 					if (np1->u.name.child->t !=
1907 					    np2->u.name.child->t)
1908 						break;
1909 					if (np1->u.name.child->t == T_NUM &&
1910 					    np1->u.name.child->u.ull !=
1911 					    np2->u.name.child->u.ull)
1912 						break;
1913 					if (np1->u.name.child->t == T_NAME &&
1914 					    strcmp(np1->u.name.child->u.name.s,
1915 					    np2->u.name.child->u.name.s) != 0)
1916 						break;
1917 					gotmatch++;
1918 				}
1919 				if (np1 == NULL && np2 == NULL) {
1920 					valuep->t = NODEPTR;
1921 					valuep->v = (uintptr_t)
1922 					    events[i]->u.event.epname;
1923 					return (1);
1924 				}
1925 			}
1926 			if (!gotmatch) {
1927 				/*
1928 				 * we're not wildcarding. However at
1929 				 * itree_create() time, we can also expand
1930 				 * simple iterators - so check for those.
1931 				 */
1932 				iterinfop = lut_lookup(ex, (void *)np->u.name.s,
1933 				    NULL);
1934 				if (iterinfop != NULL) {
1935 					valuep->t = UINT64;
1936 					valuep->v =
1937 					    (unsigned long long)iterinfop->num;
1938 					return (1);
1939 				}
1940 			}
1941 			/*
1942 			 * For anything else we'll have to wait for eval_dup().
1943 			 */
1944 			return (0);
1945 		}
1946 
1947 		/* return address of struct node */
1948 		valuep->t = NODEPTR;
1949 		valuep->v = (uintptr_t)np;
1950 		return (1);
1951 
1952 	case T_QUOTE:
1953 		valuep->t = STRING;
1954 		valuep->v = (uintptr_t)np->u.quote.s;
1955 		return (1);
1956 
1957 	case T_FUNC:
1958 		return (eval_func(np, ex, events, np->u.func.arglist,
1959 		    globals, croot, arrowp, try, valuep));
1960 
1961 	case T_NUM:
1962 	case T_TIMEVAL:
1963 		valuep->t = UINT64;
1964 		valuep->v = np->u.ull;
1965 		return (1);
1966 
1967 	default:
1968 		outfl(O_DIE, np->file, np->line,
1969 		    "eval_expr: unexpected node type: %s",
1970 		    ptree_nodetype2str(np->t));
1971 	}
1972 	/*NOTREACHED*/
1973 	return (0);
1974 }
1975 
1976 /*
1977  * eval_fru() and eval_asru() don't do much, but are called from a number
1978  * of places.
1979  */
1980 static struct node *
1981 eval_fru(struct node *np)
1982 {
1983 	ASSERT(np->t == T_NAME);
1984 	return (np);
1985 }
1986 
1987 static struct node *
1988 eval_asru(struct node *np)
1989 {
1990 	ASSERT(np->t == T_NAME);
1991 	return (np);
1992 }
1993