8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libtnf / abi.c
bloba50068eba5da555e1d6116806b67a61bdbc92274
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"
31 * Operations based on ABI bootstrap assumptions
34 #define _GET_TAG(tnf, p) \
35 _GET_REF32(tnf, p)
37 #define _GET_TAG_ARG(tnf, p) \
38 _GET_REF16(tnf, p)
40 #define _GET_SELF_SIZE(tnf, p) \
41 _GET_UINT32(tnf, &((struct tnf_array_hdr *)(p))->self_size)
43 #define _GET_NAME(tnf, p) \
44 _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->name)
46 #define _GET_PROPERTIES(tnf, p) \
47 _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->properties)
49 #define _GET_SLOT_TYPES(tnf, p) \
50 _GET_REF32(tnf, &((struct tnf_struct_type_hdr *)(p))->slot_types)
52 #define _GET_TYPE_SIZE(tnf, p) \
53 _GET_UINT32(tnf, &((struct tnf_struct_type_hdr *)(p))->type_size)
55 #define _GET_HEADER_SIZE(tnf, p) \
56 _GET_UINT32(tnf, &((struct tnf_array_type_hdr *)(p))->header_size)
58 #define _GET_DERIVED_BASE(tnf, p) \
59 _GET_REF32(tnf, &((struct tnf_derived_type_hdr *)(p))->derived_base)
62 * Static declarations
65 static caddr_t fetch_slot(TNF *, caddr_t, tnf_ref32_t *);
68 * retrieve tag slot from a record
71 tnf_ref32_t *
72 _tnf_get_tag(TNF *tnf, tnf_ref32_t *record)
74 return (_GET_TAG(tnf, record));
78 * Retrieve tag_arg from tag slot of a record
81 tnf_ref32_t *
82 _tnf_get_tag_arg(TNF *tnf, tnf_ref32_t *record)
84 return (_GET_TAG_ARG(tnf, record));
88 * Retrieve the self_size slot of an ABI array record
91 size_t
92 _tnf_get_self_size(TNF *tnf, tnf_ref32_t *array)
94 return (_GET_SELF_SIZE(tnf, array));
98 * Calculate the number of elements in ABI array record
101 unsigned
102 _tnf_get_element_count(TNF *tnf, tnf_ref32_t *array, unsigned eltsize)
104 size_t size, hdrsize;
105 #ifdef INFINITE_RECURSION_ARRAY
106 tnf_ref32_t *base_tag;
108 size = _tnf_get_self_size(tnf, array);
109 base_tag = _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array));
110 hdrsize = _tnf_get_header_size(tnf, base_tag);
111 return (((size - hdrsize) / eltsize));
112 #else
113 size = _tnf_get_self_size(tnf, array);
114 hdrsize = sizeof (struct tnf_array_hdr);
115 return (((size - hdrsize) / eltsize));
116 #endif
120 * Retrieve the base pointer of an ABI array record
123 caddr_t
124 /* ARGSUSED */
125 _tnf_get_elements(TNF *tnf, tnf_ref32_t *array)
127 #ifdef INFINITE_RECURSION_ARRAY
128 size_t hdrsize;
129 tnf_ref32_t *base_tag;
131 base_tag = _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array));
132 hdrsize = _tnf_get_header_size(tnf, base_tag);
133 return ((caddr_t)((char *)array + hdrsize));
134 #else
135 return ((caddr_t)((char *)array + sizeof (struct tnf_array_hdr)));
136 #endif
140 * Retrieve the chars in an ABI string record
143 char *
144 _tnf_get_chars(TNF *tnf, tnf_ref32_t *string)
146 return ((char *)_tnf_get_elements(tnf, string));
150 * Retrieve the string in the name slot of a type record
153 char *
154 _tnf_get_name(TNF *tnf, tnf_ref32_t *tag)
156 return (_tnf_get_chars(tnf, _GET_NAME(tnf, tag)));
160 * Retrieve the properties array slot of a type record
163 tnf_ref32_t *
164 _tnf_get_properties(TNF *tnf, tnf_ref32_t *tag)
166 return (_GET_PROPERTIES(tnf, tag));
170 * Retrieve the slot_types slot of struct_type or array_type record
173 tnf_ref32_t *
174 _tnf_get_slot_types(TNF *tnf, tnf_ref32_t *tag)
176 return (_GET_SLOT_TYPES(tnf, tag));
180 * Retrieve the header_size slot of an array_type record
183 size_t
184 _tnf_get_header_size(TNF *tnf, tnf_ref32_t *tag)
186 return (_GET_HEADER_SIZE(tnf, tag));
190 * Retrieve the derived_base slot of a derived_type record
193 tnf_ref32_t *
194 _tnf_get_derived_base(TNF *tnf, tnf_ref32_t *tag)
196 return (_GET_DERIVED_BASE(tnf, tag));
201 * Find the root (self-tagged) type record
204 tnf_ref32_t *
205 _tnf_get_root_tag(TNF *tnf, tnf_ref32_t *record)
207 if (tnf->root_tag)
208 return (tnf->root_tag);
209 else {
210 tnf_ref32_t *p1, *p2;
211 p1 = record;
212 while ((p2 = _tnf_get_tag(tnf, p1)) != p1)
213 p1 = p2;
214 tnf->root_tag = p2;
215 return (p2);
220 * Search ABI type array for a type named name
223 tnf_ref32_t *
224 _tnf_get_element_named(TNF *tnf, tnf_ref32_t *array, char *name)
226 unsigned count, i;
227 tnf_ref32_t *elts;
229 count = _tnf_get_element_count(tnf, array, sizeof (tnf_ref32_t));
230 /* LINTED pointer cast may result in improper alignment */
231 elts = (tnf_ref32_t *)_tnf_get_elements(tnf, array);
233 for (i = 0; i < count; i++) {
234 tnf_ref32_t *type_elt;
236 if ((type_elt = _GET_REF32(tnf, &elts[i])) == TNF_NULL) {
237 /* Can't have missing type records */
238 _tnf_error(tnf, TNF_ERR_BADTNF);
239 return (TNF_NULL);
242 if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)
243 /* Found a type record named name */
244 return (type_elt);
246 return (TNF_NULL);
250 * Look in type record's properties for named type.
251 * Recursively look at derived_base properties as well.
254 tnf_ref32_t *
255 _tnf_get_property(TNF *tnf, tnf_ref32_t *tag, char *name)
257 tnf_ref32_t *properties, *property;
259 if (strcmp(name, _tnf_get_name(tnf, tag)) == 0)
260 /* name is type name */
261 return (tag);
263 if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL)
264 /* no properties */
265 return (TNF_NULL);
267 if ((property = _tnf_get_element_named(tnf, properties, name))
268 != TNF_NULL)
269 /* found property named name */
270 return (property);
273 * Recursively check base type of derived types
275 if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED)
276 != TNF_NULL) {
277 /* tag is a derived type: check its derived_base */
278 tnf_ref32_t *base_tag;
280 base_tag = _tnf_get_derived_base(tnf, tag);
281 /* tnf_derived has derived_base == TNF_NULL */
282 if (base_tag != TNF_NULL)
283 return (_tnf_get_property(tnf, base_tag, name));
286 return (TNF_NULL);
290 * Get the ultimate base type of a type record
293 tnf_ref32_t *
294 _tnf_get_base_tag(TNF *tnf, tnf_ref32_t *tag)
296 tnf_ref32_t *properties;
298 if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL)
299 /* no properties */
300 return (tag);
302 if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED)
303 != TNF_NULL) {
304 tnf_ref32_t *base_tag;
306 if ((base_tag = _tnf_get_derived_base(tnf, tag)) != TNF_NULL)
307 return (_tnf_get_base_tag(tnf, base_tag));
310 return (tag);
314 * Calculate the reference size of an object with type==tag
317 size_t
318 _tnf_get_ref_size(TNF *tnf, tnf_ref32_t *tag)
320 if (HAS_PROPERTY(tnf, tag, TNF_N_TAGGED)) {
321 /* Tagged objects occupy 4 bytes for reference */
322 return ((sizeof (tnf_ref32_t)));
323 } else if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE)) {
324 /* Inline slots cannot be self sized */
325 return (_tnf_get_storage_size(tnf, tag));
326 } else {
327 /* Illegal to have references to abstract objects */
328 _tnf_error(tnf, TNF_ERR_BADTNF);
329 return ((0));
334 * Calculate storage size of an object with type==tag
337 size_t
338 _tnf_get_storage_size(TNF *tnf, tnf_ref32_t *tag)
340 if (_tnf_get_tag(tnf, tag) == _tnf_get_root_tag(tnf, tag))
341 return (_GET_TYPE_SIZE(tnf, tag));
342 else {
343 tnf_ref32_t *base_tag; /* implementation tag */
344 caddr_t sizep;
345 tnf_ref32_t *slot_types;
347 #ifndef INFINITE_RECURSION_SIZE
348 char *base_name;
349 static struct n2s {
350 char *name;
351 size_t size;
352 } n2s[] = {
353 { TNF_N_CHAR, sizeof (tnf_char_t) },
354 { TNF_N_INT8, sizeof (tnf_int8_t) },
355 { TNF_N_INT16, sizeof (tnf_int16_t) },
356 { TNF_N_INT32, sizeof (tnf_int32_t) },
357 { TNF_N_UINT8, sizeof (tnf_uint8_t) },
358 { TNF_N_UINT16, sizeof (tnf_uint16_t) },
359 { TNF_N_UINT32, sizeof (tnf_uint32_t) },
360 { TNF_N_INT64, sizeof (tnf_int64_t) },
361 { TNF_N_UINT64, sizeof (tnf_uint64_t) },
362 { TNF_N_FLOAT32, sizeof (tnf_float32_t) },
363 { TNF_N_FLOAT64, sizeof (tnf_float64_t) },
364 { NULL, 0 }
366 struct n2s *p;
367 #endif
369 base_tag = _tnf_get_base_tag(tnf, tag);
371 #ifndef INFINITE_RECURSION_SIZE
372 base_name = _tnf_get_name(tnf, base_tag);
374 /* XXX Why are we in this mess? */
375 p = n2s;
376 while (p->name) {
377 if (strcmp(p->name, base_name) == 0)
378 return (p->size);
379 p++;
381 #endif
383 sizep = _tnf_get_slot_typed(tnf, base_tag, TNF_N_TYPE_SIZE);
384 if (sizep)
385 /* Type sized */
386 /* LINTED pointer cast may result in improper alignment */
387 return (_GET_UINT32(tnf, (tnf_uint32_t *)sizep));
389 slot_types = (tnf_ref32_t *)
390 /* LINTED pointer cast may result in improper alignment */
391 _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_TYPES);
392 if (slot_types &&
393 _tnf_get_element_named(tnf, slot_types, TNF_N_SELF_SIZE))
394 /* Self sized */
395 return ((size_t)-1);
396 else
397 /* Abstract */
398 return (0);
403 * Return the alignment restriction for any tag
406 unsigned
407 _tnf_get_align(TNF *tnf, tnf_ref32_t *tag)
409 if (HAS_PROPERTY(tnf, tag, TNF_N_SCALAR)) {
410 tnf_ref32_t *base_tag;
411 caddr_t alignp;
413 base_tag = _tnf_get_base_tag(tnf, tag);
414 alignp = _tnf_get_slot_typed(tnf, base_tag, TNF_N_ALIGN);
415 if (alignp)
416 /* LINTED pointer cast may result in improper alignment */
417 return (_GET_UINT32(tnf, (tnf_uint32_t *)alignp));
419 /* default: word alignment */
420 return ((4));
424 * Only works for records
425 * Doesn't check for slot_names in tag
426 * Tag records, for example, never have named slots
429 caddr_t
430 _tnf_get_slot_typed(TNF *tnf, tnf_ref32_t *record, char *name)
432 tnf_ref32_t *tag, *base_tag;
433 tnf_ref32_t *slot_types, *types;
434 unsigned count, i;
435 unsigned offset;
437 tag = _tnf_get_tag(tnf, record);
438 base_tag = _tnf_get_base_tag(tnf, tag);
441 * The position of slot_types is ABI fixed
442 * XXX Assume it is present in tag
444 slot_types = _tnf_get_slot_types(tnf, base_tag);
445 count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
446 /* LINTED pointer cast may result in improper alignment */
447 types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
449 offset = 0;
451 for (i = 0; i < count; i++) {
452 tnf_ref32_t *type_elt;
453 size_t ref_size, align;
455 /* Find the type record for slot */
456 if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) {
457 /* Can't have missing type records */
458 _tnf_error(tnf, TNF_ERR_BADTNF);
459 return ((caddr_t)NULL);
462 /* See similar hack in init_slots() */
464 /* Calculate reference size */
465 ref_size = _tnf_get_ref_size(tnf, type_elt);
468 * Calculate alignment
469 * XXX Prevent infinite recursion by assuming that
470 * a reference size of 4 implies word alignment
472 align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt);
474 /* Adjust offset to account for alignment, if needed */
475 offset = ALIGN(offset, align);
477 /* Check whether name corresponds to type name */
478 if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)
479 /* Found the slot */
480 return (fetch_slot(tnf, (caddr_t)record + offset,
481 type_elt));
483 /* Bump offset by reference size */
484 offset += ref_size;
487 return ((caddr_t)NULL);
491 * Only works for records
494 caddr_t
495 _tnf_get_slot_named(TNF *tnf, tnf_ref32_t *record, char *name)
497 tnf_ref32_t *tag, *base_tag;
498 tnf_ref32_t *slot_types, *slot_names, *types, *names;
499 unsigned count, i;
500 unsigned offset;
502 tag = _tnf_get_tag(tnf, record);
503 base_tag = _tnf_get_base_tag(tnf, tag);
506 * slot_names are optional
508 slot_names = (tnf_ref32_t *)
509 /* LINTED pointer cast may result in improper alignment */
510 _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_NAMES);
512 /* no slot_names; use _tnf_get_slot_typed() */
513 if (slot_names == TNF_NULL)
514 return (_tnf_get_slot_typed(tnf, record, name));
517 * The position of slot_types is ABI fixed
518 * XXX Assume it is present in tag
520 slot_types = _tnf_get_slot_types(tnf, base_tag);
521 count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
522 /* LINTED pointer cast may result in improper alignment */
523 types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
524 /* LINTED pointer cast may result in improper alignment */
525 names = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names);
527 offset = 0;
529 for (i = 0; i < count; i++) {
530 tnf_ref32_t *type_elt, *name_elt;
531 size_t ref_size, align;
533 /* Find the type record for slot */
534 if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) {
535 /* Can't have missing type records */
536 _tnf_error(tnf, TNF_ERR_BADTNF);
537 return ((caddr_t)NULL);
540 /* XXX Keep consistent with init_slots() */
542 /* Calculate reference size */
543 ref_size = _tnf_get_ref_size(tnf, type_elt);
546 * Calculate alignment
547 * XXX Prevent infinite recursion by assuming that
548 * a reference size of 4 implies word alignment
550 align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt);
552 /* Adjust offset to account for alignment, if needed */
553 offset = ALIGN(offset, align);
555 /* First check slot name, then type name */
556 if ((((name_elt = _GET_REF32(tnf, &names[i])) != TNF_NULL) &&
557 (strcmp(name, _tnf_get_chars(tnf, name_elt)) == 0)) ||
558 (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0))
559 /* Found slot */
560 return (fetch_slot(tnf, (caddr_t)record + offset,
561 type_elt));
563 /* Bump offset by reference size */
564 offset += ref_size;
567 return ((caddr_t)NULL);
570 static caddr_t
571 fetch_slot(TNF *tnf, caddr_t p, tnf_ref32_t *tag)
573 if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE))
574 return (p);
575 else /* XXX assume tagged */
576 /* LINTED pointer cast may result in improper alignment */
577 return ((caddr_t)_GET_REF32(tnf, (tnf_ref32_t *)p));