tyname.c revision 1.67 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