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 int (*tddescenders[])(tdesc_t *, tdtrav_data_t *); 45 tdtrav_cb_f tdnops[]; 46 47 void 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 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 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 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 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 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 tdtrav_cb_f tdnops[] = { 119 NULL, 120 NULL, /* intrinsic */ 121 NULL, /* pointer */ 122 NULL, /* array */ 123 NULL, /* function */ 124 NULL, /* struct */ 125 NULL, /* union */ 126 NULL, /* enum */ 127 NULL, /* forward */ 128 NULL, /* typedef */ 129 NULL, /* typedef_unres */ 130 NULL, /* volatile */ 131 NULL, /* const */ 132 NULL /* restrict */ 133 }; 134 135 int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = { 136 NULL, 137 NULL, /* intrinsic */ 138 tdtrav_plain, /* pointer */ 139 tdtrav_array, /* array */ 140 tdtrav_func, /* function */ 141 tdtrav_su, /* struct */ 142 tdtrav_su, /* union */ 143 NULL, /* enum */ 144 NULL, /* forward */ 145 tdtrav_plain, /* typedef */ 146 NULL, /* typedef_unres */ 147 tdtrav_plain, /* volatile */ 148 tdtrav_plain, /* const */ 149 tdtrav_plain /* restrict */ 150 }; 151 152 int 153 tdtraverse(tdesc_t *this, tdesc_t **thisp, tdtrav_data_t *tdtd) 154 { 155 tdtrav_cb_f travcb; 156 int (*descender)(tdesc_t *, tdtrav_data_t *); 157 int descend = 1; 158 int rc; 159 160 if ((travcb = tdtd->firstops[this->t_type]) != NULL) { 161 if ((rc = travcb(this, thisp, tdtd->private)) < 0) 162 return (rc); 163 else if (rc == 0) 164 descend = 0; 165 } 166 167 if (this->t_vgen == tdtd->vgen) 168 return (1); 169 this->t_vgen = tdtd->vgen; 170 171 if (descend && (travcb = tdtd->preops[this->t_type]) != NULL) { 172 if ((rc = travcb(this, thisp, tdtd->private)) < 0) 173 return (rc); 174 else if (rc == 0) 175 descend = 0; 176 } 177 178 if (descend) { 179 if ((descender = tddescenders[this->t_type]) != NULL && 180 (rc = descender(this, tdtd)) < 0) 181 return (rc); 182 183 if ((travcb = tdtd->postops[this->t_type]) != NULL && 184 (rc = travcb(this, thisp, tdtd->private)) < 0) 185 return (rc); 186 } 187 188 return (1); 189 } 190 191 int 192 iitraverse_td(void *arg1, void *arg2) 193 { 194 iidesc_t *ii = arg1; 195 tdtrav_data_t *tdtd = arg2; 196 int i, rc; 197 198 if ((rc = tdtraverse(ii->ii_dtype, &ii->ii_dtype, tdtd)) < 0) 199 return (rc); 200 201 for (i = 0; i < ii->ii_nargs; i++) { 202 if ((rc = tdtraverse(ii->ii_args[i], &ii->ii_args[i], 203 tdtd)) < 0) 204 return (rc); 205 } 206 207 return (1); 208 } 209 210 int 211 iitraverse(iidesc_t *ii, int *vgenp, tdtrav_cb_f *firstops, tdtrav_cb_f *preops, 212 tdtrav_cb_f *postops, void *private) 213 { 214 tdtrav_data_t tdtd; 215 216 tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private); 217 218 return (iitraverse_td(ii, &tdtd)); 219 } 220 221 int 222 iitraverse_hash(hash_t *iihash, int *vgenp, tdtrav_cb_f *firstops, 223 tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private) 224 { 225 tdtrav_data_t tdtd; 226 227 tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private); 228 229 return (hash_iter(iihash, iitraverse_td, &tdtd)); 230 } 231