summaryrefslogtreecommitdiff
path: root/usr/src/lib/libtnf
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libtnf
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libtnf')
-rw-r--r--usr/src/lib/libtnf/Makefile149
-rw-r--r--usr/src/lib/libtnf/abi.c578
-rw-r--r--usr/src/lib/libtnf/access.c184
-rw-r--r--usr/src/lib/libtnf/array.c205
-rw-r--r--usr/src/lib/libtnf/datum.c214
-rw-r--r--usr/src/lib/libtnf/error.c114
-rw-r--r--usr/src/lib/libtnf/i386dep.c30
-rw-r--r--usr/src/lib/libtnf/info.c400
-rw-r--r--usr/src/lib/libtnf/libtnf.h340
-rw-r--r--usr/src/lib/libtnf/machlibtnf.h60
-rw-r--r--usr/src/lib/libtnf/reader.c191
-rw-r--r--usr/src/lib/libtnf/record.c66
-rw-r--r--usr/src/lib/libtnf/ref.c232
-rw-r--r--usr/src/lib/libtnf/scalar.c170
-rw-r--r--usr/src/lib/libtnf/sparcdep.c40
-rw-r--r--usr/src/lib/libtnf/spec/Makefile55
-rw-r--r--usr/src/lib/libtnf/spec/Makefile.targ34
-rw-r--r--usr/src/lib/libtnf/spec/amd64/Makefile44
-rw-r--r--usr/src/lib/libtnf/spec/i386/Makefile44
-rw-r--r--usr/src/lib/libtnf/spec/sparc/Makefile44
-rw-r--r--usr/src/lib/libtnf/spec/sparcv9/Makefile45
-rw-r--r--usr/src/lib/libtnf/spec/tnf.spec316
-rw-r--r--usr/src/lib/libtnf/spec/versions39
-rw-r--r--usr/src/lib/libtnf/struct.c220
-rw-r--r--usr/src/lib/libtnf/tnf.h206
-rw-r--r--usr/src/lib/libtnf/type.c137
-rw-r--r--usr/src/lib/libtnf/util.c129
27 files changed, 4286 insertions, 0 deletions
diff --git a/usr/src/lib/libtnf/Makefile b/usr/src/lib/libtnf/Makefile
new file mode 100644
index 0000000000..523845a683
--- /dev/null
+++ b/usr/src/lib/libtnf/Makefile
@@ -0,0 +1,149 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtnf/Makefile
+#
+
+LIBRARY= libtnf.a
+VERS= .1
+OBJECTS= $(MACH)dep.o \
+ ref.o \
+ abi.o \
+ util.o \
+ info.o \
+ datum.o \
+ record.o \
+ scalar.o \
+ array.o \
+ struct.o \
+ type.o \
+ error.o \
+ access.o \
+ reader.o
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+check := TARGET= check
+install := TARGET= install
+lint := TARGET= lint
+install_h := TARGET= install_h
+_msg := TARGET= _msg
+
+
+include ../Makefile.lib
+
+TEXT_DOMAIN= SUNW_OST_OSLIB
+XGETFLAGS= -a
+POFILE= $(LIBRARY:%.a=%.po)
+POFILES= _error.po
+
+SED= sed
+GREP= grep
+CP= cp
+
+LIBS= $(DYNLIB)
+
+MAPDIR= ./spec/$(MACH)
+MAPFILE= $(MAPDIR)/mapfile
+MAPOPTS= $(MAPFILE:%=-M%)
+DYNFLAGS += $(MAPOPTS)
+CLOBBERFILES += $(MAPFILE)
+
+LDLIBS += -lc
+
+HDRS= tnf.h
+ROOTHDRDIR= $(ROOT)/usr/include/tnf
+ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%)
+CHECKHDRS= $(HDRS:%.h=%.check)
+$(ROOTHDRS) := FILEMODE = 0644
+CHECKHDRS = $(HDRS:%.h=%.check)
+
+$(ROOTHDRS) := FILEMODE = 644
+
+CPPFLAGS += -D_DATUM_MACROS -D_REENTRANT
+
+LINTFLAGS += -y
+
+$(DYNLIB): $(MAPFILE)
+
+$(MAPFILE):
+ @cd $(MAPDIR); $(MAKE) mapfile
+
+
+.KEEP_STATE:
+
+all: spec .WAIT $(LIBS)
+
+install: all spec $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS)
+
+install_h: $(ROOTHDRDIR) $(ROOTHDRS)
+
+clean clobber: spec $(BUILD64)
+
+lint:
+ $(LINT.c) $(SRCS)
+
+check: $(CHECKHDRS)
+
+$(ROOTLIBDIR) $(ROOTHDRDIR):
+ $(INS.dir)
+
+$(ROOTHDRDIR)/% : %
+ $(INS.file)
+
+ASFLAGS= $(AS_PICFLAGS) -P -D_SYS_SYS_S -D_LOCORE -D_ASM -DPIC -DLOCORE $(CPPFLAGS)
+BUILD.s= $(AS) $(ASFLAGS) $< -o $@
+
+pics/%.o: ./%.s
+ $(BUILD.s)
+ $(POST_PROCESS_O)
+
+objs/%.o: ./%.s
+ $(BUILD.s)
+ $(POST_PROCESS_O)
+
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ $(CAT) $(POFILES) > $@
+
+$(POFILES):
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext *.[ch]*`
+ $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
+ $(RM) messages.po
+
+include ../Makefile.targ
+
+spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/libtnf/abi.c b/usr/src/lib/libtnf/abi.c
new file mode 100644
index 0000000000..a50068eba5
--- /dev/null
+++ b/usr/src/lib/libtnf/abi.c
@@ -0,0 +1,578 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * Operations based on ABI bootstrap assumptions
+ */
+
+#define _GET_TAG(tnf, p) \
+ _GET_REF32(tnf, p)
+
+#define _GET_TAG_ARG(tnf, p) \
+ _GET_REF16(tnf, p)
+
+#define _GET_SELF_SIZE(tnf, p) \
+ _GET_UINT32(tnf, &((struct tnf_array_hdr *)(p))->self_size)
+
+#define _GET_NAME(tnf, p) \
+ _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->name)
+
+#define _GET_PROPERTIES(tnf, p) \
+ _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->properties)
+
+#define _GET_SLOT_TYPES(tnf, p) \
+ _GET_REF32(tnf, &((struct tnf_struct_type_hdr *)(p))->slot_types)
+
+#define _GET_TYPE_SIZE(tnf, p) \
+ _GET_UINT32(tnf, &((struct tnf_struct_type_hdr *)(p))->type_size)
+
+#define _GET_HEADER_SIZE(tnf, p) \
+ _GET_UINT32(tnf, &((struct tnf_array_type_hdr *)(p))->header_size)
+
+#define _GET_DERIVED_BASE(tnf, p) \
+ _GET_REF32(tnf, &((struct tnf_derived_type_hdr *)(p))->derived_base)
+
+/*
+ * Static declarations
+ */
+
+static caddr_t fetch_slot(TNF *, caddr_t, tnf_ref32_t *);
+
+/*
+ * retrieve tag slot from a record
+ */
+
+tnf_ref32_t *
+_tnf_get_tag(TNF *tnf, tnf_ref32_t *record)
+{
+ return (_GET_TAG(tnf, record));
+}
+
+/*
+ * Retrieve tag_arg from tag slot of a record
+ */
+
+tnf_ref32_t *
+_tnf_get_tag_arg(TNF *tnf, tnf_ref32_t *record)
+{
+ return (_GET_TAG_ARG(tnf, record));
+}
+
+/*
+ * Retrieve the self_size slot of an ABI array record
+ */
+
+size_t
+_tnf_get_self_size(TNF *tnf, tnf_ref32_t *array)
+{
+ return (_GET_SELF_SIZE(tnf, array));
+}
+
+/*
+ * Calculate the number of elements in ABI array record
+ */
+
+unsigned
+_tnf_get_element_count(TNF *tnf, tnf_ref32_t *array, unsigned eltsize)
+{
+ size_t size, hdrsize;
+#ifdef INFINITE_RECURSION_ARRAY
+ tnf_ref32_t *base_tag;
+
+ size = _tnf_get_self_size(tnf, array);
+ base_tag = _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array));
+ hdrsize = _tnf_get_header_size(tnf, base_tag);
+ return (((size - hdrsize) / eltsize));
+#else
+ size = _tnf_get_self_size(tnf, array);
+ hdrsize = sizeof (struct tnf_array_hdr);
+ return (((size - hdrsize) / eltsize));
+#endif
+}
+
+/*
+ * Retrieve the base pointer of an ABI array record
+ */
+
+caddr_t
+/* ARGSUSED */
+_tnf_get_elements(TNF *tnf, tnf_ref32_t *array)
+{
+#ifdef INFINITE_RECURSION_ARRAY
+ size_t hdrsize;
+ tnf_ref32_t *base_tag;
+
+ base_tag = _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array));
+ hdrsize = _tnf_get_header_size(tnf, base_tag);
+ return ((caddr_t)((char *)array + hdrsize));
+#else
+ return ((caddr_t)((char *)array + sizeof (struct tnf_array_hdr)));
+#endif
+}
+
+/*
+ * Retrieve the chars in an ABI string record
+ */
+
+char *
+_tnf_get_chars(TNF *tnf, tnf_ref32_t *string)
+{
+ return ((char *)_tnf_get_elements(tnf, string));
+}
+
+/*
+ * Retrieve the string in the name slot of a type record
+ */
+
+char *
+_tnf_get_name(TNF *tnf, tnf_ref32_t *tag)
+{
+ return (_tnf_get_chars(tnf, _GET_NAME(tnf, tag)));
+}
+
+/*
+ * Retrieve the properties array slot of a type record
+ */
+
+tnf_ref32_t *
+_tnf_get_properties(TNF *tnf, tnf_ref32_t *tag)
+{
+ return (_GET_PROPERTIES(tnf, tag));
+}
+
+/*
+ * Retrieve the slot_types slot of struct_type or array_type record
+ */
+
+tnf_ref32_t *
+_tnf_get_slot_types(TNF *tnf, tnf_ref32_t *tag)
+{
+ return (_GET_SLOT_TYPES(tnf, tag));
+}
+
+/*
+ * Retrieve the header_size slot of an array_type record
+ */
+
+size_t
+_tnf_get_header_size(TNF *tnf, tnf_ref32_t *tag)
+{
+ return (_GET_HEADER_SIZE(tnf, tag));
+}
+
+/*
+ * Retrieve the derived_base slot of a derived_type record
+ */
+
+tnf_ref32_t *
+_tnf_get_derived_base(TNF *tnf, tnf_ref32_t *tag)
+{
+ return (_GET_DERIVED_BASE(tnf, tag));
+}
+
+
+/*
+ * Find the root (self-tagged) type record
+ */
+
+tnf_ref32_t *
+_tnf_get_root_tag(TNF *tnf, tnf_ref32_t *record)
+{
+ if (tnf->root_tag)
+ return (tnf->root_tag);
+ else {
+ tnf_ref32_t *p1, *p2;
+ p1 = record;
+ while ((p2 = _tnf_get_tag(tnf, p1)) != p1)
+ p1 = p2;
+ tnf->root_tag = p2;
+ return (p2);
+ }
+}
+
+/*
+ * Search ABI type array for a type named name
+ */
+
+tnf_ref32_t *
+_tnf_get_element_named(TNF *tnf, tnf_ref32_t *array, char *name)
+{
+ unsigned count, i;
+ tnf_ref32_t *elts;
+
+ count = _tnf_get_element_count(tnf, array, sizeof (tnf_ref32_t));
+ /* LINTED pointer cast may result in improper alignment */
+ elts = (tnf_ref32_t *)_tnf_get_elements(tnf, array);
+
+ for (i = 0; i < count; i++) {
+ tnf_ref32_t *type_elt;
+
+ if ((type_elt = _GET_REF32(tnf, &elts[i])) == TNF_NULL) {
+ /* Can't have missing type records */
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+ return (TNF_NULL);
+ }
+
+ if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)
+ /* Found a type record named name */
+ return (type_elt);
+ }
+ return (TNF_NULL);
+}
+
+/*
+ * Look in type record's properties for named type.
+ * Recursively look at derived_base properties as well.
+ */
+
+tnf_ref32_t *
+_tnf_get_property(TNF *tnf, tnf_ref32_t *tag, char *name)
+{
+ tnf_ref32_t *properties, *property;
+
+ if (strcmp(name, _tnf_get_name(tnf, tag)) == 0)
+ /* name is type name */
+ return (tag);
+
+ if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL)
+ /* no properties */
+ return (TNF_NULL);
+
+ if ((property = _tnf_get_element_named(tnf, properties, name))
+ != TNF_NULL)
+ /* found property named name */
+ return (property);
+
+ /*
+ * Recursively check base type of derived types
+ */
+ if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED)
+ != TNF_NULL) {
+ /* tag is a derived type: check its derived_base */
+ tnf_ref32_t *base_tag;
+
+ base_tag = _tnf_get_derived_base(tnf, tag);
+ /* tnf_derived has derived_base == TNF_NULL */
+ if (base_tag != TNF_NULL)
+ return (_tnf_get_property(tnf, base_tag, name));
+ }
+
+ return (TNF_NULL);
+}
+
+/*
+ * Get the ultimate base type of a type record
+ */
+
+tnf_ref32_t *
+_tnf_get_base_tag(TNF *tnf, tnf_ref32_t *tag)
+{
+ tnf_ref32_t *properties;
+
+ if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL)
+ /* no properties */
+ return (tag);
+
+ if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED)
+ != TNF_NULL) {
+ tnf_ref32_t *base_tag;
+
+ if ((base_tag = _tnf_get_derived_base(tnf, tag)) != TNF_NULL)
+ return (_tnf_get_base_tag(tnf, base_tag));
+ }
+
+ return (tag);
+}
+
+/*
+ * Calculate the reference size of an object with type==tag
+ */
+
+size_t
+_tnf_get_ref_size(TNF *tnf, tnf_ref32_t *tag)
+{
+ if (HAS_PROPERTY(tnf, tag, TNF_N_TAGGED)) {
+ /* Tagged objects occupy 4 bytes for reference */
+ return ((sizeof (tnf_ref32_t)));
+ } else if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE)) {
+ /* Inline slots cannot be self sized */
+ return (_tnf_get_storage_size(tnf, tag));
+ } else {
+ /* Illegal to have references to abstract objects */
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+ return ((0));
+ }
+}
+
+/*
+ * Calculate storage size of an object with type==tag
+ */
+
+size_t
+_tnf_get_storage_size(TNF *tnf, tnf_ref32_t *tag)
+{
+ if (_tnf_get_tag(tnf, tag) == _tnf_get_root_tag(tnf, tag))
+ return (_GET_TYPE_SIZE(tnf, tag));
+ else {
+ tnf_ref32_t *base_tag; /* implementation tag */
+ caddr_t sizep;
+ tnf_ref32_t *slot_types;
+
+#ifndef INFINITE_RECURSION_SIZE
+ char *base_name;
+ static struct n2s {
+ char *name;
+ size_t size;
+ } n2s[] = {
+ { TNF_N_CHAR, sizeof (tnf_char_t) },
+ { TNF_N_INT8, sizeof (tnf_int8_t) },
+ { TNF_N_INT16, sizeof (tnf_int16_t) },
+ { TNF_N_INT32, sizeof (tnf_int32_t) },
+ { TNF_N_UINT8, sizeof (tnf_uint8_t) },
+ { TNF_N_UINT16, sizeof (tnf_uint16_t) },
+ { TNF_N_UINT32, sizeof (tnf_uint32_t) },
+ { TNF_N_INT64, sizeof (tnf_int64_t) },
+ { TNF_N_UINT64, sizeof (tnf_uint64_t) },
+ { TNF_N_FLOAT32, sizeof (tnf_float32_t) },
+ { TNF_N_FLOAT64, sizeof (tnf_float64_t) },
+ { NULL, 0 }
+ };
+ struct n2s *p;
+#endif
+
+ base_tag = _tnf_get_base_tag(tnf, tag);
+
+#ifndef INFINITE_RECURSION_SIZE
+ base_name = _tnf_get_name(tnf, base_tag);
+
+ /* XXX Why are we in this mess? */
+ p = n2s;
+ while (p->name) {
+ if (strcmp(p->name, base_name) == 0)
+ return (p->size);
+ p++;
+ }
+#endif
+
+ sizep = _tnf_get_slot_typed(tnf, base_tag, TNF_N_TYPE_SIZE);
+ if (sizep)
+ /* Type sized */
+ /* LINTED pointer cast may result in improper alignment */
+ return (_GET_UINT32(tnf, (tnf_uint32_t *)sizep));
+
+ slot_types = (tnf_ref32_t *)
+ /* LINTED pointer cast may result in improper alignment */
+ _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_TYPES);
+ if (slot_types &&
+ _tnf_get_element_named(tnf, slot_types, TNF_N_SELF_SIZE))
+ /* Self sized */
+ return ((size_t)-1);
+ else
+ /* Abstract */
+ return (0);
+ }
+}
+
+/*
+ * Return the alignment restriction for any tag
+ */
+
+unsigned
+_tnf_get_align(TNF *tnf, tnf_ref32_t *tag)
+{
+ if (HAS_PROPERTY(tnf, tag, TNF_N_SCALAR)) {
+ tnf_ref32_t *base_tag;
+ caddr_t alignp;
+
+ base_tag = _tnf_get_base_tag(tnf, tag);
+ alignp = _tnf_get_slot_typed(tnf, base_tag, TNF_N_ALIGN);
+ if (alignp)
+ /* LINTED pointer cast may result in improper alignment */
+ return (_GET_UINT32(tnf, (tnf_uint32_t *)alignp));
+ }
+ /* default: word alignment */
+ return ((4));
+}
+
+/*
+ * Only works for records
+ * Doesn't check for slot_names in tag
+ * Tag records, for example, never have named slots
+ */
+
+caddr_t
+_tnf_get_slot_typed(TNF *tnf, tnf_ref32_t *record, char *name)
+{
+ tnf_ref32_t *tag, *base_tag;
+ tnf_ref32_t *slot_types, *types;
+ unsigned count, i;
+ unsigned offset;
+
+ tag = _tnf_get_tag(tnf, record);
+ base_tag = _tnf_get_base_tag(tnf, tag);
+
+ /*
+ * The position of slot_types is ABI fixed
+ * XXX Assume it is present in tag
+ */
+ slot_types = _tnf_get_slot_types(tnf, base_tag);
+ count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
+ /* LINTED pointer cast may result in improper alignment */
+ types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
+
+ offset = 0;
+
+ for (i = 0; i < count; i++) {
+ tnf_ref32_t *type_elt;
+ size_t ref_size, align;
+
+ /* Find the type record for slot */
+ if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) {
+ /* Can't have missing type records */
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+ return ((caddr_t)NULL);
+ }
+
+ /* See similar hack in init_slots() */
+
+ /* Calculate reference size */
+ ref_size = _tnf_get_ref_size(tnf, type_elt);
+
+ /*
+ * Calculate alignment
+ * XXX Prevent infinite recursion by assuming that
+ * a reference size of 4 implies word alignment
+ */
+ align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt);
+
+ /* Adjust offset to account for alignment, if needed */
+ offset = ALIGN(offset, align);
+
+ /* Check whether name corresponds to type name */
+ if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)
+ /* Found the slot */
+ return (fetch_slot(tnf, (caddr_t)record + offset,
+ type_elt));
+
+ /* Bump offset by reference size */
+ offset += ref_size;
+ }
+
+ return ((caddr_t)NULL);
+}
+
+/*
+ * Only works for records
+ */
+
+caddr_t
+_tnf_get_slot_named(TNF *tnf, tnf_ref32_t *record, char *name)
+{
+ tnf_ref32_t *tag, *base_tag;
+ tnf_ref32_t *slot_types, *slot_names, *types, *names;
+ unsigned count, i;
+ unsigned offset;
+
+ tag = _tnf_get_tag(tnf, record);
+ base_tag = _tnf_get_base_tag(tnf, tag);
+
+ /*
+ * slot_names are optional
+ */
+ slot_names = (tnf_ref32_t *)
+ /* LINTED pointer cast may result in improper alignment */
+ _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_NAMES);
+
+ /* no slot_names; use _tnf_get_slot_typed() */
+ if (slot_names == TNF_NULL)
+ return (_tnf_get_slot_typed(tnf, record, name));
+
+ /*
+ * The position of slot_types is ABI fixed
+ * XXX Assume it is present in tag
+ */
+ slot_types = _tnf_get_slot_types(tnf, base_tag);
+ count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
+ /* LINTED pointer cast may result in improper alignment */
+ types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
+ /* LINTED pointer cast may result in improper alignment */
+ names = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names);
+
+ offset = 0;
+
+ for (i = 0; i < count; i++) {
+ tnf_ref32_t *type_elt, *name_elt;
+ size_t ref_size, align;
+
+ /* Find the type record for slot */
+ if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) {
+ /* Can't have missing type records */
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+ return ((caddr_t)NULL);
+ }
+
+ /* XXX Keep consistent with init_slots() */
+
+ /* Calculate reference size */
+ ref_size = _tnf_get_ref_size(tnf, type_elt);
+
+ /*
+ * Calculate alignment
+ * XXX Prevent infinite recursion by assuming that
+ * a reference size of 4 implies word alignment
+ */
+ align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt);
+
+ /* Adjust offset to account for alignment, if needed */
+ offset = ALIGN(offset, align);
+
+ /* First check slot name, then type name */
+ if ((((name_elt = _GET_REF32(tnf, &names[i])) != TNF_NULL) &&
+ (strcmp(name, _tnf_get_chars(tnf, name_elt)) == 0)) ||
+ (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0))
+ /* Found slot */
+ return (fetch_slot(tnf, (caddr_t)record + offset,
+ type_elt));
+
+ /* Bump offset by reference size */
+ offset += ref_size;
+ }
+
+ return ((caddr_t)NULL);
+}
+
+static caddr_t
+fetch_slot(TNF *tnf, caddr_t p, tnf_ref32_t *tag)
+{
+ if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE))
+ return (p);
+ else /* XXX assume tagged */
+ /* LINTED pointer cast may result in improper alignment */
+ return ((caddr_t)_GET_REF32(tnf, (tnf_ref32_t *)p));
+}
diff --git a/usr/src/lib/libtnf/access.c b/usr/src/lib/libtnf/access.c
new file mode 100644
index 0000000000..817a62ffc7
--- /dev/null
+++ b/usr/src/lib/libtnf/access.c
@@ -0,0 +1,184 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * File header operations
+ */
+
+tnf_datum_t
+tnf_get_file_header(TNF *tnf)
+{
+ return (DATUM(tnf->file_header_info, (caddr_t)tnf->file_header));
+}
+
+/*
+ * Block access operations
+ */
+
+unsigned
+tnf_get_block_count(TNF *tnf)
+{
+ return (tnf->block_count);
+}
+
+tnf_datum_t
+tnf_get_block_absolute(TNF *tnf, unsigned index)
+{
+ if (index >= tnf->block_count)
+ /*
+ * access to non-existent block:
+ * no error as per spec
+ */
+ return (TNF_DATUM_NULL);
+ else
+ /*
+ * XXX Require a single block header tag
+ */
+ /* LINTED pointer cast may result in improper alignment */
+ return (DATUM(tnf->block_header_info,
+ (caddr_t)_GET_INDEX_BLOCK(tnf, index)));
+}
+
+tnf_datum_t
+tnf_get_block_relative(tnf_datum_t datum, int adjust)
+{
+ TNF *tnf;
+ tnf_ref32_t *bhdr;
+ unsigned index;
+
+ CHECK_DATUM(datum);
+
+ tnf = DATUM_TNF(datum);
+ bhdr = _GET_BLOCK(tnf, DATUM_VAL(datum));
+ index = _GET_BLOCK_INDEX(tnf, bhdr);
+
+ return (tnf_get_block_absolute(tnf, index + adjust));
+}
+
+int
+tnf_is_block_header(tnf_datum_t datum)
+{
+ struct taginfo *info;
+ caddr_t val;
+ tnf_ref32_t *bhdr;
+
+ CHECK_DATUM(datum);
+
+ info = DATUM_INFO(datum);
+ val = DATUM_VAL(datum);
+ bhdr = _GET_BLOCK(info->tnf, val);
+
+ return (((caddr_t)bhdr == val) &&
+ (info == info->tnf->block_header_info));
+}
+
+tnf_datum_t
+tnf_get_block_header(tnf_datum_t datum)
+{
+ TNF *tnf;
+ caddr_t val;
+
+ CHECK_DATUM(datum);
+
+ tnf = DATUM_TNF(datum);
+ val = DATUM_VAL(datum);
+ /*
+ * XXX Require a single block header tag
+ */
+ return (DATUM(tnf->block_header_info, (caddr_t)_GET_BLOCK(tnf, val)));
+}
+
+/*
+ * Sequential record access
+ */
+
+tnf_datum_t
+tnf_get_next_record(tnf_datum_t datum)
+{
+ TNF *tnf;
+ tnf_ref32_t *bhdr, *cell, ref32;
+ caddr_t val, nval, bval, blim;
+ size_t size, bytes;
+
+ CHECK_RECORD(datum);
+
+ tnf = DATUM_TNF(datum);
+ val = DATUM_VAL(datum);
+
+ size = tnf_get_size(datum);
+ nval = val + size;
+
+ /* Check file bounds */
+ if (nval < tnf->data_start)
+ return (tnf_get_block_absolute(tnf, 0));
+ else if (nval >= tnf->file_end)
+ return (TNF_DATUM_NULL);
+
+ /*
+ * OK, nval is in data area, start looking in block
+ */
+ bhdr = _GET_BLOCK(tnf, nval);
+ /* LINTED pointer cast may result in improper alignment */
+ bytes = _GET_BLOCK_BYTES_VALID(tnf, bhdr);
+ bval = (caddr_t)bhdr;
+ blim = bval + bytes;
+
+ /* sequentially examine valid cells in block from nval onwards */
+ while (nval < blim) {
+ /* LINTED pointer cast may result in improper alignment */
+ cell = (tnf_ref32_t *)nval;
+ ref32 = _GET_INT32(tnf, cell);
+
+ switch (TNF_REF32_TYPE(ref32)) {
+ case TNF_REF32_T_FWD: /* skip forwarding cells */
+ nval += sizeof (tnf_ref32_t);
+ break;
+ case TNF_REF32_T_RSVD: /* catch bogus cells */
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+ return (TNF_DATUM_NULL);
+ default: /* PAIR or TAG: record header */
+ return (RECORD_DATUM(tnf, cell));
+ }
+ }
+
+ /*
+ * Couldn't find it: return next non-zero block header
+ */
+ while ((bval += tnf->block_size) < tnf->file_end)
+ /* Gotta check that there is a real bhdr here */
+ /* LINTED pointer cast may result in improper alignment */
+ if (*(tnf_ref32_t *)bval != TNF_NULL)
+ /* LINTED pointer cast may result in improper alignment */
+ return (RECORD_DATUM(tnf, (tnf_ref32_t *)bval));
+
+ /*
+ * default: we're off the end of the file
+ */
+ return (TNF_DATUM_NULL);
+}
diff --git a/usr/src/lib/libtnf/array.c b/usr/src/lib/libtnf/array.c
new file mode 100644
index 0000000000..09fd89c9e7
--- /dev/null
+++ b/usr/src/lib/libtnf/array.c
@@ -0,0 +1,205 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * XXX This module assumes that all arrays are self-sized records.
+ */
+
+/*
+ *
+ */
+
+static struct taginfo * get_array_info(
+ tnf_datum_t,
+ struct taginfo **base,
+ struct taginfo **elt,
+ struct taginfo **elt_base);
+
+/*
+ * XXX Assumes arrays are (self-sized) records
+ */
+
+void
+_tnf_check_array(tnf_datum_t datum)
+{
+ struct taginfo *info;
+
+ CHECK_RECORD(datum); /* XXX */
+
+ info = DATUM_INFO(datum);
+
+ if (!INFO_ARRAY(info))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
+
+}
+
+/*
+ * Helper
+ */
+
+static struct taginfo *
+get_array_info(
+ tnf_datum_t datum,
+ struct taginfo **basep,
+ struct taginfo **eltp,
+ struct taginfo **elt_basep)
+{
+ struct taginfo *info, *base, *elt, *elt_base;
+
+ info = DATUM_INFO(datum);
+ base = INFO_DERIVED(info) ? info->base : info;
+
+ if (INFO_DERIVED(base) || (!INFO_ARRAY(base)))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_INTERNAL);
+
+ elt = base->base; /* XXX base slot is reused for elttype */
+ elt_base = INFO_DERIVED(elt) ? elt->base : elt;
+
+ *basep = base;
+ *eltp = elt;
+ *elt_basep = elt_base;
+ return (info);
+}
+
+/*
+ * Return number of elements in array
+ */
+
+unsigned
+tnf_get_element_count(tnf_datum_t datum)
+{
+ size_t hdr_size, elt_size, self_size;
+ struct taginfo *base, *elt, *elt_base;
+
+ CHECK_ARRAY(datum);
+
+ (void) get_array_info(datum, &base, &elt, &elt_base);
+ hdr_size = base->hdrsize;
+ elt_size = INFO_ELEMENT_SIZE(elt_base);
+ self_size = _tnf_get_self_size(DATUM_TNF(datum),
+ /* LINTED pointer cast may result in improper alignment */
+ DATUM_RECORD(datum));
+ return (((self_size - hdr_size) / elt_size));
+}
+
+/*
+ * Fetch indexed element
+ */
+
+tnf_datum_t
+tnf_get_element(tnf_datum_t datum, unsigned index)
+{
+ size_t hdr_size, elt_size, self_size;
+ struct taginfo *base, *elt, *elt_base;
+ unsigned count, offset;
+
+ CHECK_ARRAY(datum);
+
+ (void) get_array_info(datum, &base, &elt, &elt_base);
+ hdr_size = base->hdrsize;
+ elt_size = INFO_ELEMENT_SIZE(elt_base);
+ self_size = _tnf_get_self_size(DATUM_TNF(datum),
+ /* LINTED pointer cast may result in improper alignment */
+ DATUM_RECORD(datum));
+
+ count = (self_size - hdr_size) / elt_size;
+
+ if (index >= count)
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_BADINDEX);
+
+ offset = hdr_size + (index * elt_size);
+
+ /*
+ * If tagged, use the tag to construct datum
+ */
+ if (INFO_TAGGED(elt)) {
+ TNF *tnf;
+ tnf_ref32_t *rec;
+
+ tnf = DATUM_TNF(datum);
+ /* LINTED pointer cast may result in improper alignment */
+ rec = _GET_REF32(tnf, (tnf_ref32_t *)
+ (DATUM_VAL(datum) + offset));
+ /* NULL elements are allowed */
+ return ((rec == TNF_NULL)? TNF_DATUM_NULL :
+ RECORD_DATUM(tnf, rec));
+ } else
+ return (DATUM(elt, DATUM_VAL(datum) + offset));
+}
+
+/*
+ * Return element type of array
+ */
+
+tnf_datum_t
+tnf_get_element_type(tnf_datum_t datum)
+{
+ struct taginfo *base, *elt, *elt_base;
+
+ CHECK_ARRAY(datum);
+
+ (void) get_array_info(datum, &base, &elt, &elt_base);
+
+ return (RECORD_DATUM(DATUM_TNF(datum), elt->tag));
+}
+
+/*
+ * Return a char pointer for string record
+ */
+
+char *
+tnf_get_chars(tnf_datum_t datum)
+{
+ struct taginfo *info, *base, *elt, *elt_base;
+
+ CHECK_ARRAY(datum);
+
+ info = get_array_info(datum, &base, &elt, &elt_base);
+
+ if (!INFO_STRING(info))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
+
+ return (DATUM_VAL(datum) + base->hdrsize);
+}
+
+/*
+ * Return the base pointer of array
+ */
+
+caddr_t
+tnf_get_elements(tnf_datum_t datum)
+{
+ struct taginfo *base, *elt, *elt_base;
+
+ CHECK_ARRAY(datum);
+
+ (void) get_array_info(datum, &base, &elt, &elt_base);
+
+ return ((caddr_t)(DATUM_VAL(datum) + base->hdrsize));
+}
diff --git a/usr/src/lib/libtnf/datum.c b/usr/src/lib/libtnf/datum.c
new file mode 100644
index 0000000000..0193f23f90
--- /dev/null
+++ b/usr/src/lib/libtnf/datum.c
@@ -0,0 +1,214 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * Defines
+ */
+
+#define DATUM_KIND(d) (DATUM_INFO(d)->kind)
+
+/*
+ * Declarations
+ */
+
+static int has_prop(tnf_datum_t, tag_props_t);
+
+/*
+ * Datum operations: for more debuggability
+ */
+
+#ifndef _DATUM_MACROS
+
+tnf_datum_t
+_tnf_datum(struct taginfo *info, caddr_t val)
+{
+ return (_DATUM(info, val));
+}
+
+struct taginfo *
+_tnf_datum_info(tnf_datum_t datum)
+{
+ return ((struct taginfo *)_DATUM_HI(datum));
+}
+
+caddr_t
+_tnf_datum_val(tnf_datum_t datum)
+{
+ return ((caddr_t)_DATUM_LO(datum));
+}
+
+#endif
+
+/*
+ * Check for valid datum
+ */
+
+void
+_tnf_check_datum(tnf_datum_t datum)
+{
+ caddr_t val;
+ TNF *tnf;
+
+ if (datum == TNF_DATUM_NULL)
+ _tnf_error(NULL, TNF_ERR_BADTNF);
+
+ val = DATUM_VAL(datum);
+ tnf = DATUM_TNF(datum);
+
+ if ((val <= tnf->file_start) || (val >= tnf->file_end))
+ _tnf_error(tnf, TNF_ERR_BADDATUM);
+}
+
+/*
+ * Retrieve datum kind from cached information
+ */
+
+tnf_kind_t
+tnf_get_kind(tnf_datum_t datum)
+{
+ CHECK_DATUM(datum);
+ /* The kind field is always completely initialized */
+ return (DATUM_KIND(datum));
+}
+
+/*
+ * Classification predicates: check the cached tag props
+ */
+
+static int
+has_prop(tnf_datum_t datum, tag_props_t prop)
+{
+ CHECK_DATUM(datum);
+
+ /* Note: No need to get base info because props inherited */
+ return (INFO_PROP(DATUM_INFO(datum), prop));
+}
+
+int
+tnf_is_inline(tnf_datum_t datum)
+{
+ return (has_prop(datum, TAG_PROP_INLINE));
+}
+
+int
+tnf_is_scalar(tnf_datum_t datum)
+{
+ return (has_prop(datum, TAG_PROP_SCALAR));
+}
+
+int
+tnf_is_record(tnf_datum_t datum) /* XXX was: tnf_is_tagged */
+{
+ return (has_prop(datum, TAG_PROP_TAGGED));
+}
+
+int
+tnf_is_array(tnf_datum_t datum)
+{
+ return (has_prop(datum, TAG_PROP_ARRAY));
+}
+
+int
+tnf_is_string(tnf_datum_t datum)
+{
+ return (has_prop(datum, TAG_PROP_STRING));
+}
+
+int
+tnf_is_struct(tnf_datum_t datum)
+{
+ return (has_prop(datum, TAG_PROP_STRUCT));
+}
+
+int
+tnf_is_type(tnf_datum_t datum)
+{
+ return (has_prop(datum, TAG_PROP_TYPE));
+}
+
+/*
+ * Get the type datum for any datum
+ */
+
+tnf_datum_t
+tnf_get_type(tnf_datum_t datum)
+{
+ struct taginfo *info;
+
+ CHECK_DATUM(datum);
+
+ info = DATUM_INFO(datum);
+ return (DATUM(info->meta, (caddr_t)info->tag));
+}
+
+/*
+ * Get the type name for any datum
+ * XXX Beware: this is a pointer into the file
+ */
+
+char *
+tnf_get_type_name(tnf_datum_t datum)
+{
+ CHECK_DATUM(datum);
+ return (DATUM_INFO(datum)->name); /* cached */
+}
+
+/*
+ * Get the size of any datum
+ */
+
+size_t
+tnf_get_size(tnf_datum_t datum)
+{
+ struct taginfo *info;
+ size_t size;
+
+ CHECK_DATUM(datum);
+
+ info = DATUM_INFO(datum);
+ size = info->size;
+
+ if (size == (size_t)-1) /* self sized */
+ /* XXX tnf_get_slot_named(datum, TNF_N_SELF_SIZE) */
+ /* LINTED pointer cast may result in improper alignment */
+ return (_tnf_get_self_size(info->tnf, DATUM_RECORD(datum)));
+ else
+ return (size);
+}
+
+/*
+ * Get raw pointer to any datum
+ */
+
+caddr_t
+tnf_get_raw(tnf_datum_t datum)
+{
+ CHECK_DATUM(datum);
+ return (DATUM_VAL(datum));
+}
diff --git a/usr/src/lib/libtnf/error.c b/usr/src/lib/libtnf/error.c
new file mode 100644
index 0000000000..bad39d7f86
--- /dev/null
+++ b/usr/src/lib/libtnf/error.c
@@ -0,0 +1,114 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+#include <libintl.h>
+
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+
+/*
+ *
+ */
+
+static tnf_error_handler_t *_err_handler = &tnf_default_error_handler;
+static void *_err_arg = 0;
+
+/*
+ *
+ */
+
+void
+tnf_set_error_handler(tnf_error_handler_t *handler, void *arg)
+{
+ /* XXX Not MT-safe */
+ _err_arg = arg;
+ _err_handler = handler;
+}
+
+/*
+ *
+ */
+
+void
+_tnf_error(TNF *tnf, tnf_errcode_t err)
+{
+ (*_err_handler)(_err_arg, tnf, err);
+}
+
+/*
+ *
+ */
+
+char *
+tnf_error_message(tnf_errcode_t err)
+{
+ if (err == TNF_ERR_NONE)
+ return (dgettext(TEXT_DOMAIN, "no error"));
+ else if (err <= TNF_ERRNO_MAX)
+ return (strerror(err));
+ else {
+ switch (err) {
+ case TNF_ERR_NOTTNF:
+ return (dgettext(TEXT_DOMAIN, "not a TNF file"));
+ case TNF_ERR_BADDATUM:
+ return (dgettext(TEXT_DOMAIN,
+ "operation on bad or NULL data handle"));
+ case TNF_ERR_TYPEMISMATCH:
+ return (dgettext(TEXT_DOMAIN, "type mismatch"));
+ case TNF_ERR_BADINDEX:
+ return (dgettext(TEXT_DOMAIN, "index out of bounds"));
+ case TNF_ERR_BADSLOT:
+ return (dgettext(TEXT_DOMAIN, "no such slot"));
+ case TNF_ERR_BADREFTYPE:
+ return (dgettext(TEXT_DOMAIN, "bad reference type"));
+ case TNF_ERR_ALLOCFAIL:
+ return (dgettext(TEXT_DOMAIN,
+ "memory allocation failure"));
+ case TNF_ERR_BADTNF:
+ return (dgettext(TEXT_DOMAIN, "bad TNF file"));
+ case TNF_ERR_INTERNAL:
+ return (dgettext(TEXT_DOMAIN, "internal error"));
+ default:
+ return (dgettext(TEXT_DOMAIN, "unknown error code"));
+ }
+ }
+}
+
+/*
+ *
+ */
+
+void
+/* ARGSUSED */
+tnf_default_error_handler(void *arg, TNF *tnf, tnf_errcode_t err)
+{
+ fprintf(stderr, dgettext(TEXT_DOMAIN, "error: libtnf: %d: %s\n"),
+ err, tnf_error_message(err));
+ abort();
+}
diff --git a/usr/src/lib/libtnf/i386dep.c b/usr/src/lib/libtnf/i386dep.c
new file mode 100644
index 0000000000..7f198ccd43
--- /dev/null
+++ b/usr/src/lib/libtnf/i386dep.c
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* This file intentionally (almost) blank */
+
+static int _zero_ = 0;
diff --git a/usr/src/lib/libtnf/info.c b/usr/src/lib/libtnf/info.c
new file mode 100644
index 0000000000..8c9829aa79
--- /dev/null
+++ b/usr/src/lib/libtnf/info.c
@@ -0,0 +1,400 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+#define TAG_INDEX(x) (TNF_TAG16_ABS16(x) / sizeof (tnf_ref32_t))
+
+/*
+ *
+ */
+
+static struct taginfo * add_info(TNF *, tnf_ref32_t *);
+
+static struct taginfo *
+init_abstract_info(TNF *, tnf_ref32_t *, struct taginfo *);
+
+static struct taginfo *
+init_derived_info(TNF *, tnf_ref32_t *, struct taginfo *);
+
+static struct taginfo *
+init_scalar_info(TNF *, tnf_ref32_t *, struct taginfo *);
+
+static struct taginfo *
+init_struct_info(TNF *, tnf_ref32_t *, struct taginfo *);
+
+static struct taginfo *
+init_array_info(TNF *, tnf_ref32_t *, struct taginfo *);
+
+static void init_slots(TNF *, tnf_ref32_t *, struct taginfo *);
+
+/*
+ * Allocate tag table and directory
+ */
+
+tnf_errcode_t
+_tnf_init_tags(TNF *tnf)
+{
+ if ((tnf->tag_table = calloc(TAGTABCNT, sizeof (struct taginfo *)))
+ == NULL)
+ return (TNF_ERR_ALLOCFAIL);
+ if ((tnf->tag_directory = calloc(TAGDIRCNT(tnf->directory_size),
+ sizeof (struct taginfo *)))
+ == NULL)
+ return (TNF_ERR_ALLOCFAIL);
+ return (TNF_ERR_NONE);
+}
+
+/*
+ * Deallocate all taginfos and tables associated with TNF handle
+ */
+
+tnf_errcode_t
+_tnf_fini_tags(TNF *tnf)
+{
+ int i;
+ struct taginfo *info, *link;
+
+ /*
+ * free taginfos
+ */
+ for (i = 0; i < TAGTABCNT; i++) {
+ info = tnf->tag_table[i];
+ while (info) {
+ /* remember link */
+ link = info->link;
+ /* free slot information */
+ if (info->slotinfo)
+ free(info->slotinfo);
+ /* free taginfo */
+ free(info);
+ /* next in hash chain */
+ info = link;
+ }
+ }
+ /*
+ * free the tables
+ */
+ free(tnf->tag_table);
+ tnf->tag_table = NULL;
+ free(tnf->tag_directory);
+ tnf->tag_directory = NULL;
+
+ return (TNF_ERR_NONE);
+}
+
+/*
+ * Get info for supplied tag
+ */
+
+struct taginfo *
+_tnf_get_info(TNF *tnf, tnf_ref32_t *tag)
+{
+ struct taginfo *bucket, *info;
+
+ bucket = tnf->tag_table[TAGHASH(tnf, tag)];
+ for (info = bucket; info; info = info->link)
+ if (info->tag == tag)
+ return (info); /* found it */
+
+ /* default: not there, create */
+ return (add_info(tnf, tag));
+}
+
+/*
+ * Get info for supplied record
+ * Use fast lookup, if possible
+ */
+
+struct taginfo *
+_tnf_record_info(TNF *tnf, tnf_ref32_t *record)
+{
+ tnf_ref32_t ref32;
+ tnf_ref16_t tag16;
+ tnf_abs16_t index;
+ struct taginfo *info;
+
+ ref32 = _GET_INT32(tnf, record);
+
+ index = 0;
+ if (TNF_REF32_IS_PAIR(ref32)) {
+ tag16 = TNF_REF32_TAG16(ref32);
+ if (TNF_TAG16_IS_ABS(tag16))
+ index = TAG_INDEX(tag16);
+ }
+
+ if (index) {
+ if ((info = tnf->tag_directory[index]) != NULL)
+ return (info);
+ else { /* not in directory yet */
+ info = _tnf_get_info(tnf, _tnf_get_tag(tnf, record));
+ /* enter into tag directory */
+ return ((tnf->tag_directory[index] = info));
+ }
+ }
+
+ /* default: not referenced via index */
+ return (_tnf_get_info(tnf, _tnf_get_tag(tnf, record)));
+}
+
+/*
+ * Add a new taginfo for tag
+ */
+
+static struct taginfo *
+add_info(TNF *tnf, tnf_ref32_t *tag)
+{
+ struct taginfo *info, *bucket;
+ unsigned hash;
+ tnf_ref32_t *meta;
+
+ info = (struct taginfo *)calloc(1, sizeof (struct taginfo));
+
+ /* Initialize members */
+ info->tnf = tnf;
+ info->tag = tag;
+ info->name = _tnf_get_name(tnf, tag);
+ info->props = _tnf_get_props(tnf, tag);
+ info->kind = _tnf_get_kind(tnf, tag);
+ info->size = _tnf_get_storage_size(tnf, tag);
+ info->align = _tnf_get_align(tnf, tag);
+
+ /* Add it to table */
+ hash = TAGHASH(tnf, tag);
+ bucket = tnf->tag_table[hash];
+ info->link = bucket;
+ tnf->tag_table[hash] = info;
+
+ /* Ensure meta info is available */
+ meta = _tnf_get_tag(tnf, tag);
+ info->meta = _tnf_get_info(tnf, meta);
+
+ /*
+ * Initialize info
+ * Derived must be first clause due to property inheritance
+ */
+
+ if (INFO_DERIVED(info))
+ return (init_derived_info(tnf, tag, info));
+ else if (INFO_STRUCT(info))
+ return (init_struct_info(tnf, tag, info));
+ else if (INFO_ARRAY(info))
+ return (init_array_info(tnf, tag, info));
+ else if (INFO_SCALAR(info))
+ return (init_scalar_info(tnf, tag, info));
+ else /* XXX assume abstract type */
+ return (init_abstract_info(tnf, tag, info));
+}
+
+
+/*
+ * Initialize info for an abstract tag
+ */
+
+static struct taginfo *
+/* ARGSUSED */
+init_abstract_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
+{
+ if (INFO_SCALAR(info) || INFO_DERIVED(info) ||
+ INFO_STRUCT(info) || INFO_ARRAY(info))
+ _tnf_error(tnf, TNF_ERR_INTERNAL);
+ if (info->size == (size_t)-1)
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+ return (info);
+}
+
+/*
+ * Initialize info for a derived tag
+ */
+
+static struct taginfo *
+init_derived_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
+{
+ tnf_ref32_t *base_tag;
+
+ if (!INFO_DERIVED(info))
+ _tnf_error(tnf, TNF_ERR_INTERNAL);
+
+ /* Ensure ultimate base information is available */
+ base_tag = _tnf_get_base_tag(tnf, tag);
+ info->base = _tnf_get_info(tnf, base_tag);
+
+ return (info);
+}
+
+/*
+ * Initialize info for a scalar tag
+ */
+
+static struct taginfo *
+/* ARGSUSED */
+init_scalar_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
+{
+ if ((!INFO_SCALAR(info)) ||
+ (INFO_DERIVED(info) || INFO_ARRAY(info) || INFO_STRUCT(info)))
+ _tnf_error(tnf, TNF_ERR_INTERNAL);
+ if (info->size == (size_t)-1)
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+
+ /* XXX alignment already done */
+
+ return (info);
+}
+
+/*
+ * Initialize info for a struct tag
+ */
+
+static struct taginfo *
+init_struct_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
+{
+ if ((!INFO_STRUCT(info)) ||
+ (INFO_DERIVED(info) || INFO_ARRAY(info) || INFO_SCALAR(info)))
+ _tnf_error(tnf, TNF_ERR_INTERNAL);
+ if (info->size == (size_t)-1)
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+
+ /* Get slot information */
+ init_slots(tnf, tag, info);
+
+ return (info);
+}
+
+/*
+ * Initialize info for an array tag
+ */
+
+static struct taginfo *
+init_array_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
+{
+ tnf_ref32_t *elt_tag;
+ int defeat;
+
+ if ((!INFO_ARRAY(info)) ||
+ (INFO_DERIVED(info) || INFO_STRUCT(info) || INFO_SCALAR(info)))
+ _tnf_error(tnf, TNF_ERR_INTERNAL);
+
+ /* XXX special-case abstract array tag */
+ defeat = (strcmp(info->name, TNF_N_ARRAY) == 0);
+
+ /* Require all arrays to be self-sized records */
+ if (!(INFO_TAGGED(info) && (info->size == (size_t)-1)))
+ if (!defeat)
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+
+ /* Store array header size */
+ info->hdrsize = _tnf_get_header_size(tnf, tag);
+ /* XXX Temporary sanity check */
+ if (info->hdrsize != sizeof (struct tnf_array_hdr))
+ if (!defeat)
+ _tnf_error(tnf, TNF_ERR_BADTNF);
+
+ /* Get slot information */
+ init_slots(tnf, tag, info);
+
+ /* Get info for element type */
+ elt_tag = (tnf_ref32_t *)_tnf_get_slot_typed(tnf, tag,
+ /* LINTED pointer cast may result in improper alignment */
+ TNF_N_ELEMENT_TYPE);
+ /* XXX tnf_array has element_type == NULL */
+ info->base = elt_tag ? _tnf_get_info(tnf, elt_tag): NULL;
+
+ return (info);
+}
+
+/*
+ * Initialize slot information for aggregate tag
+ */
+
+static void
+init_slots(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info)
+{
+ tnf_ref32_t *slot_types, *slot_names;
+ tnf_ref32_t *types, *names;
+ unsigned count, i, offset;
+ struct slotinfo *slotinfo;
+
+ slot_types = (tnf_ref32_t *)
+ /* LINTED pointer cast may result in improper alignment */
+ _tnf_get_slot_typed(tnf, tag, TNF_N_SLOT_TYPES);
+ slot_names = (tnf_ref32_t *)
+ /* LINTED pointer cast may result in improper alignment */
+ _tnf_get_slot_typed(tnf, tag, TNF_N_SLOT_NAMES);
+
+ /* abstract tags have no slots */
+ if (slot_types == TNF_NULL)
+ return;
+
+ count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
+ /* LINTED pointer cast may result in improper alignment */
+ types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
+ names = ((slot_names == TNF_NULL) ? TNF_NULL :
+ /* LINTED pointer cast may result in improper alignment */
+ (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names));
+
+ slotinfo = (struct slotinfo *)
+ calloc(1, sizeof (unsigned) + (count * sizeof (struct slot)));
+ if (slotinfo == (struct slotinfo *)NULL)
+ _tnf_error(tnf, TNF_ERR_ALLOCFAIL);
+
+ slotinfo->slot_count = count;
+ offset = 0;
+
+ for (i = 0; i < count; i++) {
+ tnf_ref32_t *type_elt, *name_elt;
+ struct taginfo *elt_info;
+ size_t ref_size, align;
+
+ /* XXX No checks here for missing tags */
+ type_elt = _GET_REF32(tnf, &types[i]);
+ name_elt = names ? _GET_REF32(tnf, &names[i]) : TNF_NULL;
+
+ /* Resolve slot tag into taginfo */
+ elt_info = _tnf_get_info(tnf, type_elt);
+ slotinfo->slots[i].slot_type = elt_info;
+ slotinfo->slots[i].slot_name =
+ ((name_elt != TNF_NULL) ?
+ _tnf_get_chars(tnf, name_elt) :
+ _tnf_get_name(tnf, type_elt));
+
+ /* Get cached reference size */
+ ref_size = INFO_REF_SIZE(elt_info);
+
+ /* Get cached alignment */
+ align = INFO_ALIGN(elt_info); /* XXX */
+
+ /* Adjust offset to account for alignment, if needed */
+ offset = ALIGN(offset, align);
+
+ slotinfo->slots[i].slot_offset = offset;
+
+ /* Bump offset by reference size */
+ offset += ref_size;
+ }
+
+ info->slotinfo = slotinfo;
+}
diff --git a/usr/src/lib/libtnf/libtnf.h b/usr/src/lib/libtnf/libtnf.h
new file mode 100644
index 0000000000..27c111cbed
--- /dev/null
+++ b/usr/src/lib/libtnf/libtnf.h
@@ -0,0 +1,340 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#ifndef _LIBTNF_H
+#define _LIBTNF_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tnf/tnf.h"
+#include "machlibtnf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Info flags
+ */
+
+typedef unsigned long tag_props_t;
+
+#define TAG_PROP_INLINE (1<<0)
+#define TAG_PROP_TAGGED (1<<1)
+#define TAG_PROP_SCALAR (1<<2)
+#define TAG_PROP_DERIVED (1<<3)
+#define TAG_PROP_ARRAY (1<<4)
+#define TAG_PROP_STRING (1<<5)
+#define TAG_PROP_STRUCT (1<<6)
+#define TAG_PROP_TYPE (1<<7)
+
+/*
+ * Type tag information
+ */
+
+struct taginfo {
+ struct taginfo *link; /* hash link */
+#define INFO_MEMBER_0 link
+ TNF *tnf; /* TNF handle */
+ tnf_ref32_t *tag; /* tag record in file */
+ char *name; /* chars in file */
+ tnf_kind_t kind; /* data classification */
+ tag_props_t props; /* tag property flags */
+ struct taginfo *meta; /* meta tag info */
+ struct taginfo *base; /* last derived base or elttype */
+ size_t size; /* storage size or -1 */
+ size_t align; /* slot alignment */
+ size_t hdrsize; /* array header size */
+ struct slotinfo { /* aggregate slot information */
+ unsigned slot_count;
+ /* Embedded array */
+ struct slot {
+ struct taginfo *slot_type;
+ char *slot_name;
+ unsigned slot_offset;
+ } slots[1];
+ } *slotinfo;
+};
+
+#define INFO_PROP(ip, p) ((ip)->props & (p))
+
+#define INFO_INLINE(ip) INFO_PROP(ip, TAG_PROP_INLINE)
+#define INFO_TAGGED(ip) INFO_PROP(ip, TAG_PROP_TAGGED)
+#define INFO_SCALAR(ip) INFO_PROP(ip, TAG_PROP_SCALAR)
+#define INFO_DERIVED(ip) INFO_PROP(ip, TAG_PROP_DERIVED)
+#define INFO_ARRAY(ip) INFO_PROP(ip, TAG_PROP_ARRAY)
+#define INFO_STRING(ip) INFO_PROP(ip, TAG_PROP_STRING)
+#define INFO_STRUCT(ip) INFO_PROP(ip, TAG_PROP_STRUCT)
+#define INFO_TYPE(ip) INFO_PROP(ip, TAG_PROP_TYPE)
+
+#define INFO_REF_SIZE(ip) (INFO_TAGGED(ip)? 4: (ip)->size)
+#define INFO_ELEMENT_SIZE(ip) INFO_REF_SIZE(ip)
+
+/* Alignment is stored for all but records and derivations thereof */
+#define INFO_ALIGN(ip) (INFO_TAGGED(ip)? 4: (ip)->align)
+
+#define ALIGN(n, a) \
+ (((a) == 0) ? (n) : (((n) + (a) - 1) & ~((a) - 1)))
+
+/*
+ * Tag lookup
+ */
+
+/* Number of directory entries */
+#define TAGDIRCNT(x) ((x) / sizeof (tnf_ref32_t))
+
+/* Number of hash table buckets */
+#define TAGTABCNT 1024
+#define TAGTABMASK (TAGTABCNT-1)
+
+/* A tag is at least 32 bytes; with strings & props, assume 128 bytes */
+#define TAGTABSHIFT 7
+
+/* Hash tag by bits 17:7 of offset within data area */
+#define TAGOFF(tnf, p) ((unsigned)((caddr_t)(p) - (tnf)->data_start))
+#define TAGHASH(tnf, p) ((TAGOFF(tnf, p) >> TAGTABSHIFT) & TAGTABMASK)
+
+/*
+ * TNF handle
+ */
+
+struct TNF {
+ /*
+ * Client-supplied bounds
+ */
+ caddr_t file_start;
+ size_t file_size;
+ caddr_t file_end; /* file_start + file_size */
+
+ /*
+ * File information
+ */
+ unsigned file_magic; /* magic number of file */
+ int file_native; /* endian flag */
+
+ /* file header */
+ tnf_ref32_t *file_header; /* first record in file */
+ size_t block_size; /* size of a block */
+ size_t directory_size; /* size of directory area */
+
+ unsigned block_count; /* number of data blocks */
+ caddr_t data_start; /* file_start + 64KB */
+
+ unsigned generation_shift;
+ unsigned address_mask;
+
+ /* block headers */
+ unsigned block_shift; /* index -> bhdr */
+ unsigned block_mask; /* ptr -> bhdr */
+ unsigned block_generation_offset;
+ unsigned block_bytes_valid_offset;
+
+ /* root tag */
+ tnf_ref32_t *root_tag;
+
+ /* important taginfo */
+ struct taginfo *file_header_info;
+ struct taginfo *block_header_info;
+
+ /* tag lookup tables */
+ struct taginfo **tag_table; /* by address */
+ struct taginfo **tag_directory; /* by index */
+
+};
+
+/*
+ * File operations for reading integers
+ */
+
+#define _GET_UINT32(tnf, ptr) \
+ ((tnf)->file_native ? \
+ *(tnf_uint32_t *)(ptr) : \
+ _tnf_swap32(*(tnf_uint32_t *)(ptr)))
+
+#define _GET_INT32(tnf, ptr) \
+ ((tnf_int32_t)_GET_UINT32(tnf, ptr))
+
+#define _GET_UINT16(tnf, ptr) \
+ ((tnf)->file_native ? \
+ *(tnf_uint16_t *)(ptr) : \
+ _tnf_swap16(*(tnf_uint16_t *)(ptr)))
+
+#define _GET_INT16(tnf, ptr) \
+ ((tnf_int16_t)_GET_UINT16(tnf, ptr))
+
+/*
+ * TNF reference-chasing operations
+ */
+
+tnf_ref32_t * _tnf_get_ref32(TNF *, tnf_ref32_t *);
+tnf_ref32_t * _tnf_get_ref16(TNF *, tnf_ref32_t *);
+
+#define _GET_REF32(tnf, ptr) _tnf_get_ref32(tnf, ptr)
+#define _GET_REF16(tnf, ptr) _tnf_get_ref16(tnf, ptr)
+
+/*
+ * Block header record operations
+ * Only applicable in data area
+ */
+
+#define _GET_BLOCK(tnf, ptr) \
+ ((tnf_ref32_t *)((unsigned)(ptr) & (tnf)->block_mask))
+
+#define _GET_BLOCK_INDEX(tnf, bhdr) \
+ (((caddr_t)(bhdr) - (tnf)->data_start) >> (tnf)->block_shift)
+
+#define _GET_INDEX_BLOCK(tnf, index) \
+ ((tnf_ref32_t *)((tnf)->data_start + ((index) << (tnf)->block_shift)))
+
+#define _GET_BLOCK_GENERATION(tnf, bhdr) \
+ _GET_UINT32(tnf, (caddr_t)bhdr + tnf->block_generation_offset)
+
+#define _GET_BLOCK_BYTES_VALID(tnf, bhdr) \
+ (!(bhdr) ? 0 : _GET_UINT16(tnf, (caddr_t)bhdr + \
+ tnf->block_bytes_valid_offset))
+
+/*
+ * Datum operations
+ */
+
+#ifndef _DATUM_MACROS
+
+tnf_datum_t _tnf_datum(struct taginfo *, caddr_t);
+struct taginfo * _tnf_datum_info(tnf_datum_t);
+caddr_t _tnf_datum_val(tnf_datum_t);
+
+#define DATUM(x, y) _tnf_datum(x, y)
+#define DATUM_INFO(x) _tnf_datum_info(x)
+#define DATUM_VAL(x) _tnf_datum_val(x)
+
+#else /* _DATUM_MACROS */
+
+/* Some degree of type safety: */
+#define DATUM(x, y) _DATUM(&(x)->INFO_MEMBER_0, y)
+#define DATUM_INFO(d) ((struct taginfo *)_DATUM_HI(d))
+#define DATUM_VAL(d) ((caddr_t)_DATUM_LO(d))
+
+#endif /* _DATUM_MACROS */
+
+#define _DATUM(hi, lo) (((unsigned long long)(hi) << 32) | (unsigned)(lo))
+#define _DATUM_HI(x) ((unsigned) ((x) >> 32))
+#define _DATUM_LO(x) ((unsigned) (x))
+
+#define DATUM_RECORD(x) \
+ ((tnf_ref32_t *)DATUM_VAL(x))
+
+#define RECORD_DATUM(tnf, rec) \
+ DATUM(_tnf_record_info(tnf, rec), (caddr_t)rec)
+
+#define DATUM_TNF(x) DATUM_INFO(x)->tnf
+#define DATUM_TAG(x) DATUM_INFO(x)->tag
+
+/*
+ * Type checking operations
+ */
+
+void _tnf_check_datum(tnf_datum_t);
+#define CHECK_DATUM(x) _tnf_check_datum(x)
+
+void _tnf_check_record(tnf_datum_t);
+#define CHECK_RECORD(x) _tnf_check_record(x)
+
+void _tnf_check_slots(tnf_datum_t);
+#define CHECK_SLOTS(x) _tnf_check_slots(x)
+
+void _tnf_check_array(tnf_datum_t);
+#define CHECK_ARRAY(x) _tnf_check_array(x)
+
+void _tnf_check_type(tnf_datum_t);
+#define CHECK_TYPE(x) _tnf_check_type(x)
+
+/*
+ * Operations based on ABI layouts and bootstrap assumptions
+ */
+
+tnf_ref32_t * _tnf_get_tag(TNF *, tnf_ref32_t *);
+tnf_ref32_t * _tnf_get_tag_arg(TNF *, tnf_ref32_t *);
+size_t _tnf_get_self_size(TNF *, tnf_ref32_t *);
+unsigned _tnf_get_element_count(TNF *, tnf_ref32_t *, unsigned);
+caddr_t _tnf_get_elements(TNF *, tnf_ref32_t *);
+char * _tnf_get_chars(TNF *, tnf_ref32_t *);
+char * _tnf_get_name(TNF *, tnf_ref32_t *);
+tnf_ref32_t * _tnf_get_properties(TNF *, tnf_ref32_t *);
+tnf_ref32_t * _tnf_get_slot_types(TNF *, tnf_ref32_t *);
+size_t _tnf_get_header_size(TNF *, tnf_ref32_t *);
+tnf_ref32_t * _tnf_get_derived_base(TNF *, tnf_ref32_t *);
+
+tnf_ref32_t * _tnf_get_root_tag(TNF *, tnf_ref32_t *);
+tnf_ref32_t * _tnf_get_property(TNF *, tnf_ref32_t *, char *);
+tnf_ref32_t * _tnf_get_element_named(TNF *, tnf_ref32_t *, char *);
+tnf_ref32_t * _tnf_get_base_tag(TNF *, tnf_ref32_t *);
+
+size_t _tnf_get_storage_size(TNF *, tnf_ref32_t *);
+size_t _tnf_get_ref_size(TNF *, tnf_ref32_t *);
+
+unsigned _tnf_get_align(TNF *, tnf_ref32_t *);
+
+caddr_t _tnf_get_slot_typed(TNF *, tnf_ref32_t *, char *);
+caddr_t _tnf_get_slot_named(TNF *, tnf_ref32_t *, char *);
+
+#define HAS_PROPERTY(tnf, tag, name) \
+ (_tnf_get_property(tnf, tag, name) != TNF_NULL)
+
+/*
+ * Call the installed error handler with installed arg
+ */
+
+void _tnf_error(TNF *, tnf_errcode_t);
+
+/*
+ * Tag lookup operations
+ */
+
+struct taginfo * _tnf_get_info(TNF *, tnf_ref32_t *);
+struct taginfo * _tnf_record_info(TNF *, tnf_ref32_t *);
+
+tnf_errcode_t _tnf_init_tags(TNF *);
+tnf_errcode_t _tnf_fini_tags(TNF *);
+
+/*
+ * Classify a tag into its props and data kind
+ */
+
+tag_props_t _tnf_get_props(TNF *, tnf_ref32_t *);
+tnf_kind_t _tnf_get_kind(TNF *, tnf_ref32_t *);
+
+caddr_t _tnf_get_member(TNF *, caddr_t, struct taginfo *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBTNF_H */
diff --git a/usr/src/lib/libtnf/machlibtnf.h b/usr/src/lib/libtnf/machlibtnf.h
new file mode 100644
index 0000000000..a10fc2b219
--- /dev/null
+++ b/usr/src/lib/libtnf/machlibtnf.h
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _MACHLIBTNF_H
+#define _MACHLIBTNF_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/isa_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_BIG_ENDIAN) || defined(__sparc)
+
+tnf_uint32_t _tnf_swap32(tnf_uint32_t);
+tnf_uint16_t _tnf_swap16(tnf_uint16_t);
+
+#elif defined(_LITTLE_ENDIAN) || defined(__i386) || defined(__amd64)
+
+#include <sys/byteorder.h>
+
+#define _tnf_swap32(x) ntohl(x)
+#define _tnf_swap16(x) ntohs(x)
+
+#else
+
+#error Unknown endian
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MACHLIBTNF_H */
diff --git a/usr/src/lib/libtnf/reader.c b/usr/src/lib/libtnf/reader.c
new file mode 100644
index 0000000000..c7d3d8fe74
--- /dev/null
+++ b/usr/src/lib/libtnf/reader.c
@@ -0,0 +1,191 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * Initiate a reader session
+ */
+
+tnf_errcode_t
+tnf_reader_begin(caddr_t base, size_t size, TNF **tnfret)
+{
+ tnf_uint32_t magic;
+ int native;
+ TNF *tnf;
+ tnf_ref32_t *fhdr, *bhdr;
+ size_t tmpsz;
+ caddr_t p, genp, bvp;
+ tnf_errcode_t err;
+
+ /*
+ * Check magic number
+ */
+
+ /* LINTED pointer cast may result in improper alignment */
+ if ((magic = *(tnf_uint32_t *)base) == TNF_MAGIC)
+ native = 1; /* same endian */
+ else if (magic == TNF_MAGIC_1)
+ native = 0; /* other endian */
+ else
+ return (TNF_ERR_NOTTNF);
+
+ /*
+ * Allocate TNF struct, initialize members
+ */
+
+ if ((tnf = (TNF*)calloc(1, sizeof (*tnf))) == (TNF*)NULL)
+ return (TNF_ERR_ALLOCFAIL);
+
+ tnf->file_magic = magic;
+ tnf->file_native = native;
+ tnf->file_start = base;
+ tnf->file_size = size;
+ tnf->file_end = base + size;
+
+ /*
+ * Examine file header
+ */
+
+ /* LINTED pointer cast may result in improper alignment */
+ fhdr = (tnf_ref32_t *)(base + sizeof (magic)); /* second word */
+ tnf->file_header = fhdr;
+
+ /* Block size */
+ p = _tnf_get_slot_named(tnf, fhdr, TNF_N_BLOCK_SIZE);
+ /* LINTED pointer cast may result in improper alignment */
+ tnf->block_size = _GET_UINT32(tnf, (tnf_uint32_t *)p);
+
+ /* Directory size */
+ p = _tnf_get_slot_named(tnf, fhdr, TNF_N_DIRECTORY_SIZE);
+ /* LINTED pointer cast may result in improper alignment */
+ tnf->directory_size = _GET_UINT32(tnf, (tnf_uint32_t *)p);
+
+ /* Block count */
+ p = _tnf_get_slot_named(tnf, fhdr, TNF_N_BLOCK_COUNT);
+ /* LINTED pointer cast may result in improper alignment */
+ tnf->block_count = _GET_UINT32(tnf, (tnf_uint32_t *)p);
+ /*
+ * This member tracks data block count, not total block count
+ * (unlike the TNF file header). Discount directory blocks.
+ */
+ tnf->block_count -= tnf->directory_size / tnf->block_size;
+
+ /*
+ * 1196886: Clients may supply file_size information obtained
+ * by fstat() which is incorrect. Check it now and revise
+ * downwards if we have to.
+ */
+ tmpsz = tnf->directory_size + tnf->block_count * tnf->block_size;
+ if (tmpsz != size) {
+ if (tmpsz > size)
+ /* missing data? */
+ return (TNF_ERR_BADTNF);
+ else {
+ tnf->file_size = tmpsz;
+ tnf->file_end = base + tmpsz;
+ }
+ }
+
+ /* Calculate block shift */
+ tmpsz = 1;
+ while (tmpsz != tnf->block_size) {
+ tmpsz <<= 1;
+ tnf->block_shift++;
+ }
+
+ /* Calculate block mask */
+ tnf->block_mask = ~(tnf->block_size - 1);
+
+ /* Generation shift */
+ p = _tnf_get_slot_named(tnf, fhdr, TNF_N_FILE_LOGICAL_SIZE);
+ /* LINTED pointer cast may result in improper alignment */
+ tnf->generation_shift = _GET_UINT32(tnf, (tnf_uint32_t *)p);
+
+ /* Calculate the address mask */
+ /*
+ * Following lint complaint is unwarranted, probably an
+ * uninitialized variable in lint or something ...
+ */
+ /* LINTED constant truncated by assignment */
+ tnf->address_mask = 0xffffffff;
+ tnf->address_mask <<= tnf->generation_shift;
+ tnf->address_mask = ~(tnf->address_mask);
+
+
+ /*
+ * Examine first block header in data area
+ */
+
+ tnf->data_start = tnf->file_start + tnf->directory_size;
+ /* LINTED pointer cast may result in improper alignment */
+ bhdr = (tnf_ref32_t *)tnf->data_start;
+
+ /* Block generation offset */
+ genp = _tnf_get_slot_named(tnf, bhdr, TNF_N_GENERATION);
+ tnf->block_generation_offset = genp - (caddr_t)bhdr;
+
+ /* Block bytes valid offset */
+ bvp = _tnf_get_slot_named(tnf, bhdr, TNF_N_BYTES_VALID);
+ tnf->block_bytes_valid_offset = bvp - (caddr_t)bhdr;
+
+ /*
+ * Bootstrap taginfo system and cache important taginfo
+ */
+
+ if ((err = _tnf_init_tags(tnf)) != TNF_ERR_NONE)
+ return (err);
+
+ tnf->file_header_info = _tnf_get_info(tnf, _tnf_get_tag(tnf, fhdr));
+ tnf->block_header_info = _tnf_get_info(tnf, _tnf_get_tag(tnf, bhdr));
+
+ /*
+ * Return TNF handle and error status
+ */
+
+ *tnfret = tnf;
+ return (TNF_ERR_NONE);
+}
+
+/*
+ * Terminate a reader session
+ */
+
+tnf_errcode_t
+tnf_reader_end(TNF *tnf)
+{
+ tnf_errcode_t err;
+
+ /* Deallocate all taginfo */
+ if ((err = _tnf_fini_tags(tnf)) != TNF_ERR_NONE)
+ return (err);
+
+ /* Deallocate TNF */
+ free(tnf);
+
+ return (TNF_ERR_NONE);
+}
diff --git a/usr/src/lib/libtnf/record.c b/usr/src/lib/libtnf/record.c
new file mode 100644
index 0000000000..b5fabb0287
--- /dev/null
+++ b/usr/src/lib/libtnf/record.c
@@ -0,0 +1,66 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * Check a record datum
+ */
+
+void
+_tnf_check_record(tnf_datum_t datum)
+{
+ CHECK_DATUM(datum);
+
+ /* All records must be tagged */
+ if (!INFO_TAGGED(DATUM_INFO(datum)))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
+}
+
+/*
+ * Retrieve the tag arg, encoded in low 16 bits of tag word
+ */
+
+tnf_datum_t
+tnf_get_tag_arg(tnf_datum_t datum)
+{
+ TNF *tnf;
+ tnf_ref32_t *arg;
+
+ CHECK_RECORD(datum);
+
+ tnf = DATUM_TNF(datum);
+
+ /* Should not give an error if not found */
+ /* LINTED pointer cast may result in improper alignment */
+ arg = _tnf_get_tag_arg(tnf, DATUM_RECORD(datum));
+
+ if (arg == TNF_NULL)
+ return (TNF_DATUM_NULL);
+ else /* repackage the tag arg with its taginfo */
+ return (RECORD_DATUM(tnf, arg));
+}
diff --git a/usr/src/lib/libtnf/ref.c b/usr/src/lib/libtnf/ref.c
new file mode 100644
index 0000000000..07e0ccccfb
--- /dev/null
+++ b/usr/src/lib/libtnf/ref.c
@@ -0,0 +1,232 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * Unoptimized versions, always dereference a cell through _GET_INT32()
+ *
+ */
+
+#define LONG_SIGN_BIT 0x80000000
+
+static tnf_ref32_t *vaddr_to_phys(TNF *, tnf_ref32_t *, tnf_ref32_t);
+
+/*
+ * Return target cell referred to via src_val from src_cell, after
+ * checking that target is valid (block was not reused). Return NULL
+ * otherwise.
+ *
+ * NOTE: We must check if the destination is within the valid_bytes
+ * range of its block, so as to correctly handle tnfxtract'ed files:
+ * the block containing the target cell may have been copied out
+ * before the block containing the source cell.
+ */
+
+static tnf_ref32_t *
+vaddr_to_phys(TNF *tnf, tnf_ref32_t *src_cell, tnf_ref32_t src_val)
+{
+ char *base;
+ unsigned shft, mask;
+ tnf_uint32_t src_gen, dst_gen, exp_gen;
+ tnf_int32_t gen_delta;
+ tnf_ref32_t src_off, exp_off, dst_off, *dst_blk, *dst_cell;
+ tnf_uint32_t bytes_valid;
+
+ base = tnf->file_start;
+ shft = tnf->generation_shift;
+ mask = tnf->address_mask;
+
+ /* Generation of source cell */
+ /* LINTED pointer cast */
+ src_gen = _GET_BLOCK_GENERATION(tnf, _GET_BLOCK(tnf, src_cell));
+ /* Physical file offset of source cell */
+ src_off = (tnf_ref32_t)((char *)src_cell - base);
+ /* Expected (unadjusted) file offset of destination cell */
+ exp_off = src_off + src_val;
+ /* Generation delta */
+ gen_delta = (tnf_int32_t)((unsigned)exp_off >> shft);
+ if ((exp_off & LONG_SIGN_BIT) == LONG_SIGN_BIT) {
+ /* sign bit was a 1 - so restore sign */
+ gen_delta |= ((unsigned)mask << (32 - shft));
+ }
+ /* Expected destination generation */
+ exp_gen = src_gen + gen_delta;
+ /* Physical file offset of destination cell */
+ dst_off = (tnf_ref32_t)((unsigned)exp_off & mask);
+
+ /* Destination cell */
+ /* LINTED pointer cast */
+ dst_cell = (tnf_ref32_t *)(base + dst_off);
+ /* Destination block */
+ /* LINTED pointer cast */
+ dst_blk = _GET_BLOCK(tnf, dst_cell);
+ /* Generation of destination cell */
+ /* LINTED pointer cast */
+ dst_gen = _GET_BLOCK_GENERATION(tnf, dst_blk);
+ /* Bytes valid in destination block */
+ /* LINTED pointer cast */
+ bytes_valid = _GET_BLOCK_BYTES_VALID(tnf, dst_blk);
+
+ if ((src_gen == (tnf_uint32_t)TNF_TAG_GENERATION_NUM) ||
+ (dst_gen == (tnf_uint32_t)TNF_TAG_GENERATION_NUM) ||
+ ((dst_gen == exp_gen) &&
+ ((char *)dst_cell - (char *)dst_blk) < bytes_valid))
+ return (dst_cell);
+
+ return ((tnf_ref32_t *)NULL);
+}
+
+/*
+ * Return the target referent of a cell, chasing forwarding references.
+ * Return TNF_NULL if cell is a TNF_NULL forwarding reference.
+ */
+
+tnf_ref32_t *
+_tnf_get_ref32(TNF *tnf, tnf_ref32_t *cell)
+{
+ tnf_ref32_t ref32, reftemp;
+
+ ref32 = _GET_INT32(tnf, cell);
+
+ if (TNF_REF32_IS_NULL(ref32))
+ return (TNF_NULL);
+
+ if (TNF_REF32_IS_RSVD(ref32)) {
+ _tnf_error(tnf, TNF_ERR_BADREFTYPE);
+ return (TNF_NULL);
+ }
+
+ if (TNF_REF32_IS_PAIR(ref32)) {
+ /* We chase the high (tag) half */
+ tnf_ref16_t tag16;
+
+ tag16 = TNF_REF32_TAG16(ref32);
+
+ if (TNF_TAG16_IS_ABS(tag16)) {
+ cell = (tnf_ref32_t *)
+ ((char *)tnf->file_start
+/* LINTED pointer cast may result in improper alignment */
+ + TNF_TAG16_ABS16(tag16));
+ ref32 = _GET_INT32(tnf, cell);
+
+ } else if (TNF_TAG16_IS_REL(tag16)) {
+ cell = vaddr_to_phys(tnf, cell,
+ (tnf_ref32_t) TNF_TAG16_REF16(tag16));
+ if (cell == TNF_NULL)
+ return (TNF_NULL);
+ ref32 = _GET_INT32(tnf, cell);
+
+ } else {
+ _tnf_error(tnf, TNF_ERR_BADREFTYPE);
+ return (TNF_NULL);
+ }
+
+ } else if (TNF_REF32_IS_PERMANENT(ref32)) {
+ /* permanent space pointer */
+ reftemp = TNF_REF32_VALUE(ref32);
+ reftemp = TNF_REF32_SIGN_EXTEND(reftemp);
+ /* LINTED pointer cast may result in improper alignment */
+ cell = (tnf_ref32_t *) ((char *)tnf->file_start + reftemp);
+ ref32 = _GET_INT32(tnf, cell);
+
+ } else { /* full/tag reclaimable space reference */
+ cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32));
+ if (cell == TNF_NULL)
+ return (TNF_NULL);
+ ref32 = _GET_INT32(tnf, cell);
+ }
+
+ /* chase intermediate forwarding references */
+ while (ref32 && TNF_REF32_IS_FWD(ref32)) {
+ if (TNF_REF32_IS_PERMANENT(ref32)) {
+ reftemp = TNF_REF32_VALUE(ref32);
+ reftemp = TNF_REF32_SIGN_EXTEND(reftemp);
+ cell = (tnf_ref32_t *) ((char *)tnf->file_start +
+ /* LINTED pointer cast may result in improper alignment */
+ reftemp);
+
+ } else {
+ cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32));
+ if (cell == TNF_NULL)
+ return (TNF_NULL);
+ }
+ ref32 = _GET_INT32(tnf, cell);
+ }
+
+ return (cell);
+}
+
+/*
+ * Return the target referent of ref16 contained in cell.
+ * Return TNF_NULL if cell doesn't have a ref16.
+ */
+
+tnf_ref32_t *
+_tnf_get_ref16(TNF *tnf, tnf_ref32_t *cell)
+{
+ tnf_ref32_t ref32, reftemp;
+
+ ref32 = _GET_INT32(tnf, cell);
+
+ if (TNF_REF32_IS_PAIR(ref32)) {
+ tnf_ref16_t ref16;
+
+ ref16 = TNF_REF32_REF16(ref32);
+
+ if (TNF_REF16_VALUE(ref16) == TNF_NULL)
+ /* No ref16 was stored */
+ return (TNF_NULL);
+ else {
+ cell = vaddr_to_phys(tnf, cell,
+ (tnf_ref32_t) TNF_REF16_VALUE(ref16));
+ if (cell == TNF_NULL)
+ return (TNF_NULL);
+ ref32 = _GET_INT32(tnf, cell);
+ }
+ } else /* not a pair pointer */
+ return (TNF_NULL);
+
+ /* chase intermediate forwarding references */
+ while (ref32 && TNF_REF32_IS_FWD(ref32)) {
+ if (TNF_REF32_IS_PERMANENT(ref32)) {
+ reftemp = TNF_REF32_VALUE(ref32);
+ reftemp = TNF_REF32_SIGN_EXTEND(reftemp);
+ cell = (tnf_ref32_t *) ((char *)tnf->file_start +
+ /* LINTED pointer cast may result in improper alignment */
+ reftemp);
+
+ } else {
+ cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32));
+ if (cell == TNF_NULL)
+ return (TNF_NULL);
+ }
+ ref32 = _GET_INT32(tnf, cell);
+ }
+
+ return (cell);
+}
diff --git a/usr/src/lib/libtnf/scalar.c b/usr/src/lib/libtnf/scalar.c
new file mode 100644
index 0000000000..8d37f690a1
--- /dev/null
+++ b/usr/src/lib/libtnf/scalar.c
@@ -0,0 +1,170 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ *
+ */
+
+#define CHECK_SCALAR(datum) check_scalar(datum)
+
+#define DATUM_NATIVE(x) DATUM_TNF(datum)->file_native
+
+/*
+ *
+ */
+
+static void check_scalar(tnf_datum_t);
+
+static tnf_uint64_t get_uint64(TNF *tnf, caddr_t val);
+
+/*
+ *
+ */
+
+static void
+check_scalar(tnf_datum_t datum)
+{
+ CHECK_DATUM(datum);
+ if (!INFO_SCALAR(DATUM_INFO(datum)))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
+ /* XXX Need to check for exact scalar type match as well */
+}
+
+/*
+ * Exported scalar operations
+ */
+
+/* No swapping required: */
+
+char
+tnf_get_char(tnf_datum_t datum)
+{
+ CHECK_SCALAR(datum);
+ return (*(char *)DATUM_VAL(datum));
+}
+
+tnf_int8_t
+tnf_get_int8(tnf_datum_t datum)
+{
+ CHECK_SCALAR(datum);
+ return (*(tnf_int8_t *)DATUM_VAL(datum));
+}
+
+tnf_int16_t
+tnf_get_int16(tnf_datum_t datum)
+{
+ tnf_int16_t val;
+
+ CHECK_SCALAR(datum);
+ /* LINTED pointer cast may result in improper alignment */
+ val = *(tnf_int16_t *)DATUM_VAL(datum);
+ return (DATUM_NATIVE(datum) ? val : _tnf_swap16(val));
+}
+
+/* 32-bit integers: */
+
+tnf_int32_t
+tnf_get_int32(tnf_datum_t datum)
+{
+ CHECK_SCALAR(datum);
+ /* LINTED pointer cast may result in improper alignment */
+ return (_GET_INT32(DATUM_TNF(datum), DATUM_VAL(datum)));
+}
+
+/* 64-bit integers: */
+
+static tnf_uint64_t
+get_uint64(TNF *tnf, caddr_t val)
+{
+ tnf_uint32_t hi32, lo32; /* XXX both assumed unsigned */
+
+ /* XXX Can't rely on address alignment */
+ /* LINTED pointer cast may result in improper alignment */
+ hi32 = *(tnf_uint32_t *)val;
+ /* LINTED pointer cast may result in improper alignment */
+ lo32 = *(tnf_uint32_t *)(val + sizeof (tnf_uint32_t));
+
+#ifdef _LONG_LONG_HTOL
+ /* eg. sparc */
+ if (tnf->file_native)
+ return ((((tnf_uint64_t)hi32) << 32)
+ + (tnf_uint64_t)lo32);
+ else
+ /* XXX Assume words are swapped as well: */
+ return ((((tnf_uint64_t)_tnf_swap32(lo32)) << 32)
+ + (tnf_uint64_t)_tnf_swap32(hi32));
+#else
+ /* eg. i386 */
+ if (tnf->file_native)
+ return ((((tnf_uint64_t)lo32) << 32)
+ + (tnf_uint64_t)hi32);
+ else
+ /* XXX Assume words are swapped as well: */
+ return ((((tnf_uint64_t)_tnf_swap32(hi32)) << 32)
+ + (tnf_uint64_t)_tnf_swap32(lo32));
+#endif
+}
+
+tnf_int64_t
+tnf_get_int64(tnf_datum_t datum)
+{
+ CHECK_SCALAR(datum);
+ return (get_uint64(DATUM_TNF(datum), DATUM_VAL(datum)));
+}
+
+/* floats: */
+
+tnf_float32_t
+tnf_get_float32(tnf_datum_t datum)
+{
+ union {
+ tnf_uint32_t i32;
+ tnf_float32_t f32;
+ } u;
+
+ CHECK_SCALAR(datum);
+
+ /* LINTED pointer cast may result in improper alignment */
+ u.i32 = _GET_UINT32(DATUM_TNF(datum), DATUM_VAL(datum)); /* XXX */
+ return (u.f32);
+}
+
+tnf_float64_t
+tnf_get_float64(tnf_datum_t datum)
+{
+ union {
+ tnf_uint64_t i64;
+ tnf_float64_t f64;
+ } u;
+
+ CHECK_SCALAR(datum);
+
+ u.i64 = get_uint64(DATUM_TNF(datum), DATUM_VAL(datum)); /* XXX */
+ return (u.f64);
+}
diff --git a/usr/src/lib/libtnf/sparcdep.c b/usr/src/lib/libtnf/sparcdep.c
new file mode 100644
index 0000000000..04d006ad93
--- /dev/null
+++ b/usr/src/lib/libtnf/sparcdep.c
@@ -0,0 +1,40 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+tnf_uint32_t
+_tnf_swap32(tnf_uint32_t x)
+{
+ return (((x<<24) | (((x>>8)<<24)>>8) | (((x<<8)>>24)<<8) | (x>>24)));
+}
+
+tnf_uint16_t
+_tnf_swap16(tnf_uint16_t x)
+{
+ return (((x<<8) | (x>>8)));
+}
diff --git a/usr/src/lib/libtnf/spec/Makefile b/usr/src/lib/libtnf/spec/Makefile
new file mode 100644
index 0000000000..789cc7cbfa
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/Makefile
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libtnf/spec/Makefile
+
+#
+# no sparcv9 build of libresolv
+# if it is desirable to build one then uncomment the line below and delete
+# the rest of the lines.
+#
+#include $(SRC)/lib/Makefile.spec.arch
+
+i386_ARCHITECTURES = i386
+sparc_ARCHITECTURES = sparc
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all install clean clobber lint: $($(MACH)_ARCHITECTURES)
+
+# spec files do not have msgs or catalogs
+_msg catalog:
+
+$($(MACH)_ARCHITECTURES): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/libtnf/spec/Makefile.targ b/usr/src/lib/libtnf/spec/Makefile.targ
new file mode 100644
index 0000000000..b99ce2250a
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/Makefile.targ
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libtnf/spec/Makefile.targ
+
+LIBRARY = libtnf.a
+VERS = .1
+
+OBJECTS = tnf.o
+
+SPECCPP = -I.. -I../..
diff --git a/usr/src/lib/libtnf/spec/amd64/Makefile b/usr/src/lib/libtnf/spec/amd64/Makefile
new file mode 100644
index 0000000000..d334868181
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/amd64/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS)
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libtnf/spec/i386/Makefile b/usr/src/lib/libtnf/spec/i386/Makefile
new file mode 100644
index 0000000000..569932e5ab
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/i386/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libtnf/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#i386_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libtnf/spec/sparc/Makefile b/usr/src/lib/libtnf/spec/sparc/Makefile
new file mode 100644
index 0000000000..9f90d1bd91
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/sparc/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libtnf/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libtnf/spec/sparcv9/Makefile b/usr/src/lib/libtnf/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..cbf3eb7fa6
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/sparcv9/Makefile
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libtnf/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libtnf/spec/tnf.spec b/usr/src/lib/libtnf/spec/tnf.spec
new file mode 100644
index 0000000000..9ee8baa0f1
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/tnf.spec
@@ -0,0 +1,316 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtnf/spec/tnf.spec
+
+function tnf_default_error_handler
+include <libtnf.h>
+declaration void tnf_default_error_handler(void *arg, TNF *tnf, \
+ tnf_errcode_t err)
+version SUNWprivate_1.1
+end
+
+function tnf_error_message
+include <libtnf.h>
+declaration char * tnf_error_message(tnf_errcode_t err)
+version SUNWprivate_1.1
+end
+
+function tnf_get_block_absolute
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_block_absolute(TNF *tnf, unsigned index)
+version SUNWprivate_1.1
+end
+
+function tnf_get_block_count
+include <libtnf.h>
+declaration unsigned tnf_get_block_count(TNF *tnf)
+version SUNWprivate_1.1
+end
+
+function tnf_get_block_header
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_block_header(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_block_relative
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_block_relative(tnf_datum_t datum, \
+ int adjust)
+version SUNWprivate_1.1
+end
+
+function tnf_get_char
+include <libtnf.h>
+declaration char tnf_get_char(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_chars
+include <libtnf.h>
+declaration char * tnf_get_chars(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_element
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_element(tnf_datum_t datum, unsigned)
+version SUNWprivate_1.1
+end
+
+function tnf_get_element_count
+include <libtnf.h>
+declaration unsigned tnf_get_element_count(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_element_type
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_element_type(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_elements
+include <libtnf.h>
+declaration caddr_t tnf_get_elements(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_file_header
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_file_header(TNF *tnf)
+version SUNWprivate_1.1
+end
+
+function tnf_get_float32
+include <libtnf.h>
+declaration tnf_float32_t tnf_get_float32(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_float64
+include <libtnf.h>
+declaration tnf_float64_t tnf_get_float64(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_int16
+include <libtnf.h>
+declaration tnf_int16_t tnf_get_int16(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_int32
+include <libtnf.h>
+declaration tnf_int32_t tnf_get_int32(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_int64
+include <libtnf.h>
+declaration tnf_int64_t tnf_get_int64(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_int8
+include <libtnf.h>
+declaration tnf_int8_t tnf_get_int8(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_kind
+include <libtnf.h>
+declaration tnf_kind_t tnf_get_kind(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_next_record
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_next_record(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_raw
+include <libtnf.h>
+declaration caddr_t tnf_get_raw(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_size
+include <libtnf.h>
+declaration size_t tnf_get_size(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_slot_count
+include <libtnf.h>
+declaration unsigned tnf_get_slot_count(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_slot_index
+include <libtnf.h>
+declaration unsigned tnf_get_slot_index(tnf_datum_t datum, char *name)
+version SUNWprivate_1.1
+end
+
+function tnf_get_slot_indexed
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_slot_indexed(tnf_datum_t datum, \
+ unsigned index)
+version SUNWprivate_1.1
+end
+
+function tnf_get_slot_name
+include <libtnf.h>
+declaration char * tnf_get_slot_name(tnf_datum_t datum, unsigned index)
+version SUNWprivate_1.1
+end
+
+function tnf_get_slot_named
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_slot_named(tnf_datum_t datum, char *name)
+version SUNWprivate_1.1
+end
+
+function tnf_get_tag_arg
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_tag_arg(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_type
+include <libtnf.h>
+declaration tnf_datum_t tnf_get_type(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_get_type_name
+include <libtnf.h>
+declaration char * tnf_get_type_name(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_array
+include <libtnf.h>
+declaration int tnf_is_array(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_block_header
+include <libtnf.h>
+declaration int tnf_is_block_header(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_inline
+include <libtnf.h>
+declaration int tnf_is_inline(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_record
+include <libtnf.h>
+declaration int tnf_is_record(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_scalar
+include <libtnf.h>
+declaration int tnf_is_scalar(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_string
+include <libtnf.h>
+declaration int tnf_is_string(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_struct
+include <libtnf.h>
+declaration int tnf_is_struct(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_is_type
+include <libtnf.h>
+declaration int tnf_is_type(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_reader_begin
+include <libtnf.h>
+declaration tnf_errcode_t tnf_reader_begin(caddr_t base, size_t size, \
+ TNF **tnfret)
+version SUNWprivate_1.1
+end
+
+function tnf_reader_end
+include <libtnf.h>
+declaration tnf_errcode_t tnf_reader_end(TNF *tnf)
+version SUNWprivate_1.1
+end
+
+function tnf_set_error_handler
+include <libtnf.h>
+#declaration void tnf_set_error_handler(tnf_error_handler_t *handler, void *arg)
+# Using alternate binary equivalent for delaration
+declaration void tnf_set_error_handler(void (*handler)(void *, TNF *, tnf_errcode_t), void *arg)
+version SUNWprivate_1.1
+end
+
+function tnf_type_get_base
+include <libtnf.h>
+declaration tnf_datum_t tnf_type_get_base(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_type_get_kind
+include <libtnf.h>
+declaration tnf_kind_t tnf_type_get_kind(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_type_get_name
+include <libtnf.h>
+declaration char * tnf_type_get_name(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
+function tnf_type_get_property
+include <libtnf.h>
+declaration tnf_datum_t tnf_type_get_property(tnf_datum_t datum, char *name)
+version SUNWprivate_1.1
+end
+
+function tnf_type_get_size
+include <libtnf.h>
+declaration size_t tnf_type_get_size(tnf_datum_t datum)
+version SUNWprivate_1.1
+end
+
diff --git a/usr/src/lib/libtnf/spec/versions b/usr/src/lib/libtnf/spec/versions
new file mode 100644
index 0000000000..a542a0f7fc
--- /dev/null
+++ b/usr/src/lib/libtnf/spec/versions
@@ -0,0 +1,39 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNWprivate_1.1;
+}
diff --git a/usr/src/lib/libtnf/struct.c b/usr/src/lib/libtnf/struct.c
new file mode 100644
index 0000000000..c7aa1e6a95
--- /dev/null
+++ b/usr/src/lib/libtnf/struct.c
@@ -0,0 +1,220 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ *
+ */
+
+static struct slotinfo *get_slotinfo(tnf_datum_t);
+static struct slot * get_slot_named(struct slotinfo *, char *);
+static struct slot * get_slot_indexed(struct slotinfo *, unsigned);
+static tnf_datum_t get_slot(tnf_datum_t, struct slot *);
+
+/*
+ *
+ */
+
+void
+_tnf_check_slots(tnf_datum_t datum)
+{
+ struct taginfo *info;
+
+ CHECK_DATUM(datum);
+
+ info = DATUM_INFO(datum);
+
+ /* Must be an aggregate */
+ if (!(INFO_STRUCT(info) || INFO_ARRAY(info)))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
+}
+
+/*
+ * Helpers
+ */
+
+static struct slotinfo *
+get_slotinfo(tnf_datum_t datum)
+{
+ struct taginfo *info, *base_info;
+
+ info = DATUM_INFO(datum);
+ base_info = INFO_DERIVED(info)? info->base: info;
+
+ /* XXX base must not be a scalar tag */
+ if (INFO_SCALAR(base_info))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_BADTNF);
+
+ return (base_info->slotinfo);
+}
+
+static struct slot *
+get_slot_indexed(struct slotinfo *slotinfo, unsigned index)
+{
+ unsigned count;
+
+ count = slotinfo->slot_count;
+ if (index >= count)
+ return (NULL);
+ else
+ return (&slotinfo->slots[index]);
+}
+
+static struct slot *
+get_slot_named(struct slotinfo *slotinfo, char *name)
+{
+ unsigned count, i;
+
+ count = slotinfo->slot_count;
+
+ for (i = 0; i < count; i++)
+ if (strcmp(name, slotinfo->slots[i].slot_name) == 0)
+ return (&slotinfo->slots[i]);
+
+ return (NULL);
+}
+
+static tnf_datum_t
+get_slot(tnf_datum_t datum, struct slot *slot)
+{
+ if (slot == NULL) {
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */
+ return (TNF_DATUM_NULL);
+
+ } else if (INFO_TAGGED(slot->slot_type)) {
+ TNF *tnf;
+ tnf_ref32_t *rec;
+
+ tnf = DATUM_TNF(datum);
+ /* LINTED pointer cast may result in improper alignment */
+ rec = _GET_REF32(tnf, (tnf_ref32_t *)
+ (DATUM_VAL(datum) + slot->slot_offset));
+ /* NULL slots are allowed */
+ return ((rec == TNF_NULL)? TNF_DATUM_NULL :
+ RECORD_DATUM(tnf, rec));
+
+ } else /* inline */
+ return DATUM(slot->slot_type,
+ DATUM_VAL(datum) + slot->slot_offset);
+}
+
+/*
+ *
+ */
+
+unsigned
+tnf_get_slot_count(tnf_datum_t datum)
+{
+ struct slotinfo *slotinfo;
+
+ CHECK_SLOTS(datum);
+
+ slotinfo = get_slotinfo(datum);
+ return (slotinfo->slot_count);
+}
+
+/*
+ *
+ */
+
+unsigned
+tnf_get_slot_index(tnf_datum_t datum, char *name)
+{
+ struct slotinfo *slotinfo;
+ struct slot *slot;
+
+ CHECK_SLOTS(datum);
+
+ slotinfo = get_slotinfo(datum);
+ slot = get_slot_named(slotinfo, name);
+
+ if (slot == NULL) {
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */
+ return (((unsigned)-1));
+ } else
+ return (((char *)slot - (char *)&slotinfo->slots[0])
+ / sizeof (struct slot));
+}
+
+/*
+ *
+ */
+
+char *
+tnf_get_slot_name(tnf_datum_t datum, unsigned index)
+{
+ struct slotinfo *slotinfo;
+ struct slot *slot;
+
+ CHECK_SLOTS(datum);
+
+ slotinfo = get_slotinfo(datum);
+ slot = get_slot_indexed(slotinfo, index);
+
+ if (slot == NULL) {
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */
+ return ((char *)NULL);
+ } else
+ return (slot->slot_name);
+}
+
+/*
+ *
+ */
+
+tnf_datum_t
+tnf_get_slot_named(tnf_datum_t datum, char *name)
+{
+ struct slotinfo *slotinfo;
+ struct slot *slot;
+
+ CHECK_SLOTS(datum);
+
+ slotinfo = get_slotinfo(datum);
+ slot = get_slot_named(slotinfo, name);
+
+ return (get_slot(datum, slot));
+}
+
+/*
+ *
+ */
+
+tnf_datum_t
+tnf_get_slot_indexed(tnf_datum_t datum, unsigned index)
+{
+ struct slotinfo *slotinfo;
+ struct slot *slot;
+
+ CHECK_SLOTS(datum);
+
+ slotinfo = get_slotinfo(datum);
+ slot = get_slot_indexed(slotinfo, index);
+
+ return (get_slot(datum, slot));
+}
diff --git a/usr/src/lib/libtnf/tnf.h b/usr/src/lib/libtnf/tnf.h
new file mode 100644
index 0000000000..3560bbc35a
--- /dev/null
+++ b/usr/src/lib/libtnf/tnf.h
@@ -0,0 +1,206 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#ifndef _TNF_TNF_H
+#define _TNF_TNF_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <tnf/com.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Opaque TNF handle
+ */
+
+typedef struct TNF TNF;
+
+/*
+ * Opaque data handle
+ */
+
+typedef unsigned long long tnf_datum_t;
+
+#define TNF_DATUM_NULL ((tnf_datum_t)0)
+
+/*
+ * Reader data classification
+ */
+
+typedef enum {
+ TNF_K_UNKNOWN, /* unknown or error */
+ TNF_K_SCALAR, /* unclassified scalar */
+ TNF_K_CHAR, /* char */
+ TNF_K_INT8, /* int8 */
+ TNF_K_INT16, /* int16 */
+ TNF_K_INT32, /* int32 */
+ TNF_K_UINT8, /* uint8 */
+ TNF_K_UINT16, /* uint16 */
+ TNF_K_UINT32, /* uint32 */
+ TNF_K_INT64, /* int64 */
+ TNF_K_UINT64, /* uint64 */
+ TNF_K_FLOAT32, /* float32 */
+ TNF_K_FLOAT64, /* float64 */
+ TNF_K_ARRAY, /* array */
+ TNF_K_STRING, /* string */
+ TNF_K_STRUCT, /* struct */
+ TNF_K_TYPE /* type */
+} tnf_kind_t;
+
+/*
+ * Error codes
+ */
+
+typedef enum {
+ TNF_ERR_NONE = 0,
+
+ /* 1 through 1023 reserved for errno values */
+#define TNF_ERRNO_MAX 1023
+
+ TNF_ERR_NOTTNF = 1024, /* not TNF file */
+ TNF_ERR_BADDATUM = 1025, /* bad or NULL data handle */
+ TNF_ERR_TYPEMISMATCH = 1026, /* type mismatch */
+ TNF_ERR_BADINDEX = 1027, /* array index out of bounds */
+ TNF_ERR_BADSLOT = 1028, /* slot missing */
+ TNF_ERR_BADREFTYPE = 1029, /* invalid reference type */
+ TNF_ERR_ALLOCFAIL = 1030, /* memory allocation failure */
+ TNF_ERR_BADTNF = 1031, /* bad TNF file */
+ TNF_ERR_INTERNAL = 1032 /* internal error */
+} tnf_errcode_t;
+
+typedef void tnf_error_handler_t(void *, TNF *, tnf_errcode_t);
+
+/*
+ * TNF file interface
+ */
+
+tnf_errcode_t tnf_reader_begin(caddr_t, size_t, TNF **);
+tnf_errcode_t tnf_reader_end(TNF *);
+
+/*
+ * Error interface
+ */
+
+void tnf_set_error_handler(tnf_error_handler_t *, void *);
+char * tnf_error_message(tnf_errcode_t);
+
+tnf_error_handler_t tnf_default_error_handler;
+
+/*
+ * Data block access
+ */
+
+unsigned tnf_get_block_count(TNF *);
+tnf_datum_t tnf_get_block_absolute(TNF *, unsigned);
+tnf_datum_t tnf_get_block_relative(tnf_datum_t, int);
+int tnf_is_block_header(tnf_datum_t);
+
+/*
+ * Record access
+ */
+
+tnf_datum_t tnf_get_next_record(tnf_datum_t);
+tnf_datum_t tnf_get_block_header(tnf_datum_t);
+tnf_datum_t tnf_get_file_header(TNF *);
+
+/*
+ * Data classification predicates
+ */
+
+int tnf_is_inline(tnf_datum_t);
+int tnf_is_scalar(tnf_datum_t);
+int tnf_is_record(tnf_datum_t);
+int tnf_is_array(tnf_datum_t);
+int tnf_is_string(tnf_datum_t);
+int tnf_is_struct(tnf_datum_t);
+int tnf_is_type(tnf_datum_t);
+
+/*
+ * Data operations
+ */
+
+tnf_kind_t tnf_get_kind(tnf_datum_t);
+size_t tnf_get_size(tnf_datum_t);
+tnf_datum_t tnf_get_type(tnf_datum_t);
+char * tnf_get_type_name(tnf_datum_t);
+caddr_t tnf_get_raw(tnf_datum_t);
+
+/*
+ * Record operations
+ */
+
+tnf_datum_t tnf_get_tag_arg(tnf_datum_t);
+
+/*
+ * Array operations
+ */
+
+unsigned tnf_get_element_count(tnf_datum_t);
+tnf_datum_t tnf_get_element(tnf_datum_t, unsigned);
+tnf_datum_t tnf_get_element_type(tnf_datum_t);
+caddr_t tnf_get_elements(tnf_datum_t);
+char * tnf_get_chars(tnf_datum_t);
+
+/*
+ * Struct operations
+ */
+
+unsigned tnf_get_slot_count(tnf_datum_t);
+char * tnf_get_slot_name(tnf_datum_t, unsigned);
+unsigned tnf_get_slot_index(tnf_datum_t, char *);
+tnf_datum_t tnf_get_slot_named(tnf_datum_t, char *);
+tnf_datum_t tnf_get_slot_indexed(tnf_datum_t, unsigned);
+
+/*
+ * Scalar data conversions
+ */
+
+char tnf_get_char(tnf_datum_t);
+tnf_int8_t tnf_get_int8(tnf_datum_t);
+tnf_int16_t tnf_get_int16(tnf_datum_t);
+tnf_int32_t tnf_get_int32(tnf_datum_t);
+tnf_int64_t tnf_get_int64(tnf_datum_t);
+tnf_float32_t tnf_get_float32(tnf_datum_t);
+tnf_float64_t tnf_get_float64(tnf_datum_t);
+
+/*
+ * Type (tag) record operations
+ */
+
+tnf_kind_t tnf_type_get_kind(tnf_datum_t);
+char * tnf_type_get_name(tnf_datum_t);
+size_t tnf_type_get_size(tnf_datum_t);
+tnf_datum_t tnf_type_get_property(tnf_datum_t, char *);
+tnf_datum_t tnf_type_get_base(tnf_datum_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TNF_TNF_H */
diff --git a/usr/src/lib/libtnf/type.c b/usr/src/lib/libtnf/type.c
new file mode 100644
index 0000000000..bd18e26559
--- /dev/null
+++ b/usr/src/lib/libtnf/type.c
@@ -0,0 +1,137 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ * All types are struct records
+ */
+
+void
+_tnf_check_type(tnf_datum_t datum)
+{
+ CHECK_RECORD(datum);
+ CHECK_SLOTS(datum);
+
+ if (!INFO_TYPE(DATUM_INFO(datum)))
+ _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
+}
+
+/*
+ * Get data kind of a type record
+ */
+
+tnf_kind_t
+tnf_type_get_kind(tnf_datum_t datum)
+{
+ struct taginfo *info;
+
+ CHECK_TYPE(datum);
+
+ /* Note: DATUM_RECORD(), not DATUM_TAG() */
+ /* LINTED pointer cast may result in improper alignment */
+ info = _tnf_get_info(DATUM_TNF(datum), DATUM_RECORD(datum));
+ return (info->kind);
+}
+
+/*
+ * Retrieve type name for datum type record
+ */
+
+char *
+tnf_type_get_name(tnf_datum_t datum)
+{
+ CHECK_TYPE(datum);
+ /* XXX Dispatch to ABI routine; faster than taginfo lookup? */
+ /* LINTED pointer cast may result in improper alignment */
+ return (_tnf_get_name(DATUM_TNF(datum), DATUM_RECORD(datum)));
+}
+
+/*
+ * Fetch size member of info for datum type record
+ */
+
+size_t
+tnf_type_get_size(tnf_datum_t datum)
+{
+ struct taginfo *info;
+
+ CHECK_TYPE(datum);
+
+ /* Note: DATUM_RECORD(), not DATUM_TAG() */
+ /* LINTED pointer cast may result in improper alignment */
+ info = _tnf_get_info(DATUM_TNF(datum), DATUM_RECORD(datum));
+
+ if (INFO_ARRAY(info))
+ /* XXX All arrays are self-sized */
+ return ((size_t)-1);
+ else
+ return (info->size);
+}
+
+/*
+ * Get the base type of a type
+ */
+
+tnf_datum_t
+tnf_type_get_base(tnf_datum_t datum)
+{
+ struct taginfo *info;
+
+ CHECK_TYPE(datum);
+
+ /* Note: DATUM_RECORD(), not DATUM_TAG() */
+ /* LINTED pointer cast may result in improper alignment */
+ info = _tnf_get_info(DATUM_TNF(datum), DATUM_RECORD(datum));
+
+ if (INFO_DERIVED(info))
+ return (DATUM(info->base->meta, (caddr_t)info->base->tag));
+ else
+ return (datum);
+}
+
+/*
+ * If type record has named property, return a datum for it
+ */
+
+tnf_datum_t
+tnf_type_get_property(tnf_datum_t datum, char *name)
+{
+ tnf_ref32_t *property;
+
+ CHECK_TYPE(datum);
+
+ /* Note: DATUM_RECORD(), not DATUM_TAG() */
+ property = _tnf_get_property(DATUM_TNF(datum),
+ /* LINTED pointer cast may result in improper alignment */
+ DATUM_RECORD(datum), name);
+
+ if (property == TNF_NULL)
+ return (TNF_DATUM_NULL);
+ else
+ return (RECORD_DATUM(DATUM_TNF(datum), property));
+}
diff --git a/usr/src/lib/libtnf/util.c b/usr/src/lib/libtnf/util.c
new file mode 100644
index 0000000000..f81b8aa19c
--- /dev/null
+++ b/usr/src/lib/libtnf/util.c
@@ -0,0 +1,129 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1994, by Sun Microsytems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "libtnf.h"
+
+/*
+ *
+ */
+
+static struct ntop {
+ char *name;
+ tag_props_t prop;
+} ntop[] = {
+{ TNF_N_INLINE, TAG_PROP_INLINE },
+{ TNF_N_TAGGED, TAG_PROP_TAGGED },
+{ TNF_N_SCALAR, TAG_PROP_SCALAR },
+{ TNF_N_DERIVED, TAG_PROP_DERIVED },
+{ TNF_N_ARRAY, TAG_PROP_ARRAY },
+{ TNF_N_STRING, TAG_PROP_STRING },
+{ TNF_N_STRUCT, TAG_PROP_STRUCT },
+{ TNF_N_TYPE, TAG_PROP_TYPE },
+{ NULL, 0}
+};
+
+static struct ntok {
+ char *name;
+ tnf_kind_t kind;
+} scalar_ntok[] = {
+{ TNF_N_CHAR, TNF_K_CHAR },
+{ TNF_N_INT8, TNF_K_INT8 },
+{ TNF_N_INT16, TNF_K_INT16 },
+{ TNF_N_INT32, TNF_K_INT32 },
+{ TNF_N_UINT8, TNF_K_UINT8 },
+{ TNF_N_UINT16, TNF_K_UINT16 },
+{ TNF_N_UINT32, TNF_K_UINT32 },
+{ TNF_N_INT64, TNF_K_INT64 },
+{ TNF_N_UINT64, TNF_K_UINT64 },
+{ TNF_N_FLOAT32, TNF_K_FLOAT32 },
+{ TNF_N_FLOAT64, TNF_K_FLOAT64 },
+{ NULL, 0 }
+};
+
+/*
+ * Compute tag props
+ */
+
+tag_props_t
+_tnf_get_props(TNF *tnf, tnf_ref32_t *tag)
+{
+ tag_props_t props;
+ struct ntop *p;
+
+ props = 0;
+
+ p = ntop;
+ /* No need to get base tag for inherited properties */
+ while (p->name) {
+ if (HAS_PROPERTY(tnf, tag, p->name))
+ props |= p->prop;
+ p++;
+ }
+
+ return (props);
+}
+
+/*
+ * Data kind depends on implementation properties of base tag
+ */
+
+tnf_kind_t
+_tnf_get_kind(TNF *tnf, tnf_ref32_t *tag)
+{
+ tnf_ref32_t *base_tag;
+ char *base_name;
+
+ base_tag = _tnf_get_base_tag(tnf, tag);
+ base_name = _tnf_get_name(tnf, base_tag);
+
+ if (HAS_PROPERTY(tnf, base_tag, TNF_N_SCALAR)) {
+ struct ntok *p;
+
+ p = scalar_ntok;
+ while (p->name) {
+ if (strcmp(p->name, base_name) == 0)
+ return (p->kind);
+ p++;
+ }
+ return (TNF_K_SCALAR);
+
+ } else if (HAS_PROPERTY(tnf, base_tag, TNF_N_ARRAY)) {
+ if (strcmp(base_name, TNF_N_STRING) == 0)
+ return (TNF_K_STRING);
+ else
+ return (TNF_K_ARRAY);
+
+ } else if (HAS_PROPERTY(tnf, base_tag, TNF_N_TYPE)) {
+ return (TNF_K_TYPE);
+
+ } else if (HAS_PROPERTY(tnf, base_tag, TNF_N_STRUCT)) {
+ return (TNF_K_STRUCT);
+
+ } else { /* abstract */
+ return (TNF_K_UNKNOWN);
+ }
+}