xref: /illumos-gate/usr/src/cmd/fm/modules/common/eversholt/eval.c (revision 8aec91825357bbeaf2ab5d30fc97fe5051a6b8dd)
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 2006 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include "alloc.h"
38 #include "out.h"
39 #include "stable.h"
40 #include "literals.h"
41 #include "lut.h"
42 #include "tree.h"
43 #include "ptree.h"
44 #include "itree.h"
45 #include "ipath.h"
46 #include "eval.h"
47 #include "config.h"
48 #include "platform.h"
49 #include "fme.h"
50 #include "stats.h"
51 
52 static struct node *eval_dup(struct node *np, struct lut *ex,
53     struct node *epnames[]);
54 static int check_expr_args(struct evalue *lp, struct evalue *rp,
55     enum datatype dtype, struct node *np);
56 
57 /*
58  * begins_with -- return true if rhs path begins with everything in lhs path
59  */
60 static int
61 begins_with(struct node *lhs, struct node *rhs)
62 {
63 	int lnum;
64 	int rnum;
65 
66 	if (lhs == NULL)
67 		return (1);	/* yep -- it all matched */
68 
69 	if (rhs == NULL)
70 		return (0);	/* nope, ran out of rhs first */
71 
72 	ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str);
73 	ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str);
74 
75 	if (lhs->u.name.s != rhs->u.name.s)
76 		return (0);	/* nope, different component names */
77 
78 	if (lhs->u.name.child && lhs->u.name.child->t == T_NUM)
79 		lnum = (int)lhs->u.name.child->u.ull;
80 	else
81 		out(O_DIE, "begins_with: unexpected lhs child");
82 
83 	if (rhs->u.name.child && rhs->u.name.child->t == T_NUM)
84 		rnum = (int)rhs->u.name.child->u.ull;
85 	else
86 		out(O_DIE, "begins_with: unexpected rhs child");
87 
88 	if (lnum != rnum)
89 		return (0);	/* nope, instance numbers were different */
90 
91 	return (begins_with(lhs->u.name.next, rhs->u.name.next));
92 }
93 
94 /*
95  * evaluate a variety of functions and place result in valuep.  return 1 if
96  * function evaluation was successful; 0 if otherwise (e.g., the case of an
97  * invalid argument to the function)
98  */
99 /*ARGSUSED*/
100 static int
101 eval_func(struct node *funcnp, struct lut *ex, struct node *epnames[],
102     struct node *np, struct lut **globals,
103     struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
104 {
105 	const char *funcname = funcnp->u.func.s;
106 
107 	if (funcname == L_within) {
108 		/* within()'s are not really constraints -- always true */
109 		valuep->t = UINT64;
110 		valuep->v = 1;
111 		return (1);
112 	} else if (funcname == L_is_under) {
113 		struct node *lhs;
114 		struct node *rhs;
115 
116 		if (np->u.expr.left->t == T_NAME)
117 			lhs = np->u.expr.left;
118 		else if (np->u.expr.left->u.func.s == L_fru)
119 			lhs = eval_fru(np->u.expr.left->u.func.arglist);
120 		else if (np->u.expr.left->u.func.s == L_asru)
121 			lhs = eval_asru(np->u.expr.left->u.func.arglist);
122 		else
123 			out(O_DIE, "is_under: unexpected lhs type: %s",
124 			    ptree_nodetype2str(np->u.expr.left->t));
125 
126 		if (np->u.expr.right->t == T_NAME)
127 			rhs = np->u.expr.right;
128 		else if (np->u.expr.right->u.func.s == L_fru)
129 			rhs = eval_fru(np->u.expr.right->u.func.arglist);
130 		else if (np->u.expr.right->u.func.s == L_asru)
131 			rhs = eval_asru(np->u.expr.right->u.func.arglist);
132 		else
133 			out(O_DIE, "is_under: unexpected rhs type: %s",
134 			    ptree_nodetype2str(np->u.expr.right->t));
135 
136 		/* eval_dup will expand wildcards, iterators, etc... */
137 		lhs = eval_dup(lhs, ex, epnames);
138 		rhs = eval_dup(rhs, ex, epnames);
139 		valuep->t = UINT64;
140 		valuep->v = begins_with(lhs, rhs);
141 
142 		out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
143 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
144 		out(O_ALTFP|O_VERB2|O_NONL, ",");
145 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
146 		out(O_ALTFP|O_VERB2, ") returned %d", (int)valuep->v);
147 
148 		tree_free(lhs);
149 		tree_free(rhs);
150 
151 		return (1);
152 	} else if (funcname == L_confprop || funcname == L_confprop_defined) {
153 		struct config *cp;
154 		struct node *lhs;
155 		char *path;
156 		const char *s;
157 
158 		if (np->u.expr.left->u.func.s == L_fru)
159 			lhs = eval_fru(np->u.expr.left->u.func.arglist);
160 		else if (np->u.expr.left->u.func.s == L_asru)
161 			lhs = eval_asru(np->u.expr.left->u.func.arglist);
162 		else
163 			out(O_DIE, "%s: unexpected lhs type: %s",
164 			    funcname, ptree_nodetype2str(np->u.expr.left->t));
165 
166 		/* for now s will point to a quote [see addconfigprop()] */
167 		ASSERT(np->u.expr.right->t == T_QUOTE);
168 
169 		/* eval_dup will expand wildcards, iterators, etc... */
170 		lhs = eval_dup(lhs, ex, epnames);
171 		path = ipath2str(NULL, ipath(lhs));
172 		cp = config_lookup(croot, path, 0);
173 		tree_free(lhs);
174 		if (cp == NULL) {
175 			out(O_ALTFP|O_VERB3, "%s: path %s not found",
176 			    funcname, path);
177 			FREE((void *)path);
178 			if (funcname == L_confprop_defined) {
179 				valuep->v = 0;
180 				valuep->t = UINT64;
181 				return (1);
182 			} else {
183 				return (0);
184 			}
185 		}
186 		s = config_getprop(cp, np->u.expr.right->u.quote.s);
187 		if (s == NULL) {
188 			out(O_ALTFP|O_VERB3, "%s: \"%s\" not found for path %s",
189 			    funcname, np->u.expr.right->u.quote.s, path);
190 			FREE((void *)path);
191 			if (funcname == L_confprop_defined) {
192 				valuep->v = 0;
193 				valuep->t = UINT64;
194 				return (1);
195 			} else {
196 				return (0);
197 			}
198 		}
199 
200 		if (funcname == L_confprop) {
201 			valuep->v = (uintptr_t)stable(s);
202 			valuep->t = STRING;
203 			out(O_ALTFP|O_VERB3, "%s(\"%s\", \"%s\") = \"%s\"",
204 			    funcname, path, np->u.expr.right->u.quote.s,
205 			    (char *)(uintptr_t)valuep->v);
206 		} else {
207 			valuep->v = 1;
208 			valuep->t = UINT64;
209 		}
210 		FREE((void *)path);
211 		return (1);
212 	}
213 
214 	if (try)
215 		return (0);
216 
217 	if (funcname == L_fru) {
218 		valuep->t = NODEPTR;
219 		valuep->v = (uintptr_t)eval_fru(np);
220 		return (1);
221 	} else if (funcname == L_asru) {
222 		valuep->t = NODEPTR;
223 		valuep->v = (uintptr_t)eval_asru(np);
224 		return (1);
225 	} else if (funcname == L_defined) {
226 		ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
227 		valuep->t = UINT64;
228 		valuep->v = (lut_lookup(*globals,
229 		    (void *)np->u.globid.s, NULL) != NULL);
230 		return (1);
231 	} else if (funcname == L_call) {
232 		return (! platform_call(np, globals, croot, arrowp, valuep));
233 	} else if (funcname == L_is_connected) {
234 		return (! config_is_connected(np, croot, valuep));
235 	} else if (funcname == L_is_on) {
236 		return (! config_is_on(np, croot, valuep));
237 	} else if (funcname == L_is_present) {
238 		return (! config_is_present(np, croot, valuep));
239 	} else if (funcname == L_is_type) {
240 		return (! config_is_type(np, croot, valuep));
241 	} else if (funcname == L_envprop) {
242 		outfl(O_DIE, np->file, np->line,
243 		    "eval_func: %s not yet supported", funcname);
244 	} else if (funcname == L_payloadprop) {
245 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
246 		    "payloadprop(\"%s\") ", np->u.quote.s);
247 
248 		if (platform_payloadprop(np, valuep)) {
249 			/* platform_payloadprop() returned false */
250 			out(O_ALTFP|O_VERB, "payloadprop \"%s\" not found.",
251 			    np->u.quote.s);
252 			return (0);
253 		} else {
254 			switch (valuep->t) {
255 			case UINT64:
256 			case NODEPTR:
257 				out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
258 				break;
259 			case STRING:
260 				out(O_ALTFP|O_VERB2, "found: \"%s\"",
261 				    (char *)(uintptr_t)valuep->v);
262 				break;
263 			default:
264 				out(O_ALTFP|O_VERB2, "found: undefined");
265 				break;
266 			}
267 			return (1);
268 		}
269 	} else if (funcname == L_setpayloadprop) {
270 		struct evalue *payloadvalp;
271 
272 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
273 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
274 		    ptree_nodetype2str(np->u.expr.left->t));
275 
276 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
277 		    "setpayloadprop: %s: %s=",
278 		    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
279 		    np->u.expr.left->u.quote.s);
280 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
281 
282 		/*
283 		 * allocate a struct evalue to hold the payload property's
284 		 * value, unless we've been here already, in which case we
285 		 * might calculate a different value, but we'll store it
286 		 * in the already-allocated struct evalue.
287 		 */
288 		if ((payloadvalp = (struct evalue *)lut_lookup(
289 		    arrowp->tail->myevent->payloadprops,
290 		    (void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
291 			payloadvalp = MALLOC(sizeof (*payloadvalp));
292 		}
293 
294 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
295 		    arrowp, try, payloadvalp)) {
296 			out(O_ALTFP|O_VERB2, " (cannot eval, using zero)");
297 			payloadvalp->t = UINT64;
298 			payloadvalp->v = 0;
299 		} else {
300 			if (payloadvalp->t == UINT64)
301 				out(O_ALTFP|O_VERB2,
302 				    " (%llu)", payloadvalp->v);
303 			else
304 				out(O_ALTFP|O_VERB2, " (\"%s\")",
305 				    (char *)(uintptr_t)payloadvalp->v);
306 		}
307 
308 		/* add to table of payload properties for current problem */
309 		arrowp->tail->myevent->payloadprops =
310 		    lut_add(arrowp->tail->myevent->payloadprops,
311 		    (void *)np->u.expr.left->u.quote.s,
312 		    (void *)payloadvalp, NULL);
313 
314 		/* function is always true */
315 		valuep->t = UINT64;
316 		valuep->v = 1;
317 		return (1);
318 	} else if (funcname == L_payloadprop_defined) {
319 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
320 		    "payloadprop_defined(\"%s\") ", np->u.quote.s);
321 
322 		if (platform_payloadprop(np, NULL)) {
323 			/* platform_payloadprop() returned false */
324 			valuep->v = 0;
325 			out(O_ALTFP|O_VERB2, "payloadprop_defined: \"%s\" "
326 			    "not defined.", np->u.quote.s);
327 		} else {
328 			valuep->v = 1;
329 			out(O_ALTFP|O_VERB2, "found.");
330 		}
331 		valuep->t = UINT64;
332 		return (1);
333 	} else if (funcname == L_payloadprop_contains) {
334 		int nvals;
335 		struct evalue *vals;
336 		struct evalue cmpval;
337 
338 		ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
339 		ASSERTinfo(np->u.expr.left->t == T_QUOTE,
340 		    ptree_nodetype2str(np->u.expr.left->t));
341 
342 		outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
343 		    "payloadprop_contains(\"%s\", ",
344 		    np->u.expr.left->u.quote.s);
345 		ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
346 		out(O_ALTFP|O_VERB2|O_NONL, ") ");
347 
348 		/* evaluate the expression we're comparing against */
349 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
350 		    arrowp, try, &cmpval)) {
351 			out(O_ALTFP|O_VERB2|O_NONL,
352 			    "(cannot eval, using zero) ");
353 			cmpval.t = UINT64;
354 			cmpval.v = 0;
355 		} else {
356 			switch (cmpval.t) {
357 			case UNDEFINED:
358 				out(O_ALTFP|O_VERB2, "(undefined type)");
359 				break;
360 
361 			case UINT64:
362 				out(O_ALTFP|O_VERB2,
363 				    "(%llu) ", cmpval.v);
364 				break;
365 
366 			case STRING:
367 				out(O_ALTFP|O_VERB2,
368 				    "(\"%s\") ", (char *)(uintptr_t)cmpval.v);
369 				break;
370 
371 			case NODEPTR:
372 				out(O_ALTFP|O_VERB2|O_NONL, "(");
373 				ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
374 				    (struct node *)(uintptr_t)(cmpval.v));
375 				out(O_ALTFP|O_VERB2, ") ");
376 				break;
377 			}
378 		}
379 
380 		/* get the payload values and check for a match */
381 		vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
382 		    &nvals);
383 		valuep->t = UINT64;
384 		valuep->v = 0;
385 		if (nvals == 0) {
386 			out(O_ALTFP|O_VERB2, "not found.");
387 		} else {
388 			struct evalue preval;
389 			int i;
390 
391 			out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
392 
393 			for (i = 0; i < nvals; i++) {
394 
395 				preval.t = vals[i].t;
396 				preval.v = vals[i].v;
397 
398 				if (check_expr_args(&vals[i], &cmpval,
399 				    UNDEFINED, np))
400 					continue;
401 
402 				/*
403 				 * If we auto-converted the value to a
404 				 * string, we need to free the
405 				 * original tree value.
406 				 */
407 				if (preval.t == NODEPTR &&
408 				    ((struct node *)(uintptr_t)(preval.v))->t ==
409 				    T_NAME) {
410 					tree_free((struct node *)(uintptr_t)
411 					    preval.v);
412 				}
413 
414 				if (vals[i].v == cmpval.v) {
415 					valuep->v = 1;
416 					break;
417 				}
418 			}
419 
420 			if (valuep->v)
421 				out(O_ALTFP|O_VERB2, "match.");
422 			else
423 				out(O_ALTFP|O_VERB2, "no match.");
424 
425 			for (i = 0; i < nvals; i++) {
426 				if (vals[i].t == NODEPTR) {
427 					tree_free((struct node *)(uintptr_t)
428 					    vals[i].v);
429 					break;
430 				}
431 			}
432 			FREE(vals);
433 		}
434 		return (1);
435 	} else if (funcname == L_confcall) {
436 		return (!platform_confcall(np, globals, croot, arrowp, valuep));
437 	} else if (funcname == L_count) {
438 		struct stats *statp;
439 		struct istat_entry ent;
440 
441 		ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
442 
443 		ent.ename = np->u.event.ename->u.name.s;
444 		ent.ipath = ipath(np->u.event.epname);
445 
446 		valuep->t = UINT64;
447 		if ((statp = (struct stats *)
448 		    lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
449 			valuep->v = 0;
450 		else
451 			valuep->v = stats_counter_value(statp);
452 
453 		return (1);
454 	} else
455 		outfl(O_DIE, np->file, np->line,
456 		    "eval_func: unexpected func: %s", funcname);
457 	/*NOTREACHED*/
458 	return (0);
459 }
460 
461 static struct node *
462 eval_wildcardedname(struct node *np, struct lut *ex, struct node *epnames[])
463 {
464 	struct node *npstart, *npend, *npref, *newnp;
465 	struct node *np1, *np2, *retp;
466 	int i;
467 
468 	if (epnames == NULL || epnames[0] == NULL)
469 		return (NULL);
470 
471 	for (i = 0; epnames[i] != NULL; i++) {
472 		if (tree_namecmp(np, epnames[i]) == 0)
473 			return (NULL);
474 	}
475 
476 	/*
477 	 * get to this point if np does not match any of the entries in
478 	 * epnames.  check if np is a path that must preceded by a wildcard
479 	 * portion.  for this case we must first determine which epnames[]
480 	 * entry should be used for wildcarding.
481 	 */
482 	npstart = NULL;
483 	for (i = 0; epnames[i] != NULL; i++) {
484 		for (npref = epnames[i]; npref; npref = npref->u.name.next) {
485 			if (npref->u.name.s == np->u.name.s) {
486 				for (np1 = npref, np2 = np;
487 				    np1 != NULL && np2 != NULL;
488 				    np1 = np1->u.name.next,
489 					    np2 = np2->u.name.next) {
490 					if (np1->u.name.s != np2->u.name.s)
491 						break;
492 				}
493 				if (np2 == NULL) {
494 					npstart = epnames[i];
495 					npend = npref;
496 					if (np1 == NULL)
497 						break;
498 				}
499 			}
500 		}
501 
502 		if (npstart != NULL)
503 			break;
504 	}
505 
506 	if (npstart == NULL) {
507 		/* no match; np is not a path to be wildcarded */
508 		return (NULL);
509 	}
510 
511 	/*
512 	 * dup (npstart -- npend) which is the wildcarded portion.  all
513 	 * children should be T_NUMs.
514 	 */
515 	retp = NULL;
516 	for (npref = npstart;
517 	    ! (npref == NULL || npref == npend);
518 	    npref = npref->u.name.next) {
519 		newnp = newnode(T_NAME, np->file, np->line);
520 
521 		newnp->u.name.t = npref->u.name.t;
522 		newnp->u.name.s = npref->u.name.s;
523 		newnp->u.name.last = newnp;
524 		newnp->u.name.it = npref->u.name.it;
525 		newnp->u.name.cp = npref->u.name.cp;
526 
527 		ASSERT(npref->u.name.child != NULL);
528 		ASSERT(npref->u.name.child->t == T_NUM);
529 		newnp->u.name.child = newnode(T_NUM, np->file, np->line);
530 		newnp->u.name.child->u.ull = npref->u.name.child->u.ull;
531 
532 		if (retp == NULL) {
533 			retp = newnp;
534 		} else {
535 			retp->u.name.last->u.name.next = newnp;
536 			retp->u.name.last = newnp;
537 		}
538 	}
539 
540 	ASSERT(retp != NULL);
541 
542 	/* now append the nonwildcarded portion */
543 	retp = tree_name_append(retp, eval_dup(np, ex, NULL));
544 
545 	return (retp);
546 }
547 
548 static struct node *
549 eval_dup(struct node *np, struct lut *ex, struct node *epnames[])
550 {
551 	struct node *newnp;
552 
553 	if (np == NULL)
554 		return (NULL);
555 
556 	switch (np->t) {
557 	case T_GLOBID:
558 		return (tree_globid(np->u.globid.s, np->file, np->line));
559 
560 	case T_ASSIGN:
561 	case T_CONDIF:
562 	case T_CONDELSE:
563 	case T_NE:
564 	case T_EQ:
565 	case T_LT:
566 	case T_LE:
567 	case T_GT:
568 	case T_GE:
569 	case T_BITAND:
570 	case T_BITOR:
571 	case T_BITXOR:
572 	case T_BITNOT:
573 	case T_LSHIFT:
574 	case T_RSHIFT:
575 	case T_LIST:
576 	case T_AND:
577 	case T_OR:
578 	case T_NOT:
579 	case T_ADD:
580 	case T_SUB:
581 	case T_MUL:
582 	case T_DIV:
583 	case T_MOD:
584 		return (tree_expr(np->t,
585 				    eval_dup(np->u.expr.left, ex, epnames),
586 				    eval_dup(np->u.expr.right, ex, epnames)));
587 
588 	case T_NAME: {
589 		struct iterinfo *iterinfop;
590 		struct node *newchild = NULL;
591 
592 		iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
593 		if (iterinfop != NULL) {
594 			/* explicit iterator; not part of pathname */
595 			newnp = newnode(T_NUM, np->file, np->line);
596 			newnp->u.ull = iterinfop->num;
597 			return (newnp);
598 		}
599 
600 		/* see if np is a path with wildcard portion */
601 		newnp = eval_wildcardedname(np, ex, epnames);
602 		if (newnp != NULL)
603 			return (newnp);
604 
605 		/* turn off wildcarding for child */
606 		newchild = eval_dup(np->u.name.child, ex, NULL);
607 
608 		if (newchild != NULL) {
609 			if (newchild->t != T_NUM) {
610 				/*
611 				 * not a number, eh?  we must resolve this
612 				 * to a number.
613 				 */
614 				struct evalue value;
615 
616 				if (eval_expr(newchild, ex, epnames,
617 				    NULL, NULL, NULL, 1, &value) == 0 ||
618 				    value.t != UINT64) {
619 					outfl(O_DIE, np->file, np->line,
620 					    "eval_dup: could not resolve "
621 					    "iterator of %s", np->u.name.s);
622 				}
623 
624 				tree_free(newchild);
625 				newchild = newnode(T_NUM, np->file, np->line);
626 				newchild->u.ull = value.v;
627 			}
628 
629 			newnp = newnode(np->t, np->file, np->line);
630 			newnp->u.name.s = np->u.name.s;
631 			newnp->u.name.it = np->u.name.it;
632 			newnp->u.name.cp = np->u.name.cp;
633 
634 			newnp->u.name.last = newnp;
635 			newnp->u.name.child = newchild;
636 
637 			if (np->u.name.next != NULL) {
638 				/* turn off wildcarding for next */
639 				return (tree_name_append(newnp,
640 					eval_dup(np->u.name.next, ex, NULL)));
641 			} else {
642 				return (newnp);
643 			}
644 		} else {
645 			outfl(O_DIE, np->file, np->line,
646 			    "eval_dup: internal error: \"%s\" is neither "
647 			    "an iterator nor a pathname", np->u.name.s);
648 		}
649 		/*NOTREACHED*/
650 		break;
651 	}
652 
653 	case T_EVENT:
654 		newnp = newnode(T_NAME, np->file, np->line);
655 
656 		newnp->u.name.t = np->u.event.ename->u.name.t;
657 		newnp->u.name.s = np->u.event.ename->u.name.s;
658 		newnp->u.name.it = np->u.event.ename->u.name.it;
659 		newnp->u.name.last = newnp;
660 
661 		return (tree_event(newnp,
662 		    eval_dup(np->u.event.epname, ex, epnames),
663 		    eval_dup(np->u.event.eexprlist, ex, epnames)));
664 
665 	case T_FUNC:
666 		return (tree_func(np->u.func.s,
667 		    eval_dup(np->u.func.arglist, ex, epnames),
668 		    np->file, np->line));
669 
670 	case T_QUOTE:
671 		newnp = newnode(T_QUOTE, np->file, np->line);
672 		newnp->u.quote.s = np->u.quote.s;
673 		return (newnp);
674 
675 	case T_NUM:
676 		newnp = newnode(T_NUM, np->file, np->line);
677 		newnp->u.ull = np->u.ull;
678 		return (newnp);
679 
680 	default:
681 		outfl(O_DIE, np->file, np->line,
682 		    "eval_dup: unexpected node type: %s",
683 		    ptree_nodetype2str(np->t));
684 	}
685 	/*NOTREACHED*/
686 	return (0);
687 }
688 
689 /*
690  * eval_potential -- see if constraint is potentially true
691  *
692  * this function is used at instance tree creation time to see if
693  * any constraints are already known to be false.  if this function
694  * returns false, then the constraint will always be false and there's
695  * no need to include the propagation arrow in the instance tree.
696  *
697  * if this routine returns true, either the constraint is known to
698  * be always true (so there's no point in attaching the constraint
699  * to the propagation arrow in the instance tree), or the constraint
700  * contains "deferred" expressions like global variables or poller calls
701  * and so it must be evaluated during calls to fme_eval().  in this last
702  * case, where a constraint needs to be attached to the propagation arrow
703  * in the instance tree, this routine returns a newly created constraint
704  * in *newc where all the non-deferred things have been filled in.
705  *
706  * so in summary:
707  *
708  *	return of false: constraint can never be true, *newc will be NULL.
709  *
710  *	return of true with *newc unchanged: constraint will always be true.
711  *
712  *	return of true with *newc changed: use new constraint in *newc.
713  *
714  * the lookup table for all explicit iterators, ex, is passed in.
715  *
716  * *newc can either be NULL on entry, or if can contain constraints from
717  * previous calls to eval_potential() (i.e. for building up an instance
718  * tree constraint from several potential constraints).  if *newc already
719  * contains constraints, anything added to it will be joined by adding
720  * a T_AND node at the top of *newc.
721  */
722 int
723 eval_potential(struct node *np, struct lut *ex, struct node *epnames[],
724 	    struct node **newc, struct config *croot)
725 {
726 	struct node *newnp;
727 	struct evalue value;
728 
729 	if (eval_expr(np, ex, epnames, NULL, croot, NULL, 1, &value) == 0) {
730 		/*
731 		 * couldn't eval expression because
732 		 * it contains deferred items.  make
733 		 * a duplicate expression with all the
734 		 * non-deferred items expanded.
735 		 */
736 		newnp = eval_dup(np, ex, epnames);
737 
738 		if (*newc == NULL) {
739 			/*
740 			 * constraint is potentially true if deferred
741 			 * expression in newnp is true.  *newc was NULL
742 			 * so new constraint is just the one in newnp.
743 			 */
744 			*newc = newnp;
745 			return (1);
746 		} else {
747 			/*
748 			 * constraint is potentially true if deferred
749 			 * expression in newnp is true.  *newc already
750 			 * contained a constraint so add an AND with the
751 			 * constraint in newnp.
752 			 */
753 			*newc = tree_expr(T_AND, *newc, newnp);
754 			return (1);
755 		}
756 	} else if (value.t == UNDEFINED) {
757 		/* constraint can never be true */
758 		return (0);
759 	} else if (value.t == UINT64 && value.v == 0) {
760 		/* constraint can never be true */
761 		return (0);
762 	} else {
763 		/* constraint is always true (nothing deferred to eval) */
764 		return (1);
765 	}
766 }
767 
768 static int
769 check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
770 		struct node *np)
771 {
772 	/* auto-convert T_NAMES to strings */
773 	if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
774 	    T_NAME) {
775 		char *s = ipath2str(NULL,
776 		    ipath((struct node *)(uintptr_t)lp->v));
777 		lp->t = STRING;
778 		lp->v = (uintptr_t)stable(s);
779 		FREE(s);
780 		out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
781 		    (char *)(uintptr_t)lp->v);
782 	}
783 	if (rp != NULL &&
784 	    rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
785 	    T_NAME) {
786 		char *s = ipath2str(NULL,
787 		    ipath((struct node *)(uintptr_t)rp->v));
788 		rp->t = STRING;
789 		rp->v = (uintptr_t)stable(s);
790 		FREE(s);
791 		out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
792 		    (char *)(uintptr_t)rp->v);
793 	}
794 
795 	/* auto-convert strings to numbers */
796 	if (dtype == UINT64) {
797 		if (lp->t == STRING) {
798 			lp->t = UINT64;
799 			lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
800 		}
801 		if (rp != NULL && rp->t == STRING) {
802 			rp->t = UINT64;
803 			rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
804 		}
805 	}
806 
807 	if (dtype != UNDEFINED && lp->t != dtype) {
808 		outfl(O_OK, np->file, np->line,
809 			"invalid datatype of argument for operation %s",
810 			ptree_nodetype2str(np->t));
811 		return (1);
812 	}
813 
814 	if (rp != NULL && lp->t != rp->t) {
815 		outfl(O_OK, np->file, np->line,
816 			"mismatch in datatype of arguments for operation %s",
817 			ptree_nodetype2str(np->t));
818 		return (1);
819 	}
820 
821 	return (0);
822 }
823 
824 /*
825  * eval_expr -- evaluate expression into *valuep
826  *
827  * the meaning of the return value depends on the input value of try.
828  *
829  * for try == 1: if any deferred items are encounted, bail out and return
830  * false.  returns true if we made it through entire expression without
831  * hitting any deferred items.
832  *
833  * for try == 0: return true if all operations were performed successfully.
834  * return false if otherwise.  for example, any of the following conditions
835  * will result in a false return value:
836  *   - attempted use of an uninitialized global variable
837  *   - failure in function evaluation
838  *   - illegal arithmetic operation (argument out of range)
839  */
840 int
841 eval_expr(struct node *np, struct lut *ex, struct node *epnames[],
842 	struct lut **globals, struct config *croot, struct arrow *arrowp,
843 	int try, struct evalue *valuep)
844 {
845 	struct evalue *gval;
846 	struct evalue lval;
847 	struct evalue rval;
848 
849 	if (np == NULL) {
850 		valuep->t = UINT64;
851 		valuep->v = 1;	/* no constraint means "true" */
852 		return (1);
853 	}
854 
855 	valuep->t = UNDEFINED;
856 
857 	switch (np->t) {
858 	case T_GLOBID:
859 		if (try)
860 			return (0);
861 
862 		/*
863 		 * only handle case of getting (and not setting) the value
864 		 * of a global variable
865 		 */
866 		gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
867 		if (gval == NULL) {
868 			valuep->t = UNDEFINED;
869 			return (0);
870 		} else {
871 			valuep->t = gval->t;
872 			valuep->v = gval->v;
873 			return (1);
874 		}
875 
876 	case T_ASSIGN:
877 		if (try)
878 			return (0);
879 
880 		/*
881 		 * first evaluate rhs, then try to store value in lhs which
882 		 * should be a global variable
883 		 */
884 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
885 			    arrowp, try, &rval))
886 			return (0);
887 
888 		ASSERT(np->u.expr.left->t == T_GLOBID);
889 		gval = lut_lookup(*globals,
890 				(void *)np->u.expr.left->u.globid.s, NULL);
891 
892 		if (gval == NULL) {
893 			gval = MALLOC(sizeof (*gval));
894 			*globals = lut_add(*globals,
895 					(void *) np->u.expr.left->u.globid.s,
896 					gval, NULL);
897 		}
898 
899 		gval->t = rval.t;
900 		gval->v = rval.v;
901 
902 		if (gval->t == UINT64) {
903 			out(O_ALTFP|O_VERB2,
904 			    "assign $%s=%llu",
905 			    np->u.expr.left->u.globid.s, gval->v);
906 		} else {
907 			out(O_ALTFP|O_VERB2,
908 			    "assign $%s=\"%s\"",
909 			    np->u.expr.left->u.globid.s,
910 			    (char *)(uintptr_t)gval->v);
911 		}
912 
913 		/*
914 		 * but always return true -- an assignment should not
915 		 * cause a constraint to be false.
916 		 */
917 		valuep->t = UINT64;
918 		valuep->v = 1;
919 		return (1);
920 
921 	case T_EQ:
922 #define	IMPLICIT_ASSIGN_IN_EQ
923 #ifdef IMPLICIT_ASSIGN_IN_EQ
924 		/*
925 		 * if lhs is an uninitialized global variable, perform
926 		 * an assignment.
927 		 *
928 		 * one insidious side effect of implicit assignment is
929 		 * that the "==" operator does not return a Boolean if
930 		 * implicit assignment was performed.
931 		 */
932 		if (try == 0 &&
933 		    np->u.expr.left->t == T_GLOBID &&
934 		    (gval = lut_lookup(*globals,
935 			(void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
936 			if (!eval_expr(np->u.expr.right, ex, epnames, globals,
937 					croot, arrowp, try, &rval))
938 				return (0);
939 
940 			gval = MALLOC(sizeof (*gval));
941 			*globals = lut_add(*globals,
942 					(void *) np->u.expr.left->u.globid.s,
943 					gval, NULL);
944 
945 			gval->t = rval.t;
946 			gval->v = rval.v;
947 			valuep->t = rval.t;
948 			valuep->v = rval.v;
949 			return (1);
950 		}
951 #endif  /* IMPLICIT_ASSIGN_IN_EQ */
952 
953 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
954 				arrowp, try, &lval))
955 			return (0);
956 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
957 				arrowp, try, &rval))
958 			return (0);
959 		if (check_expr_args(&lval, &rval, UNDEFINED, np))
960 			return (0);
961 
962 		valuep->t = UINT64;
963 		valuep->v = (lval.v == rval.v);
964 		return (1);
965 
966 	case T_LT:
967 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
968 				arrowp, try, &lval))
969 			return (0);
970 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
971 				arrowp, try, &rval))
972 			return (0);
973 		if (check_expr_args(&lval, &rval, UINT64, np))
974 			return (0);
975 
976 		valuep->t = UINT64;
977 		valuep->v = (lval.v < rval.v);
978 		return (1);
979 
980 	case T_LE:
981 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
982 				arrowp, try, &lval))
983 			return (0);
984 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
985 				arrowp, try, &rval))
986 			return (0);
987 		if (check_expr_args(&lval, &rval, UINT64, np))
988 			return (0);
989 
990 		valuep->t = UINT64;
991 		valuep->v = (lval.v <= rval.v);
992 		return (1);
993 
994 	case T_GT:
995 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
996 				arrowp, try, &lval))
997 			return (0);
998 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
999 				arrowp, try, &rval))
1000 			return (0);
1001 		if (check_expr_args(&lval, &rval, UINT64, np))
1002 			return (0);
1003 
1004 		valuep->t = UINT64;
1005 		valuep->v = (lval.v > rval.v);
1006 		return (1);
1007 
1008 	case T_GE:
1009 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1010 				arrowp, try, &lval))
1011 			return (0);
1012 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1013 				arrowp, try, &rval))
1014 			return (0);
1015 		if (check_expr_args(&lval, &rval, UINT64, np))
1016 			return (0);
1017 
1018 		valuep->t = UINT64;
1019 		valuep->v = (lval.v >= rval.v);
1020 		return (1);
1021 
1022 	case T_BITAND:
1023 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1024 				arrowp, try, &lval))
1025 			return (0);
1026 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1027 				arrowp, try, &rval))
1028 			return (0);
1029 		if (check_expr_args(&lval, &rval, UINT64, np))
1030 			return (0);
1031 
1032 		valuep->t = lval.t;
1033 		valuep->v = (lval.v & rval.v);
1034 		return (1);
1035 
1036 	case T_BITOR:
1037 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1038 				arrowp, try, &lval))
1039 			return (0);
1040 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1041 				arrowp, try, &rval))
1042 			return (0);
1043 		if (check_expr_args(&lval, &rval, UINT64, np))
1044 			return (0);
1045 
1046 		valuep->t = lval.t;
1047 		valuep->v = (lval.v | rval.v);
1048 		return (1);
1049 
1050 	case T_BITXOR:
1051 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1052 				arrowp, try, &lval))
1053 			return (0);
1054 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1055 				arrowp, try, &rval))
1056 			return (0);
1057 		if (check_expr_args(&lval, &rval, UINT64, np))
1058 			return (0);
1059 
1060 		valuep->t = lval.t;
1061 		valuep->v = (lval.v ^ rval.v);
1062 		return (1);
1063 
1064 	case T_BITNOT:
1065 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1066 				arrowp, try, &lval))
1067 			return (0);
1068 		ASSERT(np->u.expr.right == NULL);
1069 		if (check_expr_args(&lval, NULL, UINT64, np))
1070 			return (0);
1071 
1072 		valuep->t = UINT64;
1073 		valuep->v = ~ lval.v;
1074 		return (1);
1075 
1076 	case T_LSHIFT:
1077 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1078 				arrowp, try, &lval))
1079 			return (0);
1080 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1081 				arrowp, try, &rval))
1082 			return (0);
1083 		if (check_expr_args(&lval, &rval, UINT64, np))
1084 			return (0);
1085 
1086 		valuep->t = UINT64;
1087 		valuep->v = (lval.v << rval.v);
1088 		return (1);
1089 
1090 	case T_RSHIFT:
1091 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1092 				arrowp, try, &lval))
1093 			return (0);
1094 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1095 				arrowp, try, &rval))
1096 			return (0);
1097 		if (check_expr_args(&lval, &rval, UINT64, np))
1098 			return (0);
1099 
1100 		valuep->t = UINT64;
1101 		valuep->v = (lval.v >> rval.v);
1102 		return (1);
1103 
1104 	case T_CONDIF: {
1105 		struct node *retnp;
1106 		int dotrue = 0;
1107 
1108 		/*
1109 		 * evaluate
1110 		 *	expression ? stmtA [ : stmtB ]
1111 		 *
1112 		 * first see if expression is true or false, then determine
1113 		 * if stmtA (or stmtB, if it exists) should be evaluated.
1114 		 *
1115 		 * "dotrue = 1" means stmtA should be evaluated.
1116 		 */
1117 		if (eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1118 				arrowp, try, &lval) &&
1119 		    lval.t != UNDEFINED && lval.v != 0)
1120 			dotrue = 1;
1121 
1122 		ASSERT(np->u.expr.right != NULL);
1123 		if (np->u.expr.right->t == T_CONDELSE) {
1124 			if (dotrue)
1125 				retnp = np->u.expr.right->u.expr.left;
1126 			else
1127 				retnp = np->u.expr.right->u.expr.right;
1128 		} else {
1129 			/* no ELSE clause */
1130 			if (dotrue)
1131 				retnp = np->u.expr.right;
1132 			else {
1133 				valuep->t = UINT64;
1134 				valuep->v = 0;
1135 				return (0);
1136 			}
1137 		}
1138 
1139 		if (!eval_expr(retnp, ex, epnames, globals, croot,
1140 			    arrowp, try, valuep))
1141 			return (0);
1142 		return (1);
1143 	}
1144 
1145 	case T_CONDELSE:
1146 		/*
1147 		 * shouldn't get here, since T_CONDELSE is supposed to be
1148 		 * evaluated as part of T_CONDIF
1149 		 */
1150 		out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
1151 		    ptree_nodetype2str(np->t));
1152 		return (0);
1153 
1154 	case T_NE:
1155 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1156 				arrowp, try, &lval))
1157 			return (0);
1158 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1159 				arrowp, try, &rval))
1160 			return (0);
1161 		if (check_expr_args(&lval, &rval, UNDEFINED, np))
1162 			return (0);
1163 
1164 		valuep->t = UINT64;
1165 		valuep->v = (lval.v != rval.v);
1166 		return (1);
1167 
1168 	case T_LIST:
1169 	case T_AND:
1170 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1171 				arrowp, try, valuep)) {
1172 			/*
1173 			 * if lhs is unknown, still check rhs. If that
1174 			 * is false we can return false irrespectice of lhs
1175 			 */
1176 			if (!eval_expr(np->u.expr.right, ex, epnames, globals,
1177 			    croot, arrowp, try, valuep))
1178 				return (0);
1179 			if (valuep->v != 0)
1180 				return (0);
1181 		}
1182 		if (valuep->v == 0) {
1183 			valuep->t = UINT64;
1184 			return (1);
1185 		}
1186 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1187 				arrowp, try, valuep))
1188 			return (0);
1189 		valuep->t = UINT64;
1190 		valuep->v = valuep->v == 0 ? 0 : 1;
1191 		return (1);
1192 
1193 	case T_OR:
1194 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1195 				arrowp, try, valuep)) {
1196 			/*
1197 			 * if lhs is unknown, still check rhs. If that
1198 			 * is true we can return true irrespectice of lhs
1199 			 */
1200 			if (!eval_expr(np->u.expr.right, ex, epnames, globals,
1201 			    croot, arrowp, try, valuep))
1202 				return (0);
1203 			if (valuep->v == 0)
1204 				return (0);
1205 		}
1206 		if (valuep->v != 0) {
1207 			valuep->t = UINT64;
1208 			valuep->v = 1;
1209 			return (1);
1210 		}
1211 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1212 				arrowp, try, valuep))
1213 			return (0);
1214 		valuep->t = UINT64;
1215 		valuep->v = valuep->v == 0 ? 0 : 1;
1216 		return (1);
1217 
1218 	case T_NOT:
1219 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1220 				arrowp, try, valuep))
1221 			return (0);
1222 		valuep->t = UINT64;
1223 		valuep->v = ! valuep->v;
1224 		return (1);
1225 
1226 	case T_ADD:
1227 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1228 				arrowp, try, &lval))
1229 			return (0);
1230 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1231 				arrowp, try, &rval))
1232 			return (0);
1233 		if (check_expr_args(&lval, &rval, UINT64, np))
1234 			return (0);
1235 
1236 		valuep->t = lval.t;
1237 		valuep->v = lval.v + rval.v;
1238 		return (1);
1239 
1240 	case T_SUB:
1241 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1242 				arrowp, try, &lval))
1243 			return (0);
1244 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1245 				arrowp, try, &rval))
1246 			return (0);
1247 		if (check_expr_args(&lval, &rval, UINT64, np))
1248 			return (0);
1249 
1250 		/* since valuep is unsigned, return false if lval.v < rval.v */
1251 		if (lval.v < rval.v) {
1252 			out(O_ERR, "eval_expr: T_SUB result is out of range");
1253 			valuep->t = UNDEFINED;
1254 			return (0);
1255 		}
1256 
1257 		valuep->t = lval.t;
1258 		valuep->v = lval.v - rval.v;
1259 		return (1);
1260 
1261 	case T_MUL:
1262 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1263 				arrowp, try, &lval))
1264 			return (0);
1265 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1266 				arrowp, try, &rval))
1267 			return (0);
1268 		if (check_expr_args(&lval, &rval, UINT64, np))
1269 			return (0);
1270 
1271 		valuep->t = lval.t;
1272 		valuep->v = lval.v * rval.v;
1273 		return (1);
1274 
1275 	case T_DIV:
1276 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1277 				arrowp, try, &lval))
1278 			return (0);
1279 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1280 				arrowp, try, &rval))
1281 			return (0);
1282 		if (check_expr_args(&lval, &rval, UINT64, np))
1283 			return (0);
1284 
1285 		/* return false if dividing by zero */
1286 		if (rval.v == 0) {
1287 			out(O_ERR, "eval_expr: T_DIV division by zero");
1288 			valuep->t = UNDEFINED;
1289 			return (0);
1290 		}
1291 
1292 		valuep->t = lval.t;
1293 		valuep->v = lval.v / rval.v;
1294 		return (1);
1295 
1296 	case T_MOD:
1297 		if (!eval_expr(np->u.expr.left, ex, epnames, globals, croot,
1298 				arrowp, try, &lval))
1299 			return (0);
1300 		if (!eval_expr(np->u.expr.right, ex, epnames, globals, croot,
1301 				arrowp, try, &rval))
1302 			return (0);
1303 		if (check_expr_args(&lval, &rval, UINT64, np))
1304 			return (0);
1305 
1306 		/* return false if dividing by zero */
1307 		if (rval.v == 0) {
1308 			out(O_ERR, "eval_expr: T_MOD division by zero");
1309 			valuep->t = UNDEFINED;
1310 			return (0);
1311 		}
1312 
1313 		valuep->t = lval.t;
1314 		valuep->v = lval.v % rval.v;
1315 		return (1);
1316 
1317 	case T_NAME:
1318 		if (try) {
1319 			struct iterinfo *iterinfop;
1320 
1321 			/*
1322 			 * at itree_create() time, we can expand simple
1323 			 * iterators.  anything else we'll punt on.
1324 			 */
1325 			iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
1326 			if (iterinfop != NULL) {
1327 				/* explicit iterator; not part of pathname */
1328 				valuep->t = UINT64;
1329 				valuep->v = (unsigned long long)iterinfop->num;
1330 				return (1);
1331 			}
1332 			return (0);
1333 		}
1334 
1335 		/* return address of struct node */
1336 		valuep->t = NODEPTR;
1337 		valuep->v = (uintptr_t)np;
1338 		return (1);
1339 
1340 	case T_QUOTE:
1341 		valuep->t = STRING;
1342 		valuep->v = (uintptr_t)np->u.quote.s;
1343 		return (1);
1344 
1345 	case T_FUNC:
1346 		return (eval_func(np, ex, epnames, np->u.func.arglist,
1347 				globals, croot, arrowp, try, valuep));
1348 
1349 	case T_NUM:
1350 		valuep->t = UINT64;
1351 		valuep->v = np->u.ull;
1352 		return (1);
1353 
1354 	default:
1355 		outfl(O_DIE, np->file, np->line,
1356 		    "eval_expr: unexpected node type: %s",
1357 		    ptree_nodetype2str(np->t));
1358 	}
1359 	/*NOTREACHED*/
1360 	return (0);
1361 }
1362 
1363 /*
1364  * eval_fru() and eval_asru() don't do much, but are called from a number
1365  * of places.
1366  */
1367 struct node *
1368 eval_fru(struct node *np)
1369 {
1370 	ASSERT(np->t == T_NAME);
1371 	return (np);
1372 }
1373 
1374 struct node *
1375 eval_asru(struct node *np)
1376 {
1377 	ASSERT(np->t == T_NAME);
1378 	return (np);
1379 }
1380