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
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]
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
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
60 _tnf_init_tags(TNF
*tnf
)
62 if ((tnf
->tag_table
= calloc(TAGTABCNT
, sizeof (struct taginfo
*)))
64 return (TNF_ERR_ALLOCFAIL
);
65 if ((tnf
->tag_directory
= calloc(TAGDIRCNT(tnf
->directory_size
),
66 sizeof (struct taginfo
*)))
68 return (TNF_ERR_ALLOCFAIL
);
69 return (TNF_ERR_NONE
);
73 * Deallocate all taginfos and tables associated with TNF handle
77 _tnf_fini_tags(TNF
*tnf
)
80 struct taginfo
*info
, *link
;
85 for (i
= 0; i
< TAGTABCNT
; i
++) {
86 info
= tnf
->tag_table
[i
];
90 /* free slot information */
95 /* next in hash chain */
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
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
134 _tnf_record_info(TNF
*tnf
, tnf_ref32_t
*record
)
139 struct taginfo
*info
;
141 ref32
= _GET_INT32(tnf
, record
);
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
);
151 if ((info
= tnf
->tag_directory
[index
]) != NULL
)
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
;
175 info
= (struct taginfo
*)calloc(1, sizeof (struct taginfo
));
177 /* Initialize members */
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
];
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
);
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
*
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
);
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
);
250 * Initialize info for a scalar tag
253 static struct taginfo
*
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 */
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
);
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
;
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)))
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
))
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 */
323 /* XXX tnf_array has element_type == NULL */
324 info
->base
= elt_tag
? _tnf_get_info(tnf
, elt_tag
): NULL
;
330 * Initialize slot information for aggregate tag
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
)
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
;
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 */
399 info
->slotinfo
= slotinfo
;