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 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "out.h"
36 #include "stable.h"
37 #include "literals.h"
38 #include "lut.h"
39 #include "tree.h"
40 #include "ptree.h"
41
42 int Pchildgen;
43
44 #ifdef FMAPLUGIN
45
46 #include "itree.h"
47 #include "eval.h"
48 #include "config.h"
49
50 static void
cp2num(struct config * cp,int * num)51 cp2num(struct config *cp, int *num)
52 {
53 config_getcompname(cp, NULL, num);
54 }
55
56 #else
57
58 /*ARGSUSED*/
59 static void
cp2num(struct config * cp,int * num)60 cp2num(struct config *cp, int *num)
61 {
62 out(O_DIE, "ptree: non-NULL cp");
63 }
64
65 #endif /* FMAPLUGIN */
66
67 static int
is_stmt(struct node * np)68 is_stmt(struct node *np)
69 {
70 switch (np->t) {
71 case T_FAULT:
72 case T_UPSET:
73 case T_DEFECT:
74 case T_ERROR:
75 case T_EREPORT:
76 case T_SERD:
77 case T_STAT:
78 case T_PROP:
79 case T_MASK:
80 case T_ASRU:
81 case T_FRU:
82 case T_CONFIG:
83 return (1);
84 /*NOTREACHED*/
85 break;
86 default:
87 break;
88 }
89
90 return (0);
91 }
92
93 void
ptree(int flags,struct node * np,int no_iterators,int fileline)94 ptree(int flags, struct node *np, int no_iterators, int fileline)
95 {
96 if (np == NULL)
97 return;
98
99 switch (np->t) {
100 case T_NOTHING:
101 break;
102 case T_NAME:
103 out(flags|O_NONL, "%s", np->u.name.s);
104 if (!no_iterators) {
105 if (np->u.name.cp != NULL) {
106 int num;
107 cp2num(np->u.name.cp, &num);
108 out(flags|O_NONL, "%d", num);
109 } else if (np->u.name.it == IT_HORIZONTAL) {
110 if (np->u.name.child == NULL ||
111 (np->u.name.childgen && !Pchildgen))
112 out(flags|O_NONL, "<>");
113 else {
114 out(flags|O_NONL, "<");
115 ptree(flags, np->u.name.child,
116 no_iterators, fileline);
117 out(flags|O_NONL, ">");
118 }
119 } else if (np->u.name.child &&
120 (!np->u.name.childgen || Pchildgen)) {
121 if (np->u.name.it != IT_NONE)
122 out(flags|O_NONL, "[");
123 ptree(flags, np->u.name.child, no_iterators,
124 fileline);
125 if (np->u.name.it != IT_NONE)
126 out(flags|O_NONL, "]");
127 }
128 }
129 if (np->u.name.next) {
130 ASSERT(np->u.name.next->t == T_NAME);
131 if (np->u.name.it == IT_ENAME)
132 out(flags|O_NONL, ".");
133 else
134 out(flags|O_NONL, "/");
135 ptree(flags, np->u.name.next, no_iterators, fileline);
136 }
137 break;
138 case T_TIMEVAL:
139 ptree_timeval(flags, &np->u.ull);
140 break;
141 case T_NUM:
142 out(flags|O_NONL, "%llu", np->u.ull);
143 break;
144 case T_QUOTE:
145 out(flags|O_NONL, "\"%s\"", np->u.quote.s);
146 break;
147 case T_GLOBID:
148 out(flags|O_NONL, "$%s", np->u.globid.s);
149 break;
150 case T_FUNC:
151 out(flags|O_NONL, "%s(", np->u.func.s);
152 ptree(flags, np->u.func.arglist, no_iterators, fileline);
153 out(flags|O_NONL, ")");
154 break;
155 case T_NVPAIR:
156 ptree(flags, np->u.expr.left, no_iterators, fileline);
157 out(flags|O_NONL, "=");
158 ptree(flags, np->u.expr.right, no_iterators, fileline);
159 break;
160 case T_EVENT:
161 ptree(flags, np->u.event.ename, no_iterators, fileline);
162 if (np->u.event.epname) {
163 out(flags|O_NONL, "@");
164 ptree(flags, np->u.event.epname,
165 no_iterators, fileline);
166 }
167 if (np->u.event.eexprlist) {
168 out(flags|O_NONL, "{");
169 ptree(flags, np->u.event.eexprlist,
170 no_iterators, fileline);
171 out(flags|O_NONL, "}");
172 }
173 break;
174 case T_ASSIGN:
175 out(flags|O_NONL, "(");
176 ptree(flags, np->u.expr.left, no_iterators, fileline);
177 out(flags|O_NONL, "=");
178 ptree(flags, np->u.expr.right, no_iterators, fileline);
179 out(flags|O_NONL, ")");
180 break;
181 case T_NOT:
182 out(flags|O_NONL, "(");
183 out(flags|O_NONL, "!");
184 ptree(flags, np->u.expr.left, no_iterators, fileline);
185 out(flags|O_NONL, ")");
186 break;
187 case T_AND:
188 out(flags|O_NONL, "(");
189 ptree(flags, np->u.expr.left, no_iterators, fileline);
190 out(flags|O_NONL, "&&");
191 ptree(flags, np->u.expr.right, no_iterators, fileline);
192 out(flags|O_NONL, ")");
193 break;
194 case T_OR:
195 out(flags|O_NONL, "(");
196 ptree(flags, np->u.expr.left, no_iterators, fileline);
197 out(flags|O_NONL, "||");
198 ptree(flags, np->u.expr.right, no_iterators, fileline);
199 out(flags|O_NONL, ")");
200 break;
201 case T_EQ:
202 out(flags|O_NONL, "(");
203 ptree(flags, np->u.expr.left, no_iterators, fileline);
204 out(flags|O_NONL, "==");
205 ptree(flags, np->u.expr.right, no_iterators, fileline);
206 out(flags|O_NONL, ")");
207 break;
208 case T_NE:
209 out(flags|O_NONL, "(");
210 ptree(flags, np->u.expr.left, no_iterators, fileline);
211 out(flags|O_NONL, "!=");
212 ptree(flags, np->u.expr.right, no_iterators, fileline);
213 out(flags|O_NONL, ")");
214 break;
215 case T_SUB:
216 out(flags|O_NONL, "(");
217 ptree(flags, np->u.expr.left, no_iterators, fileline);
218 out(flags|O_NONL, "-");
219 ptree(flags, np->u.expr.right, no_iterators, fileline);
220 out(flags|O_NONL, ")");
221 break;
222 case T_ADD:
223 out(flags|O_NONL, "(");
224 ptree(flags, np->u.expr.left, no_iterators, fileline);
225 out(flags|O_NONL, "+");
226 ptree(flags, np->u.expr.right, no_iterators, fileline);
227 out(flags|O_NONL, ")");
228 break;
229 case T_MUL:
230 out(flags|O_NONL, "(");
231 ptree(flags, np->u.expr.left, no_iterators, fileline);
232 out(flags|O_NONL, "*");
233 ptree(flags, np->u.expr.right, no_iterators, fileline);
234 out(flags|O_NONL, ")");
235 break;
236 case T_DIV:
237 out(flags|O_NONL, "(");
238 ptree(flags, np->u.expr.left, no_iterators, fileline);
239 out(flags|O_NONL, "/");
240 ptree(flags, np->u.expr.right, no_iterators, fileline);
241 out(flags|O_NONL, ")");
242 break;
243 case T_MOD:
244 out(flags|O_NONL, "(");
245 ptree(flags, np->u.expr.left, no_iterators, fileline);
246 out(flags|O_NONL, "%%");
247 ptree(flags, np->u.expr.right, no_iterators, fileline);
248 out(flags|O_NONL, ")");
249 break;
250 case T_LT:
251 out(flags|O_NONL, "(");
252 ptree(flags, np->u.expr.left, no_iterators, fileline);
253 out(flags|O_NONL, "<");
254 ptree(flags, np->u.expr.right, no_iterators, fileline);
255 out(flags|O_NONL, ")");
256 break;
257 case T_LE:
258 out(flags|O_NONL, "(");
259 ptree(flags, np->u.expr.left, no_iterators, fileline);
260 out(flags|O_NONL, "<=");
261 ptree(flags, np->u.expr.right, no_iterators, fileline);
262 out(flags|O_NONL, ")");
263 break;
264 case T_GT:
265 out(flags|O_NONL, "(");
266 ptree(flags, np->u.expr.left, no_iterators, fileline);
267 out(flags|O_NONL, ">");
268 ptree(flags, np->u.expr.right, no_iterators, fileline);
269 out(flags|O_NONL, ")");
270 break;
271 case T_GE:
272 out(flags|O_NONL, "(");
273 ptree(flags, np->u.expr.left, no_iterators, fileline);
274 out(flags|O_NONL, ">=");
275 ptree(flags, np->u.expr.right, no_iterators, fileline);
276 out(flags|O_NONL, ")");
277 break;
278 case T_BITNOT:
279 out(flags|O_NONL, "(");
280 out(flags|O_NONL, "~");
281 ptree(flags, np->u.expr.left, no_iterators, fileline);
282 out(flags|O_NONL, ")");
283 break;
284 case T_BITAND:
285 out(flags|O_NONL, "(");
286 ptree(flags, np->u.expr.left, no_iterators, fileline);
287 out(flags|O_NONL, "&");
288 ptree(flags, np->u.expr.right, no_iterators, fileline);
289 out(flags|O_NONL, ")");
290 break;
291 case T_BITOR:
292 out(flags|O_NONL, "(");
293 ptree(flags, np->u.expr.left, no_iterators, fileline);
294 out(flags|O_NONL, "|");
295 ptree(flags, np->u.expr.right, no_iterators, fileline);
296 out(flags|O_NONL, ")");
297 break;
298 case T_BITXOR:
299 out(flags|O_NONL, "(");
300 ptree(flags, np->u.expr.left, no_iterators, fileline);
301 out(flags|O_NONL, "^");
302 ptree(flags, np->u.expr.right, no_iterators, fileline);
303 out(flags|O_NONL, ")");
304 break;
305 case T_LSHIFT:
306 out(flags|O_NONL, "(");
307 ptree(flags, np->u.expr.left, no_iterators, fileline);
308 out(flags|O_NONL, "<<");
309 ptree(flags, np->u.expr.right, no_iterators, fileline);
310 out(flags|O_NONL, ")");
311 break;
312 case T_RSHIFT:
313 out(flags|O_NONL, "(");
314 ptree(flags, np->u.expr.left, no_iterators, fileline);
315 out(flags|O_NONL, ">>");
316 ptree(flags, np->u.expr.right, no_iterators, fileline);
317 out(flags|O_NONL, ")");
318 break;
319 case T_CONDIF:
320 out(flags|O_NONL, "(");
321 ptree(flags, np->u.expr.left, no_iterators, fileline);
322 out(flags|O_NONL, "?");
323 ptree(flags, np->u.expr.right, no_iterators, fileline);
324 out(flags|O_NONL, ")");
325 break;
326 case T_CONDELSE:
327 out(flags|O_NONL, "(");
328 ptree(flags, np->u.expr.left, no_iterators, fileline);
329 out(flags|O_NONL, ":");
330 ptree(flags, np->u.expr.right, no_iterators, fileline);
331 out(flags|O_NONL, ")");
332 break;
333 case T_ARROW:
334 ptree(flags, np->u.arrow.lhs, no_iterators, fileline);
335 if (np->u.arrow.nnp) {
336 out(flags|O_NONL, "(");
337 ptree(flags, np->u.arrow.nnp, no_iterators, fileline);
338 out(flags|O_NONL, ")");
339 }
340 out(flags|O_NONL, "->");
341 if (np->u.arrow.knp) {
342 out(flags|O_NONL, "(");
343 ptree(flags, np->u.arrow.knp, no_iterators, fileline);
344 out(flags|O_NONL, ")");
345 }
346 ptree(flags, np->u.arrow.rhs, no_iterators, fileline);
347 break;
348 case T_LIST:
349 ptree(flags, np->u.expr.left, no_iterators, fileline);
350 if (np->u.expr.left && np->u.expr.right &&
351 (np->u.expr.left->t != T_LIST ||
352 ! is_stmt(np->u.expr.right)))
353 out(flags|O_NONL, ",");
354 ptree(flags, np->u.expr.right, no_iterators, fileline);
355 break;
356 case T_FAULT:
357 case T_UPSET:
358 case T_DEFECT:
359 case T_ERROR:
360 case T_EREPORT:
361 if (fileline)
362 out(flags, "# %d \"%s\"", np->line, np->file);
363 out(flags|O_NONL, "event ");
364 ptree(flags, np->u.stmt.np, no_iterators, fileline);
365 if (np->u.stmt.nvpairs) {
366 out(flags|O_NONL, " ");
367 ptree(flags, np->u.stmt.nvpairs, no_iterators,
368 fileline);
369 }
370 out(flags, ";");
371 break;
372 case T_SERD:
373 case T_STAT:
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
ptree_plut(void * name,void * val,void * arg)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
ptree_name(int flags,struct node * np)474 ptree_name(int flags, struct node *np)
475 {
476 ptree(flags, np, 1, 0);
477 }
478
479 void
ptree_name_iter(int flags,struct node * np)480 ptree_name_iter(int flags, struct node *np)
481 {
482 ptree(flags, np, 0, 0);
483 }
484
485 const char *
ptree_nodetype2str(enum nodetype t)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_STAT: return L_stat;
536 case T_PROP: return L_prop;
537 case T_MASK: return L_mask;
538 default:
539 (void) sprintf(buf, "[unexpected nodetype: %d]", t);
540 return (buf);
541 }
542 }
543
544 const char *
ptree_nametype2str(enum nametype t)545 ptree_nametype2str(enum nametype t)
546 {
547 static char buf[100];
548
549 switch (t) {
550 case N_UNSPEC: return L_N_UNSPEC;
551 case N_FAULT: return L_fault;
552 case N_DEFECT: return L_defect;
553 case N_UPSET: return L_upset;
554 case N_ERROR: return L_error;
555 case N_EREPORT: return L_ereport;
556 case N_SERD: return L_serd;
557 case N_STAT: return L_stat;
558 default:
559 (void) sprintf(buf, "[unexpected nametype: %d]", t);
560 return (buf);
561 }
562 }
563
564 struct printer_info {
565 enum nodetype t;
566 const char *pat;
567 int flags;
568 };
569
570 static int
name_pattern_match(struct node * np,const char * pat)571 name_pattern_match(struct node *np, const char *pat)
572 {
573 const char *cend; /* first character not in component in pat */
574
575 if (pat == NULL || *pat == '\0')
576 return (1); /* either no pattern or we've matched it all */
577
578 if (np == NULL)
579 return (0); /* there's more pattern and nothing to match */
580
581 ASSERTeq(np->t, T_NAME, ptree_nodetype2str);
582
583 cend = strchr(pat, '/');
584 if (cend == NULL)
585 cend = strchr(pat, '.');
586 if (cend == NULL)
587 cend = &pat[strlen(pat)];
588
589 while (np) {
590 const char *s = np->u.name.s;
591
592 while (*s) {
593 const char *cstart = pat;
594
595 while (*s && tolower(*s) == tolower(*cstart)) {
596 cstart++;
597 if (cstart == cend) {
598 /* component matched */
599 while (*cend == '/')
600 cend++;
601 return
602 name_pattern_match(np->u.name.next,
603 cend);
604 }
605 s++;
606 }
607 if (*s)
608 s++;
609 }
610 np = np->u.name.next;
611 }
612 return (0);
613 }
614
615 static int
name_pattern_match_in_subtree(struct node * np,const char * pat)616 name_pattern_match_in_subtree(struct node *np, const char *pat)
617 {
618 if (pat == NULL || *pat == '\0')
619 return (1);
620
621 if (np == NULL)
622 return (0);
623
624 if (np->t == T_NAME)
625 return (name_pattern_match(np, pat));
626 else if (np->t == T_EVENT)
627 return (name_pattern_match_in_subtree(np->u.event.ename, pat) ||
628 name_pattern_match_in_subtree(np->u.event.epname, pat) ||
629 name_pattern_match_in_subtree(np->u.event.eexprlist, pat));
630 else if (np->t == T_ARROW)
631 return (name_pattern_match_in_subtree(np->u.arrow.lhs, pat) ||
632 name_pattern_match_in_subtree(np->u.arrow.rhs, pat));
633 else if (np->t == T_ASSIGN ||
634 np->t == T_CONDIF ||
635 np->t == T_CONDELSE ||
636 np->t == T_NOT ||
637 np->t == T_AND ||
638 np->t == T_OR ||
639 np->t == T_EQ ||
640 np->t == T_NE ||
641 np->t == T_SUB ||
642 np->t == T_ADD ||
643 np->t == T_MUL ||
644 np->t == T_DIV ||
645 np->t == T_MOD ||
646 np->t == T_LT ||
647 np->t == T_LE ||
648 np->t == T_GT ||
649 np->t == T_GE ||
650 np->t == T_BITAND ||
651 np->t == T_BITOR ||
652 np->t == T_BITXOR ||
653 np->t == T_BITNOT ||
654 np->t == T_LSHIFT ||
655 np->t == T_RSHIFT ||
656 np->t == T_LIST) {
657 return (name_pattern_match_in_subtree(np->u.expr.left, pat) ||
658 name_pattern_match_in_subtree(np->u.expr.right, pat));
659 } else if (np->t == T_FUNC) {
660 return (name_pattern_match_in_subtree(np->u.func.arglist, pat));
661 }
662 return (0);
663 }
664
665 static void
byname_printer(struct node * lhs,struct node * rhs,void * arg)666 byname_printer(struct node *lhs, struct node *rhs, void *arg)
667 {
668 struct printer_info *infop = (struct printer_info *)arg;
669
670 if (infop->t != T_NOTHING && rhs->t != infop->t)
671 return;
672 if (!name_pattern_match(lhs, infop->pat))
673 return;
674 ptree(infop->flags, rhs, 0, 0);
675 }
676
677 static void
ptree_type_pattern(int flags,enum nodetype t,const char * pat)678 ptree_type_pattern(int flags, enum nodetype t, const char *pat)
679 {
680 struct printer_info info;
681 struct node *np;
682
683 info.flags = flags;
684 info.pat = pat;
685 info.t = t;
686
687 switch (t) {
688 case T_FAULT:
689 lut_walk(Faults, (lut_cb)byname_printer, (void *)&info);
690 return;
691 case T_UPSET:
692 lut_walk(Upsets, (lut_cb)byname_printer, (void *)&info);
693 return;
694 case T_DEFECT:
695 lut_walk(Defects, (lut_cb)byname_printer, (void *)&info);
696 return;
697 case T_ERROR:
698 lut_walk(Errors, (lut_cb)byname_printer, (void *)&info);
699 return;
700 case T_EREPORT:
701 lut_walk(Ereports, (lut_cb)byname_printer, (void *)&info);
702 return;
703 case T_SERD:
704 lut_walk(SERDs, (lut_cb)byname_printer, (void *)&info);
705 return;
706 case T_STAT:
707 lut_walk(STATs, (lut_cb)byname_printer, (void *)&info);
708 return;
709 case T_ASRU:
710 lut_walk(ASRUs, (lut_cb)byname_printer, (void *)&info);
711 return;
712 case T_FRU:
713 lut_walk(FRUs, (lut_cb)byname_printer, (void *)&info);
714 return;
715 case T_CONFIG:
716 lut_walk(Configs, (lut_cb)byname_printer, (void *)&info);
717 return;
718 case T_PROP:
719 for (np = Props; 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 case T_MASK:
724 for (np = Masks; np; np = np->u.stmt.next)
725 if (name_pattern_match_in_subtree(np->u.stmt.np, pat))
726 ptree(flags, np, 0, 0);
727 return;
728 default:
729 ptree(flags, tree_root(NULL), 0, 0);
730 }
731 }
732
733 void
ptree_all(int flags,const char * pat)734 ptree_all(int flags, const char *pat)
735 {
736 ptree_type_pattern(flags, T_NOTHING, pat);
737 }
738
739 void
ptree_fault(int flags,const char * pat)740 ptree_fault(int flags, const char *pat)
741 {
742 ptree_type_pattern(flags, T_FAULT, pat);
743 }
744
745 void
ptree_upset(int flags,const char * pat)746 ptree_upset(int flags, const char *pat)
747 {
748 ptree_type_pattern(flags, T_UPSET, pat);
749 }
750
751 void
ptree_defect(int flags,const char * pat)752 ptree_defect(int flags, const char *pat)
753 {
754 ptree_type_pattern(flags, T_DEFECT, pat);
755 }
756
757 void
ptree_error(int flags,const char * pat)758 ptree_error(int flags, const char *pat)
759 {
760 ptree_type_pattern(flags, T_ERROR, pat);
761 }
762
763 void
ptree_ereport(int flags,const char * pat)764 ptree_ereport(int flags, const char *pat)
765 {
766 ptree_type_pattern(flags, T_EREPORT, pat);
767 }
768
769 void
ptree_serd(int flags,const char * pat)770 ptree_serd(int flags, const char *pat)
771 {
772 ptree_type_pattern(flags, T_SERD, pat);
773 }
774
775 void
ptree_stat(int flags,const char * pat)776 ptree_stat(int flags, const char *pat)
777 {
778 ptree_type_pattern(flags, T_STAT, pat);
779 }
780
781 void
ptree_asru(int flags,const char * pat)782 ptree_asru(int flags, const char *pat)
783 {
784 ptree_type_pattern(flags, T_ASRU, pat);
785 }
786
787 void
ptree_fru(int flags,const char * pat)788 ptree_fru(int flags, const char *pat)
789 {
790 ptree_type_pattern(flags, T_FRU, pat);
791 }
792
793 void
ptree_prop(int flags,const char * pat)794 ptree_prop(int flags, const char *pat)
795 {
796 ptree_type_pattern(flags, T_PROP, pat);
797 }
798
799 void
ptree_mask(int flags,const char * pat)800 ptree_mask(int flags, const char *pat)
801 {
802 ptree_type_pattern(flags, T_MASK, pat);
803 }
804
805 void
ptree_timeval(int flags,unsigned long long * ullp)806 ptree_timeval(int flags, unsigned long long *ullp)
807 {
808 unsigned long long val;
809
810 #define NOREMAINDER(den, num, val) (((val) = ((den) / (num))) * (num) == (den))
811 if (*ullp == 0)
812 out(flags|O_NONL, "0us");
813 else if (*ullp >= TIMEVAL_EVENTUALLY)
814 out(flags|O_NONL, "infinity");
815 else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24*365, val))
816 out(flags|O_NONL, "%lluyear%s", val, (val == 1) ? "" : "s");
817 else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24*30, val))
818 out(flags|O_NONL, "%llumonth%s", val, (val == 1) ? "" : "s");
819 else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24*7, val))
820 out(flags|O_NONL, "%lluweek%s", val, (val == 1) ? "" : "s");
821 else if (NOREMAINDER(*ullp, 1000000000ULL*60*60*24, val))
822 out(flags|O_NONL, "%lluday%s", val, (val == 1) ? "" : "s");
823 else if (NOREMAINDER(*ullp, 1000000000ULL*60*60, val))
824 out(flags|O_NONL, "%lluhour%s", val, (val == 1) ? "" : "s");
825 else if (NOREMAINDER(*ullp, 1000000000ULL*60, val))
826 out(flags|O_NONL, "%lluminute%s", val, (val == 1) ? "" : "s");
827 else if (NOREMAINDER(*ullp, 1000000000ULL, val))
828 out(flags|O_NONL, "%llusecond%s", val, (val == 1) ? "" : "s");
829 else if (NOREMAINDER(*ullp, 1000000ULL, val))
830 out(flags|O_NONL, "%llums", val);
831 else if (NOREMAINDER(*ullp, 1000ULL, val))
832 out(flags|O_NONL, "%lluus", val);
833 else
834 out(flags|O_NONL, "%lluns", *ullp);
835 }
836