/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * Events, FMRIs and authorities must be declared before they can be used. * Routines in this file, driven by the parser, create the data structures * associated with the declarations. */ #include #include #include #include #include #include #include static inj_hash_t inj_decls[ITEMTYPE_NITEMS]; static int inj_decls_initialized; static inj_hash_t * item2hash(inj_itemtype_t item) { int i; assert(item >= 0 && item < sizeof (inj_decls) / sizeof (inj_hash_t)); if (!inj_decls_initialized) { for (i = 0; i < sizeof (inj_decls) / sizeof (inj_hash_t); i++) inj_strhash_create(&inj_decls[i]); inj_decls_initialized = 1; } return (&inj_decls[item]); } inj_decl_t * inj_decl_lookup(const char *name, inj_itemtype_t type) { inj_hash_t *hash = item2hash(type); inj_var_t *v; if ((v = inj_strhash_lookup(hash, name)) == NULL) return (NULL); return (inj_hash_get_cookie(v)); } void inj_decl_mem_destroy(inj_declmem_t *dlm) { inj_strfree(dlm->dlm_name); if (dlm->dlm_type == MEMTYPE_ENUM) inj_strhash_destroy(dlm->dlm_enumvals); } inj_declmem_t * inj_decl_mem_create(const char *name, inj_memtype_t type) { inj_declmem_t *dlm = inj_zalloc(sizeof (inj_declmem_t)); dlm->dlm_name = name; dlm->dlm_type = type; return (dlm); } /* An embedded event, authority, or FMRI */ inj_declmem_t * inj_decl_mem_create_defined(const char *name, const char *declnm, inj_itemtype_t type) { inj_declmem_t *dlm = inj_zalloc(sizeof (inj_declmem_t)); dlm->dlm_name = name; dlm->dlm_type = inj_item2mem(type); if ((dlm->dlm_decl = inj_decl_lookup(declnm, type)) == NULL) { yyerror("unknown %s %s", inj_item2str(type), declnm); return (NULL); } return (dlm); } inj_declmem_t * inj_decl_mem_create_enum(const char *name, inj_hash_t *vals) { inj_declmem_t *dlm = inj_zalloc(sizeof (inj_declmem_t)); dlm->dlm_name = name; dlm->dlm_type = MEMTYPE_ENUM; dlm->dlm_enumvals = vals; return (dlm); } /* Turn a previously-declared member into an array */ void inj_decl_mem_make_array(inj_declmem_t *dlm, uint_t dim) { dlm->dlm_flags |= DECLMEM_F_ARRAY; dlm->dlm_arrdim = dim; } void inj_decl_destroy(inj_decl_t *decl) { inj_declmem_t *m, *n; inj_strfree(decl->decl_name); inj_strhash_destroy(&decl->decl_memhash); for (m = inj_list_next(&decl->decl_members); m != NULL; m = n) { n = inj_list_next(m); inj_decl_mem_destroy(m); } inj_free(decl, sizeof (inj_declmem_t)); } inj_decl_t * inj_decl_create(inj_declmem_t *dlm) { inj_decl_t *decl = inj_zalloc(sizeof (inj_decl_t)); decl->decl_lineno = yylineno; inj_strhash_create(&decl->decl_memhash); inj_list_append(&decl->decl_members, dlm); (void) inj_strhash_insert(&decl->decl_memhash, dlm->dlm_name, (uintptr_t)dlm); return (decl); } void inj_decl_addmem(inj_decl_t *decl, inj_declmem_t *dlm) { inj_var_t *v; if ((v = inj_strhash_lookup(&decl->decl_memhash, dlm->dlm_name)) != NULL) { inj_decl_t *other = inj_hash_get_cookie(v); yyerror("duplicate member name %s (other on line %d)\n", dlm->dlm_name, other->decl_lineno); inj_decl_destroy(decl); return; } inj_list_append(&decl->decl_members, dlm); (void) inj_strhash_insert(&decl->decl_memhash, dlm->dlm_name, (uintptr_t)dlm); } /* * The various declaration types - events, FMRIs, and authorities - each have * their own semantic validation requirements. */ /* No user-defined class member. If ena isn't present, we'll generate it */ static int inj_decl_validate_event(inj_decl_t *decl) { if (inj_strhash_lookup(&decl->decl_memhash, "class") != NULL) { yyerror("class may not be explicitly declared\n"); return (0); } if (inj_strhash_lookup(&decl->decl_memhash, "ena") == NULL) decl->decl_flags |= DECL_F_AUTOENA; return (1); } /* FMRIs must have a string scheme member */ static int inj_decl_validate_fmri(inj_decl_t *decl) { inj_declmem_t *dlm; inj_var_t *v; if ((v = inj_strhash_lookup(&decl->decl_memhash, "scheme")) == NULL) { yyerror("fmri declared without scheme member\n"); return (0); } dlm = inj_hash_get_cookie(v); if (dlm->dlm_type != MEMTYPE_STRING) { yyerror("scheme member must be a string\n"); return (0); } return (1); } /*ARGSUSED*/ static int inj_decl_validate_nop(inj_decl_t *decl) { return (1); } void inj_decl_finish(inj_decl_t *decl, const char *name, inj_itemtype_t type) { static int (*const validators[])(inj_decl_t *) = { inj_decl_validate_event, inj_decl_validate_fmri, inj_decl_validate_nop, /* no validation for auth */ inj_decl_validate_nop /* no validation for lists */ }; inj_hash_t *hash = item2hash(type); inj_var_t *v; decl->decl_name = name; decl->decl_type = type; if (!validators[type](decl)) { inj_decl_destroy(decl); return; } if ((v = inj_strhash_lookup(hash, name)) != NULL) { inj_decl_t *other = inj_hash_get_cookie(v); yyerror("duplicate %s name %s (other on line %d)\n", inj_item2str(type), name, other->decl_lineno); inj_decl_destroy(decl); return; } (void) inj_strhash_insert(hash, name, (uintptr_t)decl); }