9162 libpp: this statement may fall through
[unleashed.git] / usr / src / lib / libtnf / info.c
blob8c9829aa79177d3592b5efce3439ab6376c5d6e1
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include "libtnf.h"
30 #define TAG_INDEX(x) (TNF_TAG16_ABS16(x) / sizeof (tnf_ref32_t))
36 static struct taginfo * add_info(TNF *, tnf_ref32_t *);
38 static struct taginfo *
39 init_abstract_info(TNF *, tnf_ref32_t *, struct taginfo *);
41 static struct taginfo *
42 init_derived_info(TNF *, tnf_ref32_t *, struct taginfo *);
44 static struct taginfo *
45 init_scalar_info(TNF *, tnf_ref32_t *, struct taginfo *);
47 static struct taginfo *
48 init_struct_info(TNF *, tnf_ref32_t *, struct taginfo *);
50 static struct taginfo *
51 init_array_info(TNF *, tnf_ref32_t *, struct taginfo *);
53 static void init_slots(TNF *, tnf_ref32_t *, struct taginfo *);
56 * Allocate tag table and directory
59 tnf_errcode_t
60 _tnf_init_tags(TNF *tnf)
62 if ((tnf->tag_table = calloc(TAGTABCNT, sizeof (struct taginfo *)))
63 == NULL)
64 return (TNF_ERR_ALLOCFAIL);
65 if ((tnf->tag_directory = calloc(TAGDIRCNT(tnf->directory_size),
66 sizeof (struct taginfo *)))
67 == NULL)
68 return (TNF_ERR_ALLOCFAIL);
69 return (TNF_ERR_NONE);
73 * Deallocate all taginfos and tables associated with TNF handle
76 tnf_errcode_t
77 _tnf_fini_tags(TNF *tnf)
79 int i;
80 struct taginfo *info, *link;
83 * free taginfos
85 for (i = 0; i < TAGTABCNT; i++) {
86 info = tnf->tag_table[i];
87 while (info) {
88 /* remember link */
89 link = info->link;
90 /* free slot information */
91 if (info->slotinfo)
92 free(info->slotinfo);
93 /* free taginfo */
94 free(info);
95 /* next in hash chain */
96 info = link;
100 * free the tables
102 free(tnf->tag_table);
103 tnf->tag_table = NULL;
104 free(tnf->tag_directory);
105 tnf->tag_directory = NULL;
107 return (TNF_ERR_NONE);
111 * Get info for supplied tag
114 struct taginfo *
115 _tnf_get_info(TNF *tnf, tnf_ref32_t *tag)
117 struct taginfo *bucket, *info;
119 bucket = tnf->tag_table[TAGHASH(tnf, tag)];
120 for (info = bucket; info; info = info->link)
121 if (info->tag == tag)
122 return (info); /* found it */
124 /* default: not there, create */
125 return (add_info(tnf, tag));
129 * Get info for supplied record
130 * Use fast lookup, if possible
133 struct taginfo *
134 _tnf_record_info(TNF *tnf, tnf_ref32_t *record)
136 tnf_ref32_t ref32;
137 tnf_ref16_t tag16;
138 tnf_abs16_t index;
139 struct taginfo *info;
141 ref32 = _GET_INT32(tnf, record);
143 index = 0;
144 if (TNF_REF32_IS_PAIR(ref32)) {
145 tag16 = TNF_REF32_TAG16(ref32);
146 if (TNF_TAG16_IS_ABS(tag16))
147 index = TAG_INDEX(tag16);
150 if (index) {
151 if ((info = tnf->tag_directory[index]) != NULL)
152 return (info);
153 else { /* not in directory yet */
154 info = _tnf_get_info(tnf, _tnf_get_tag(tnf, record));
155 /* enter into tag directory */
156 return ((tnf->tag_directory[index] = info));
160 /* default: not referenced via index */
161 return (_tnf_get_info(tnf, _tnf_get_tag(tnf, record)));
165 * Add a new taginfo for tag
168 static struct taginfo *
169 add_info(TNF *tnf, tnf_ref32_t *tag)
171 struct taginfo *info, *bucket;
172 unsigned hash;
173 tnf_ref32_t *meta;
175 info = (struct taginfo *)calloc(1, sizeof (struct taginfo));
177 /* Initialize members */
178 info->tnf = tnf;
179 info->tag = tag;
180 info->name = _tnf_get_name(tnf, tag);
181 info->props = _tnf_get_props(tnf, tag);
182 info->kind = _tnf_get_kind(tnf, tag);
183 info->size = _tnf_get_storage_size(tnf, tag);
184 info->align = _tnf_get_align(tnf, tag);
186 /* Add it to table */
187 hash = TAGHASH(tnf, tag);
188 bucket = tnf->tag_table[hash];
189 info->link = bucket;
190 tnf->tag_table[hash] = info;
192 /* Ensure meta info is available */
193 meta = _tnf_get_tag(tnf, tag);
194 info->meta = _tnf_get_info(tnf, meta);
197 * Initialize info
198 * Derived must be first clause due to property inheritance
201 if (INFO_DERIVED(info))
202 return (init_derived_info(tnf, tag, info));
203 else if (INFO_STRUCT(info))
204 return (init_struct_info(tnf, tag, info));
205 else if (INFO_ARRAY(info))
206 return (init_array_info(tnf, tag, info));
207 else if (INFO_SCALAR(info))
208 return (init_scalar_info(tnf, tag, info));
209 else /* XXX assume abstract type */
210 return (init_abstract_info(tnf, tag, info));
215 * Initialize info for an abstract tag
218 static struct taginfo *
219 /* ARGSUSED */
220 init_abstract_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
222 if (INFO_SCALAR(info) || INFO_DERIVED(info) ||
223 INFO_STRUCT(info) || INFO_ARRAY(info))
224 _tnf_error(tnf, TNF_ERR_INTERNAL);
225 if (info->size == (size_t)-1)
226 _tnf_error(tnf, TNF_ERR_BADTNF);
227 return (info);
231 * Initialize info for a derived tag
234 static struct taginfo *
235 init_derived_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
237 tnf_ref32_t *base_tag;
239 if (!INFO_DERIVED(info))
240 _tnf_error(tnf, TNF_ERR_INTERNAL);
242 /* Ensure ultimate base information is available */
243 base_tag = _tnf_get_base_tag(tnf, tag);
244 info->base = _tnf_get_info(tnf, base_tag);
246 return (info);
250 * Initialize info for a scalar tag
253 static struct taginfo *
254 /* ARGSUSED */
255 init_scalar_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
257 if ((!INFO_SCALAR(info)) ||
258 (INFO_DERIVED(info) || INFO_ARRAY(info) || INFO_STRUCT(info)))
259 _tnf_error(tnf, TNF_ERR_INTERNAL);
260 if (info->size == (size_t)-1)
261 _tnf_error(tnf, TNF_ERR_BADTNF);
263 /* XXX alignment already done */
265 return (info);
269 * Initialize info for a struct tag
272 static struct taginfo *
273 init_struct_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
275 if ((!INFO_STRUCT(info)) ||
276 (INFO_DERIVED(info) || INFO_ARRAY(info) || INFO_SCALAR(info)))
277 _tnf_error(tnf, TNF_ERR_INTERNAL);
278 if (info->size == (size_t)-1)
279 _tnf_error(tnf, TNF_ERR_BADTNF);
281 /* Get slot information */
282 init_slots(tnf, tag, info);
284 return (info);
288 * Initialize info for an array tag
291 static struct taginfo *
292 init_array_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
294 tnf_ref32_t *elt_tag;
295 int defeat;
297 if ((!INFO_ARRAY(info)) ||
298 (INFO_DERIVED(info) || INFO_STRUCT(info) || INFO_SCALAR(info)))
299 _tnf_error(tnf, TNF_ERR_INTERNAL);
301 /* XXX special-case abstract array tag */
302 defeat = (strcmp(info->name, TNF_N_ARRAY) == 0);
304 /* Require all arrays to be self-sized records */
305 if (!(INFO_TAGGED(info) && (info->size == (size_t)-1)))
306 if (!defeat)
307 _tnf_error(tnf, TNF_ERR_BADTNF);
309 /* Store array header size */
310 info->hdrsize = _tnf_get_header_size(tnf, tag);
311 /* XXX Temporary sanity check */
312 if (info->hdrsize != sizeof (struct tnf_array_hdr))
313 if (!defeat)
314 _tnf_error(tnf, TNF_ERR_BADTNF);
316 /* Get slot information */
317 init_slots(tnf, tag, info);
319 /* Get info for element type */
320 elt_tag = (tnf_ref32_t *)_tnf_get_slot_typed(tnf, tag,
321 /* LINTED pointer cast may result in improper alignment */
322 TNF_N_ELEMENT_TYPE);
323 /* XXX tnf_array has element_type == NULL */
324 info->base = elt_tag ? _tnf_get_info(tnf, elt_tag): NULL;
326 return (info);
330 * Initialize slot information for aggregate tag
333 static void
334 init_slots(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
336 tnf_ref32_t *slot_types, *slot_names;
337 tnf_ref32_t *types, *names;
338 unsigned count, i, offset;
339 struct slotinfo *slotinfo;
341 slot_types = (tnf_ref32_t *)
342 /* LINTED pointer cast may result in improper alignment */
343 _tnf_get_slot_typed(tnf, tag, TNF_N_SLOT_TYPES);
344 slot_names = (tnf_ref32_t *)
345 /* LINTED pointer cast may result in improper alignment */
346 _tnf_get_slot_typed(tnf, tag, TNF_N_SLOT_NAMES);
348 /* abstract tags have no slots */
349 if (slot_types == TNF_NULL)
350 return;
352 count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
353 /* LINTED pointer cast may result in improper alignment */
354 types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
355 names = ((slot_names == TNF_NULL) ? TNF_NULL :
356 /* LINTED pointer cast may result in improper alignment */
357 (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names));
359 slotinfo = (struct slotinfo *)
360 calloc(1, sizeof (unsigned) + (count * sizeof (struct slot)));
361 if (slotinfo == (struct slotinfo *)NULL)
362 _tnf_error(tnf, TNF_ERR_ALLOCFAIL);
364 slotinfo->slot_count = count;
365 offset = 0;
367 for (i = 0; i < count; i++) {
368 tnf_ref32_t *type_elt, *name_elt;
369 struct taginfo *elt_info;
370 size_t ref_size, align;
372 /* XXX No checks here for missing tags */
373 type_elt = _GET_REF32(tnf, &types[i]);
374 name_elt = names ? _GET_REF32(tnf, &names[i]) : TNF_NULL;
376 /* Resolve slot tag into taginfo */
377 elt_info = _tnf_get_info(tnf, type_elt);
378 slotinfo->slots[i].slot_type = elt_info;
379 slotinfo->slots[i].slot_name =
380 ((name_elt != TNF_NULL) ?
381 _tnf_get_chars(tnf, name_elt) :
382 _tnf_get_name(tnf, type_elt));
384 /* Get cached reference size */
385 ref_size = INFO_REF_SIZE(elt_info);
387 /* Get cached alignment */
388 align = INFO_ALIGN(elt_info); /* XXX */
390 /* Adjust offset to account for alignment, if needed */
391 offset = ALIGN(offset, align);
393 slotinfo->slots[i].slot_offset = offset;
395 /* Bump offset by reference size */
396 offset += ref_size;
399 info->slotinfo = slotinfo;