1 1.67 rillig /* $NetBSD: tyname.c,v 1.67 2025/09/14 11:14:00 rillig Exp $ */ 2 1.3 skrll 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 2005 The NetBSD Foundation, Inc. 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * This code is derived from software contributed to The NetBSD Foundation 8 1.1 christos * by Christos Zoulas. 9 1.1 christos * 10 1.1 christos * Redistribution and use in source and binary forms, with or without 11 1.1 christos * modification, are permitted provided that the following conditions 12 1.1 christos * are met: 13 1.1 christos * 1. Redistributions of source code must retain the above copyright 14 1.1 christos * notice, this list of conditions and the following disclaimer. 15 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 christos * notice, this list of conditions and the following disclaimer in the 17 1.1 christos * documentation and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 christos * POSSIBILITY OF SUCH DAMAGE. 30 1.1 christos */ 31 1.1 christos 32 1.1 christos #if HAVE_NBTOOL_CONFIG_H 33 1.1 christos #include "nbtool_config.h" 34 1.1 christos #endif 35 1.1 christos 36 1.1 christos #include <sys/cdefs.h> 37 1.51 rillig #if defined(__RCSID) 38 1.67 rillig __RCSID("$NetBSD: tyname.c,v 1.67 2025/09/14 11:14:00 rillig Exp $"); 39 1.1 christos #endif 40 1.1 christos 41 1.54 rillig #include <assert.h> 42 1.1 christos #include <limits.h> 43 1.8 christos #include <string.h> 44 1.1 christos #include <stdlib.h> 45 1.1 christos 46 1.58 rillig #if IS_LINT1 47 1.39 rillig #include "lint1.h" 48 1.39 rillig #else 49 1.39 rillig #include "lint2.h" 50 1.39 rillig #endif 51 1.1 christos 52 1.20 rillig /* A tree of strings. */ 53 1.20 rillig typedef struct name_tree_node { 54 1.44 rillig const char *ntn_name; 55 1.20 rillig struct name_tree_node *ntn_less; 56 1.20 rillig struct name_tree_node *ntn_greater; 57 1.20 rillig } name_tree_node; 58 1.20 rillig 59 1.20 rillig static name_tree_node *type_names; 60 1.20 rillig 61 1.20 rillig static name_tree_node * 62 1.20 rillig new_name_tree_node(const char *name) 63 1.20 rillig { 64 1.20 rillig name_tree_node *n; 65 1.20 rillig 66 1.37 rillig n = xmalloc(sizeof(*n)); 67 1.20 rillig n->ntn_name = xstrdup(name); 68 1.20 rillig n->ntn_less = NULL; 69 1.20 rillig n->ntn_greater = NULL; 70 1.20 rillig return n; 71 1.20 rillig } 72 1.20 rillig 73 1.44 rillig /* Return the canonical instance of the string, with unlimited lifetime. */ 74 1.26 rillig static const char * 75 1.20 rillig intern(const char *name) 76 1.20 rillig { 77 1.25 rillig name_tree_node *n = type_names, **next; 78 1.20 rillig int cmp; 79 1.20 rillig 80 1.20 rillig if (n == NULL) { 81 1.20 rillig n = new_name_tree_node(name); 82 1.20 rillig type_names = n; 83 1.20 rillig return n->ntn_name; 84 1.20 rillig } 85 1.20 rillig 86 1.20 rillig while ((cmp = strcmp(name, n->ntn_name)) != 0) { 87 1.25 rillig next = cmp < 0 ? &n->ntn_less : &n->ntn_greater; 88 1.25 rillig if (*next == NULL) { 89 1.25 rillig *next = new_name_tree_node(name); 90 1.25 rillig return (*next)->ntn_name; 91 1.20 rillig } 92 1.25 rillig n = *next; 93 1.20 rillig } 94 1.20 rillig return n->ntn_name; 95 1.20 rillig } 96 1.20 rillig 97 1.65 rillig #if !IS_LINT1 98 1.65 rillig static 99 1.65 rillig #endif 100 1.60 rillig void 101 1.20 rillig buf_init(buffer *buf) 102 1.20 rillig { 103 1.20 rillig buf->len = 0; 104 1.20 rillig buf->cap = 128; 105 1.20 rillig buf->data = xmalloc(buf->cap); 106 1.20 rillig buf->data[0] = '\0'; 107 1.20 rillig } 108 1.20 rillig 109 1.20 rillig static void 110 1.20 rillig buf_done(buffer *buf) 111 1.20 rillig { 112 1.20 rillig free(buf->data); 113 1.20 rillig } 114 1.20 rillig 115 1.20 rillig static void 116 1.60 rillig buf_add_mem(buffer *buf, const char *s, size_t n) 117 1.20 rillig { 118 1.60 rillig while (buf->len + n + 1 >= buf->cap) { 119 1.60 rillig buf->cap *= 2; 120 1.60 rillig buf->data = xrealloc(buf->data, buf->cap); 121 1.60 rillig } 122 1.20 rillig 123 1.60 rillig memcpy(buf->data + buf->len, s, n); 124 1.60 rillig buf->len += n; 125 1.60 rillig buf->data[buf->len] = '\0'; 126 1.60 rillig } 127 1.60 rillig 128 1.61 rillig #if IS_LINT1 129 1.60 rillig void 130 1.60 rillig buf_add_char(buffer *buf, char c) 131 1.60 rillig { 132 1.60 rillig buf_add_mem(buf, &c, 1); 133 1.60 rillig } 134 1.61 rillig #endif 135 1.20 rillig 136 1.65 rillig #if !IS_LINT1 137 1.65 rillig static 138 1.65 rillig #endif 139 1.65 rillig void 140 1.60 rillig buf_add(buffer *buf, const char *s) 141 1.60 rillig { 142 1.60 rillig buf_add_mem(buf, s, strlen(s)); 143 1.20 rillig } 144 1.20 rillig 145 1.20 rillig static void 146 1.20 rillig buf_add_int(buffer *buf, int n) 147 1.20 rillig { 148 1.37 rillig char num[1 + sizeof(n) * CHAR_BIT + 1]; 149 1.20 rillig 150 1.45 rillig (void)snprintf(num, sizeof(num), "%d", n); 151 1.20 rillig buf_add(buf, num); 152 1.20 rillig } 153 1.20 rillig 154 1.1 christos const char * 155 1.18 rillig tspec_name(tspec_t t) 156 1.1 christos { 157 1.49 rillig const char *name = ttab[t].tt_name; 158 1.54 rillig assert(name != NULL); 159 1.48 rillig return name; 160 1.1 christos } 161 1.1 christos 162 1.21 rillig static void 163 1.21 rillig type_name_of_function(buffer *buf, const type_t *tp) 164 1.21 rillig { 165 1.21 rillig const char *sep = ""; 166 1.21 rillig 167 1.21 rillig buf_add(buf, "("); 168 1.21 rillig if (tp->t_proto) { 169 1.58 rillig #if IS_LINT1 170 1.62 rillig const sym_t *param = tp->u.params; 171 1.57 rillig if (param == NULL) 172 1.42 rillig buf_add(buf, "void"); 173 1.57 rillig for (; param != NULL; param = param->s_next) { 174 1.21 rillig buf_add(buf, sep), sep = ", "; 175 1.57 rillig buf_add(buf, type_name(param->s_type)); 176 1.21 rillig } 177 1.50 rillig #else 178 1.66 rillig const type_t **argtype; 179 1.21 rillig 180 1.42 rillig argtype = tp->t_args; 181 1.64 rillig if (*argtype == NULL) 182 1.42 rillig buf_add(buf, "void"); 183 1.42 rillig for (; *argtype != NULL; argtype++) { 184 1.21 rillig buf_add(buf, sep), sep = ", "; 185 1.21 rillig buf_add(buf, type_name(*argtype)); 186 1.21 rillig } 187 1.21 rillig #endif 188 1.21 rillig } 189 1.21 rillig if (tp->t_vararg) { 190 1.22 rillig buf_add(buf, sep); 191 1.21 rillig buf_add(buf, "..."); 192 1.21 rillig } 193 1.21 rillig buf_add(buf, ") returning "); 194 1.21 rillig buf_add(buf, type_name(tp->t_subt)); 195 1.21 rillig } 196 1.21 rillig 197 1.32 rillig static void 198 1.32 rillig type_name_of_struct_or_union(buffer *buf, const type_t *tp) 199 1.32 rillig { 200 1.32 rillig buf_add(buf, " "); 201 1.58 rillig #if IS_LINT1 202 1.62 rillig if (tp->u.sou->sou_tag->s_name == unnamed && 203 1.62 rillig tp->u.sou->sou_first_typedef != NULL) { 204 1.32 rillig buf_add(buf, "typedef "); 205 1.62 rillig buf_add(buf, tp->u.sou->sou_first_typedef->s_name); 206 1.32 rillig } else { 207 1.62 rillig buf_add(buf, tp->u.sou->sou_tag->s_name); 208 1.32 rillig } 209 1.32 rillig #else 210 1.32 rillig buf_add(buf, tp->t_isuniqpos ? "*anonymous*" : tp->t_tag->h_name); 211 1.32 rillig #endif 212 1.32 rillig } 213 1.32 rillig 214 1.32 rillig static void 215 1.32 rillig type_name_of_enum(buffer *buf, const type_t *tp) 216 1.32 rillig { 217 1.32 rillig buf_add(buf, " "); 218 1.58 rillig #if IS_LINT1 219 1.62 rillig if (tp->u.enumer->en_tag->s_name == unnamed && 220 1.62 rillig tp->u.enumer->en_first_typedef != NULL) { 221 1.32 rillig buf_add(buf, "typedef "); 222 1.62 rillig buf_add(buf, tp->u.enumer->en_first_typedef->s_name); 223 1.32 rillig } else { 224 1.62 rillig buf_add(buf, tp->u.enumer->en_tag->s_name); 225 1.32 rillig } 226 1.32 rillig #else 227 1.32 rillig buf_add(buf, tp->t_isuniqpos ? "*anonymous*" : tp->t_tag->h_name); 228 1.32 rillig #endif 229 1.32 rillig } 230 1.32 rillig 231 1.33 rillig static void 232 1.33 rillig type_name_of_array(buffer *buf, const type_t *tp) 233 1.33 rillig { 234 1.33 rillig buf_add(buf, "["); 235 1.58 rillig #if IS_LINT1 236 1.33 rillig if (tp->t_incomplete_array) 237 1.33 rillig buf_add(buf, "unknown_size"); 238 1.33 rillig else 239 1.62 rillig buf_add_int(buf, tp->u.dimension); 240 1.33 rillig #else 241 1.33 rillig buf_add_int(buf, tp->t_dim); 242 1.33 rillig #endif 243 1.33 rillig buf_add(buf, "]"); 244 1.34 rillig buf_add(buf, " of "); 245 1.34 rillig buf_add(buf, type_name(tp->t_subt)); 246 1.33 rillig } 247 1.33 rillig 248 1.1 christos const char * 249 1.20 rillig type_name(const type_t *tp) 250 1.1 christos { 251 1.20 rillig tspec_t t; 252 1.20 rillig buffer buf; 253 1.20 rillig const char *name; 254 1.1 christos 255 1.11 christos if (tp == NULL) 256 1.11 christos return "(null)"; 257 1.20 rillig 258 1.29 rillig if ((t = tp->t_tspec) == INT && tp->t_is_enum) 259 1.1 christos t = ENUM; 260 1.1 christos 261 1.20 rillig buf_init(&buf); 262 1.8 christos if (tp->t_const) 263 1.20 rillig buf_add(&buf, "const "); 264 1.8 christos if (tp->t_volatile) 265 1.20 rillig buf_add(&buf, "volatile "); 266 1.63 rillig #if IS_LINT1 267 1.63 rillig if (tp->t_noreturn) 268 1.63 rillig buf_add(&buf, "noreturn "); 269 1.63 rillig #endif 270 1.32 rillig 271 1.58 rillig #if IS_LINT1 272 1.62 rillig if (is_struct_or_union(t) && tp->u.sou->sou_incomplete) 273 1.38 rillig buf_add(&buf, "incomplete "); 274 1.38 rillig #endif 275 1.20 rillig buf_add(&buf, tspec_name(t)); 276 1.1 christos 277 1.58 rillig #if IS_LINT1 278 1.53 rillig if (tp->t_bitfield) { 279 1.53 rillig buf_add(&buf, ":"); 280 1.56 rillig buf_add_int(&buf, (int)tp->t_bit_field_width); 281 1.53 rillig } 282 1.53 rillig #endif 283 1.53 rillig 284 1.1 christos switch (t) { 285 1.1 christos case PTR: 286 1.20 rillig buf_add(&buf, " to "); 287 1.20 rillig buf_add(&buf, type_name(tp->t_subt)); 288 1.1 christos break; 289 1.1 christos case ENUM: 290 1.32 rillig type_name_of_enum(&buf, tp); 291 1.1 christos break; 292 1.1 christos case STRUCT: 293 1.1 christos case UNION: 294 1.32 rillig type_name_of_struct_or_union(&buf, tp); 295 1.1 christos break; 296 1.1 christos case ARRAY: 297 1.33 rillig type_name_of_array(&buf, tp); 298 1.1 christos break; 299 1.21 rillig case FUNC: 300 1.21 rillig type_name_of_function(&buf, tp); 301 1.21 rillig break; 302 1.1 christos default: 303 1.46 rillig break; 304 1.1 christos } 305 1.20 rillig 306 1.20 rillig name = intern(buf.data); 307 1.20 rillig buf_done(&buf); 308 1.20 rillig return name; 309 1.1 christos } 310 1.67 rillig 311 1.67 rillig #if IS_LINT1 312 1.67 rillig const char * 313 1.67 rillig expr_type_name(const tnode_t *tn) 314 1.67 rillig { 315 1.67 rillig const char *tp_name = type_name(tn->tn_type); 316 1.67 rillig const char *otp_name = type_name(before_conversion(tn)->tn_type); 317 1.67 rillig if (tp_name == otp_name) 318 1.67 rillig return tp_name; 319 1.67 rillig buffer buf; 320 1.67 rillig buf_init(&buf); 321 1.67 rillig buf_add(&buf, tp_name); 322 1.67 rillig buf_add(&buf, " promoted from "); 323 1.67 rillig buf_add(&buf, otp_name); 324 1.67 rillig const char *name = intern(buf.data); 325 1.67 rillig buf_done(&buf); 326 1.67 rillig return name; 327 1.67 rillig } 328 1.67 rillig #endif 329