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 #include <stdio.h>
  34 #include <assert.h>
  35 
  36 #include "ctftools.h"
  37 #include "traverse.h"
  38 #include "memory.h"
  39 
  40 int (*tddescenders[])();
  41 int (*tdnops[])();
  42 
  43 int tdtraverse(tdesc_t *, tdesc_t **, tdtrav_data_t *);
  44 
  45 void
  46 tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops,
  47     tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
  48 {
  49         tdtd->vgen = ++(*vgenp);
  50         tdtd->firstops = firstops ? firstops : tdnops;
  51         tdtd->preops = preops ? preops : tdnops;
  52         tdtd->postops = postops ? postops : tdnops;
  53         tdtd->private = private;
  54 }
  55 
  56 static int
  57 tdtrav_plain(tdesc_t *this, tdtrav_data_t *tdtd)
  58 {
  59         return (tdtraverse(this->t_tdesc, &this->t_tdesc, tdtd));
  60 }
  61 
  62 static int
  63 tdtrav_func(tdesc_t *this, tdtrav_data_t *tdtd)
  64 {
  65         fndef_t *fn = this->t_fndef;
  66         int i, rc;
  67 
  68         if ((rc = tdtraverse(fn->fn_ret, &fn->fn_ret, tdtd)) < 0)
  69                 return (rc);
  70 
  71         for (i = 0; i < fn->fn_nargs; i++) {
  72                 if ((rc = tdtraverse(fn->fn_args[i], &fn->fn_args[i],
  73                     tdtd)) < 0)
  74                         return (rc);
  75         }
  76 
  77         return (0);
  78 }
  79 
  80 static int
  81 tdtrav_array(tdesc_t *this, tdtrav_data_t *tdtd)
  82 {
  83         ardef_t *ardef = this->t_ardef;
  84         int rc;
  85 
  86         if ((rc = tdtraverse(ardef->ad_contents, &ardef->ad_contents,
  87             tdtd)) < 0)
  88                 return (rc);
  89 
  90         return (tdtraverse(ardef->ad_idxtype, &ardef->ad_idxtype, tdtd));
  91 }
  92 
  93 static int
  94 tdtrav_su(tdesc_t *this, tdtrav_data_t *tdtd)
  95 {
  96         mlist_t *ml;
  97         int rc = 0;
  98 
  99         for (ml = this->t_members; ml; ml = ml->ml_next) {
 100                 if ((rc = tdtraverse(ml->ml_type, &ml->ml_type, tdtd)) < 0)
 101                         return (rc);
 102         }
 103 
 104         return (rc);
 105 }
 106 
 107 /*ARGSUSED*/
 108 int
 109 tdtrav_assert(tdesc_t *node, tdesc_t **nodep, void *private)
 110 {
 111         assert(1 == 0);
 112 
 113         return (-1);
 114 }
 115 
 116 tdtrav_cb_f tdnops[] = {
 117         NULL,
 118         NULL,                   /* intrinsic */
 119         NULL,                   /* pointer */
 120         NULL,                   /* array */
 121         NULL,                   /* function */
 122         NULL,                   /* struct */
 123         NULL,                   /* union */
 124         NULL,                   /* enum */
 125         NULL,                   /* forward */
 126         NULL,                   /* typedef */
 127         NULL,                   /* typedef_unres */
 128         NULL,                   /* volatile */
 129         NULL,                   /* const */
 130         NULL                    /* restrict */
 131 };
 132 
 133 int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
 134         NULL,
 135         NULL,                   /* intrinsic */
 136         tdtrav_plain,           /* pointer */
 137         tdtrav_array,           /* array */
 138         tdtrav_func,            /* function */
 139         tdtrav_su,              /* struct */
 140         tdtrav_su,              /* union */
 141         NULL,                   /* enum */
 142         NULL,                   /* forward */
 143         tdtrav_plain,           /* typedef */
 144         NULL,                   /* typedef_unres */
 145         tdtrav_plain,           /* volatile */
 146         tdtrav_plain,           /* const */
 147         tdtrav_plain            /* restrict */
 148 };
 149 
 150 int
 151 tdtraverse(tdesc_t *this, tdesc_t **thisp, tdtrav_data_t *tdtd)
 152 {
 153         tdtrav_cb_f travcb;
 154         int (*descender)();
 155         int descend = 1;
 156         int rc;
 157 
 158         if ((travcb = tdtd->firstops[this->t_type]) != NULL) {
 159                 if ((rc = travcb(this, thisp, tdtd->private)) < 0)
 160                         return (rc);
 161                 else if (rc == 0)
 162                         descend = 0;
 163         }
 164 
 165         if (this->t_vgen == tdtd->vgen)
 166                 return (1);
 167         this->t_vgen = tdtd->vgen;
 168 
 169         if (descend && (travcb = tdtd->preops[this->t_type]) != NULL) {
 170                 if ((rc = travcb(this, thisp, tdtd->private)) < 0)
 171                         return (rc);
 172                 else if (rc == 0)
 173                         descend = 0;
 174         }
 175 
 176         if (descend) {
 177                 if ((descender = tddescenders[this->t_type]) != NULL &&
 178                     (rc = descender(this, tdtd)) < 0)
 179                         return (rc);
 180 
 181                 if ((travcb = tdtd->postops[this->t_type]) != NULL &&
 182                     (rc = travcb(this, thisp, tdtd->private)) < 0)
 183                         return (rc);
 184         }
 185 
 186         return (1);
 187 }
 188 
 189 int
 190 iitraverse_td(iidesc_t *ii, tdtrav_data_t *tdtd)
 191 {
 192         int i, rc;
 193 
 194         if ((rc = tdtraverse(ii->ii_dtype, &ii->ii_dtype, tdtd)) < 0)
 195                 return (rc);
 196 
 197         for (i = 0; i < ii->ii_nargs; i++) {
 198                 if ((rc = tdtraverse(ii->ii_args[i], &ii->ii_args[i],
 199                     tdtd)) < 0)
 200                         return (rc);
 201         }
 202 
 203         return (1);
 204 }
 205 
 206 int
 207 iitraverse(iidesc_t *ii, int *vgenp, tdtrav_cb_f *firstops, tdtrav_cb_f *preops,
 208     tdtrav_cb_f *postops, void *private)
 209 {
 210         tdtrav_data_t tdtd;
 211 
 212         tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
 213 
 214         return (iitraverse_td(ii, &tdtd));
 215 }
 216 
 217 int
 218 iitraverse_hash(hash_t *iihash, int *vgenp, tdtrav_cb_f *firstops,
 219     tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
 220 {
 221         tdtrav_data_t tdtd;
 222 
 223         tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
 224 
 225         return (hash_iter(iihash, (int (*)())iitraverse_td, &tdtd));
 226 }