1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * Routines used to traverse tdesc trees, invoking user-supplied callbacks
30 * as the tree is traversed.
31 */
32
33 #if HAVE_NBTOOL_CONFIG_H
34 # include "nbtool_config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <assert.h>
39
40 #include "ctftools.h"
41 #include "traverse.h"
42 #include "memory.h"
43
44 static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *);
45 static tdtrav_cb_f tdnops[];
46
47 void
tdtrav_init(tdtrav_data_t * tdtd,int * vgenp,tdtrav_cb_f * firstops,tdtrav_cb_f * preops,tdtrav_cb_f * postops,void * private)48 tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops,
49 tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
50 {
51 tdtd->vgen = ++(*vgenp);
52 tdtd->firstops = firstops ? firstops : tdnops;
53 tdtd->preops = preops ? preops : tdnops;
54 tdtd->postops = postops ? postops : tdnops;
55 tdtd->private = private;
56 }
57
58 static int
tdtrav_plain(tdesc_t * this,tdtrav_data_t * tdtd)59 tdtrav_plain(tdesc_t *this, tdtrav_data_t *tdtd)
60 {
61 return (tdtraverse(this->t_tdesc, &this->t_tdesc, tdtd));
62 }
63
64 static int
tdtrav_func(tdesc_t * this,tdtrav_data_t * tdtd)65 tdtrav_func(tdesc_t *this, tdtrav_data_t *tdtd)
66 {
67 fndef_t *fn = this->t_fndef;
68 int i, rc;
69
70 if ((rc = tdtraverse(fn->fn_ret, &fn->fn_ret, tdtd)) < 0)
71 return (rc);
72
73 for (i = 0; i < (int) fn->fn_nargs; i++) {
74 if ((rc = tdtraverse(fn->fn_args[i], &fn->fn_args[i],
75 tdtd)) < 0)
76 return (rc);
77 }
78
79 return (0);
80 }
81
82 static int
tdtrav_array(tdesc_t * this,tdtrav_data_t * tdtd)83 tdtrav_array(tdesc_t *this, tdtrav_data_t *tdtd)
84 {
85 ardef_t *ardef = this->t_ardef;
86 int rc;
87
88 if ((rc = tdtraverse(ardef->ad_contents, &ardef->ad_contents,
89 tdtd)) < 0)
90 return (rc);
91
92 return (tdtraverse(ardef->ad_idxtype, &ardef->ad_idxtype, tdtd));
93 }
94
95 static int
tdtrav_su(tdesc_t * this,tdtrav_data_t * tdtd)96 tdtrav_su(tdesc_t *this, tdtrav_data_t *tdtd)
97 {
98 mlist_t *ml;
99 int rc = 0;
100
101 for (ml = this->t_members; ml; ml = ml->ml_next) {
102 if ((rc = tdtraverse(ml->ml_type, &ml->ml_type, tdtd)) < 0)
103 return (rc);
104 }
105
106 return (rc);
107 }
108
109 /*ARGSUSED*/
110 int
tdtrav_assert(tdesc_t * node __unused,tdesc_t ** nodep __unused,void * private __unused)111 tdtrav_assert(tdesc_t *node __unused, tdesc_t **nodep __unused, void *private __unused)
112 {
113 assert(1 == 0);
114
115 return (-1);
116 }
117
118 static tdtrav_cb_f tdnops[] = {
119 NULL,
120 NULL, /* intrinsic */
121 NULL, /* pointer */
122 NULL, /* reference */
123 NULL, /* array */
124 NULL, /* function */
125 NULL, /* struct */
126 NULL, /* union */
127 NULL, /* class */
128 NULL, /* enum */
129 NULL, /* forward */
130 NULL, /* typedef */
131 NULL, /* typedef_unres */
132 NULL, /* volatile */
133 NULL, /* const */
134 NULL /* restrict */
135 };
136
137 static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
138 NULL,
139 NULL, /* intrinsic */
140 tdtrav_plain, /* pointer */
141 tdtrav_plain, /* reference */
142 tdtrav_array, /* array */
143 tdtrav_func, /* function */
144 tdtrav_su, /* struct */
145 tdtrav_su, /* union */
146 tdtrav_su, /* class */
147 NULL, /* enum */
148 NULL, /* forward */
149 tdtrav_plain, /* typedef */
150 NULL, /* typedef_unres */
151 tdtrav_plain, /* volatile */
152 tdtrav_plain, /* const */
153 tdtrav_plain /* restrict */
154 };
155
156 int
tdtraverse(tdesc_t * this,tdesc_t ** thisp,tdtrav_data_t * tdtd)157 tdtraverse(tdesc_t *this, tdesc_t **thisp, tdtrav_data_t *tdtd)
158 {
159 tdtrav_cb_f travcb;
160 int (*descender)(tdesc_t *, tdtrav_data_t *);
161 int descend = 1;
162 int rc;
163
164 if ((travcb = tdtd->firstops[this->t_type]) != NULL) {
165 if ((rc = travcb(this, thisp, tdtd->private)) < 0)
166 return (rc);
167 else if (rc == 0)
168 descend = 0;
169 }
170
171 if (this->t_vgen == tdtd->vgen)
172 return (1);
173 this->t_vgen = tdtd->vgen;
174
175 if (descend && (travcb = tdtd->preops[this->t_type]) != NULL) {
176 if ((rc = travcb(this, thisp, tdtd->private)) < 0)
177 return (rc);
178 else if (rc == 0)
179 descend = 0;
180 }
181
182 if (descend) {
183 if ((descender = tddescenders[this->t_type]) != NULL &&
184 (rc = descender(this, tdtd)) < 0)
185 return (rc);
186
187 if ((travcb = tdtd->postops[this->t_type]) != NULL &&
188 (rc = travcb(this, thisp, tdtd->private)) < 0)
189 return (rc);
190 }
191
192 return (1);
193 }
194
195 int
iitraverse_td(void * arg1,void * arg2)196 iitraverse_td(void *arg1, void *arg2)
197 {
198 iidesc_t *ii = arg1;
199 tdtrav_data_t *tdtd = arg2;
200 int i, rc;
201
202 if ((rc = tdtraverse(ii->ii_dtype, &ii->ii_dtype, tdtd)) < 0)
203 return (rc);
204
205 for (i = 0; i < ii->ii_nargs; i++) {
206 if ((rc = tdtraverse(ii->ii_args[i], &ii->ii_args[i],
207 tdtd)) < 0)
208 return (rc);
209 }
210
211 return (1);
212 }
213
214 int
iitraverse(iidesc_t * ii,int * vgenp,tdtrav_cb_f * firstops,tdtrav_cb_f * preops,tdtrav_cb_f * postops,void * private)215 iitraverse(iidesc_t *ii, int *vgenp, tdtrav_cb_f *firstops, tdtrav_cb_f *preops,
216 tdtrav_cb_f *postops, void *private)
217 {
218 tdtrav_data_t tdtd;
219
220 tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
221
222 return (iitraverse_td(ii, &tdtd));
223 }
224
225 int
iitraverse_hash(hash_t * iihash,int * vgenp,tdtrav_cb_f * firstops,tdtrav_cb_f * preops,tdtrav_cb_f * postops,void * private)226 iitraverse_hash(hash_t *iihash, int *vgenp, tdtrav_cb_f *firstops,
227 tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
228 {
229 tdtrav_data_t tdtd;
230
231 tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
232
233 return (hash_iter(iihash, iitraverse_td, &tdtd));
234 }
235