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 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Events, FMRIs and authorities must be declared before they can be used. 31 * Routines in this file, driven by the parser, create the data structures 32 * associated with the declarations. 33 */ 34 35 #include <assert.h> 36 #include <string.h> 37 38 #include <inj_event.h> 39 #include <inj_err.h> 40 #include <inj_lex.h> 41 #include <inj_list.h> 42 #include <inj.h> 43 44 static inj_hash_t inj_decls[ITEMTYPE_NITEMS]; 45 static int inj_decls_initialized; 46 47 static inj_hash_t * 48 item2hash(inj_itemtype_t item) 49 { 50 int i; 51 52 assert(item >= 0 && item < sizeof (inj_decls) / sizeof (inj_hash_t)); 53 54 if (!inj_decls_initialized) { 55 for (i = 0; i < sizeof (inj_decls) / sizeof (inj_hash_t); i++) 56 inj_strhash_create(&inj_decls[i]); 57 inj_decls_initialized = 1; 58 } 59 60 return (&inj_decls[item]); 61 } 62 63 inj_decl_t * 64 inj_decl_lookup(const char *name, inj_itemtype_t type) 65 { 66 inj_hash_t *hash = item2hash(type); 67 inj_var_t *v; 68 69 if ((v = inj_strhash_lookup(hash, name)) == NULL) 70 return (NULL); 71 72 return (inj_hash_get_cookie(v)); 73 } 74 75 void 76 inj_decl_mem_destroy(inj_declmem_t *dlm) 77 { 78 inj_strfree(dlm->dlm_name); 79 80 if (dlm->dlm_type == MEMTYPE_ENUM) 81 inj_strhash_destroy(dlm->dlm_enumvals); 82 } 83 84 inj_declmem_t * 85 inj_decl_mem_create(const char *name, inj_memtype_t type) 86 { 87 inj_declmem_t *dlm = inj_zalloc(sizeof (inj_declmem_t)); 88 89 dlm->dlm_name = name; 90 dlm->dlm_type = type; 91 92 return (dlm); 93 } 94 95 /* An embedded event, authority, or FMRI */ 96 inj_declmem_t * 97 inj_decl_mem_create_defined(const char *name, const char *declnm, 98 inj_itemtype_t type) 99 { 100 inj_declmem_t *dlm = inj_zalloc(sizeof (inj_declmem_t)); 101 102 dlm->dlm_name = name; 103 dlm->dlm_type = inj_item2mem(type); 104 105 if ((dlm->dlm_decl = inj_decl_lookup(declnm, type)) == NULL) { 106 yyerror("unknown %s %s", inj_item2str(type), declnm); 107 return (NULL); 108 } 109 110 return (dlm); 111 } 112 113 inj_declmem_t * 114 inj_decl_mem_create_enum(const char *name, inj_hash_t *vals) 115 { 116 inj_declmem_t *dlm = inj_zalloc(sizeof (inj_declmem_t)); 117 118 dlm->dlm_name = name; 119 dlm->dlm_type = MEMTYPE_ENUM; 120 dlm->dlm_enumvals = vals; 121 122 return (dlm); 123 } 124 125 /* Turn a previously-declared member into an array */ 126 void 127 inj_decl_mem_make_array(inj_declmem_t *dlm, uint_t dim) 128 { 129 dlm->dlm_flags |= DECLMEM_F_ARRAY; 130 dlm->dlm_arrdim = dim; 131 } 132 133 void 134 inj_decl_destroy(inj_decl_t *decl) 135 { 136 inj_declmem_t *m, *n; 137 138 inj_strfree(decl->decl_name); 139 inj_strhash_destroy(&decl->decl_memhash); 140 141 for (m = inj_list_next(&decl->decl_members); m != NULL; m = n) { 142 n = inj_list_next(m); 143 144 inj_decl_mem_destroy(m); 145 } 146 147 inj_free(decl, sizeof (inj_declmem_t)); 148 } 149 150 inj_decl_t * 151 inj_decl_create(inj_declmem_t *dlm) 152 { 153 inj_decl_t *decl = inj_zalloc(sizeof (inj_decl_t)); 154 155 decl->decl_lineno = yylineno; 156 157 inj_strhash_create(&decl->decl_memhash); 158 159 inj_list_append(&decl->decl_members, dlm); 160 (void) inj_strhash_insert(&decl->decl_memhash, dlm->dlm_name, 161 (uintmax_t)dlm); 162 163 return (decl); 164 } 165 166 void 167 inj_decl_addmem(inj_decl_t *decl, inj_declmem_t *dlm) 168 { 169 inj_var_t *v; 170 171 if ((v = inj_strhash_lookup(&decl->decl_memhash, dlm->dlm_name)) != 172 NULL) { 173 inj_decl_t *other = inj_hash_get_cookie(v); 174 175 yyerror("duplicate member name %s (other on line %d)\n", 176 dlm->dlm_name, other->decl_lineno); 177 inj_decl_destroy(decl); 178 return; 179 } 180 181 inj_list_append(&decl->decl_members, dlm); 182 (void) inj_strhash_insert(&decl->decl_memhash, dlm->dlm_name, 183 (uintmax_t)dlm); 184 } 185 186 /* 187 * The various declaration types - events, FMRIs, and authorities - each have 188 * their own semantic validation requirements. 189 */ 190 191 /* No user-defined class member. If ena isn't present, we'll generate it */ 192 static int 193 inj_decl_validate_event(inj_decl_t *decl) 194 { 195 if (inj_strhash_lookup(&decl->decl_memhash, "class") != NULL) { 196 yyerror("class may not be explicitly declared\n"); 197 return (0); 198 } 199 200 if (inj_strhash_lookup(&decl->decl_memhash, "ena") == NULL) 201 decl->decl_flags |= DECL_F_AUTOENA; 202 203 return (1); 204 } 205 206 /* FMRIs must have a string scheme member */ 207 static int 208 inj_decl_validate_fmri(inj_decl_t *decl) 209 { 210 inj_declmem_t *dlm; 211 inj_var_t *v; 212 213 if ((v = inj_strhash_lookup(&decl->decl_memhash, "scheme")) == NULL) { 214 yyerror("fmri declared without scheme member\n"); 215 return (0); 216 } 217 218 dlm = inj_hash_get_cookie(v); 219 if (dlm->dlm_type != MEMTYPE_STRING) { 220 yyerror("scheme member must be a string\n"); 221 return (0); 222 } 223 224 return (1); 225 } 226 227 /*ARGSUSED*/ 228 static int 229 inj_decl_validate_nop(inj_decl_t *decl) 230 { 231 return (1); 232 } 233 234 void 235 inj_decl_finish(inj_decl_t *decl, const char *name, inj_itemtype_t type) 236 { 237 static int (*const validators[])(inj_decl_t *) = { 238 inj_decl_validate_event, 239 inj_decl_validate_fmri, 240 inj_decl_validate_nop, /* no validation for auth */ 241 inj_decl_validate_nop /* no validation for lists */ 242 }; 243 244 inj_hash_t *hash = item2hash(type); 245 inj_var_t *v; 246 247 decl->decl_name = name; 248 decl->decl_type = type; 249 250 if (!validators[type](decl)) { 251 inj_decl_destroy(decl); 252 return; 253 } 254 255 if ((v = inj_strhash_lookup(hash, name)) != NULL) { 256 inj_decl_t *other = inj_hash_get_cookie(v); 257 258 yyerror("duplicate %s name %s (other on line %d)\n", 259 inj_item2str(type), name, other->decl_lineno); 260 inj_decl_destroy(decl); 261 return; 262 } 263 264 (void) inj_strhash_insert(hash, name, (uintmax_t)decl); 265 } 266