xref: /titanic_41/usr/src/cmd/fm/eversholt/common/ptree.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * ptree.c -- routines for printing the prop tree
27  *
28  * this module contains routines to print portions of the parse tree.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "out.h"
38 #include "stable.h"
39 #include "literals.h"
40 #include "lut.h"
41 #include "tree.h"
42 #include "ptree.h"
43 
44 int Pchildgen;
45 
46 #ifdef	FMAPLUGIN
47 
48 #include "itree.h"
49 #include "eval.h"
50 #include "config.h"
51 
52 static void
53 cp2num(struct config *cp, int *num)
54 {
55 	config_getcompname(cp, NULL, num);
56 }
57 
58 #else
59 
60 /*ARGSUSED*/
61 static void
62 cp2num(struct config *cp, int *num)
63 {
64 	out(O_DIE, "ptree: non-NULL cp");
65 }
66 
67 #endif	/* FMAPLUGIN */
68 
69 static int
70 is_stmt(struct node *np)
71 {
72 	switch (np->t) {
73 	case T_FAULT:
74 	case T_UPSET:
75 	case T_DEFECT:
76 	case T_ERROR:
77 	case T_EREPORT:
78 	case T_SERD:
79 	case T_PROP:
80 	case T_MASK:
81 	case T_ASRU:
82 	case T_FRU:
83 	case T_CONFIG:
84 		return (1);
85 		/*NOTREACHED*/
86 		break;
87 	default:
88 		break;
89 	}
90 
91 	return (0);
92 }
93 
94 void
95 ptree(int flags, struct node *np, int no_iterators, int fileline)
96 {
97 	if (np == NULL)
98 		return;
99 
100 	switch (np->t) {
101 	case T_NOTHING:
102 		break;
103 	case T_NAME:
104 		out(flags|O_NONL, "%s", np->u.name.s);
105 		if (!no_iterators) {
106 			if (np->u.name.cp != NULL) {
107 				int num;
108 				cp2num(np->u.name.cp, &num);
109 				out(flags|O_NONL, "%d", num);
110 			} else if (np->u.name.it == IT_HORIZONTAL) {
111 				if (np->u.name.child == NULL ||
112 				    (np->u.name.childgen && !Pchildgen))
113 					out(flags|O_NONL, "<>");
114 				else {
115 					out(flags|O_NONL, "<");
116 					ptree(flags, np->u.name.child,
117 					    no_iterators, fileline);
118 					out(flags|O_NONL, ">");
119 				}
120 			} else if (np->u.name.child &&
121 			    (!np->u.name.childgen || Pchildgen)) {
122 				if (np->u.name.it != IT_NONE)
123 					out(flags|O_NONL, "[");
124 				ptree(flags, np->u.name.child, no_iterators,
125 				    fileline);
126 				if (np->u.name.it != IT_NONE)
127 					out(flags|O_NONL, "]");
128 			}
129 		}
130 		if (np->u.name.next) {
131 			ASSERT(np->u.name.next->t == T_NAME);
132 			if (np->u.name.it == IT_ENAME)
133 				out(flags|O_NONL, ".");
134 			else
135 				out(flags|O_NONL, "/");
136 			ptree(flags, np->u.name.next, no_iterators, fileline);
137 		}
138 		break;
139 	case T_TIMEVAL:
140 		ptree_timeval(flags, &np->u.ull);
141 		break;
142 	case T_NUM:
143 		out(flags|O_NONL, "%llu", np->u.ull);
144 		break;
145 	case T_QUOTE:
146 		out(flags|O_NONL, "\"%s\"", np->u.quote.s);
147 		break;
148 	case T_GLOBID:
149 		out(flags|O_NONL, "$%s", np->u.globid.s);
150 		break;
151 	case T_FUNC:
152 		out(flags|O_NONL, "%s(", np->u.func.s);
153 		ptree(flags, np->u.func.arglist, no_iterators, fileline);
154 		out(flags|O_NONL, ")");
155 		break;
156 	case T_NVPAIR:
157 		ptree(flags, np->u.expr.left, no_iterators, fileline);
158 		out(flags|O_NONL, "=");
159 		ptree(flags, np->u.expr.right, no_iterators, fileline);
160 		break;
161 	case T_EVENT:
162 		ptree(flags, np->u.event.ename, no_iterators, fileline);
163 		if (np->u.event.epname) {
164 			out(flags|O_NONL, "@");
165 			ptree(flags, np->u.event.epname,
166 			    no_iterators, fileline);
167 		}
168 		if (np->u.event.eexprlist) {
169 			out(flags|O_NONL, "{");
170 			ptree(flags, np->u.event.eexprlist,
171 			    no_iterators, fileline);
172 			out(flags|O_NONL, "}");
173 		}
174 		break;
175 	case T_ASSIGN:
176 		out(flags|O_NONL, "(");
177 		ptree(flags, np->u.expr.left, no_iterators, fileline);
178 		out(flags|O_NONL, "=");
179 		ptree(flags, np->u.expr.right, no_iterators, fileline);
180 		out(flags|O_NONL, ")");
181 		break;
182 	case T_NOT:
183 		out(flags|O_NONL, "(");
184 		out(flags|O_NONL, "!");
185 		ptree(flags, np->u.expr.left, no_iterators, fileline);
186 		out(flags|O_NONL, ")");
187 		break;
188 	case T_AND:
189 		out(flags|O_NONL, "(");
190 		ptree(flags, np->u.expr.left, no_iterators, fileline);
191 		out(flags|O_NONL, "&&");
192 		ptree(flags, np->u.expr.right, no_iterators, fileline);
193 		out(flags|O_NONL, ")");
194 		break;
195 	case T_OR:
196 		out(flags|O_NONL, "(");
197 		ptree(flags, np->u.expr.left, no_iterators, fileline);
198 		out(flags|O_NONL, "||");
199 		ptree(flags, np->u.expr.right, no_iterators, fileline);
200 		out(flags|O_NONL, ")");
201 		break;
202 	case T_EQ:
203 		out(flags|O_NONL, "(");
204 		ptree(flags, np->u.expr.left, no_iterators, fileline);
205 		out(flags|O_NONL, "==");
206 		ptree(flags, np->u.expr.right, no_iterators, fileline);
207 		out(flags|O_NONL, ")");
208 		break;
209 	case T_NE:
210 		out(flags|O_NONL, "(");
211 		ptree(flags, np->u.expr.left, no_iterators, fileline);
212 		out(flags|O_NONL, "!=");
213 		ptree(flags, np->u.expr.right, no_iterators, fileline);
214 		out(flags|O_NONL, ")");
215 		break;
216 	case T_SUB:
217 		out(flags|O_NONL, "(");
218 		ptree(flags, np->u.expr.left, no_iterators, fileline);
219 		out(flags|O_NONL, "-");
220 		ptree(flags, np->u.expr.right, no_iterators, fileline);
221 		out(flags|O_NONL, ")");
222 		break;
223 	case T_ADD:
224 		out(flags|O_NONL, "(");
225 		ptree(flags, np->u.expr.left, no_iterators, fileline);
226 		out(flags|O_NONL, "+");
227 		ptree(flags, np->u.expr.right, no_iterators, fileline);
228 		out(flags|O_NONL, ")");
229 		break;
230 	case T_MUL:
231 		out(flags|O_NONL, "(");
232 		ptree(flags, np->u.expr.left, no_iterators, fileline);
233 		out(flags|O_NONL, "*");
234 		ptree(flags, np->u.expr.right, no_iterators, fileline);
235 		out(flags|O_NONL, ")");
236 		break;
237 	case T_DIV:
238 		out(flags|O_NONL, "(");
239 		ptree(flags, np->u.expr.left, no_iterators, fileline);
240 		out(flags|O_NONL, "/");
241 		ptree(flags, np->u.expr.right, no_iterators, fileline);
242 		out(flags|O_NONL, ")");
243 		break;
244 	case T_MOD:
245 		out(flags|O_NONL, "(");
246 		ptree(flags, np->u.expr.left, no_iterators, fileline);
247 		out(flags|O_NONL, "%%");
248 		ptree(flags, np->u.expr.right, no_iterators, fileline);
249 		out(flags|O_NONL, ")");
250 		break;
251 	case T_LT:
252 		out(flags|O_NONL, "(");
253 		ptree(flags, np->u.expr.left, no_iterators, fileline);
254 		out(flags|O_NONL, "<");
255 		ptree(flags, np->u.expr.right, no_iterators, fileline);
256 		out(flags|O_NONL, ")");
257 		break;
258 	case T_LE:
259 		out(flags|O_NONL, "(");
260 		ptree(flags, np->u.expr.left, no_iterators, fileline);
261 		out(flags|O_NONL, "<=");
262 		ptree(flags, np->u.expr.right, no_iterators, fileline);
263 		out(flags|O_NONL, ")");
264 		break;
265 	case T_GT:
266 		out(flags|O_NONL, "(");
267 		ptree(flags, np->u.expr.left, no_iterators, fileline);
268 		out(flags|O_NONL, ">");
269 		ptree(flags, np->u.expr.right, no_iterators, fileline);
270 		out(flags|O_NONL, ")");
271 		break;
272 	case T_GE:
273 		out(flags|O_NONL, "(");
274 		ptree(flags, np->u.expr.left, no_iterators, fileline);
275 		out(flags|O_NONL, ">=");
276 		ptree(flags, np->u.expr.right, no_iterators, fileline);
277 		out(flags|O_NONL, ")");
278 		break;
279 	case T_BITNOT:
280 		out(flags|O_NONL, "(");
281 		out(flags|O_NONL, "~");
282 		ptree(flags, np->u.expr.left, no_iterators, fileline);
283 		out(flags|O_NONL, ")");
284 		break;
285 	case T_BITAND:
286 		out(flags|O_NONL, "(");
287 		ptree(flags, np->u.expr.left, no_iterators, fileline);
288 		out(flags|O_NONL, "&");
289 		ptree(flags, np->u.expr.right, no_iterators, fileline);
290 		out(flags|O_NONL, ")");
291 		break;
292 	case T_BITOR:
293 		out(flags|O_NONL, "(");
294 		ptree(flags, np->u.expr.left, no_iterators, fileline);
295 		out(flags|O_NONL, "|");
296 		ptree(flags, np->u.expr.right, no_iterators, fileline);
297 		out(flags|O_NONL, ")");
298 		break;
299 	case T_BITXOR:
300 		out(flags|O_NONL, "(");
301 		ptree(flags, np->u.expr.left, no_iterators, fileline);
302 		out(flags|O_NONL, "^");
303 		ptree(flags, np->u.expr.right, no_iterators, fileline);
304 		out(flags|O_NONL, ")");
305 		break;
306 	case T_LSHIFT:
307 		out(flags|O_NONL, "(");
308 		ptree(flags, np->u.expr.left, no_iterators, fileline);
309 		out(flags|O_NONL, "<<");
310 		ptree(flags, np->u.expr.right, no_iterators, fileline);
311 		out(flags|O_NONL, ")");
312 		break;
313 	case T_RSHIFT:
314 		out(flags|O_NONL, "(");
315 		ptree(flags, np->u.expr.left, no_iterators, fileline);
316 		out(flags|O_NONL, ">>");
317 		ptree(flags, np->u.expr.right, no_iterators, fileline);
318 		out(flags|O_NONL, ")");
319 		break;
320 	case T_CONDIF:
321 		out(flags|O_NONL, "(");
322 		ptree(flags, np->u.expr.left, no_iterators, fileline);
323 		out(flags|O_NONL, "?");
324 		ptree(flags, np->u.expr.right, no_iterators, fileline);
325 		out(flags|O_NONL, ")");
326 		break;
327 	case T_CONDELSE:
328 		out(flags|O_NONL, "(");
329 		ptree(flags, np->u.expr.left, no_iterators, fileline);
330 		out(flags|O_NONL, ":");
331 		ptree(flags, np->u.expr.right, no_iterators, fileline);
332 		out(flags|O_NONL, ")");
333 		break;
334 	case T_ARROW:
335 		ptree(flags, np->u.arrow.lhs, no_iterators, fileline);
336 		if (np->u.arrow.nnp) {
337 			out(flags|O_NONL, "(");
338 			ptree(flags, np->u.arrow.nnp, no_iterators, fileline);
339 			out(flags|O_NONL, ")");
340 		}
341 		out(flags|O_NONL, "->");
342 		if (np->u.arrow.knp) {
343 			out(flags|O_NONL, "(");
344 			ptree(flags, np->u.arrow.knp, no_iterators, fileline);
345 			out(flags|O_NONL, ")");
346 		}
347 		ptree(flags, np->u.arrow.rhs, no_iterators, fileline);
348 		break;
349 	case T_LIST:
350 		ptree(flags, np->u.expr.left, no_iterators, fileline);
351 		if (np->u.expr.left && np->u.expr.right &&
352 		    (np->u.expr.left->t != T_LIST ||
353 		    ! is_stmt(np->u.expr.right)))
354 			out(flags|O_NONL, ",");
355 		ptree(flags, np->u.expr.right, no_iterators, fileline);
356 		break;
357 	case T_FAULT:
358 	case T_UPSET:
359 	case T_DEFECT:
360 	case T_ERROR:
361 	case T_EREPORT:
362 		if (fileline)
363 			out(flags, "# %d \"%s\"", np->line, np->file);
364 		out(flags|O_NONL, "event ");
365 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
366 		if (np->u.stmt.nvpairs) {
367 			out(flags|O_NONL, " ");
368 			ptree(flags, np->u.stmt.nvpairs, no_iterators,
369 			    fileline);
370 		}
371 		out(flags, ";");
372 		break;
373 	case T_SERD:
374 		if (fileline)
375 			out(flags, "# %d \"%s\"", np->line, np->file);
376 		out(flags|O_NONL, "engine ");
377 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
378 		if (np->u.stmt.nvpairs) {
379 			out(flags|O_NONL, " ");
380 			ptree(flags, np->u.stmt.nvpairs, no_iterators,
381 			    fileline);
382 		} else if (np->u.stmt.lutp) {
383 			struct plut_wlk_data pd;
384 
385 			pd.flags = flags;
386 			pd.first = 0;
387 
388 			lut_walk(np->u.stmt.lutp, ptree_plut, &pd);
389 		}
390 		out(flags, ";");
391 		break;
392 	case T_ASRU:
393 		if (fileline)
394 			out(flags, "# %d \"%s\"", np->line, np->file);
395 		out(flags|O_NONL, "asru ");
396 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
397 		if (np->u.stmt.nvpairs) {
398 			out(flags|O_NONL, " ");
399 			ptree(flags, np->u.stmt.nvpairs, no_iterators,
400 			    fileline);
401 		}
402 		out(flags, ";");
403 		break;
404 	case T_FRU:
405 		if (fileline)
406 			out(flags, "# %d \"%s\"", np->line, np->file);
407 		out(flags|O_NONL, "fru ");
408 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
409 		if (np->u.stmt.nvpairs) {
410 			out(flags|O_NONL, " ");
411 			ptree(flags, np->u.stmt.nvpairs, no_iterators,
412 			    fileline);
413 		}
414 		out(flags, ";");
415 		break;
416 	case T_CONFIG:
417 		if (fileline)
418 			out(flags, "# %d \"%s\"", np->line, np->file);
419 		out(flags|O_NONL, "config ");
420 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
421 		if (np->u.stmt.nvpairs) {
422 			out(flags|O_NONL, " ");
423 			ptree(flags, np->u.stmt.nvpairs, no_iterators,
424 				fileline);
425 		}
426 		out(flags, ";");
427 		break;
428 	case T_PROP:
429 		if (fileline)
430 			out(flags, "# %d \"%s\"", np->line, np->file);
431 		out(flags|O_NONL, "prop ");
432 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
433 		out(flags, ";");
434 		break;
435 	case T_MASK:
436 		if (fileline)
437 			out(flags, "# %d \"%s\"", np->line, np->file);
438 		out(flags|O_NONL, "mask ");
439 		ptree(flags, np->u.stmt.np, no_iterators, fileline);
440 		out(flags, ";");
441 		break;
442 	default:
443 		out(O_DIE,
444 		    "internal error: ptree unexpected nodetype: %d", np->t);
445 		/*NOTREACHED*/
446 	}
447 }
448 
449 void
450 ptree_plut(void *name, void *val, void *arg)
451 {
452 	struct plut_wlk_data *pd = (struct plut_wlk_data *)arg;
453 	int c;
454 	static int indent;
455 
456 	indent++;
457 
458 	if (pd->first == 0)
459 		out(pd->flags, ",");
460 	else
461 		pd->first = 0;
462 
463 	for (c = indent; c > 0; c--)
464 		out(pd->flags|O_NONL, "\t");
465 	out(pd->flags|O_NONL, "%s", (char *)name);
466 
467 	out(pd->flags|O_NONL, "=");
468 	ptree(pd->flags, val, 0, 0);
469 
470 	indent--;
471 }
472 
473 void
474 ptree_name(int flags, struct node *np)
475 {
476 	ptree(flags, np, 1, 0);
477 }
478 
479 void
480 ptree_name_iter(int flags, struct node *np)
481 {
482 	ptree(flags, np, 0, 0);
483 }
484 
485 const char *
486 ptree_nodetype2str(enum nodetype t)
487 {
488 	static char buf[100];
489 
490 	switch (t) {
491 	case T_NOTHING: return L_T_NOTHING;
492 	case T_NAME: return L_T_NAME;
493 	case T_GLOBID: return L_T_GLOBID;
494 	case T_EVENT: return L_T_EVENT;
495 	case T_ENGINE: return L_T_ENGINE;
496 	case T_ASRU: return L_asru;
497 	case T_FRU: return L_fru;
498 	case T_CONFIG: return L_config;
499 	case T_TIMEVAL: return L_T_TIMEVAL;
500 	case T_NUM: return L_T_NUM;
501 	case T_QUOTE: return L_T_QUOTE;
502 	case T_FUNC: return L_T_FUNC;
503 	case T_NVPAIR: return L_T_NVPAIR;
504 	case T_ASSIGN: return L_T_ASSIGN;
505 	case T_CONDIF: return L_T_CONDIF;
506 	case T_CONDELSE: return L_T_CONDELSE;
507 	case T_NOT: return L_T_NOT;
508 	case T_AND: return L_T_AND;
509 	case T_OR: return L_T_OR;
510 	case T_EQ: return L_T_EQ;
511 	case T_NE: return L_T_NE;
512 	case T_SUB: return L_T_SUB;
513 	case T_ADD: return L_T_ADD;
514 	case T_MUL: return L_T_MUL;
515 	case T_DIV: return L_T_DIV;
516 	case T_MOD: return L_T_MOD;
517 	case T_LT: return L_T_LT;
518 	case T_LE: return L_T_LE;
519 	case T_GT: return L_T_GT;
520 	case T_GE: return L_T_GE;
521 	case T_BITAND: return L_T_BITAND;
522 	case T_BITOR: return L_T_BITOR;
523 	case T_BITXOR: return L_T_BITXOR;
524 	case T_BITNOT: return L_T_BITNOT;
525 	case T_LSHIFT: return L_T_LSHIFT;
526 	case T_RSHIFT: return L_T_RSHIFT;
527 	case T_ARROW: return L_T_ARROW;
528 	case T_LIST: return L_T_LIST;
529 	case T_FAULT: return L_fault;
530 	case T_UPSET: return L_upset;
531 	case T_DEFECT: return L_defect;
532 	case T_ERROR: return L_error;
533 	case T_EREPORT: return L_ereport;
534 	case T_SERD: return L_serd;
535 	case T_PROP: return L_prop;
536 	case T_MASK: return L_mask;
537 	default:
538 		(void) sprintf(buf, "[unexpected nodetype: %d]", t);
539 		return (buf);
540 	}
541 }
542 
543 const char *
544 ptree_nametype2str(enum nametype t)
545 {
546 	static char buf[100];
547 
548 	switch (t) {
549 	case N_UNSPEC: return L_N_UNSPEC;
550 	case N_FAULT: return L_fault;
551 	case N_DEFECT: return L_defect;
552 	case N_UPSET: return L_upset;
553 	case N_ERROR: return L_error;
554 	case N_EREPORT: return L_ereport;
555 	case N_SERD: return L_serd;
556 	default:
557 		(void) sprintf(buf, "[unexpected nametype: %d]", t);
558 		return (buf);
559 	}
560 }
561 
562 struct printer_info {
563 	enum nodetype t;
564 	const char *pat;
565 	int flags;
566 };
567 
568 static int
569 name_pattern_match(struct node *np, const char *pat)
570 {
571 	const char *cend;	/* first character not in component in pat */
572 
573 	if (pat == NULL || *pat == '\0')
574 		return (1);	/* either no pattern or we've matched it all */
575 
576 	if (np == NULL)
577 		return (0);	/* there's more pattern and nothing to match */
578 
579 	ASSERTeq(np->t, T_NAME, ptree_nodetype2str);
580 
581 	cend = strchr(pat, '/');
582 	if (cend == NULL)
583 		cend = strchr(pat, '.');
584 	if (cend == NULL)
585 		cend = &pat[strlen(pat)];
586 
587 	while (np) {
588 		const char *s = np->u.name.s;
589 
590 		while (*s) {
591 			const char *cstart = pat;
592 
593 			while (*s && tolower(*s) == tolower(*cstart)) {
594 				cstart++;
595 				if (cstart == cend) {
596 					/* component matched */
597 					while (*cend == '/')
598 						cend++;
599 					return
600 					    name_pattern_match(np->u.name.next,
601 					    cend);
602 				}
603 				s++;
604 			}
605 			if (*s)
606 				s++;
607 		}
608 		np = np->u.name.next;
609 	}
610 	return (0);
611 }
612 
613 static int
614 name_pattern_match_in_subtree(struct node *np, const char *pat)
615 {
616 	if (pat == NULL || *pat == '\0')
617 		return (1);
618 
619 	if (np == NULL)
620 		return (0);
621 
622 	if (np->t == T_NAME)
623 		return (name_pattern_match(np, pat));
624 	else if (np->t == T_EVENT)
625 		return (name_pattern_match_in_subtree(np->u.event.ename, pat) ||
626 		    name_pattern_match_in_subtree(np->u.event.epname, pat) ||
627 		    name_pattern_match_in_subtree(np->u.event.eexprlist, pat));
628 	else if (np->t == T_ARROW)
629 		return (name_pattern_match_in_subtree(np->u.arrow.lhs, pat) ||
630 		    name_pattern_match_in_subtree(np->u.arrow.rhs, pat));
631 	else if (np->t == T_ASSIGN ||
632 			np->t == T_CONDIF ||
633 			np->t == T_CONDELSE ||
634 			np->t == T_NOT ||
635 			np->t == T_AND ||
636 			np->t == T_OR ||
637 			np->t == T_EQ ||
638 			np->t == T_NE ||
639 			np->t == T_SUB ||
640 			np->t == T_ADD ||
641 			np->t == T_MUL ||
642 			np->t == T_DIV ||
643 			np->t == T_MOD ||
644 			np->t == T_LT ||
645 			np->t == T_LE ||
646 			np->t == T_GT ||
647 			np->t == T_GE ||
648 			np->t == T_BITAND ||
649 			np->t == T_BITOR ||
650 			np->t == T_BITXOR ||
651 			np->t == T_BITNOT ||
652 			np->t == T_LSHIFT ||
653 			np->t == T_RSHIFT ||
654 			np->t == T_LIST) {
655 		return (name_pattern_match_in_subtree(np->u.expr.left, pat) ||
656 		    name_pattern_match_in_subtree(np->u.expr.right, pat));
657 	} else if (np->t == T_FUNC) {
658 		return (name_pattern_match_in_subtree(np->u.func.arglist, pat));
659 	}
660 	return (0);
661 }
662 
663 static void
664 byname_printer(struct node *lhs, struct node *rhs, void *arg)
665 {
666 	struct printer_info *infop = (struct printer_info *)arg;
667 
668 	if (infop->t != T_NOTHING && rhs->t != infop->t)
669 		return;
670 	if (!name_pattern_match(lhs, infop->pat))
671 		return;
672 	ptree(infop->flags, rhs, 0, 0);
673 }
674 
675 static void
676 ptree_type_pattern(int flags, enum nodetype t, const char *pat)
677 {
678 	struct printer_info info;
679 	struct node *np;
680 
681 	info.flags = flags;
682 	info.pat = pat;
683 	info.t = t;
684 
685 	switch (t) {
686 	case T_FAULT:
687 		lut_walk(Faults, (lut_cb)byname_printer, (void *)&info);
688 		return;
689 	case T_UPSET:
690 		lut_walk(Upsets, (lut_cb)byname_printer, (void *)&info);
691 		return;
692 	case T_DEFECT:
693 		lut_walk(Defects, (lut_cb)byname_printer, (void *)&info);
694 		return;
695 	case T_ERROR:
696 		lut_walk(Errors, (lut_cb)byname_printer, (void *)&info);
697 		return;
698 	case T_EREPORT:
699 		lut_walk(Ereports, (lut_cb)byname_printer, (void *)&info);
700 		return;
701 	case T_SERD:
702 		lut_walk(SERDs, (lut_cb)byname_printer, (void *)&info);
703 		return;
704 	case T_ASRU:
705 		lut_walk(ASRUs, (lut_cb)byname_printer, (void *)&info);
706 		return;
707 	case T_FRU:
708 		lut_walk(FRUs, (lut_cb)byname_printer, (void *)&info);
709 		return;
710 	case T_CONFIG:
711 		lut_walk(Configs, (lut_cb)byname_printer, (void *)&info);
712 		return;
713 	case T_PROP:
714 		for (np = Props; np; np = np->u.stmt.next)
715 			if (name_pattern_match_in_subtree(np->u.stmt.np, pat))
716 				ptree(flags, np, 0, 0);
717 		return;
718 	case T_MASK:
719 		for (np = Masks; np; np = np->u.stmt.next)
720 			if (name_pattern_match_in_subtree(np->u.stmt.np, pat))
721 				ptree(flags, np, 0, 0);
722 		return;
723 	default:
724 		ptree(flags, tree_root(NULL), 0, 0);
725 	}
726 }
727 
728 void
729 ptree_all(int flags, const char *pat)
730 {
731 	ptree_type_pattern(flags, T_NOTHING, pat);
732 }
733 
734 void
735 ptree_fault(int flags, const char *pat)
736 {
737 	ptree_type_pattern(flags, T_FAULT, pat);
738 }
739 
740 void
741 ptree_upset(int flags, const char *pat)
742 {
743 	ptree_type_pattern(flags, T_UPSET, pat);
744 }
745 
746 void
747 ptree_defect(int flags, const char *pat)
748 {
749 	ptree_type_pattern(flags, T_DEFECT, pat);
750 }
751 
752 void
753 ptree_error(int flags, const char *pat)
754 {
755 	ptree_type_pattern(flags, T_ERROR, pat);
756 }
757 
758 void
759 ptree_ereport(int flags, const char *pat)
760 {
761 	ptree_type_pattern(flags, T_EREPORT, pat);
762 }
763 
764 void
765 ptree_serd(int flags, const char *pat)
766 {
767 	ptree_type_pattern(flags, T_SERD, pat);
768 }
769 
770 void
771 ptree_asru(int flags, const char *pat)
772 {
773 	ptree_type_pattern(flags, T_ASRU, pat);
774 }
775 
776 void
777 ptree_fru(int flags, const char *pat)
778 {
779 	ptree_type_pattern(flags, T_FRU, pat);
780 }
781 
782 void
783 ptree_prop(int flags, const char *pat)
784 {
785 	ptree_type_pattern(flags, T_PROP, pat);
786 }
787 
788 void
789 ptree_mask(int flags, const char *pat)
790 {
791 	ptree_type_pattern(flags, T_MASK, pat);
792 }
793 
794 void
795 ptree_timeval(int flags, unsigned long long *ullp)
796 {
797 	unsigned long long val;
798 
799 #define	NOREMAINDER(den, num, val) (((val) = ((den) / (num))) * (num) == (den))
800 	if (*ullp == 0)
801 		out(flags|O_NONL, "0us");
802 	else if (*ullp >= TIMEVAL_EVENTUALLY)
803 		out(flags|O_NONL, "infinity");
804 	else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24*365, val))
805 		out(flags|O_NONL, "%lluyear%s", val, (val == 1) ? "" : "s");
806 	else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24*30, val))
807 		out(flags|O_NONL, "%llumonth%s", val, (val == 1) ? "" : "s");
808 	else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24*7, val))
809 		out(flags|O_NONL, "%lluweek%s", val, (val == 1) ? "" : "s");
810 	else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24, val))
811 		out(flags|O_NONL, "%lluday%s", val, (val == 1) ? "" : "s");
812 	else if (NOREMAINDER(*ullp, 1000000000ULL*60*60, val))
813 		out(flags|O_NONL, "%lluhour%s", val, (val == 1) ? "" : "s");
814 	else if (NOREMAINDER(*ullp, 1000000000ULL*60, val))
815 		out(flags|O_NONL, "%lluminute%s", val, (val == 1) ? "" : "s");
816 	else if (NOREMAINDER(*ullp, 1000000000ULL, val))
817 		out(flags|O_NONL, "%llusecond%s", val, (val == 1) ? "" : "s");
818 	else if (NOREMAINDER(*ullp, 1000000ULL, val))
819 		out(flags|O_NONL, "%llums", val);
820 	else if (NOREMAINDER(*ullp, 1000ULL, val))
821 		out(flags|O_NONL, "%lluus", val);
822 	else
823 		out(flags|O_NONL, "%lluns", *ullp);
824 }
825