emit2.c revision 1.42 1 /* $NetBSD: emit2.c,v 1.42 2025/05/24 07:38:59 rillig Exp $ */
2
3 /*
4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
5 * Copyright (c) 1994, 1995 Jochen Pohl
6 * All Rights Reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Jochen Pohl for
19 * The NetBSD Project.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #if defined(__RCSID)
37 __RCSID("$NetBSD: emit2.c,v 1.42 2025/05/24 07:38:59 rillig Exp $");
38 #endif
39
40 #include "lint2.h"
41
42 static void outfiles(void);
43
44 /* Write type into the output file. */
45 static void
46 outtype(const type_t *tp)
47 {
48 #ifdef INT128_SIZE
49 static const char tt[NTSPEC] = "???BCCCSSIILLQQJJDDD?XXXV?TTTPAF";
50 static const char ss[NTSPEC] = "??? su u u u u us l?s l ?sue ";
51 #else
52 static const char tt[NTSPEC] = "???BCCCSSIILLQQDDD?XXXV?TTTPAF";
53 static const char ss[NTSPEC] = "??? su u u u us l?s l ?sue ";
54 #endif
55
56 while (tp != NULL) {
57 tspec_t ts = tp->t_tspec;
58 if (ts == INT && tp->t_is_enum)
59 ts = ENUM;
60 if (!ch_isupper(tt[ts]))
61 errx(1, "internal error: outtype(%d)", ts);
62 if (tp->t_const)
63 outchar('c');
64 if (tp->t_volatile)
65 outchar('v');
66 if (ss[ts] != ' ')
67 outchar(ss[ts]);
68 if (ts == FUNC && tp->t_args != NULL && !tp->t_proto)
69 outchar('f');
70 else
71 outchar(tt[ts]);
72
73 if (ts == ARRAY) {
74 outint(tp->t_dim);
75 } else if (ts == ENUM || ts == STRUCT || ts == UNION) {
76 if (tp->t_istag) {
77 outint(1);
78 outname(tp->t_tag->h_name);
79 } else if (tp->t_istynam) {
80 outint(2);
81 outname(tp->t_tynam->h_name);
82 } else if (tp->t_isuniqpos) {
83 outint(3);
84 outint(tp->t_uniqpos.p_line);
85 outchar('.');
86 outint(tp->t_uniqpos.p_file);
87 outchar('.');
88 outint(tp->t_uniqpos.p_uniq);
89 } else
90 errx(1, "internal error: outtype");
91 } else if (ts == FUNC && tp->t_args != NULL) {
92 int na = 0;
93 for (const type_t **ap = tp->t_args; *ap != NULL; ap++)
94 na++;
95 if (tp->t_vararg)
96 na++;
97 outint(na);
98 for (const type_t **ap = tp->t_args; *ap != NULL; ap++)
99 outtype(*ap);
100 if (tp->t_vararg)
101 outchar('E');
102 }
103 tp = tp->t_subt;
104 }
105 }
106
107 /* Write a definition. */
108 static void
109 outdef(const hte_t *hte, const sym_t *sym)
110 {
111
112 outint(0); /* line number in C source file */
113 outchar('d'); /* definition */
114 outint(0); /* index of file where symbol was defined */
115 outchar('.');
116 outint(0); /* line number of definition */
117
118 /* flags */
119 if (sym->s_check_only_first_args) {
120 outchar('v');
121 outint(sym->s_check_num_args);
122 }
123 if (sym->s_scanflike) {
124 outchar('S');
125 outint(sym->s_scanflike_arg);
126 }
127 if (sym->s_printflike) {
128 outchar('P');
129 outint(sym->s_printflike_arg);
130 }
131 /* definition or tentative definition */
132 outchar(sym->s_def == DEF ? 'd' : 't');
133 if (TP(sym->s_type)->t_tspec == FUNC) {
134 if (sym->s_function_has_return_value)
135 outchar('r');
136 if (sym->s_old_style_function)
137 outchar('o');
138 }
139 outchar('u'); /* used (no warning if not used) */
140 outname(hte->h_name);
141 outtype(TP(sym->s_type));
142 outchar('\n');
143 }
144
145 /* Write the first definition of a name into the lint library. */
146 static void
147 dumpname(const hte_t *hte)
148 {
149 sym_t *sym, *def;
150
151 /* static and undefined symbols are not written */
152 if (hte->h_static || !hte->h_def)
153 return;
154
155 /*
156 * If there is a definition, write it. Otherwise, write a tentative
157 * definition. This is necessary because more than one tentative
158 * definition is allowed (except with sflag).
159 */
160 def = NULL;
161 for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
162 if (sym->s_def == DEF) {
163 def = sym;
164 break;
165 }
166 if (sym->s_def == TDEF && def == NULL)
167 def = sym;
168 }
169 if (def == NULL)
170 errx(1, "internal error: dumpname %s", hte->h_name);
171
172 outdef(hte, def);
173 }
174
175 /* Write a new lint library. */
176 void
177 outlib(const char *name)
178 {
179
180 outopen(name);
181
182 outsrc(name); /* name of the lint library */
183
184 outint(0); /* filename index of the lint library */
185 outchar('s');
186 outstrg(name);
187 outchar('\n');
188
189 /* All files referenced by unnamed struct/union/enum declarations. */
190 outfiles();
191
192 /* Write all definitions with external linkage. */
193 symtab_forall_sorted(dumpname);
194
195 outclose();
196 }
197
198 /* Write out the name of a file referenced by a type. */
199 struct outflist {
200 short ofl_num;
201 struct outflist *ofl_next;
202 };
203 static struct outflist *outflist;
204
205 int
206 addoutfile(short num)
207 {
208 struct outflist *ofl, **pofl;
209 int i;
210
211 ofl = outflist;
212 pofl = &outflist;
213 i = 1; /* library is 0 */
214
215 while (ofl != NULL) {
216 if (ofl->ofl_num == num)
217 break;
218
219 pofl = &ofl->ofl_next;
220 ofl = ofl->ofl_next;
221 i++;
222 }
223
224 if (ofl == NULL) {
225 ofl = *pofl = xmalloc(sizeof(**pofl));
226 ofl->ofl_num = num;
227 ofl->ofl_next = NULL;
228 }
229 return i;
230 }
231
232 static void
233 outfiles(void)
234 {
235 struct outflist *ofl;
236 int i;
237
238 for (ofl = outflist, i = 1; ofl != NULL; ofl = ofl->ofl_next, i++) {
239 outint(i);
240 outchar('s');
241 outstrg(fnames[ofl->ofl_num]);
242 outchar('\n');
243 }
244 }
245