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
44 int Pchildgen;
45
46 #ifdef FMAPLUGIN
47
48 #include "itree.h"
49 #include "eval.h"
50 #include "config.h"
51
52 static void
cp2num(struct config * cp,int * num)53 cp2num(struct config *cp, int *num)
54 {
55 config_getcompname(cp, NULL, num);
56 }
57
58 #else
59
60 /*ARGSUSED*/
61 static void
cp2num(struct config * cp,int * num)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
is_stmt(struct node * np)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_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
95 void
ptree(int flags,struct node * np,int no_iterators,int fileline)96 ptree(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
451 void
ptree_plut(void * name,void * val,void * arg)452 ptree_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
475 void
ptree_name(int flags,struct node * np)476 ptree_name(int flags, struct node *np)
477 {
478 ptree(flags, np, 1, 0);
479 }
480
481 void
ptree_name_iter(int flags,struct node * np)482 ptree_name_iter(int flags, struct node *np)
483 {
484 ptree(flags, np, 0, 0);
485 }
486
487 const char *
ptree_nodetype2str(enum nodetype t)488 ptree_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
546 const char *
ptree_nametype2str(enum nametype t)547 ptree_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
566 struct printer_info {
567 enum nodetype t;
568 const char *pat;
569 int flags;
570 };
571
572 static int
name_pattern_match(struct node * np,const char * pat)573 name_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
617 static int
name_pattern_match_in_subtree(struct node * np,const char * pat)618 name_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
667 static void
byname_printer(struct node * lhs,struct node * rhs,void * arg)668 byname_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
679 static void
ptree_type_pattern(int flags,enum nodetype t,const char * pat)680 ptree_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
735 void
ptree_all(int flags,const char * pat)736 ptree_all(int flags, const char *pat)
737 {
738 ptree_type_pattern(flags, T_NOTHING, pat);
739 }
740
741 void
ptree_fault(int flags,const char * pat)742 ptree_fault(int flags, const char *pat)
743 {
744 ptree_type_pattern(flags, T_FAULT, pat);
745 }
746
747 void
ptree_upset(int flags,const char * pat)748 ptree_upset(int flags, const char *pat)
749 {
750 ptree_type_pattern(flags, T_UPSET, pat);
751 }
752
753 void
ptree_defect(int flags,const char * pat)754 ptree_defect(int flags, const char *pat)
755 {
756 ptree_type_pattern(flags, T_DEFECT, pat);
757 }
758
759 void
ptree_error(int flags,const char * pat)760 ptree_error(int flags, const char *pat)
761 {
762 ptree_type_pattern(flags, T_ERROR, pat);
763 }
764
765 void
ptree_ereport(int flags,const char * pat)766 ptree_ereport(int flags, const char *pat)
767 {
768 ptree_type_pattern(flags, T_EREPORT, pat);
769 }
770
771 void
ptree_serd(int flags,const char * pat)772 ptree_serd(int flags, const char *pat)
773 {
774 ptree_type_pattern(flags, T_SERD, pat);
775 }
776
777 void
ptree_stat(int flags,const char * pat)778 ptree_stat(int flags, const char *pat)
779 {
780 ptree_type_pattern(flags, T_STAT, pat);
781 }
782
783 void
ptree_asru(int flags,const char * pat)784 ptree_asru(int flags, const char *pat)
785 {
786 ptree_type_pattern(flags, T_ASRU, pat);
787 }
788
789 void
ptree_fru(int flags,const char * pat)790 ptree_fru(int flags, const char *pat)
791 {
792 ptree_type_pattern(flags, T_FRU, pat);
793 }
794
795 void
ptree_prop(int flags,const char * pat)796 ptree_prop(int flags, const char *pat)
797 {
798 ptree_type_pattern(flags, T_PROP, pat);
799 }
800
801 void
ptree_mask(int flags,const char * pat)802 ptree_mask(int flags, const char *pat)
803 {
804 ptree_type_pattern(flags, T_MASK, pat);
805 }
806
807 void
ptree_timeval(int flags,unsigned long long * ullp)808 ptree_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