1178525Sjb/*
2178525Sjb * CDDL HEADER START
3178525Sjb *
4178525Sjb * The contents of this file are subject to the terms of the
5178525Sjb * Common Development and Distribution License, Version 1.0 only
6178525Sjb * (the "License").  You may not use this file except in compliance
7178525Sjb * with the License.
8178525Sjb *
9178525Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10178525Sjb * or http://www.opensolaris.org/os/licensing.
11178525Sjb * See the License for the specific language governing permissions
12178525Sjb * and limitations under the License.
13178525Sjb *
14178525Sjb * When distributing Covered Code, include this CDDL HEADER in each
15178525Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16178525Sjb * If applicable, add the following below this CDDL HEADER, with the
17178525Sjb * fields enclosed by brackets "[]" replaced with your own identifying
18178525Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
19178525Sjb *
20178525Sjb * CDDL HEADER END
21178525Sjb */
22178525Sjb/*
23178525Sjb * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24178525Sjb * Use is subject to license terms.
25178525Sjb */
26178525Sjb
27178525Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
28178525Sjb
29178525Sjb#include <ctf_impl.h>
30178525Sjb
31178525Sjb/*
32178525Sjb * Simple doubly-linked list append routine.  This implementation assumes that
33178525Sjb * each list element contains an embedded ctf_list_t as the first member.
34178525Sjb * An additional ctf_list_t is used to store the head (l_next) and tail
35178525Sjb * (l_prev) pointers.  The current head and tail list elements have their
36178525Sjb * previous and next pointers set to NULL, respectively.
37178525Sjb */
38178525Sjbvoid
39178525Sjbctf_list_append(ctf_list_t *lp, void *new)
40178525Sjb{
41178525Sjb	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
42178525Sjb	ctf_list_t *q = new;		/* q = new list element */
43178525Sjb
44178525Sjb	lp->l_prev = q;
45178525Sjb	q->l_prev = p;
46178525Sjb	q->l_next = NULL;
47178525Sjb
48178525Sjb	if (p != NULL)
49178525Sjb		p->l_next = q;
50178525Sjb	else
51178525Sjb		lp->l_next = q;
52178525Sjb}
53178525Sjb
54178525Sjb/*
55178525Sjb * Prepend the specified existing element to the given ctf_list_t.  The
56178525Sjb * existing pointer should be pointing at a struct with embedded ctf_list_t.
57178525Sjb */
58178525Sjbvoid
59178525Sjbctf_list_prepend(ctf_list_t *lp, void *new)
60178525Sjb{
61178525Sjb	ctf_list_t *p = new;		/* p = new list element */
62178525Sjb	ctf_list_t *q = lp->l_next;	/* q = head list element */
63178525Sjb
64178525Sjb	lp->l_next = p;
65178525Sjb	p->l_prev = NULL;
66178525Sjb	p->l_next = q;
67178525Sjb
68178525Sjb	if (q != NULL)
69178525Sjb		q->l_prev = p;
70178525Sjb	else
71178525Sjb		lp->l_prev = p;
72178525Sjb}
73178525Sjb
74178525Sjb/*
75178525Sjb * Delete the specified existing element from the given ctf_list_t.  The
76178525Sjb * existing pointer should be pointing at a struct with embedded ctf_list_t.
77178525Sjb */
78178525Sjbvoid
79178525Sjbctf_list_delete(ctf_list_t *lp, void *existing)
80178525Sjb{
81178525Sjb	ctf_list_t *p = existing;
82178525Sjb
83178525Sjb	if (p->l_prev != NULL)
84178525Sjb		p->l_prev->l_next = p->l_next;
85178525Sjb	else
86178525Sjb		lp->l_next = p->l_next;
87178525Sjb
88178525Sjb	if (p->l_next != NULL)
89178525Sjb		p->l_next->l_prev = p->l_prev;
90178525Sjb	else
91178525Sjb		lp->l_prev = p->l_prev;
92178525Sjb}
93178525Sjb
94178525Sjb/*
95178525Sjb * Convert an encoded CTF string name into a pointer to a C string by looking
96178525Sjb * up the appropriate string table buffer and then adding the offset.
97178525Sjb */
98178525Sjbconst char *
99178525Sjbctf_strraw(ctf_file_t *fp, uint_t name)
100178525Sjb{
101178525Sjb	ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)];
102178525Sjb
103178525Sjb	if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET(name) < ctsp->cts_len)
104178525Sjb		return (ctsp->cts_strs + CTF_NAME_OFFSET(name));
105178525Sjb
106178525Sjb	/* string table not loaded or corrupt offset */
107178525Sjb	return (NULL);
108178525Sjb}
109178525Sjb
110178525Sjbconst char *
111178525Sjbctf_strptr(ctf_file_t *fp, uint_t name)
112178525Sjb{
113178525Sjb	const char *s = ctf_strraw(fp, name);
114178525Sjb	return (s != NULL ? s : "(?)");
115178525Sjb}
116178525Sjb
117178525Sjb/*
118178525Sjb * Same strdup(3C), but use ctf_alloc() to do the memory allocation.
119178525Sjb */
120178525Sjbchar *
121178525Sjbctf_strdup(const char *s1)
122178525Sjb{
123178525Sjb	char *s2 = ctf_alloc(strlen(s1) + 1);
124178525Sjb
125178525Sjb	if (s2 != NULL)
126178525Sjb		(void) strcpy(s2, s1);
127178525Sjb
128178525Sjb	return (s2);
129178525Sjb}
130178525Sjb
131178525Sjb/*
132178525Sjb * Store the specified error code into errp if it is non-NULL, and then
133178525Sjb * return NULL for the benefit of the caller.
134178525Sjb */
135178525Sjbctf_file_t *
136178525Sjbctf_set_open_errno(int *errp, int error)
137178525Sjb{
138178525Sjb	if (errp != NULL)
139178525Sjb		*errp = error;
140178525Sjb	return (NULL);
141178525Sjb}
142178525Sjb
143178525Sjb/*
144178525Sjb * Store the specified error code into the CTF container, and then return
145178525Sjb * CTF_ERR for the benefit of the caller.
146178525Sjb */
147178525Sjblong
148178525Sjbctf_set_errno(ctf_file_t *fp, int err)
149178525Sjb{
150178525Sjb	fp->ctf_errno = err;
151178525Sjb	return (CTF_ERR);
152178525Sjb}
153