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