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