1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 2869 gavinm * Common Development and Distribution License (the "License"). 6 2869 gavinm * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 5947 stephh * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel * 25 0 stevel * tree.c -- routines for manipulating the prop tree 26 0 stevel * 27 0 stevel * the actions in escparse.y call these routines to construct 28 0 stevel * the parse tree. these routines, in turn, call the check_X() 29 0 stevel * routines for semantic checking. 30 0 stevel */ 31 0 stevel 32 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 33 0 stevel 34 0 stevel #include <stdio.h> 35 0 stevel #include <stdlib.h> 36 0 stevel #include <ctype.h> 37 0 stevel #include <strings.h> 38 0 stevel #include <alloca.h> 39 0 stevel #include "alloc.h" 40 0 stevel #include "out.h" 41 0 stevel #include "stats.h" 42 0 stevel #include "stable.h" 43 0 stevel #include "literals.h" 44 0 stevel #include "lut.h" 45 0 stevel #include "esclex.h" 46 0 stevel #include "tree.h" 47 0 stevel #include "check.h" 48 0 stevel #include "ptree.h" 49 0 stevel 50 0 stevel static struct node *Root; 51 0 stevel 52 0 stevel static char *Newname; 53 0 stevel 54 0 stevel static struct stats *Faultcount; 55 0 stevel static struct stats *Upsetcount; 56 0 stevel static struct stats *Defectcount; 57 0 stevel static struct stats *Errorcount; 58 0 stevel static struct stats *Ereportcount; 59 0 stevel static struct stats *SERDcount; 60 1414 cindi static struct stats *STATcount; 61 0 stevel static struct stats *ASRUcount; 62 0 stevel static struct stats *FRUcount; 63 0 stevel static struct stats *Configcount; 64 0 stevel static struct stats *Propcount; 65 0 stevel static struct stats *Maskcount; 66 0 stevel static struct stats *Nodecount; 67 0 stevel static struct stats *Namecount; 68 0 stevel static struct stats *Nodesize; 69 4436 stephh 70 4436 stephh struct lut *Usedprops; 71 0 stevel 72 0 stevel void 73 0 stevel tree_init(void) 74 0 stevel { 75 0 stevel Faultcount = stats_new_counter("parser.fault", "fault decls", 1); 76 0 stevel Upsetcount = stats_new_counter("parser.upset", "upset decls", 1); 77 0 stevel Defectcount = stats_new_counter("parser.defect", "defect decls", 1); 78 0 stevel Errorcount = stats_new_counter("parser.error", "error decls", 1); 79 0 stevel Ereportcount = stats_new_counter("parser.ereport", "ereport decls", 1); 80 0 stevel SERDcount = stats_new_counter("parser.SERD", "SERD engine decls", 1); 81 1414 cindi STATcount = stats_new_counter("parser.STAT", "STAT engine decls", 1); 82 0 stevel ASRUcount = stats_new_counter("parser.ASRU", "ASRU decls", 1); 83 0 stevel FRUcount = stats_new_counter("parser.FRU", "FRU decls", 1); 84 0 stevel Configcount = stats_new_counter("parser.config", "config stmts", 1); 85 0 stevel Propcount = stats_new_counter("parser.prop", "prop stmts", 1); 86 0 stevel Maskcount = stats_new_counter("parser.mask", "mask stmts", 1); 87 0 stevel Nodecount = stats_new_counter("parser.node", "nodes created", 1); 88 0 stevel Namecount = stats_new_counter("parser.name", "names created", 1); 89 0 stevel Nodesize = 90 0 stevel stats_new_counter("parser.nodesize", "sizeof(struct node)", 1); 91 0 stevel stats_counter_add(Nodesize, sizeof (struct node)); 92 0 stevel } 93 0 stevel 94 0 stevel void 95 0 stevel tree_fini(void) 96 0 stevel { 97 0 stevel stats_delete(Faultcount); 98 0 stevel stats_delete(Upsetcount); 99 0 stevel stats_delete(Defectcount); 100 0 stevel stats_delete(Errorcount); 101 0 stevel stats_delete(Ereportcount); 102 0 stevel stats_delete(SERDcount); 103 1414 cindi stats_delete(STATcount); 104 0 stevel stats_delete(ASRUcount); 105 0 stevel stats_delete(FRUcount); 106 0 stevel stats_delete(Configcount); 107 0 stevel stats_delete(Propcount); 108 0 stevel stats_delete(Maskcount); 109 0 stevel stats_delete(Nodecount); 110 0 stevel stats_delete(Namecount); 111 0 stevel stats_delete(Nodesize); 112 0 stevel 113 0 stevel /* free entire parse tree */ 114 0 stevel tree_free(Root); 115 0 stevel 116 0 stevel /* free up the luts we keep for decls */ 117 0 stevel lut_free(Faults, NULL, NULL); 118 0 stevel Faults = NULL; 119 0 stevel lut_free(Upsets, NULL, NULL); 120 0 stevel Upsets = NULL; 121 0 stevel lut_free(Defects, NULL, NULL); 122 0 stevel Defects = NULL; 123 0 stevel lut_free(Errors, NULL, NULL); 124 0 stevel Errors = NULL; 125 0 stevel lut_free(Ereports, NULL, NULL); 126 0 stevel Ereports = NULL; 127 0 stevel lut_free(Ereportenames, NULL, NULL); 128 0 stevel Ereportenames = NULL; 129 6640 cth lut_free(Ereportenames_discard, NULL, NULL); 130 6640 cth Ereportenames_discard = NULL; 131 0 stevel lut_free(SERDs, NULL, NULL); 132 0 stevel SERDs = NULL; 133 1414 cindi lut_free(STATs, NULL, NULL); 134 1414 cindi STATs = NULL; 135 0 stevel lut_free(ASRUs, NULL, NULL); 136 0 stevel ASRUs = NULL; 137 0 stevel lut_free(FRUs, NULL, NULL); 138 0 stevel FRUs = NULL; 139 0 stevel lut_free(Configs, NULL, NULL); 140 0 stevel Configs = NULL; 141 5947 stephh lut_free(Usedprops, NULL, NULL); 142 5947 stephh Usedprops = NULL; 143 0 stevel 144 0 stevel Props = Lastprops = NULL; 145 0 stevel Masks = Lastmasks = NULL; 146 0 stevel Problems = Lastproblems = NULL; 147 0 stevel 148 0 stevel if (Newname != NULL) { 149 0 stevel FREE(Newname); 150 0 stevel Newname = NULL; 151 0 stevel } 152 0 stevel } 153 0 stevel 154 4436 stephh /*ARGSUSED*/ 155 4436 stephh static int 156 4436 stephh nodesize(enum nodetype t, struct node *ret) 157 4436 stephh { 158 4436 stephh int size = sizeof (struct node); 159 4436 stephh 160 4436 stephh switch (t) { 161 4436 stephh case T_NAME: 162 4436 stephh size += sizeof (ret->u.name) - sizeof (ret->u); 163 4436 stephh break; 164 4436 stephh 165 4436 stephh case T_GLOBID: 166 4436 stephh size += sizeof (ret->u.globid) - sizeof (ret->u); 167 4436 stephh break; 168 4436 stephh 169 4436 stephh case T_TIMEVAL: 170 4436 stephh case T_NUM: 171 4436 stephh size += sizeof (ret->u.ull) - sizeof (ret->u); 172 4436 stephh break; 173 4436 stephh 174 4436 stephh case T_QUOTE: 175 4436 stephh size += sizeof (ret->u.quote) - sizeof (ret->u); 176 4436 stephh break; 177 4436 stephh 178 4436 stephh case T_FUNC: 179 4436 stephh size += sizeof (ret->u.func) - sizeof (ret->u); 180 4436 stephh break; 181 4436 stephh 182 4436 stephh case T_FAULT: 183 4436 stephh case T_UPSET: 184 4436 stephh case T_DEFECT: 185 4436 stephh case T_ERROR: 186 4436 stephh case T_EREPORT: 187 4436 stephh case T_ASRU: 188 4436 stephh case T_FRU: 189 4436 stephh case T_SERD: 190 4436 stephh case T_STAT: 191 4436 stephh case T_CONFIG: 192 4436 stephh case T_PROP: 193 4436 stephh case T_MASK: 194 4436 stephh size += sizeof (ret->u.stmt) - sizeof (ret->u); 195 4436 stephh break; 196 4436 stephh 197 4436 stephh case T_EVENT: 198 4436 stephh size += sizeof (ret->u.event) - sizeof (ret->u); 199 4436 stephh break; 200 4436 stephh 201 4436 stephh case T_ARROW: 202 4436 stephh size += sizeof (ret->u.arrow) - sizeof (ret->u); 203 4436 stephh break; 204 4436 stephh 205 4436 stephh default: 206 4436 stephh size += sizeof (ret->u.expr) - sizeof (ret->u); 207 4436 stephh break; 208 4436 stephh } 209 4436 stephh return (size); 210 4436 stephh } 211 4436 stephh 212 0 stevel struct node * 213 0 stevel newnode(enum nodetype t, const char *file, int line) 214 0 stevel { 215 4436 stephh struct node *ret = NULL; 216 4436 stephh int size = nodesize(t, ret); 217 0 stevel 218 4436 stephh ret = alloc_xmalloc(size); 219 0 stevel stats_counter_bump(Nodecount); 220 4436 stephh bzero(ret, size); 221 0 stevel ret->t = t; 222 0 stevel ret->file = (file == NULL) ? "<nofile>" : file; 223 0 stevel ret->line = line; 224 0 stevel 225 0 stevel return (ret); 226 0 stevel } 227 0 stevel 228 0 stevel /*ARGSUSED*/ 229 0 stevel void 230 0 stevel tree_free(struct node *root) 231 0 stevel { 232 0 stevel if (root == NULL) 233 0 stevel return; 234 0 stevel 235 0 stevel switch (root->t) { 236 0 stevel case T_NAME: 237 0 stevel tree_free(root->u.name.child); 238 0 stevel tree_free(root->u.name.next); 239 0 stevel break; 240 0 stevel case T_FUNC: 241 0 stevel tree_free(root->u.func.arglist); 242 0 stevel break; 243 0 stevel case T_AND: 244 0 stevel case T_OR: 245 0 stevel case T_EQ: 246 0 stevel case T_NE: 247 0 stevel case T_ADD: 248 0 stevel case T_DIV: 249 0 stevel case T_MOD: 250 0 stevel case T_MUL: 251 0 stevel case T_SUB: 252 0 stevel case T_LT: 253 0 stevel case T_LE: 254 0 stevel case T_GT: 255 0 stevel case T_GE: 256 0 stevel case T_BITAND: 257 0 stevel case T_BITOR: 258 0 stevel case T_BITXOR: 259 0 stevel case T_BITNOT: 260 0 stevel case T_LSHIFT: 261 0 stevel case T_RSHIFT: 262 0 stevel case T_NVPAIR: 263 0 stevel case T_ASSIGN: 264 0 stevel case T_CONDIF: 265 0 stevel case T_CONDELSE: 266 0 stevel case T_LIST: 267 0 stevel tree_free(root->u.expr.left); 268 0 stevel tree_free(root->u.expr.right); 269 0 stevel break; 270 0 stevel case T_EVENT: 271 0 stevel tree_free(root->u.event.ename); 272 0 stevel tree_free(root->u.event.epname); 273 0 stevel tree_free(root->u.event.eexprlist); 274 0 stevel break; 275 0 stevel case T_NOT: 276 0 stevel tree_free(root->u.expr.left); 277 0 stevel break; 278 0 stevel case T_ARROW: 279 0 stevel tree_free(root->u.arrow.lhs); 280 0 stevel tree_free(root->u.arrow.nnp); 281 0 stevel tree_free(root->u.arrow.knp); 282 0 stevel tree_free(root->u.arrow.rhs); 283 0 stevel break; 284 0 stevel case T_PROP: 285 0 stevel case T_MASK: 286 0 stevel tree_free(root->u.stmt.np); 287 0 stevel break; 288 0 stevel case T_FAULT: 289 0 stevel case T_UPSET: 290 0 stevel case T_DEFECT: 291 0 stevel case T_ERROR: 292 0 stevel case T_EREPORT: 293 0 stevel case T_ASRU: 294 0 stevel case T_FRU: 295 0 stevel case T_SERD: 296 1414 cindi case T_STAT: 297 0 stevel case T_CONFIG: 298 0 stevel tree_free(root->u.stmt.np); 299 0 stevel if (root->u.stmt.nvpairs) 300 0 stevel tree_free(root->u.stmt.nvpairs); 301 0 stevel if (root->u.stmt.lutp) 302 0 stevel lut_free(root->u.stmt.lutp, NULL, NULL); 303 0 stevel break; 304 0 stevel case T_TIMEVAL: 305 0 stevel case T_NUM: 306 0 stevel case T_QUOTE: 307 0 stevel case T_GLOBID: 308 0 stevel case T_NOTHING: 309 0 stevel break; 310 0 stevel default: 311 0 stevel out(O_DIE, 312 0 stevel "internal error: tree_free unexpected nodetype: %d", 313 0 stevel root->t); 314 0 stevel /*NOTREACHED*/ 315 0 stevel } 316 4436 stephh alloc_xfree((char *)root, nodesize(root->t, root)); 317 0 stevel } 318 0 stevel 319 0 stevel static int 320 0 stevel tree_treecmp(struct node *np1, struct node *np2, enum nodetype t, 321 0 stevel lut_cmp cmp_func) 322 0 stevel { 323 0 stevel if (np1 == NULL || np2 == NULL) 324 0 stevel return (0); 325 0 stevel 326 0 stevel if (np1->t != np2->t) 327 0 stevel return (1); 328 0 stevel 329 0 stevel ASSERT(cmp_func != NULL); 330 0 stevel 331 0 stevel if (np1->t == t) 332 0 stevel return ((*cmp_func)(np1, np2)); 333 0 stevel 334 0 stevel switch (np1->t) { 335 0 stevel case T_NAME: 336 0 stevel if (tree_treecmp(np1->u.name.child, np2->u.name.child, t, 337 4436 stephh cmp_func)) 338 0 stevel return (1); 339 0 stevel return (tree_treecmp(np1->u.name.next, np2->u.name.next, t, 340 4436 stephh cmp_func)); 341 0 stevel /*NOTREACHED*/ 342 0 stevel break; 343 0 stevel case T_FUNC: 344 0 stevel return (tree_treecmp(np1->u.func.arglist, np2->u.func.arglist, 345 4436 stephh t, cmp_func)); 346 0 stevel /*NOTREACHED*/ 347 0 stevel break; 348 0 stevel case T_AND: 349 0 stevel case T_OR: 350 0 stevel case T_EQ: 351 0 stevel case T_NE: 352 0 stevel case T_ADD: 353 0 stevel case T_DIV: 354 0 stevel case T_MOD: 355 0 stevel case T_MUL: 356 0 stevel case T_SUB: 357 0 stevel case T_LT: 358 0 stevel case T_LE: 359 0 stevel case T_GT: 360 0 stevel case T_GE: 361 0 stevel case T_BITAND: 362 0 stevel case T_BITOR: 363 0 stevel case T_BITXOR: 364 0 stevel case T_BITNOT: 365 0 stevel case T_LSHIFT: 366 0 stevel case T_RSHIFT: 367 0 stevel case T_NVPAIR: 368 0 stevel case T_ASSIGN: 369 0 stevel case T_CONDIF: 370 0 stevel case T_CONDELSE: 371 0 stevel case T_LIST: 372 0 stevel if (tree_treecmp(np1->u.expr.left, np2->u.expr.left, t, 373 4436 stephh cmp_func)) 374 0 stevel return (1); 375 0 stevel return (tree_treecmp(np1->u.expr.right, np2->u.expr.right, t, 376 4436 stephh cmp_func)); 377 0 stevel /*NOTREACHED*/ 378 0 stevel break; 379 0 stevel case T_EVENT: 380 0 stevel if (tree_treecmp(np1->u.event.ename, np2->u.event.ename, t, 381 4436 stephh cmp_func)) 382 0 stevel return (1); 383 0 stevel if (tree_treecmp(np1->u.event.epname, np2->u.event.epname, t, 384 4436 stephh cmp_func)) 385 0 stevel return (1); 386 0 stevel return (tree_treecmp(np1->u.event.eexprlist, 387 4436 stephh np2->u.event.eexprlist, t, cmp_func)); 388 0 stevel /*NOTREACHED*/ 389 0 stevel break; 390 0 stevel case T_NOT: 391 0 stevel return (tree_treecmp(np1->u.expr.left, np2->u.expr.left, t, 392 4436 stephh cmp_func)); 393 0 stevel /*NOTREACHED*/ 394 0 stevel break; 395 0 stevel case T_ARROW: 396 0 stevel if (tree_treecmp(np1->u.arrow.lhs, np2->u.arrow.lhs, t, 397 4436 stephh cmp_func)) 398 0 stevel return (1); 399 0 stevel if (tree_treecmp(np1->u.arrow.nnp, np2->u.arrow.nnp, t, 400 4436 stephh cmp_func)) 401 0 stevel return (1); 402 0 stevel if (tree_treecmp(np1->u.arrow.knp, np2->u.arrow.knp, t, 403 4436 stephh cmp_func)) 404 0 stevel return (1); 405 0 stevel return (tree_treecmp(np1->u.arrow.rhs, np2->u.arrow.rhs, t, 406 4436 stephh cmp_func)); 407 0 stevel /*NOTREACHED*/ 408 0 stevel break; 409 0 stevel case T_PROP: 410 0 stevel case T_MASK: 411 0 stevel return (tree_treecmp(np1->u.stmt.np, np2->u.stmt.np, t, 412 4436 stephh cmp_func)); 413 0 stevel /*NOTREACHED*/ 414 0 stevel break; 415 0 stevel case T_FAULT: 416 0 stevel case T_UPSET: 417 0 stevel case T_DEFECT: 418 0 stevel case T_ERROR: 419 0 stevel case T_EREPORT: 420 0 stevel case T_ASRU: 421 0 stevel case T_FRU: 422 0 stevel case T_SERD: 423 1414 cindi case T_STAT: 424 0 stevel if (tree_treecmp(np1->u.stmt.np, np2->u.stmt.np, t, cmp_func)) 425 0 stevel return (1); 426 0 stevel return (tree_treecmp(np1->u.stmt.nvpairs, np2->u.stmt.nvpairs, 427 4436 stephh t, cmp_func)); 428 0 stevel /*NOTREACHED*/ 429 0 stevel break; 430 0 stevel case T_TIMEVAL: 431 0 stevel case T_NUM: 432 0 stevel case T_QUOTE: 433 0 stevel case T_GLOBID: 434 0 stevel case T_NOTHING: 435 0 stevel break; 436 0 stevel default: 437 0 stevel out(O_DIE, 438 0 stevel "internal error: tree_treecmp unexpected nodetype: %d", 439 0 stevel np1->t); 440 0 stevel /*NOTREACHED*/ 441 0 stevel break; 442 0 stevel } 443 0 stevel 444 0 stevel return (0); 445 0 stevel } 446 0 stevel 447 0 stevel struct node * 448 0 stevel tree_root(struct node *np) 449 0 stevel { 450 0 stevel if (np) 451 0 stevel Root = np; 452 0 stevel return (Root); 453 0 stevel } 454 0 stevel 455 0 stevel struct node * 456 0 stevel tree_nothing(void) 457 0 stevel { 458 0 stevel return (newnode(T_NOTHING, L_nofile, 0)); 459 0 stevel } 460 0 stevel 461 0 stevel struct node * 462 0 stevel tree_expr(enum nodetype t, struct node *left, struct node *right) 463 0 stevel { 464 0 stevel struct node *ret; 465 0 stevel 466 0 stevel ASSERTinfo(left != NULL || right != NULL, ptree_nodetype2str(t)); 467 0 stevel 468 0 stevel ret = newnode(t, 469 0 stevel (left) ? left->file : right->file, 470 0 stevel (left) ? left->line : right->line); 471 0 stevel 472 0 stevel ret->u.expr.left = left; 473 0 stevel ret->u.expr.right = right; 474 0 stevel 475 0 stevel check_expr(ret); 476 0 stevel 477 0 stevel return (ret); 478 0 stevel } 479 0 stevel 480 0 stevel /* 481 0 stevel * ename_compress -- convert event class name in to more space-efficient form 482 0 stevel * 483 0 stevel * this routine is called after the parser has completed an "ename", which 484 0 stevel * is that part of an event that contains the class name (like ereport.x.y.z). 485 0 stevel * after this routine gets done with the ename, two things are true: 486 0 stevel * 1. the ename uses only a single struct node 487 0 stevel * 2. ename->u.name.s contains the *complete* class name, dots and all, 488 0 stevel * entered into the string table. 489 0 stevel * 490 0 stevel * so in addition to saving space by using fewer struct nodes, this routine 491 0 stevel * allows consumers of the fault tree to assume the ename is a single 492 0 stevel * string, rather than a linked list of strings. 493 0 stevel */ 494 0 stevel static struct node * 495 0 stevel ename_compress(struct node *ename) 496 0 stevel { 497 0 stevel char *buf; 498 0 stevel char *cp; 499 0 stevel int len = 0; 500 0 stevel struct node *np; 501 0 stevel 502 0 stevel if (ename == NULL) 503 0 stevel return (ename); 504 0 stevel 505 0 stevel ASSERT(ename->t == T_NAME); 506 0 stevel 507 0 stevel if (ename->u.name.next == NULL) 508 0 stevel return (ename); /* no compression to be applied here */ 509 0 stevel 510 0 stevel for (np = ename; np != NULL; np = np->u.name.next) { 511 0 stevel ASSERT(np->t == T_NAME); 512 0 stevel len++; /* room for '.' and final '\0' */ 513 0 stevel len += strlen(np->u.name.s); 514 0 stevel } 515 0 stevel cp = buf = alloca(len); 516 0 stevel for (np = ename; np != NULL; np = np->u.name.next) { 517 0 stevel ASSERT(np->t == T_NAME); 518 0 stevel if (np != ename) 519 0 stevel *cp++ = '.'; 520 0 stevel (void) strcpy(cp, np->u.name.s); 521 0 stevel cp += strlen(cp); 522 0 stevel } 523 0 stevel 524 0 stevel ename->u.name.s = stable(buf); 525 0 stevel tree_free(ename->u.name.next); 526 0 stevel ename->u.name.next = NULL; 527 0 stevel ename->u.name.last = ename; 528 0 stevel return (ename); 529 0 stevel } 530 0 stevel 531 0 stevel struct node * 532 0 stevel tree_event(struct node *ename, struct node *epname, struct node *eexprlist) 533 0 stevel { 534 0 stevel struct node *ret; 535 0 stevel 536 0 stevel ASSERT(ename != NULL); 537 0 stevel 538 0 stevel ret = newnode(T_EVENT, ename->file, ename->line); 539 0 stevel 540 0 stevel ret->u.event.ename = ename_compress(ename); 541 0 stevel ret->u.event.epname = epname; 542 0 stevel ret->u.event.eexprlist = eexprlist; 543 0 stevel 544 0 stevel check_event(ret); 545 0 stevel 546 0 stevel return (ret); 547 0 stevel } 548 0 stevel 549 0 stevel struct node * 550 0 stevel tree_name(const char *s, enum itertype it, const char *file, int line) 551 0 stevel { 552 0 stevel struct node *ret = newnode(T_NAME, file, line); 553 0 stevel 554 0 stevel ASSERT(s != NULL); 555 0 stevel 556 0 stevel stats_counter_bump(Namecount); 557 0 stevel ret->u.name.t = N_UNSPEC; 558 0 stevel ret->u.name.s = stable(s); 559 0 stevel ret->u.name.it = it; 560 0 stevel ret->u.name.last = ret; 561 0 stevel 562 0 stevel if (it == IT_ENAME) { 563 0 stevel /* PHASE2, possible optimization: convert to table driven */ 564 0 stevel if (s == L_fault) 565 0 stevel ret->u.name.t = N_FAULT; 566 0 stevel else if (s == L_upset) 567 0 stevel ret->u.name.t = N_UPSET; 568 0 stevel else if (s == L_defect) 569 0 stevel ret->u.name.t = N_DEFECT; 570 0 stevel else if (s == L_error) 571 0 stevel ret->u.name.t = N_ERROR; 572 0 stevel else if (s == L_ereport) 573 0 stevel ret->u.name.t = N_EREPORT; 574 0 stevel else if (s == L_serd) 575 0 stevel ret->u.name.t = N_SERD; 576 1414 cindi else if (s == L_stat) 577 1414 cindi ret->u.name.t = N_STAT; 578 0 stevel else 579 0 stevel outfl(O_ERR, file, line, "unknown class: %s", s); 580 0 stevel } 581 0 stevel return (ret); 582 0 stevel } 583 0 stevel 584 0 stevel struct node * 585 0 stevel tree_iname(const char *s, const char *file, int line) 586 0 stevel { 587 0 stevel struct node *ret; 588 0 stevel char *ss; 589 0 stevel char *ptr; 590 0 stevel 591 0 stevel ASSERT(s != NULL && *s != '\0'); 592 0 stevel 593 0 stevel ss = STRDUP(s); 594 0 stevel 595 0 stevel ptr = &ss[strlen(ss) - 1]; 596 0 stevel if (!isdigit(*ptr)) { 597 0 stevel outfl(O_ERR, file, line, 598 0 stevel "instanced name expected (i.e. \"x0/y1\")"); 599 0 stevel FREE(ss); 600 0 stevel return (tree_name(s, IT_NONE, file, line)); 601 0 stevel } 602 0 stevel while (ptr > ss && isdigit(*(ptr - 1))) 603 0 stevel ptr--; 604 0 stevel 605 0 stevel ret = newnode(T_NAME, file, line); 606 0 stevel stats_counter_bump(Namecount); 607 0 stevel ret->u.name.child = tree_num(ptr, file, line); 608 0 stevel *ptr = '\0'; 609 0 stevel ret->u.name.t = N_UNSPEC; 610 0 stevel ret->u.name.s = stable(ss); 611 0 stevel ret->u.name.it = IT_NONE; 612 0 stevel ret->u.name.last = ret; 613 0 stevel FREE(ss); 614 0 stevel 615 0 stevel return (ret); 616 0 stevel } 617 0 stevel 618 0 stevel struct node * 619 0 stevel tree_globid(const char *s, const char *file, int line) 620 0 stevel { 621 0 stevel struct node *ret = newnode(T_GLOBID, file, line); 622 0 stevel 623 0 stevel ASSERT(s != NULL); 624 0 stevel 625 0 stevel ret->u.globid.s = stable(s); 626 0 stevel 627 0 stevel return (ret); 628 0 stevel } 629 0 stevel 630 0 stevel struct node * 631 0 stevel tree_name_append(struct node *np1, struct node *np2) 632 0 stevel { 633 0 stevel ASSERT(np1 != NULL && np2 != NULL); 634 0 stevel 635 0 stevel if (np1->t != T_NAME) 636 0 stevel outfl(O_DIE, np1->file, np1->line, 637 0 stevel "tree_name_append: internal error (np1 type %d)", np1->t); 638 0 stevel if (np2->t != T_NAME) 639 0 stevel outfl(O_DIE, np2->file, np2->line, 640 0 stevel "tree_name_append: internal error (np2 type %d)", np2->t); 641 0 stevel 642 0 stevel ASSERT(np1->u.name.last != NULL); 643 0 stevel 644 0 stevel np1->u.name.last->u.name.next = np2; 645 0 stevel np1->u.name.last = np2; 646 0 stevel return (np1); 647 0 stevel } 648 0 stevel 649 0 stevel /* 650 0 stevel * tree_name_repairdash -- repair a class name that contained a dash 651 0 stevel * 652 0 stevel * this routine is called by the parser when a dash is encountered 653 0 stevel * in a class name. the event protocol allows the dashes but our 654 0 stevel * lexer considers them a separate token (arithmetic minus). an extra 655 0 stevel * rule in the parser catches this case and calls this routine to fixup 656 0 stevel * the last component of the class name (so far) by constructing the 657 0 stevel * new stable entry for a name including the dash. 658 0 stevel */ 659 0 stevel struct node * 660 0 stevel tree_name_repairdash(struct node *np, const char *s) 661 0 stevel { 662 0 stevel int len; 663 0 stevel char *buf; 664 0 stevel 665 0 stevel ASSERT(np != NULL && s != NULL); 666 0 stevel 667 0 stevel if (np->t != T_NAME) 668 0 stevel outfl(O_DIE, np->file, np->line, 669 0 stevel "tree_name_repairdash: internal error (np type %d)", 670 0 stevel np->t); 671 0 stevel 672 0 stevel ASSERT(np->u.name.last != NULL); 673 0 stevel 674 0 stevel len = strlen(np->u.name.last->u.name.s) + 1 + strlen(s) + 1; 675 0 stevel buf = MALLOC(len); 676 0 stevel (void) snprintf(buf, len, "%s-%s", np->u.name.last->u.name.s, s); 677 2869 gavinm np->u.name.last->u.name.s = stable(buf); 678 2869 gavinm FREE(buf); 679 2869 gavinm return (np); 680 2869 gavinm } 681 2869 gavinm 682 2869 gavinm struct node * 683 2869 gavinm tree_name_repairdash2(const char *s, struct node *np) 684 2869 gavinm { 685 2869 gavinm int len; 686 2869 gavinm char *buf; 687 2869 gavinm 688 2869 gavinm ASSERT(np != NULL && s != NULL); 689 2869 gavinm 690 2869 gavinm if (np->t != T_NAME) 691 2869 gavinm outfl(O_DIE, np->file, np->line, 692 2869 gavinm "tree_name_repairdash: internal error (np type %d)", 693 2869 gavinm np->t); 694 2869 gavinm 695 2869 gavinm ASSERT(np->u.name.last != NULL); 696 2869 gavinm 697 2869 gavinm len = strlen(np->u.name.last->u.name.s) + 1 + strlen(s) + 1; 698 2869 gavinm buf = MALLOC(len); 699 2869 gavinm (void) snprintf(buf, len, "%s-%s", s, np->u.name.last->u.name.s); 700 0 stevel np->u.name.last->u.name.s = stable(buf); 701 0 stevel FREE(buf); 702 0 stevel return (np); 703 0 stevel } 704 0 stevel 705 0 stevel struct node * 706 0 stevel tree_name_iterator(struct node *np1, struct node *np2) 707 0 stevel { 708 0 stevel ASSERT(np1 != NULL); 709 0 stevel ASSERT(np2 != NULL); 710 0 stevel ASSERTinfo(np1->t == T_NAME, ptree_nodetype2str(np1->t)); 711 0 stevel 712 0 stevel np1->u.name.child = np2; 713 0 stevel 714 0 stevel check_name_iterator(np1); 715 0 stevel 716 0 stevel return (np1); 717 0 stevel } 718 0 stevel 719 0 stevel struct node * 720 0 stevel tree_timeval(const char *s, const char *suffix, const char *file, int line) 721 0 stevel { 722 0 stevel struct node *ret = newnode(T_TIMEVAL, file, line); 723 0 stevel const unsigned long long *ullp; 724 0 stevel 725 0 stevel ASSERT(s != NULL); 726 0 stevel ASSERT(suffix != NULL); 727 0 stevel 728 0 stevel if ((ullp = lex_s2ullp_lut_lookup(Timesuffixlut, suffix)) == NULL) { 729 0 stevel outfl(O_ERR, file, line, 730 0 stevel "unrecognized number suffix: %s", suffix); 731 0 stevel /* still construct a valid timeval node so parsing continues */ 732 0 stevel ret->u.ull = 1; 733 0 stevel } else { 734 0 stevel ret->u.ull = (unsigned long long)strtoul(s, NULL, 0) * *ullp; 735 0 stevel } 736 0 stevel 737 0 stevel return (ret); 738 0 stevel } 739 0 stevel 740 0 stevel struct node * 741 0 stevel tree_num(const char *s, const char *file, int line) 742 0 stevel { 743 0 stevel struct node *ret = newnode(T_NUM, file, line); 744 0 stevel 745 0 stevel ret->u.ull = (unsigned long long)strtoul(s, NULL, 0); 746 0 stevel return (ret); 747 0 stevel } 748 0 stevel 749 0 stevel struct node * 750 0 stevel tree_quote(const char *s, const char *file, int line) 751 0 stevel { 752 0 stevel struct node *ret = newnode(T_QUOTE, file, line); 753 0 stevel 754 0 stevel ret->u.quote.s = stable(s); 755 0 stevel return (ret); 756 0 stevel } 757 0 stevel 758 0 stevel struct node * 759 0 stevel tree_func(const char *s, struct node *np, const char *file, int line) 760 0 stevel { 761 0 stevel struct node *ret = newnode(T_FUNC, file, line); 762 4436 stephh const char *ptr; 763 0 stevel 764 0 stevel ret->u.func.s = s; 765 0 stevel ret->u.func.arglist = np; 766 0 stevel 767 0 stevel check_func(ret); 768 4436 stephh 769 4436 stephh /* 770 4436 stephh * keep track of the properties we're interested in so we can ignore the 771 4436 stephh * rest 772 4436 stephh */ 773 4436 stephh if (strcmp(s, L_confprop) == 0 || strcmp(s, L_confprop_defined) == 0) { 774 4436 stephh ptr = stable(np->u.expr.right->u.quote.s); 775 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 776 4436 stephh } else if (strcmp(s, L_is_connected) == 0) { 777 4436 stephh ptr = stable("connected"); 778 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 779 4436 stephh ptr = stable("CONNECTED"); 780 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 781 4436 stephh } else if (strcmp(s, L_is_type) == 0) { 782 4436 stephh ptr = stable("type"); 783 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 784 4436 stephh ptr = stable("TYPE"); 785 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 786 4436 stephh } else if (strcmp(s, L_is_on) == 0) { 787 4436 stephh ptr = stable("on"); 788 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 789 4436 stephh ptr = stable("ON"); 790 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 791 4436 stephh } 792 0 stevel 793 0 stevel return (ret); 794 0 stevel } 795 0 stevel 796 0 stevel /* 797 0 stevel * given a list from a prop or mask statement or a function argument, 798 0 stevel * convert all iterators to explicit iterators by inventing appropriate 799 0 stevel * iterator names. 800 0 stevel */ 801 0 stevel static void 802 1414 cindi make_explicit(struct node *np, int eventonly) 803 0 stevel { 804 0 stevel struct node *pnp; /* component of pathname */ 805 0 stevel struct node *pnp2; 806 0 stevel int count; 807 0 stevel static size_t namesz; 808 0 stevel 809 0 stevel if (Newname == NULL) { 810 0 stevel namesz = 200; 811 0 stevel Newname = MALLOC(namesz); 812 0 stevel } 813 0 stevel 814 0 stevel if (np == NULL) 815 0 stevel return; /* all done */ 816 0 stevel 817 0 stevel switch (np->t) { 818 1414 cindi case T_ASSIGN: 819 1414 cindi case T_CONDIF: 820 1414 cindi case T_CONDELSE: 821 1414 cindi case T_NE: 822 1414 cindi case T_EQ: 823 1414 cindi case T_LT: 824 1414 cindi case T_LE: 825 1414 cindi case T_GT: 826 1414 cindi case T_GE: 827 1414 cindi case T_BITAND: 828 1414 cindi case T_BITOR: 829 1414 cindi case T_BITXOR: 830 1414 cindi case T_BITNOT: 831 1414 cindi case T_LSHIFT: 832 1414 cindi case T_RSHIFT: 833 0 stevel case T_LIST: 834 1414 cindi case T_AND: 835 1414 cindi case T_OR: 836 1414 cindi case T_NOT: 837 1414 cindi case T_ADD: 838 1414 cindi case T_SUB: 839 1414 cindi case T_MUL: 840 1414 cindi case T_DIV: 841 1414 cindi case T_MOD: 842 1414 cindi make_explicit(np->u.expr.left, eventonly); 843 1414 cindi make_explicit(np->u.expr.right, eventonly); 844 0 stevel break; 845 0 stevel 846 0 stevel case T_EVENT: 847 1414 cindi make_explicit(np->u.event.epname, 0); 848 1414 cindi make_explicit(np->u.event.eexprlist, 1); 849 1414 cindi break; 850 1414 cindi 851 1414 cindi case T_FUNC: 852 1414 cindi make_explicit(np->u.func.arglist, eventonly); 853 0 stevel break; 854 0 stevel 855 0 stevel case T_NAME: 856 1414 cindi if (eventonly) 857 1414 cindi return; 858 0 stevel for (pnp = np; pnp != NULL; pnp = pnp->u.name.next) 859 0 stevel if (pnp->u.name.child == NULL) { 860 0 stevel /* 861 0 stevel * found implicit iterator. convert 862 0 stevel * it to an explicit iterator by 863 0 stevel * using the name of the component 864 0 stevel * appended with '#' and the number 865 0 stevel * of times we've seen this same 866 0 stevel * component name in this path so far. 867 0 stevel */ 868 0 stevel count = 0; 869 0 stevel for (pnp2 = np; pnp2 != NULL; 870 0 stevel pnp2 = pnp2->u.name.next) 871 0 stevel if (pnp2 == pnp) 872 0 stevel break; 873 0 stevel else if (pnp2->u.name.s == 874 0 stevel pnp->u.name.s) 875 0 stevel count++; 876 0 stevel 877 0 stevel if (namesz < strlen(pnp->u.name.s) + 878 0 stevel 100) { 879 0 stevel namesz = strlen(pnp->u.name.s) + 880 0 stevel 100; 881 0 stevel FREE(Newname); 882 0 stevel Newname = MALLOC(namesz); 883 0 stevel } 884 0 stevel /* 885 0 stevel * made up interator name is: 886 0 stevel * name#ordinal 887 0 stevel * or 888 0 stevel * name##ordinal 889 0 stevel * the first one is used for vertical 890 0 stevel * expansion, the second for horizontal. 891 0 stevel * either way, the '#' embedded in 892 0 stevel * the name makes it impossible to 893 0 stevel * collide with an actual iterator 894 0 stevel * given to us in the eversholt file. 895 0 stevel */ 896 0 stevel (void) snprintf(Newname, namesz, 897 0 stevel "%s#%s%d", pnp->u.name.s, 898 0 stevel (pnp->u.name.it == IT_HORIZONTAL) ? 899 0 stevel "#" : "", count); 900 0 stevel 901 0 stevel pnp->u.name.child = tree_name(Newname, 902 0 stevel IT_NONE, pnp->file, pnp->line); 903 0 stevel pnp->u.name.childgen = 1; 904 0 stevel } 905 0 stevel break; 906 0 stevel } 907 0 stevel } 908 0 stevel 909 0 stevel struct node * 910 0 stevel tree_pname(struct node *np) 911 0 stevel { 912 1414 cindi make_explicit(np, 0); 913 0 stevel return (np); 914 0 stevel } 915 0 stevel 916 0 stevel struct node * 917 0 stevel tree_arrow(struct node *lhs, struct node *nnp, struct node *knp, 918 0 stevel struct node *rhs) 919 0 stevel { 920 0 stevel struct node *ret; 921 0 stevel 922 0 stevel ASSERT(lhs != NULL || rhs != NULL); 923 0 stevel 924 0 stevel ret = newnode(T_ARROW, 925 0 stevel (lhs) ? lhs->file : rhs->file, 926 0 stevel (lhs) ? lhs->line : rhs->line); 927 0 stevel 928 0 stevel ret->u.arrow.lhs = lhs; 929 0 stevel ret->u.arrow.nnp = nnp; 930 0 stevel ret->u.arrow.knp = knp; 931 0 stevel ret->u.arrow.rhs = rhs; 932 0 stevel 933 1414 cindi make_explicit(lhs, 0); 934 1414 cindi make_explicit(rhs, 0); 935 0 stevel 936 0 stevel check_arrow(ret); 937 0 stevel 938 0 stevel return (ret); 939 0 stevel } 940 0 stevel 941 0 stevel static struct lut * 942 0 stevel nvpair2lut(struct node *np, struct lut *lutp, enum nodetype t) 943 0 stevel { 944 0 stevel if (np) { 945 0 stevel if (np->t == T_NVPAIR) { 946 0 stevel ASSERTeq(np->u.expr.left->t, T_NAME, 947 0 stevel ptree_nodetype2str); 948 0 stevel check_stmt_allowed_properties(t, np, lutp); 949 0 stevel lutp = tree_s2np_lut_add(lutp, 950 0 stevel np->u.expr.left->u.name.s, np->u.expr.right); 951 0 stevel } else if (np->t == T_LIST) { 952 0 stevel lutp = nvpair2lut(np->u.expr.left, lutp, t); 953 0 stevel lutp = nvpair2lut(np->u.expr.right, lutp, t); 954 0 stevel } else 955 0 stevel outfl(O_DIE, np->file, np->line, 956 0 stevel "internal error: nvpair2lut type %s", 957 0 stevel ptree_nodetype2str(np->t)); 958 0 stevel } 959 0 stevel 960 0 stevel return (lutp); 961 0 stevel } 962 0 stevel 963 0 stevel struct lut * 964 0 stevel tree_s2np_lut_add(struct lut *root, const char *s, struct node *np) 965 0 stevel { 966 0 stevel return (lut_add(root, (void *)s, (void *)np, NULL)); 967 0 stevel } 968 0 stevel 969 0 stevel struct node * 970 0 stevel tree_s2np_lut_lookup(struct lut *root, const char *s) 971 0 stevel { 972 0 stevel return (struct node *)lut_lookup(root, (void *)s, NULL); 973 0 stevel } 974 0 stevel 975 0 stevel struct lut * 976 0 stevel tree_name2np_lut_add(struct lut *root, struct node *namep, struct node *np) 977 0 stevel { 978 0 stevel return (lut_add(root, (void *)namep, (void *)np, 979 0 stevel (lut_cmp)tree_namecmp)); 980 0 stevel } 981 0 stevel 982 0 stevel struct node * 983 0 stevel tree_name2np_lut_lookup(struct lut *root, struct node *namep) 984 0 stevel { 985 0 stevel return (struct node *) 986 0 stevel lut_lookup(root, (void *)namep, (lut_cmp)tree_namecmp); 987 0 stevel } 988 0 stevel 989 0 stevel struct node * 990 0 stevel tree_name2np_lut_lookup_name(struct lut *root, struct node *namep) 991 0 stevel { 992 0 stevel return (struct node *) 993 0 stevel lut_lookup_lhs(root, (void *)namep, (lut_cmp)tree_namecmp); 994 0 stevel } 995 0 stevel 996 0 stevel struct lut * 997 0 stevel tree_event2np_lut_add(struct lut *root, struct node *enp, struct node *np) 998 0 stevel { 999 0 stevel return (lut_add(root, (void *)enp, (void *)np, (lut_cmp)tree_eventcmp)); 1000 0 stevel } 1001 0 stevel 1002 0 stevel struct node * 1003 0 stevel tree_event2np_lut_lookup(struct lut *root, struct node *enp) 1004 0 stevel { 1005 0 stevel return ((struct node *) 1006 0 stevel lut_lookup(root, (void *)enp, (lut_cmp)tree_eventcmp)); 1007 0 stevel } 1008 0 stevel 1009 0 stevel struct node * 1010 0 stevel tree_event2np_lut_lookup_event(struct lut *root, struct node *enp) 1011 0 stevel { 1012 0 stevel return ((struct node *) 1013 0 stevel lut_lookup_lhs(root, (void *)enp, (lut_cmp)tree_eventcmp)); 1014 0 stevel } 1015 0 stevel 1016 0 stevel static struct node * 1017 0 stevel dodecl(enum nodetype t, const char *file, int line, 1018 0 stevel struct node *np, struct node *nvpairs, struct lut **lutpp, 1019 0 stevel struct stats *countp, int justpath) 1020 0 stevel { 1021 0 stevel struct node *ret; 1022 0 stevel struct node *decl; 1023 0 stevel 1024 0 stevel /* allocate parse tree node */ 1025 0 stevel ret = newnode(t, file, line); 1026 0 stevel ret->u.stmt.np = np; 1027 0 stevel ret->u.stmt.nvpairs = nvpairs; 1028 0 stevel 1029 0 stevel /* 1030 0 stevel * the global lut pointed to by lutpp (Faults, Defects, Upsets, 1031 0 stevel * Errors, Ereports, Serds, FRUs, or ASRUs) keeps the first decl. 1032 0 stevel * if this isn't the first declr, we merge the 1033 0 stevel * nvpairs into the first decl so we have a 1034 0 stevel * merged table to look up properties from. 1035 0 stevel * if this is the first time we've seen this fault, 1036 0 stevel * we add it to the global lut and start lutp 1037 0 stevel * off with any nvpairs from this declaration statement. 1038 0 stevel */ 1039 0 stevel if (justpath && (decl = tree_name2np_lut_lookup(*lutpp, np)) == NULL) { 1040 0 stevel /* this is the first time name is declared */ 1041 0 stevel stats_counter_bump(countp); 1042 0 stevel *lutpp = tree_name2np_lut_add(*lutpp, np, ret); 1043 0 stevel ret->u.stmt.lutp = nvpair2lut(nvpairs, NULL, t); 1044 0 stevel } else if (!justpath && 1045 0 stevel (decl = tree_event2np_lut_lookup(*lutpp, np)) == NULL) { 1046 0 stevel /* this is the first time event is declared */ 1047 0 stevel stats_counter_bump(countp); 1048 0 stevel *lutpp = tree_event2np_lut_add(*lutpp, np, ret); 1049 0 stevel ret->u.stmt.lutp = nvpair2lut(nvpairs, NULL, t); 1050 0 stevel } else { 1051 0 stevel /* was declared before, just add new nvpairs to its lutp */ 1052 0 stevel decl->u.stmt.lutp = nvpair2lut(nvpairs, decl->u.stmt.lutp, t); 1053 0 stevel } 1054 0 stevel 1055 0 stevel return (ret); 1056 0 stevel } 1057 0 stevel 1058 0 stevel /*ARGSUSED*/ 1059 0 stevel static void 1060 0 stevel update_serd_refstmt(void *lhs, void *rhs, void *arg) 1061 0 stevel { 1062 0 stevel struct node *serd; 1063 0 stevel 1064 0 stevel ASSERT(rhs != NULL); 1065 0 stevel 1066 0 stevel serd = tree_s2np_lut_lookup(((struct node *)rhs)->u.stmt.lutp, 1067 4436 stephh L_engine); 1068 0 stevel if (serd == NULL) 1069 0 stevel return; 1070 0 stevel 1071 0 stevel ASSERT(serd->t == T_EVENT); 1072 0 stevel if (arg != NULL && tree_eventcmp(serd, (struct node *)arg) != 0) 1073 0 stevel return; 1074 0 stevel 1075 0 stevel serd = tree_event2np_lut_lookup(SERDs, serd); 1076 0 stevel if (serd != NULL) 1077 0 stevel serd->u.stmt.flags |= STMT_REF; 1078 0 stevel } 1079 0 stevel 1080 0 stevel struct node * 1081 0 stevel tree_decl(enum nodetype t, struct node *np, struct node *nvpairs, 1082 0 stevel const char *file, int line) 1083 0 stevel { 1084 0 stevel struct node *decl; 1085 0 stevel struct node *ret; 1086 0 stevel 1087 0 stevel ASSERT(np != NULL); 1088 0 stevel 1089 0 stevel check_type_iterator(np); 1090 0 stevel 1091 0 stevel switch (t) { 1092 0 stevel case T_EVENT: 1093 0 stevel /* determine the type of event being declared */ 1094 0 stevel ASSERT(np->u.event.ename->t == T_NAME); 1095 0 stevel switch (np->u.event.ename->u.name.t) { 1096 0 stevel case N_FAULT: 1097 0 stevel ret = dodecl(T_FAULT, file, line, np, nvpairs, 1098 0 stevel &Faults, Faultcount, 0); 1099 7197 stephh 1100 7197 stephh /* increment serd statement reference */ 1101 7197 stephh decl = tree_event2np_lut_lookup(Faults, np); 1102 7197 stephh update_serd_refstmt(NULL, decl, NULL); 1103 0 stevel break; 1104 0 stevel 1105 0 stevel case N_UPSET: 1106 0 stevel ret = dodecl(T_UPSET, file, line, np, nvpairs, 1107 0 stevel &Upsets, Upsetcount, 0); 1108 0 stevel 1109 0 stevel /* increment serd statement reference */ 1110 0 stevel decl = tree_event2np_lut_lookup(Upsets, np); 1111 0 stevel update_serd_refstmt(NULL, decl, NULL); 1112 0 stevel break; 1113 0 stevel 1114 0 stevel case N_DEFECT: 1115 0 stevel ret = dodecl(T_DEFECT, file, line, np, nvpairs, 1116 0 stevel &Defects, Defectcount, 0); 1117 7197 stephh 1118 7197 stephh /* increment serd statement reference */ 1119 7197 stephh decl = tree_event2np_lut_lookup(Defects, np); 1120 7197 stephh update_serd_refstmt(NULL, decl, NULL); 1121 0 stevel break; 1122 0 stevel 1123 0 stevel case N_ERROR: 1124 0 stevel ret = dodecl(T_ERROR, file, line, np, nvpairs, 1125 0 stevel &Errors, Errorcount, 0); 1126 0 stevel break; 1127 0 stevel 1128 0 stevel case N_EREPORT: 1129 0 stevel ret = dodecl(T_EREPORT, file, line, np, nvpairs, 1130 0 stevel &Ereports, Ereportcount, 0); 1131 0 stevel /* 1132 6640 cth * Keep a lut of just the enames, so that the DE 1133 0 stevel * can subscribe to a uniqified list of event 1134 0 stevel * classes. 1135 0 stevel */ 1136 0 stevel Ereportenames = 1137 0 stevel tree_name2np_lut_add(Ereportenames, 1138 0 stevel np->u.event.ename, np); 1139 6640 cth 1140 6640 cth /* 1141 6640 cth * Keep a lut of the enames (event classes) to 1142 6640 cth * silently discard if we can't find a matching 1143 6640 cth * configuration node when an ereport of of a given 1144 6640 cth * class is received. Such events are declaired 1145 6640 cth * with 'discard_if_config_unknown=1'. 1146 6640 cth */ 1147 6640 cth if (tree_s2np_lut_lookup(ret->u.stmt.lutp, 1148 6640 cth L_discard_if_config_unknown)) { 1149 6640 cth Ereportenames_discard = lut_add( 1150 6640 cth Ereportenames_discard, 1151 6640 cth (void *)np->u.event.ename->u.name.s, 1152 6640 cth (void *)np->u.event.ename->u.name.s, NULL); 1153 6640 cth } 1154 0 stevel break; 1155 0 stevel 1156 0 stevel default: 1157 0 stevel outfl(O_ERR, file, line, 1158 0 stevel "tree_decl: internal error, event name type %s", 1159 0 stevel ptree_nametype2str(np->u.event.ename->u.name.t)); 1160 0 stevel } 1161 0 stevel break; 1162 0 stevel 1163 0 stevel case T_ENGINE: 1164 0 stevel /* determine the type of engine being declared */ 1165 0 stevel ASSERT(np->u.event.ename->t == T_NAME); 1166 0 stevel switch (np->u.event.ename->u.name.t) { 1167 0 stevel case N_SERD: 1168 0 stevel ret = dodecl(T_SERD, file, line, np, nvpairs, 1169 0 stevel &SERDs, SERDcount, 0); 1170 0 stevel lut_walk(Upsets, update_serd_refstmt, np); 1171 0 stevel break; 1172 0 stevel 1173 1414 cindi case N_STAT: 1174 1414 cindi ret = dodecl(T_STAT, file, line, np, nvpairs, 1175 1414 cindi &STATs, STATcount, 0); 1176 1414 cindi break; 1177 1414 cindi 1178 0 stevel default: 1179 0 stevel outfl(O_ERR, file, line, 1180 0 stevel "tree_decl: internal error, engine name type %s", 1181 0 stevel ptree_nametype2str(np->u.event.ename->u.name.t)); 1182 0 stevel } 1183 0 stevel break; 1184 0 stevel case T_ASRU: 1185 0 stevel ret = dodecl(T_ASRU, file, line, np, nvpairs, 1186 0 stevel &ASRUs, ASRUcount, 1); 1187 0 stevel break; 1188 0 stevel 1189 0 stevel case T_FRU: 1190 0 stevel ret = dodecl(T_FRU, file, line, np, nvpairs, 1191 0 stevel &FRUs, FRUcount, 1); 1192 0 stevel break; 1193 0 stevel 1194 0 stevel case T_CONFIG: 1195 0 stevel /* 1196 0 stevel * config statements are different from above: they 1197 0 stevel * are not merged at all (until the configuration cache 1198 0 stevel * code does its own style of merging. and the properties 1199 0 stevel * are a free-for-all -- we don't check for allowed or 1200 0 stevel * required config properties. 1201 0 stevel */ 1202 0 stevel ret = newnode(T_CONFIG, file, line); 1203 0 stevel ret->u.stmt.np = np; 1204 0 stevel ret->u.stmt.nvpairs = nvpairs; 1205 0 stevel ret->u.stmt.lutp = nvpair2lut(nvpairs, NULL, T_CONFIG); 1206 0 stevel 1207 0 stevel if (lut_lookup(Configs, np, (lut_cmp)tree_namecmp) == NULL) 1208 0 stevel stats_counter_bump(Configcount); 1209 0 stevel 1210 0 stevel Configs = lut_add(Configs, (void *)np, (void *)ret, NULL); 1211 0 stevel break; 1212 0 stevel 1213 0 stevel default: 1214 0 stevel out(O_DIE, "tree_decl: internal error, type %s", 1215 0 stevel ptree_nodetype2str(t)); 1216 0 stevel } 1217 0 stevel 1218 0 stevel return (ret); 1219 0 stevel } 1220 0 stevel 1221 0 stevel /* keep backpointers in arrows to the prop they belong to (used for scoping) */ 1222 0 stevel static void 1223 0 stevel set_arrow_prop(struct node *prop, struct node *np) 1224 0 stevel { 1225 0 stevel if (np == NULL) 1226 0 stevel return; 1227 0 stevel 1228 0 stevel if (np->t == T_ARROW) { 1229 0 stevel np->u.arrow.prop = prop; 1230 0 stevel set_arrow_prop(prop, np->u.arrow.lhs); 1231 0 stevel /* 1232 0 stevel * no need to recurse right or handle T_LIST since 1233 0 stevel * T_ARROWs always cascade left and are at the top 1234 0 stevel * of the parse tree. (you can see this in the rule 1235 0 stevel * for "propbody" in escparse.y.) 1236 0 stevel */ 1237 0 stevel } 1238 0 stevel } 1239 0 stevel 1240 0 stevel struct node * 1241 0 stevel tree_stmt(enum nodetype t, struct node *np, const char *file, int line) 1242 0 stevel { 1243 0 stevel struct node *ret = newnode(t, file, line); 1244 0 stevel struct node *pp; 1245 0 stevel int inlist = 0; 1246 0 stevel 1247 0 stevel ret->u.stmt.np = np; 1248 0 stevel 1249 0 stevel switch (t) { 1250 0 stevel case T_PROP: 1251 854 rw145199 check_proplists(t, np); 1252 0 stevel check_propnames(t, np, 0, 0); 1253 0 stevel check_propscope(np); 1254 0 stevel set_arrow_prop(ret, np); 1255 0 stevel 1256 0 stevel for (pp = Props; pp; pp = pp->u.stmt.next) { 1257 0 stevel if (tree_treecmp(pp, ret, T_NAME, 1258 4436 stephh (lut_cmp)tree_namecmp) == 0) { 1259 0 stevel inlist = 1; 1260 0 stevel break; 1261 0 stevel } 1262 0 stevel } 1263 0 stevel if (inlist == 0) 1264 0 stevel stats_counter_bump(Propcount); 1265 0 stevel 1266 0 stevel /* "Props" is a linked list of all prop statements */ 1267 0 stevel if (Lastprops) 1268 0 stevel Lastprops->u.stmt.next = ret; 1269 0 stevel else 1270 0 stevel Props = ret; 1271 0 stevel Lastprops = ret; 1272 0 stevel break; 1273 0 stevel 1274 0 stevel case T_MASK: 1275 854 rw145199 check_proplists(t, np); 1276 0 stevel check_propnames(t, np, 0, 0); 1277 0 stevel check_propscope(np); 1278 0 stevel set_arrow_prop(ret, np); 1279 0 stevel 1280 0 stevel for (pp = Masks; pp; pp = pp->u.stmt.next) { 1281 0 stevel if (tree_treecmp(pp, ret, T_NAME, 1282 4436 stephh (lut_cmp)tree_namecmp) == 0) { 1283 0 stevel inlist = 1; 1284 0 stevel break; 1285 0 stevel } 1286 0 stevel } 1287 0 stevel if (inlist == 0) 1288 0 stevel stats_counter_bump(Maskcount); 1289 0 stevel 1290 0 stevel /* "Masks" is a linked list of all mask statements */ 1291 0 stevel if (Lastmasks) 1292 0 stevel Lastmasks->u.stmt.next = ret; 1293 0 stevel else 1294 0 stevel Masks = ret; 1295 0 stevel Lastmasks = ret; 1296 0 stevel stats_counter_bump(Maskcount); 1297 0 stevel break; 1298 0 stevel 1299 0 stevel default: 1300 0 stevel outfl(O_DIE, np->file, np->line, 1301 0 stevel "tree_stmt: internal error (t %d)", t); 1302 0 stevel } 1303 0 stevel 1304 0 stevel return (ret); 1305 0 stevel } 1306 0 stevel 1307 0 stevel void 1308 0 stevel tree_report() 1309 0 stevel { 1310 0 stevel /* 1311 0 stevel * The only declarations with required properties 1312 0 stevel * currently are faults and serds. Make sure the 1313 0 stevel * the declarations have the required properties. 1314 0 stevel */ 1315 0 stevel lut_walk(Faults, (lut_cb)check_required_props, (void *)T_FAULT); 1316 0 stevel lut_walk(Upsets, (lut_cb)check_required_props, (void *)T_UPSET); 1317 0 stevel lut_walk(Errors, (lut_cb)check_required_props, (void *)T_ERROR); 1318 0 stevel lut_walk(Ereports, (lut_cb)check_required_props, (void *)T_EREPORT); 1319 0 stevel lut_walk(SERDs, (lut_cb)check_required_props, (void *)T_SERD); 1320 1414 cindi lut_walk(STATs, (lut_cb)check_required_props, (void *)T_STAT); 1321 0 stevel 1322 0 stevel /* 1323 0 stevel * we do this now rather than while building the parse 1324 0 stevel * tree because it is inconvenient for the user if we 1325 0 stevel * require SERD engines to be declared before used in 1326 0 stevel * an upset "engine" property. 1327 0 stevel */ 1328 0 stevel lut_walk(Faults, (lut_cb)check_refcount, (void *)T_FAULT); 1329 7197 stephh lut_walk(Faults, (lut_cb)check_upset_engine, (void *)T_FAULT); 1330 7197 stephh lut_walk(Defects, (lut_cb)check_upset_engine, (void *)T_DEFECT); 1331 0 stevel lut_walk(Upsets, (lut_cb)check_upset_engine, (void *)T_UPSET); 1332 0 stevel lut_walk(Upsets, (lut_cb)check_refcount, (void *)T_UPSET); 1333 0 stevel lut_walk(Errors, (lut_cb)check_refcount, (void *)T_ERROR); 1334 0 stevel lut_walk(Ereports, (lut_cb)check_refcount, (void *)T_EREPORT); 1335 0 stevel lut_walk(SERDs, (lut_cb)check_refcount, (void *)T_SERD); 1336 0 stevel 1337 0 stevel /* check for cycles */ 1338 0 stevel lut_walk(Errors, (lut_cb)check_cycle, (void *)0); 1339 0 stevel } 1340 0 stevel 1341 0 stevel /* compare two T_NAMES by only looking at components, not iterators */ 1342 0 stevel int 1343 0 stevel tree_namecmp(struct node *np1, struct node *np2) 1344 0 stevel { 1345 0 stevel ASSERT(np1 != NULL); 1346 0 stevel ASSERT(np2 != NULL); 1347 0 stevel ASSERTinfo(np1->t == T_NAME, ptree_nodetype2str(np1->t)); 1348 0 stevel ASSERTinfo(np2->t == T_NAME, ptree_nodetype2str(np1->t)); 1349 0 stevel 1350 0 stevel while (np1 && np2 && np1->u.name.s == np2->u.name.s) { 1351 0 stevel np1 = np1->u.name.next; 1352 0 stevel np2 = np2->u.name.next; 1353 0 stevel } 1354 0 stevel if (np1 == NULL) 1355 0 stevel if (np2 == NULL) 1356 0 stevel return (0); 1357 0 stevel else 1358 0 stevel return (-1); 1359 0 stevel else if (np2 == NULL) 1360 0 stevel return (1); 1361 0 stevel else 1362 0 stevel return (np2->u.name.s - np1->u.name.s); 1363 0 stevel } 1364 0 stevel 1365 0 stevel int 1366 0 stevel tree_eventcmp(struct node *np1, struct node *np2) 1367 0 stevel { 1368 0 stevel int ret; 1369 0 stevel 1370 0 stevel ASSERT(np1 != NULL); 1371 0 stevel ASSERT(np2 != NULL); 1372 0 stevel ASSERTinfo(np1->t == T_EVENT, ptree_nodetype2str(np1->t)); 1373 0 stevel ASSERTinfo(np2->t == T_EVENT, ptree_nodetype2str(np2->t)); 1374 0 stevel 1375 0 stevel if ((ret = tree_namecmp(np1->u.event.ename, 1376 4436 stephh np2->u.event.ename)) == 0) { 1377 0 stevel if (np1->u.event.epname == NULL && 1378 4436 stephh np2->u.event.epname == NULL) 1379 0 stevel return (0); 1380 0 stevel else if (np1->u.event.epname == NULL) 1381 0 stevel return (-1); 1382 0 stevel else if (np2->u.event.epname == NULL) 1383 0 stevel return (1); 1384 0 stevel else 1385 0 stevel return tree_namecmp(np1->u.event.epname, 1386 4436 stephh np2->u.event.epname); 1387 0 stevel } else 1388 0 stevel return (ret); 1389 0 stevel } 1390