xref: /illumos-gate/usr/src/cmd/fm/modules/common/eversholt/eval.c (revision 945e3b4bc345679cad92f0a896670030a411c8f8)
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 2010 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 			nvlist_free(rsrc);
541 		}
542 		valuep->t = UINT64;
543 		return (1);
544 	} else if (funcname == L_count) {
545 		struct stats *statp;
546 		struct istat_entry ent;
547 
548 		ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
549 
550 		nodep = np->u.event.epname;
551 		if (try) {
552 			if (eval_expr(nodep, ex, events, globals,
553 			    croot, arrowp, try, &val) && val.t == NODEPTR)
554 				nodep = (struct node *)(uintptr_t)val.v;
555 			else {
556 				duped = 1;
557 				nodep = eval_dup(nodep, ex, events);
558 			}
559 		}
560 		ent.ename = np->u.event.ename->u.name.s;
561 		ent.ipath = ipath(nodep);
562 		valuep->t = UINT64;
563 		if ((statp = (struct stats *)
564 		    lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
565 			valuep->v = 0;
566 		else
567 			valuep->v = stats_counter_value(statp);
568 		if (duped)
569 			tree_free(nodep);
570 		return (1);
571 	} else if (funcname == L_envprop) {
572 		outfl(O_DIE, np->file, np->line,
573 		    "eval_func: %s not yet supported", funcname);
574 	}
575 
576 	if (try)
577 		return (0);
578 
579 	if (funcname == L_fru) {
580 		valuep->t = NODEPTR;
581 		valuep->v = (uintptr_t)eval_fru(np);
582 		return (1);
583 	} else if (funcname == L_asru) {
584 		valuep->t = NODEPTR;
585 		valuep->v = (uintptr_t)eval_asru(np);
586 		return (1);
587 	} else if (funcname == L_defined) {
588 		ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
589 		valuep->t = UINT64;
590 		valuep->v = (lut_lookup(*globals,
591 		    (void *)np->u.globid.s, NULL) != NULL);
592 		return (1);
593 	} else if (funcname == L_call) {
594 		return (! platform_call(np, globals, croot, arrowp, valuep));
595 	} else if (funcname == L_payloadprop) {
596 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
597 		    "payloadprop(\"%s\") ", np->u.quote.s);
598 
599 		if (arrowp->head->myevent->count == 0) {
600 			/*
601 			 * Haven't seen this ereport yet, so must defer
602 			 */
603 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
604 			return (0);
605 		} else if (platform_payloadprop(np, valuep)) {
606 			/* platform_payloadprop() returned false */
607 			out(O_ALTFP|O_VERB, "not found.");
608 			valuep->t = UNDEFINED;
609 			return (1);
610 		} else {
611 			switch (valuep->t) {
612 			case NODEPTR:
613 				if (((struct node *)(uintptr_t)
614 				    (valuep->v))->t == T_NAME) {
615 					char *s = ipath2str(NULL,
616 					    ipath((struct node *)
617 					    (uintptr_t)valuep->v));
618 					out(O_ALTFP|O_VERB2,
619 					    "found: \"%s\"", s);
620 					FREE(s);
621 				} else
622 					out(O_ALTFP|O_VERB2, "found: %llu",
623 					    valuep->v);
624 				break;
625 			case UINT64:
626 				out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
627 				break;
628 			case STRING:
629 				out(O_ALTFP|O_VERB2, "found: \"%s\"",
630 				    (char *)(uintptr_t)valuep->v);
631 				break;
632 			default:
633 				out(O_ALTFP|O_VERB2, "found: undefined");
634 				break;
635 			}
636 			return (1);
637 		}
638 	} else if (funcname == L_setpayloadprop) {
639 		struct evalue *payloadvalp;
640 		int alloced = 0;
641 
642 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
643 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
644 		    ptree_nodetype2str(np->u.expr.left->t));
645 
646 		if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
647 			return (0);
648 
649 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
650 		    "setpayloadprop: %s: %s=",
651 		    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
652 		    np->u.expr.left->u.quote.s);
653 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
654 
655 		/*
656 		 * allocate a struct evalue to hold the payload property's
657 		 * value, unless we've been here already, in which case we
658 		 * might calculate a different value, but we'll store it
659 		 * in the already-allocated struct evalue.
660 		 */
661 		if ((payloadvalp = (struct evalue *)lut_lookup(
662 		    arrowp->tail->myevent->payloadprops,
663 		    (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
664 			payloadvalp = MALLOC(sizeof (*payloadvalp));
665 			alloced = 1;
666 		}
667 
668 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
669 		    arrowp, try, payloadvalp)) {
670 			out(O_ALTFP|O_VERB2, " (cannot eval)");
671 			if (alloced)
672 				FREE(payloadvalp);
673 			return (0);
674 		} else {
675 			if (payloadvalp->t == UNDEFINED) {
676 				/* function is always true */
677 				out(O_ALTFP|O_VERB2, " (undefined)");
678 				valuep->t = UINT64;
679 				valuep->v = 1;
680 				return (1);
681 			}
682 			if (payloadvalp->t == UINT64)
683 				out(O_ALTFP|O_VERB2,
684 				    " (%llu)", payloadvalp->v);
685 			else
686 				out(O_ALTFP|O_VERB2, " (\"%s\")",
687 				    (char *)(uintptr_t)payloadvalp->v);
688 		}
689 
690 		/* add to table of payload properties for current problem */
691 		arrowp->tail->myevent->payloadprops =
692 		    lut_add(arrowp->tail->myevent->payloadprops,
693 		    (void *)np->u.expr.left->u.quote.s,
694 		    (void *)payloadvalp, NULL);
695 
696 		/* function is always true */
697 		valuep->t = UINT64;
698 		valuep->v = 1;
699 		return (1);
700 	} else if (funcname == L_cat) {
701 		int retval = eval_cat(np, ex, events, globals, croot,
702 		    arrowp, try, valuep);
703 
704 		outfl(O_ALTFP|O_VERB2, np->file, np->line,
705 		    "cat: returns %s", (char *)(uintptr_t)valuep->v);
706 		return (retval);
707 	} else if (funcname == L_setserdn || funcname == L_setserdt ||
708 	    funcname == L_setserdsuffix || funcname == L_setserdincrement) {
709 		struct evalue *serdvalp;
710 		int alloced = 0;
711 		char *str;
712 		struct event *flt = arrowp->tail->myevent;
713 
714 		if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
715 			return (0);
716 
717 		if (funcname == L_setserdn)
718 			str = "n";
719 		else if (funcname == L_setserdt)
720 			str = "t";
721 		else if (funcname == L_setserdsuffix)
722 			str = "suffix";
723 		else if (funcname == L_setserdincrement)
724 			str = "increment";
725 
726 		/*
727 		 * allocate a struct evalue to hold the serd property's
728 		 * value, unless we've been here already, in which case we
729 		 * might calculate a different value, but we'll store it
730 		 * in the already-allocated struct evalue.
731 		 */
732 		if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops,
733 		    (void *)str, (lut_cmp)strcmp)) == NULL) {
734 			serdvalp = MALLOC(sizeof (*serdvalp));
735 			alloced = 1;
736 		}
737 
738 		if (!eval_expr(np, ex, events, globals, croot, arrowp, try,
739 		    serdvalp)) {
740 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
741 			    "setserd%s: %s: ", str,
742 			    flt->enode->u.event.ename->u.name.s);
743 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
744 			out(O_ALTFP|O_VERB2, " (cannot eval)");
745 			if (alloced)
746 				FREE(serdvalp);
747 			return (0);
748 		} else if (serdvalp->t == UNDEFINED) {
749 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
750 			    "setserd%s: %s: ", str,
751 			    flt->enode->u.event.ename->u.name.s);
752 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
753 			out(O_ALTFP|O_VERB2, " (undefined)");
754 		} else {
755 			outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
756 			    "setserd%s: %s: ", str,
757 			    flt->enode->u.event.ename->u.name.s);
758 			ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
759 			if ((funcname == L_setserdincrement ||
760 			    funcname == L_setserdn) && serdvalp->t == STRING) {
761 				serdvalp->t = UINT64;
762 				serdvalp->v = strtoull((char *)
763 				    (uintptr_t)serdvalp->v, NULL, 0);
764 			}
765 			if (funcname == L_setserdt && serdvalp->t == UINT64) {
766 				int len = snprintf(NULL, 0, "%lldns",
767 				    serdvalp->v);
768 				char *buf = MALLOC(len + 1);
769 
770 				(void) snprintf(buf, len + 1, "%lldns",
771 				    serdvalp->v);
772 				serdvalp->t = STRING;
773 				serdvalp->v = (uintptr_t)stable(buf);
774 				FREE(buf);
775 			}
776 			if (funcname == L_setserdsuffix &&
777 			    serdvalp->t == UINT64) {
778 				int len = snprintf(NULL, 0, "%lld",
779 				    serdvalp->v);
780 				char *buf = MALLOC(len + 1);
781 
782 				(void) snprintf(buf, len + 1, "%lld",
783 				    serdvalp->v);
784 				serdvalp->t = STRING;
785 				serdvalp->v = (uintptr_t)stable(buf);
786 				FREE(buf);
787 			}
788 
789 			if (serdvalp->t == UINT64)
790 				out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v);
791 			else
792 				out(O_ALTFP|O_VERB2, " (\"%s\")",
793 				    (char *)(uintptr_t)serdvalp->v);
794 			flt->serdprops = lut_add(flt->serdprops, (void *)str,
795 			    (void *)serdvalp, (lut_cmp)strcmp);
796 		}
797 		valuep->t = UINT64;
798 		valuep->v = 1;
799 		return (1);
800 	} else if (funcname == L_payloadprop_defined) {
801 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
802 		    "payloadprop_defined(\"%s\") ", np->u.quote.s);
803 
804 		if (arrowp->head->myevent->count == 0) {
805 			/*
806 			 * Haven't seen this ereport yet, so must defer
807 			 */
808 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
809 			return (0);
810 		} else if (platform_payloadprop(np, NULL)) {
811 			/* platform_payloadprop() returned false */
812 			valuep->v = 0;
813 			out(O_ALTFP|O_VERB2, "not found.");
814 		} else {
815 			valuep->v = 1;
816 			out(O_ALTFP|O_VERB2, "found.");
817 		}
818 		valuep->t = UINT64;
819 		return (1);
820 	} else if (funcname == L_payloadprop_contains) {
821 		int nvals;
822 		struct evalue *vals;
823 		struct evalue cmpval;
824 
825 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
826 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
827 		    ptree_nodetype2str(np->u.expr.left->t));
828 
829 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
830 		    "payloadprop_contains(\"%s\", ",
831 		    np->u.expr.left->u.quote.s);
832 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
833 		out(O_ALTFP|O_VERB2|O_NONL, ") ");
834 
835 		/* evaluate the expression we're comparing against */
836 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
837 		    arrowp, try, &cmpval)) {
838 			out(O_ALTFP|O_VERB2|O_NONL,
839 			    "(cannot eval) ");
840 			return (0);
841 		} else {
842 			switch (cmpval.t) {
843 			case UNDEFINED:
844 				out(O_ALTFP|O_VERB2, "(undefined type)");
845 				break;
846 
847 			case UINT64:
848 				out(O_ALTFP|O_VERB2,
849 				    "(%llu) ", cmpval.v);
850 				break;
851 
852 			case STRING:
853 				out(O_ALTFP|O_VERB2,
854 				    "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
855 				break;
856 
857 			case NODEPTR:
858 				out(O_ALTFP|O_VERB2|O_NONL, "(");
859 				ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
860 				    (struct node *)(uintptr_t)(cmpval.v));
861 				out(O_ALTFP|O_VERB2, ") ");
862 				break;
863 			}
864 		}
865 
866 		/* get the payload values and check for a match */
867 		vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
868 		    &nvals);
869 		valuep->t = UINT64;
870 		valuep->v = 0;
871 		if (arrowp->head->myevent->count == 0) {
872 			/*
873 			 * Haven't seen this ereport yet, so must defer
874 			 */
875 			out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
876 			return (0);
877 		} else if (nvals == 0) {
878 			out(O_ALTFP|O_VERB2, "not found.");
879 			return (1);
880 		} else {
881 			struct evalue preval;
882 			int i;
883 
884 			out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
885 
886 			for (i = 0; i < nvals; i++) {
887 
888 				preval.t = vals[i].t;
889 				preval.v = vals[i].v;
890 
891 				if (check_expr_args(&vals[i], &cmpval,
892 				    UNDEFINED, np))
893 					continue;
894 
895 				/*
896 				 * If we auto-converted the value to a
897 				 * string, we need to free the
898 				 * original tree value.
899 				 */
900 				if (preval.t == NODEPTR &&
901 				    ((struct node *)(uintptr_t)(preval.v))->t ==
902 				    T_NAME) {
903 					tree_free((struct node *)(uintptr_t)
904 					    preval.v);
905 				}
906 
907 				if (vals[i].v == cmpval.v) {
908 					valuep->v = 1;
909 					break;
910 				}
911 			}
912 
913 			if (valuep->v)
914 				out(O_ALTFP|O_VERB2, "match.");
915 			else
916 				out(O_ALTFP|O_VERB2, "no match.");
917 
918 			for (i = 0; i < nvals; i++) {
919 				if (vals[i].t == NODEPTR) {
920 					tree_free((struct node *)(uintptr_t)
921 					    vals[i].v);
922 					break;
923 				}
924 			}
925 			FREE(vals);
926 		}
927 		return (1);
928 	} else if (funcname == L_confcall) {
929 		return (!platform_confcall(np, globals, croot, arrowp, valuep));
930 	} else
931 		outfl(O_DIE, np->file, np->line,
932 		    "eval_func: unexpected func: %s", funcname);
933 	/*NOTREACHED*/
934 	return (0);
935 }
936 
937 /*
938  * defines for u.expr.temp - these are used for T_OR and T_AND so that if
939  * we worked out that part of the expression was true or false during an
940  * earlier eval_expr, then we don't need to dup that part.
941  */
942 
943 #define	EXPR_TEMP_BOTH_UNK	0
944 #define	EXPR_TEMP_LHS_UNK	1
945 #define	EXPR_TEMP_RHS_UNK	2
946 
947 static struct node *
948 eval_dup(struct node *np, struct lut *ex, struct node *events[])
949 {
950 	struct node *newnp;
951 
952 	if (np == NULL)
953 		return (NULL);
954 
955 	switch (np->t) {
956 	case T_GLOBID:
957 		return (tree_globid(np->u.globid.s, np->file, np->line));
958 
959 	case T_ASSIGN:
960 	case T_CONDIF:
961 	case T_CONDELSE:
962 	case T_NE:
963 	case T_EQ:
964 	case T_LT:
965 	case T_LE:
966 	case T_GT:
967 	case T_GE:
968 	case T_BITAND:
969 	case T_BITOR:
970 	case T_BITXOR:
971 	case T_BITNOT:
972 	case T_LSHIFT:
973 	case T_RSHIFT:
974 	case T_NOT:
975 	case T_ADD:
976 	case T_SUB:
977 	case T_MUL:
978 	case T_DIV:
979 	case T_MOD:
980 		return (tree_expr(np->t,
981 		    eval_dup(np->u.expr.left, ex, events),
982 		    eval_dup(np->u.expr.right, ex, events)));
983 	case T_LIST:
984 	case T_AND:
985 		switch (np->u.expr.temp) {
986 		case EXPR_TEMP_LHS_UNK:
987 			return (eval_dup(np->u.expr.left, ex, events));
988 		case EXPR_TEMP_RHS_UNK:
989 			return (eval_dup(np->u.expr.right, ex, events));
990 		default:
991 			return (tree_expr(np->t,
992 			    eval_dup(np->u.expr.left, ex, events),
993 			    eval_dup(np->u.expr.right, ex, events)));
994 		}
995 
996 	case T_OR:
997 		switch (np->u.expr.temp) {
998 		case EXPR_TEMP_LHS_UNK:
999 			return (eval_dup(np->u.expr.left, ex, events));
1000 		case EXPR_TEMP_RHS_UNK:
1001 			return (eval_dup(np->u.expr.right, ex, events));
1002 		default:
1003 			return (tree_expr(T_OR,
1004 			    eval_dup(np->u.expr.left, ex, events),
1005 			    eval_dup(np->u.expr.right, ex, events)));
1006 		}
1007 
1008 	case T_NAME: {
1009 		struct iterinfo *iterinfop;
1010 		int got_matchf = 0;
1011 		int got_matcht = 0;
1012 		struct evalue value;
1013 		struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
1014 		struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
1015 
1016 		/*
1017 		 * Check if we already have a match of the nonwildcarded path
1018 		 * in oldepname (check both to and from events).
1019 		 */
1020 		for (np1f = np, np2f = events[0]->u.event.oldepname;
1021 		    np1f != NULL && np2f != NULL;
1022 		    np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
1023 			if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
1024 				break;
1025 			if (np1f->u.name.child->t != np2f->u.name.child->t)
1026 				break;
1027 			if (np1f->u.name.child->t == T_NUM &&
1028 			    np1f->u.name.child->u.ull !=
1029 			    np2f->u.name.child->u.ull)
1030 				break;
1031 			if (np1f->u.name.child->t == T_NAME &&
1032 			    strcmp(np1f->u.name.child->u.name.s,
1033 			    np2f->u.name.child->u.name.s) != 0)
1034 				break;
1035 			got_matchf++;
1036 		}
1037 		for (np1t = np, np2t = events[1]->u.event.oldepname;
1038 		    np1t != NULL && np2t != NULL;
1039 		    np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
1040 			if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
1041 				break;
1042 			if (np1t->u.name.child->t != np2t->u.name.child->t)
1043 				break;
1044 			if (np1t->u.name.child->t == T_NUM &&
1045 			    np1t->u.name.child->u.ull !=
1046 			    np2t->u.name.child->u.ull)
1047 				break;
1048 			if (np1t->u.name.child->t == T_NAME &&
1049 			    strcmp(np1t->u.name.child->u.name.s,
1050 			    np2t->u.name.child->u.name.s) != 0)
1051 				break;
1052 			got_matcht++;
1053 		}
1054 		nprest = np;
1055 		if (got_matchf || got_matcht) {
1056 			/*
1057 			 * so we are wildcarding. Copy ewname in full, plus
1058 			 * matching section of oldepname. Use whichever gives
1059 			 * the closest match.
1060 			 */
1061 			if (got_matchf > got_matcht) {
1062 				npstart = events[0]->u.event.ewname;
1063 				npcont = events[0]->u.event.oldepname;
1064 				npend = np2f;
1065 				nprest = np1f;
1066 			} else {
1067 				npstart = events[1]->u.event.ewname;
1068 				npcont = events[1]->u.event.oldepname;
1069 				npend = np2t;
1070 				nprest = np1t;
1071 			}
1072 			for (npref = npstart; npref != NULL;
1073 			    npref = npref->u.name.next) {
1074 				newnp = newnode(T_NAME, np->file, np->line);
1075 				newnp->u.name.t = npref->u.name.t;
1076 				newnp->u.name.s = npref->u.name.s;
1077 				newnp->u.name.last = newnp;
1078 				newnp->u.name.it = npref->u.name.it;
1079 				newnp->u.name.cp = npref->u.name.cp;
1080 				newnp->u.name.child =
1081 				    newnode(T_NUM, np->file, np->line);
1082 				if (eval_expr(npref->u.name.child, ex, events,
1083 				    NULL, NULL, NULL, 1, &value) == 0 ||
1084 				    value.t != UINT64) {
1085 					outfl(O_DIE, np->file, np->line,
1086 					    "eval_dup: could not resolve "
1087 					    "iterator of %s", np->u.name.s);
1088 				}
1089 				newnp->u.name.child->u.ull = value.v;
1090 				if (retp == NULL) {
1091 					retp = newnp;
1092 				} else {
1093 					retp->u.name.last->u.name.next = newnp;
1094 					retp->u.name.last = newnp;
1095 				}
1096 			}
1097 			for (npref = npcont; npref != NULL && npref != npend;
1098 			    npref = npref->u.name.next) {
1099 				newnp = newnode(T_NAME, np->file, np->line);
1100 				newnp->u.name.t = npref->u.name.t;
1101 				newnp->u.name.s = npref->u.name.s;
1102 				newnp->u.name.last = newnp;
1103 				newnp->u.name.it = npref->u.name.it;
1104 				newnp->u.name.cp = npref->u.name.cp;
1105 				newnp->u.name.child =
1106 				    newnode(T_NUM, np->file, np->line);
1107 				if (eval_expr(npref->u.name.child, ex, events,
1108 				    NULL, NULL, NULL, 1, &value) == 0 ||
1109 				    value.t != UINT64) {
1110 					outfl(O_DIE, np->file, np->line,
1111 					    "eval_dup: could not resolve "
1112 					    "iterator of %s", np->u.name.s);
1113 				}
1114 				newnp->u.name.child->u.ull = value.v;
1115 				if (retp == NULL) {
1116 					retp = newnp;
1117 				} else {
1118 					retp->u.name.last->u.name.next = newnp;
1119 					retp->u.name.last = newnp;
1120 				}
1121 			}
1122 		} else {
1123 			/*
1124 			 * not wildcarding - check if explicit iterator
1125 			 */
1126 			iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
1127 			if (iterinfop != NULL) {
1128 				/* explicit iterator; not part of pathname */
1129 				newnp = newnode(T_NUM, np->file, np->line);
1130 				newnp->u.ull = iterinfop->num;
1131 				return (newnp);
1132 			}
1133 		}
1134 
1135 		/*
1136 		 * finally, whether wildcarding or not, we need to copy the
1137 		 * remaining part of the path (if any). This must be defined
1138 		 * absolutely (no more expansion/wildcarding).
1139 		 */
1140 		for (npref = nprest; npref != NULL;
1141 		    npref = npref->u.name.next) {
1142 			newnp = newnode(T_NAME, np->file, np->line);
1143 			newnp->u.name.t = npref->u.name.t;
1144 			newnp->u.name.s = npref->u.name.s;
1145 			newnp->u.name.last = newnp;
1146 			newnp->u.name.it = npref->u.name.it;
1147 			newnp->u.name.cp = npref->u.name.cp;
1148 			newnp->u.name.child =
1149 			    newnode(T_NUM, np->file, np->line);
1150 			if (eval_expr(npref->u.name.child, ex, events,
1151 			    NULL, NULL, NULL, 1, &value) == 0 ||
1152 			    value.t != UINT64) {
1153 				outfl(O_DIE, np->file, np->line,
1154 				    "eval_dup: could not resolve "
1155 				    "iterator of %s", np->u.name.s);
1156 			}
1157 			newnp->u.name.child->u.ull = value.v;
1158 			if (retp == NULL) {
1159 				retp = newnp;
1160 			} else {
1161 				retp->u.name.last->u.name.next = newnp;
1162 				retp->u.name.last = newnp;
1163 			}
1164 		}
1165 		return (retp);
1166 	}
1167 
1168 	case T_EVENT:
1169 		newnp = newnode(T_NAME, np->file, np->line);
1170 
1171 		newnp->u.name.t = np->u.event.ename->u.name.t;
1172 		newnp->u.name.s = np->u.event.ename->u.name.s;
1173 		newnp->u.name.it = np->u.event.ename->u.name.it;
1174 		newnp->u.name.last = newnp;
1175 
1176 		return (tree_event(newnp,
1177 		    eval_dup(np->u.event.epname, ex, events),
1178 		    eval_dup(np->u.event.eexprlist, ex, events)));
1179 
1180 	case T_FUNC:
1181 		return (tree_func(np->u.func.s,
1182 		    eval_dup(np->u.func.arglist, ex, events),
1183 		    np->file, np->line));
1184 
1185 	case T_QUOTE:
1186 		newnp = newnode(T_QUOTE, np->file, np->line);
1187 		newnp->u.quote.s = np->u.quote.s;
1188 		return (newnp);
1189 
1190 	case T_NUM:
1191 		newnp = newnode(T_NUM, np->file, np->line);
1192 		newnp->u.ull = np->u.ull;
1193 		return (newnp);
1194 
1195 	case T_TIMEVAL:
1196 		newnp = newnode(T_TIMEVAL, np->file, np->line);
1197 		newnp->u.ull = np->u.ull;
1198 		return (newnp);
1199 
1200 	default:
1201 		outfl(O_DIE, np->file, np->line,
1202 		    "eval_dup: unexpected node type: %s",
1203 		    ptree_nodetype2str(np->t));
1204 	}
1205 	/*NOTREACHED*/
1206 	return (0);
1207 }
1208 
1209 /*
1210  * eval_potential -- see if constraint is potentially true
1211  *
1212  * this function is used at instance tree creation time to see if
1213  * any constraints are already known to be false.  if this function
1214  * returns false, then the constraint will always be false and there's
1215  * no need to include the propagation arrow in the instance tree.
1216  *
1217  * if this routine returns true, either the constraint is known to
1218  * be always true (so there's no point in attaching the constraint
1219  * to the propagation arrow in the instance tree), or the constraint
1220  * contains "deferred" expressions like global variables or poller calls
1221  * and so it must be evaluated during calls to fme_eval().  in this last
1222  * case, where a constraint needs to be attached to the propagation arrow
1223  * in the instance tree, this routine returns a newly created constraint
1224  * in *newc where all the non-deferred things have been filled in.
1225  *
1226  * so in summary:
1227  *
1228  *	return of false: constraint can never be true, *newc will be NULL.
1229  *
1230  *	return of true with *newc unchanged: constraint will always be true.
1231  *
1232  *	return of true with *newc changed: use new constraint in *newc.
1233  *
1234  * the lookup table for all explicit iterators, ex, is passed in.
1235  *
1236  * *newc can either be NULL on entry, or if can contain constraints from
1237  * previous calls to eval_potential() (i.e. for building up an instance
1238  * tree constraint from several potential constraints).  if *newc already
1239  * contains constraints, anything added to it will be joined by adding
1240  * a T_AND node at the top of *newc.
1241  */
1242 int
1243 eval_potential(struct node *np, struct lut *ex, struct node *events[],
1244 	    struct node **newc, struct config *croot)
1245 {
1246 	struct node *newnp;
1247 	struct evalue value;
1248 
1249 	if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
1250 		/*
1251 		 * couldn't eval expression because
1252 		 * it contains deferred items.  make
1253 		 * a duplicate expression with all the
1254 		 * non-deferred items expanded.
1255 		 */
1256 		newnp = eval_dup(np, ex, events);
1257 
1258 		if (*newc == NULL) {
1259 			/*
1260 			 * constraint is potentially true if deferred
1261 			 * expression in newnp is true.  *newc was NULL
1262 			 * so new constraint is just the one in newnp.
1263 			 */
1264 			*newc = newnp;
1265 			return (1);
1266 		} else {
1267 			/*
1268 			 * constraint is potentially true if deferred
1269 			 * expression in newnp is true.  *newc already
1270 			 * contained a constraint so add an AND with the
1271 			 * constraint in newnp.
1272 			 */
1273 			*newc = tree_expr(T_AND, *newc, newnp);
1274 			return (1);
1275 		}
1276 	} else if (value.t == UNDEFINED) {
1277 		/* constraint can never be true */
1278 		return (0);
1279 	} else if (value.t == UINT64 && value.v == 0) {
1280 		/* constraint can never be true */
1281 		return (0);
1282 	} else {
1283 		/* constraint is always true (nothing deferred to eval) */
1284 		return (1);
1285 	}
1286 }
1287 
1288 static int
1289 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
1290 		struct node *np)
1291 {
1292 	/* auto-convert T_NAMES to strings */
1293 	if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
1294 	    T_NAME) {
1295 		char *s = ipath2str(NULL,
1296 		    ipath((struct node *)(uintptr_t)lp->v));
1297 		lp->t = STRING;
1298 		lp->v = (uintptr_t)stable(s);
1299 		FREE(s);
1300 		out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
1301 		    (char *)(uintptr_t)lp->v);
1302 	}
1303 	if (rp != NULL &&
1304 	    rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
1305 	    T_NAME) {
1306 		char *s = ipath2str(NULL,
1307 		    ipath((struct node *)(uintptr_t)rp->v));
1308 		rp->t = STRING;
1309 		rp->v = (uintptr_t)stable(s);
1310 		FREE(s);
1311 		out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
1312 		    (char *)(uintptr_t)rp->v);
1313 	}
1314 
1315 	/* auto-convert numbers to strings */
1316 	if (dtype == STRING) {
1317 		if (lp->t == UINT64) {
1318 			int len = snprintf(NULL, 0, "%llx", lp->v);
1319 			char *s = MALLOC(len + 1);
1320 
1321 			(void) snprintf(s, len + 1, "%llx", lp->v);
1322 			lp->t = STRING;
1323 			lp->v = (uintptr_t)stable(s);
1324 			FREE(s);
1325 		}
1326 		if (rp != NULL && rp->t == UINT64) {
1327 			int len = snprintf(NULL, 0, "%llx", rp->v);
1328 			char *s = MALLOC(len + 1);
1329 
1330 			(void) snprintf(s, len + 1, "%llx", rp->v);
1331 			rp->t = STRING;
1332 			rp->v = (uintptr_t)stable(s);
1333 			FREE(s);
1334 		}
1335 	}
1336 
1337 	/* auto-convert strings to numbers */
1338 	if (dtype == UINT64) {
1339 		if (lp->t == STRING) {
1340 			lp->t = UINT64;
1341 			lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
1342 		}
1343 		if (rp != NULL && rp->t == STRING) {
1344 			rp->t = UINT64;
1345 			rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
1346 		}
1347 	}
1348 
1349 	if (dtype != UNDEFINED && lp->t != dtype) {
1350 		outfl(O_DIE, np->file, np->line,
1351 		    "invalid datatype of argument for operation %s",
1352 		    ptree_nodetype2str(np->t));
1353 		/* NOTREACHED */
1354 		return (1);
1355 	}
1356 
1357 	if (rp != NULL && lp->t != rp->t) {
1358 		outfl(O_DIE, np->file, np->line,
1359 		    "mismatch in datatype of arguments for operation %s",
1360 		    ptree_nodetype2str(np->t));
1361 		/* NOTREACHED */
1362 		return (1);
1363 	}
1364 
1365 	return (0);
1366 }
1367 
1368 /*
1369  * eval_expr -- evaluate expression into *valuep
1370  *
1371  * the meaning of the return value depends on the input value of try.
1372  *
1373  * for try == 1: if any deferred items are encounted, bail out and return
1374  * false.  returns true if we made it through entire expression without
1375  * hitting any deferred items.
1376  *
1377  * for try == 0: return true if all operations were performed successfully.
1378  * return false if otherwise.  for example, any of the following conditions
1379  * will result in a false return value:
1380  *   - attempted use of an uninitialized global variable
1381  *   - failure in function evaluation
1382  *   - illegal arithmetic operation (argument out of range)
1383  */
1384 int
1385 eval_expr(struct node *np, struct lut *ex, struct node *events[],
1386 	struct lut **globals, struct config *croot, struct arrow *arrowp,
1387 	int try, struct evalue *valuep)
1388 {
1389 	struct evalue *gval;
1390 	struct evalue lval;
1391 	struct evalue rval;
1392 
1393 	if (np == NULL) {
1394 		valuep->t = UINT64;
1395 		valuep->v = 1;	/* no constraint means "true" */
1396 		return (1);
1397 	}
1398 
1399 	valuep->t = UNDEFINED;
1400 
1401 	switch (np->t) {
1402 	case T_GLOBID:
1403 		if (try)
1404 			return (0);
1405 
1406 		/*
1407 		 * only handle case of getting (and not setting) the value
1408 		 * of a global variable
1409 		 */
1410 		gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
1411 		if (gval == NULL) {
1412 			return (0);
1413 		} else {
1414 			valuep->t = gval->t;
1415 			valuep->v = gval->v;
1416 			return (1);
1417 		}
1418 
1419 	case T_ASSIGN:
1420 		if (try)
1421 			return (0);
1422 
1423 		/*
1424 		 * first evaluate rhs, then try to store value in lhs which
1425 		 * should be a global variable
1426 		 */
1427 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1428 		    arrowp, try, &rval))
1429 			return (0);
1430 
1431 		ASSERT(np->u.expr.left->t == T_GLOBID);
1432 		gval = lut_lookup(*globals,
1433 		    (void *)np->u.expr.left->u.globid.s, NULL);
1434 
1435 		if (gval == NULL) {
1436 			gval = MALLOC(sizeof (*gval));
1437 			*globals = lut_add(*globals,
1438 			    (void *) np->u.expr.left->u.globid.s, gval, NULL);
1439 		}
1440 
1441 		gval->t = rval.t;
1442 		gval->v = rval.v;
1443 
1444 		if (gval->t == UINT64) {
1445 			out(O_ALTFP|O_VERB2,
1446 			    "assign $%s=%llu",
1447 			    np->u.expr.left->u.globid.s, gval->v);
1448 		} else {
1449 			out(O_ALTFP|O_VERB2,
1450 			    "assign $%s=\"%s\"",
1451 			    np->u.expr.left->u.globid.s,
1452 			    (char *)(uintptr_t)gval->v);
1453 		}
1454 
1455 		/*
1456 		 * but always return true -- an assignment should not
1457 		 * cause a constraint to be false.
1458 		 */
1459 		valuep->t = UINT64;
1460 		valuep->v = 1;
1461 		return (1);
1462 
1463 	case T_EQ:
1464 #define	IMPLICIT_ASSIGN_IN_EQ
1465 #ifdef IMPLICIT_ASSIGN_IN_EQ
1466 		/*
1467 		 * if lhs is an uninitialized global variable, perform
1468 		 * an assignment.
1469 		 *
1470 		 * one insidious side effect of implicit assignment is
1471 		 * that the "==" operator does not return a Boolean if
1472 		 * implicit assignment was performed.
1473 		 */
1474 		if (try == 0 &&
1475 		    np->u.expr.left->t == T_GLOBID &&
1476 		    (gval = lut_lookup(*globals,
1477 		    (void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
1478 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1479 			    croot, arrowp, try, &rval))
1480 				return (0);
1481 
1482 			gval = MALLOC(sizeof (*gval));
1483 			*globals = lut_add(*globals,
1484 			    (void *) np->u.expr.left->u.globid.s,
1485 			    gval, NULL);
1486 
1487 			gval->t = rval.t;
1488 			gval->v = rval.v;
1489 			valuep->t = rval.t;
1490 			valuep->v = rval.v;
1491 			return (1);
1492 		}
1493 #endif  /* IMPLICIT_ASSIGN_IN_EQ */
1494 
1495 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1496 		    arrowp, try, &lval))
1497 			return (0);
1498 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1499 		    arrowp, try, &rval))
1500 			return (0);
1501 		if (rval.t == UINT64 || lval.t == UINT64) {
1502 			if (check_expr_args(&lval, &rval, UINT64, np))
1503 				return (0);
1504 		} else {
1505 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
1506 				return (0);
1507 		}
1508 
1509 		valuep->t = UINT64;
1510 		valuep->v = (lval.v == rval.v);
1511 		return (1);
1512 
1513 	case T_LT:
1514 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1515 		    arrowp, try, &lval))
1516 			return (0);
1517 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1518 		    arrowp, try, &rval))
1519 			return (0);
1520 		if (check_expr_args(&lval, &rval, UINT64, np))
1521 			return (0);
1522 
1523 		valuep->t = UINT64;
1524 		valuep->v = (lval.v < rval.v);
1525 		return (1);
1526 
1527 	case T_LE:
1528 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1529 		    arrowp, try, &lval))
1530 			return (0);
1531 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1532 		    arrowp, try, &rval))
1533 			return (0);
1534 		if (check_expr_args(&lval, &rval, UINT64, np))
1535 			return (0);
1536 
1537 		valuep->t = UINT64;
1538 		valuep->v = (lval.v <= rval.v);
1539 		return (1);
1540 
1541 	case T_GT:
1542 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1543 		    arrowp, try, &lval))
1544 			return (0);
1545 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1546 		    arrowp, try, &rval))
1547 			return (0);
1548 		if (check_expr_args(&lval, &rval, UINT64, np))
1549 			return (0);
1550 
1551 		valuep->t = UINT64;
1552 		valuep->v = (lval.v > rval.v);
1553 		return (1);
1554 
1555 	case T_GE:
1556 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1557 		    arrowp, try, &lval))
1558 			return (0);
1559 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1560 		    arrowp, try, &rval))
1561 			return (0);
1562 		if (check_expr_args(&lval, &rval, UINT64, np))
1563 			return (0);
1564 
1565 		valuep->t = UINT64;
1566 		valuep->v = (lval.v >= rval.v);
1567 		return (1);
1568 
1569 	case T_BITAND:
1570 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1571 		    arrowp, try, &lval))
1572 			return (0);
1573 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1574 		    arrowp, try, &rval))
1575 			return (0);
1576 		if (check_expr_args(&lval, &rval, UINT64, np))
1577 			return (0);
1578 
1579 		valuep->t = lval.t;
1580 		valuep->v = (lval.v & rval.v);
1581 		return (1);
1582 
1583 	case T_BITOR:
1584 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1585 		    arrowp, try, &lval))
1586 			return (0);
1587 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1588 		    arrowp, try, &rval))
1589 			return (0);
1590 		if (check_expr_args(&lval, &rval, UINT64, np))
1591 			return (0);
1592 
1593 		valuep->t = lval.t;
1594 		valuep->v = (lval.v | rval.v);
1595 		return (1);
1596 
1597 	case T_BITXOR:
1598 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1599 		    arrowp, try, &lval))
1600 			return (0);
1601 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1602 		    arrowp, try, &rval))
1603 			return (0);
1604 		if (check_expr_args(&lval, &rval, UINT64, np))
1605 			return (0);
1606 
1607 		valuep->t = lval.t;
1608 		valuep->v = (lval.v ^ rval.v);
1609 		return (1);
1610 
1611 	case T_BITNOT:
1612 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1613 		    arrowp, try, &lval))
1614 			return (0);
1615 		ASSERT(np->u.expr.right == NULL);
1616 		if (check_expr_args(&lval, NULL, UINT64, np))
1617 			return (0);
1618 
1619 		valuep->t = UINT64;
1620 		valuep->v = ~ lval.v;
1621 		return (1);
1622 
1623 	case T_LSHIFT:
1624 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1625 		    arrowp, try, &lval))
1626 			return (0);
1627 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1628 		    arrowp, try, &rval))
1629 			return (0);
1630 		if (check_expr_args(&lval, &rval, UINT64, np))
1631 			return (0);
1632 
1633 		valuep->t = UINT64;
1634 		valuep->v = (lval.v << rval.v);
1635 		return (1);
1636 
1637 	case T_RSHIFT:
1638 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1639 		    arrowp, try, &lval))
1640 			return (0);
1641 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1642 		    arrowp, try, &rval))
1643 			return (0);
1644 		if (check_expr_args(&lval, &rval, UINT64, np))
1645 			return (0);
1646 
1647 		valuep->t = UINT64;
1648 		valuep->v = (lval.v >> rval.v);
1649 		return (1);
1650 
1651 	case T_CONDIF: {
1652 		struct node *retnp;
1653 		int dotrue = 0;
1654 
1655 		/*
1656 		 * evaluate
1657 		 *	expression ? stmtA [ : stmtB ]
1658 		 *
1659 		 * first see if expression is true or false, then determine
1660 		 * if stmtA (or stmtB, if it exists) should be evaluated.
1661 		 *
1662 		 * "dotrue = 1" means stmtA should be evaluated.
1663 		 */
1664 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1665 		    arrowp, try, &lval))
1666 			return (0);
1667 
1668 		if (lval.t != UNDEFINED && lval.v != 0)
1669 			dotrue = 1;
1670 
1671 		ASSERT(np->u.expr.right != NULL);
1672 		if (np->u.expr.right->t == T_CONDELSE) {
1673 			if (dotrue)
1674 				retnp = np->u.expr.right->u.expr.left;
1675 			else
1676 				retnp = np->u.expr.right->u.expr.right;
1677 		} else {
1678 			/* no ELSE clause */
1679 			if (dotrue)
1680 				retnp = np->u.expr.right;
1681 			else {
1682 				outfl(O_DIE, np->file, np->line,
1683 				    "eval_expr: missing condelse");
1684 			}
1685 		}
1686 
1687 		if (!eval_expr(retnp, ex, events, globals, croot,
1688 		    arrowp, try, valuep))
1689 			return (0);
1690 		return (1);
1691 	}
1692 
1693 	case T_CONDELSE:
1694 		/*
1695 		 * shouldn't get here, since T_CONDELSE is supposed to be
1696 		 * evaluated as part of T_CONDIF
1697 		 */
1698 		out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
1699 		    ptree_nodetype2str(np->t));
1700 		/*NOTREACHED*/
1701 		break;
1702 
1703 	case T_NE:
1704 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1705 		    arrowp, try, &lval))
1706 			return (0);
1707 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1708 		    arrowp, try, &rval))
1709 			return (0);
1710 		if (rval.t == UINT64 || lval.t == UINT64) {
1711 			if (check_expr_args(&lval, &rval, UINT64, np))
1712 				return (0);
1713 		} else {
1714 			if (check_expr_args(&lval, &rval, UNDEFINED, np))
1715 				return (0);
1716 		}
1717 
1718 		valuep->t = UINT64;
1719 		valuep->v = (lval.v != rval.v);
1720 		return (1);
1721 
1722 	case T_LIST:
1723 	case T_AND:
1724 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1725 		    arrowp, try, valuep)) {
1726 			/*
1727 			 * if lhs is unknown, still check rhs. If that
1728 			 * is false we can return false irrespective of lhs
1729 			 */
1730 			if (!try) {
1731 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1732 				return (0);
1733 			}
1734 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1735 			    croot, arrowp, try, valuep)) {
1736 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1737 				return (0);
1738 			}
1739 			if (valuep->v != 0) {
1740 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
1741 				return (0);
1742 			}
1743 		}
1744 		if (valuep->v == 0) {
1745 			valuep->t = UINT64;
1746 			return (1);
1747 		}
1748 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1749 		    arrowp, try, valuep)) {
1750 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
1751 			return (0);
1752 		}
1753 		valuep->t = UINT64;
1754 		valuep->v = valuep->v == 0 ? 0 : 1;
1755 		return (1);
1756 
1757 	case T_OR:
1758 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1759 		    arrowp, try, valuep)) {
1760 			/*
1761 			 * if lhs is unknown, still check rhs. If that
1762 			 * is true we can return true irrespective of lhs
1763 			 */
1764 			if (!try) {
1765 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1766 				return (0);
1767 			}
1768 			if (!eval_expr(np->u.expr.right, ex, events, globals,
1769 			    croot, arrowp, try, valuep)) {
1770 				np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
1771 				return (0);
1772 			}
1773 			if (valuep->v == 0) {
1774 				np->u.expr.temp = EXPR_TEMP_LHS_UNK;
1775 				return (0);
1776 			}
1777 		}
1778 		if (valuep->v != 0) {
1779 			valuep->t = UINT64;
1780 			valuep->v = 1;
1781 			return (1);
1782 		}
1783 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1784 		    arrowp, try, valuep)) {
1785 			np->u.expr.temp = EXPR_TEMP_RHS_UNK;
1786 			return (0);
1787 		}
1788 		valuep->t = UINT64;
1789 		valuep->v = valuep->v == 0 ? 0 : 1;
1790 		return (1);
1791 
1792 	case T_NOT:
1793 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1794 		    arrowp, try, valuep))
1795 			return (0);
1796 		valuep->t = UINT64;
1797 		valuep->v = ! valuep->v;
1798 		return (1);
1799 
1800 	case T_ADD:
1801 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1802 		    arrowp, try, &lval))
1803 			return (0);
1804 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1805 		    arrowp, try, &rval))
1806 			return (0);
1807 		if (check_expr_args(&lval, &rval, UINT64, np))
1808 			return (0);
1809 
1810 		valuep->t = lval.t;
1811 		valuep->v = lval.v + rval.v;
1812 		return (1);
1813 
1814 	case T_SUB:
1815 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1816 		    arrowp, try, &lval))
1817 			return (0);
1818 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1819 		    arrowp, try, &rval))
1820 			return (0);
1821 		if (check_expr_args(&lval, &rval, UINT64, np))
1822 			return (0);
1823 
1824 		/* since valuep is unsigned, return false if lval.v < rval.v */
1825 		if (lval.v < rval.v) {
1826 			outfl(O_DIE, np->file, np->line,
1827 			    "eval_expr: T_SUB result is out of range");
1828 		}
1829 
1830 		valuep->t = lval.t;
1831 		valuep->v = lval.v - rval.v;
1832 		return (1);
1833 
1834 	case T_MUL:
1835 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1836 		    arrowp, try, &lval))
1837 			return (0);
1838 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1839 		    arrowp, try, &rval))
1840 			return (0);
1841 		if (check_expr_args(&lval, &rval, UINT64, np))
1842 			return (0);
1843 
1844 		valuep->t = lval.t;
1845 		valuep->v = lval.v * rval.v;
1846 		return (1);
1847 
1848 	case T_DIV:
1849 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1850 		    arrowp, try, &lval))
1851 			return (0);
1852 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1853 		    arrowp, try, &rval))
1854 			return (0);
1855 		if (check_expr_args(&lval, &rval, UINT64, np))
1856 			return (0);
1857 
1858 		/* return false if dividing by zero */
1859 		if (rval.v == 0) {
1860 			outfl(O_DIE, np->file, np->line,
1861 			    "eval_expr: T_DIV division by zero");
1862 		}
1863 
1864 		valuep->t = lval.t;
1865 		valuep->v = lval.v / rval.v;
1866 		return (1);
1867 
1868 	case T_MOD:
1869 		if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
1870 		    arrowp, try, &lval))
1871 			return (0);
1872 		if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
1873 		    arrowp, try, &rval))
1874 			return (0);
1875 		if (check_expr_args(&lval, &rval, UINT64, np))
1876 			return (0);
1877 
1878 		/* return false if dividing by zero */
1879 		if (rval.v == 0) {
1880 			outfl(O_DIE, np->file, np->line,
1881 			    "eval_expr: T_MOD division by zero");
1882 		}
1883 
1884 		valuep->t = lval.t;
1885 		valuep->v = lval.v % rval.v;
1886 		return (1);
1887 
1888 	case T_NAME:
1889 		if (try) {
1890 			struct iterinfo *iterinfop;
1891 			struct node *np1, *np2;
1892 			int i, gotmatch = 0;
1893 
1894 			/*
1895 			 * Check if we have an exact match of the nonwildcarded
1896 			 * path in oldepname - if so we can just use the
1897 			 * full wildcarded path in epname.
1898 			 */
1899 			for (i = 0; i < 1; i++) {
1900 				for (np1 = np,
1901 				    np2 = events[i]->u.event.oldepname;
1902 				    np1 != NULL && np2 != NULL;
1903 				    np1 = np1->u.name.next,
1904 				    np2 = np2->u.name.next) {
1905 					if (strcmp(np1->u.name.s,
1906 					    np2->u.name.s) != 0)
1907 						break;
1908 					if (np1->u.name.child->t !=
1909 					    np2->u.name.child->t)
1910 						break;
1911 					if (np1->u.name.child->t == T_NUM &&
1912 					    np1->u.name.child->u.ull !=
1913 					    np2->u.name.child->u.ull)
1914 						break;
1915 					if (np1->u.name.child->t == T_NAME &&
1916 					    strcmp(np1->u.name.child->u.name.s,
1917 					    np2->u.name.child->u.name.s) != 0)
1918 						break;
1919 					gotmatch++;
1920 				}
1921 				if (np1 == NULL && np2 == NULL) {
1922 					valuep->t = NODEPTR;
1923 					valuep->v = (uintptr_t)
1924 					    events[i]->u.event.epname;
1925 					return (1);
1926 				}
1927 			}
1928 			if (!gotmatch) {
1929 				/*
1930 				 * we're not wildcarding. However at
1931 				 * itree_create() time, we can also expand
1932 				 * simple iterators - so check for those.
1933 				 */
1934 				iterinfop = lut_lookup(ex, (void *)np->u.name.s,
1935 				    NULL);
1936 				if (iterinfop != NULL) {
1937 					valuep->t = UINT64;
1938 					valuep->v =
1939 					    (unsigned long long)iterinfop->num;
1940 					return (1);
1941 				}
1942 			}
1943 			/*
1944 			 * For anything else we'll have to wait for eval_dup().
1945 			 */
1946 			return (0);
1947 		}
1948 
1949 		/* return address of struct node */
1950 		valuep->t = NODEPTR;
1951 		valuep->v = (uintptr_t)np;
1952 		return (1);
1953 
1954 	case T_QUOTE:
1955 		valuep->t = STRING;
1956 		valuep->v = (uintptr_t)np->u.quote.s;
1957 		return (1);
1958 
1959 	case T_FUNC:
1960 		return (eval_func(np, ex, events, np->u.func.arglist,
1961 		    globals, croot, arrowp, try, valuep));
1962 
1963 	case T_NUM:
1964 	case T_TIMEVAL:
1965 		valuep->t = UINT64;
1966 		valuep->v = np->u.ull;
1967 		return (1);
1968 
1969 	default:
1970 		outfl(O_DIE, np->file, np->line,
1971 		    "eval_expr: unexpected node type: %s",
1972 		    ptree_nodetype2str(np->t));
1973 	}
1974 	/*NOTREACHED*/
1975 	return (0);
1976 }
1977 
1978 /*
1979  * eval_fru() and eval_asru() don't do much, but are called from a number
1980  * of places.
1981  */
1982 static struct node *
1983 eval_fru(struct node *np)
1984 {
1985 	ASSERT(np->t == T_NAME);
1986 	return (np);
1987 }
1988 
1989 static struct node *
1990 eval_asru(struct node *np)
1991 {
1992 	ASSERT(np->t == T_NAME);
1993 	return (np);
1994 }
1995