emit2.c revision 1.38
1/* $NetBSD: emit2.c,v 1.38 2024/03/02 09:32:19 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.38 2024/03/02 09:32:19 rillig Exp $");
38#endif
39
40#include "lint2.h"
41
42static void outtype(type_t *);
43static void outdef(hte_t *, sym_t *);
44static void dumpname(hte_t *);
45static void outfiles(void);
46
47/* Write type into the output file. */
48static void
49outtype(type_t *tp)
50{
51#ifdef INT128_SIZE
52	static const char tt[NTSPEC] = "???BCCCSSIILLQQJJDDD?XXXVTTTPAF";
53	static const char ss[NTSPEC] = "???  su u u u u us l?s l sue   ";
54#else
55	static const char tt[NTSPEC] = "???BCCCSSIILLQQDDD?XXXVTTTPAF";
56	static const char ss[NTSPEC] = "???  su u u u us l?s l sue   ";
57#endif
58
59	while (tp != NULL) {
60		tspec_t ts = tp->t_tspec;
61		if (ts == INT && tp->t_is_enum)
62			ts = ENUM;
63		if (!isupper((unsigned char)tt[ts]))
64			errx(1, "internal error: outtype(%d)", ts);
65		if (tp->t_const)
66			outchar('c');
67		if (tp->t_volatile)
68			outchar('v');
69		if (ss[ts] != ' ')
70			outchar(ss[ts]);
71		if (ts == FUNC && tp->t_args != NULL && !tp->t_proto)
72			outchar('f');
73		else
74			outchar(tt[ts]);
75
76		if (ts == ARRAY) {
77			outint(tp->t_dim);
78		} else if (ts == ENUM || ts == STRUCT || ts == UNION) {
79			if (tp->t_istag) {
80				outint(1);
81				outname(tp->t_tag->h_name);
82			} else if (tp->t_istynam) {
83				outint(2);
84				outname(tp->t_tynam->h_name);
85			} else if (tp->t_isuniqpos) {
86				outint(3);
87				outint(tp->t_uniqpos.p_line);
88				outchar('.');
89				outint(tp->t_uniqpos.p_file);
90				outchar('.');
91				outint(tp->t_uniqpos.p_uniq);
92			} else
93				errx(1, "internal error: outtype");
94		} else if (ts == FUNC && tp->t_args != NULL) {
95			int na = 0;
96			for (type_t **ap = tp->t_args; *ap != NULL; ap++)
97				na++;
98			if (tp->t_vararg)
99				na++;
100			outint(na);
101			for (type_t **ap = tp->t_args; *ap != NULL; ap++)
102				outtype(*ap);
103			if (tp->t_vararg)
104				outchar('E');
105		}
106		tp = tp->t_subt;
107	}
108}
109
110/* Write a definition. */
111static void
112outdef(hte_t *hte, sym_t *sym)
113{
114
115	outint(0);		/* line number in C source file */
116	outchar('d');		/* definition */
117	outint(0);		/* index of file where symbol was defined */
118	outchar('.');
119	outint(0);		/* line number of definition */
120
121	/* flags */
122	if (sym->s_check_only_first_args) {
123		outchar('v');
124		outint(sym->s_check_num_args);
125	}
126	if (sym->s_scanflike) {
127		outchar('S');
128		outint(sym->s_scanflike_arg);
129	}
130	if (sym->s_printflike) {
131		outchar('P');
132		outint(sym->s_printflike_arg);
133	}
134	/* definition or tentative definition */
135	outchar(sym->s_def == DEF ? 'd' : 't');
136	if (TP(sym->s_type)->t_tspec == FUNC) {
137		if (sym->s_function_has_return_value)
138			outchar('r');
139		if (sym->s_old_style_function)
140			outchar('o');
141	}
142	outchar('u');		/* used (no warning if not used) */
143	outname(hte->h_name);
144	outtype(TP(sym->s_type));
145	outchar('\n');
146}
147
148/* Write the first definition of a name into the lint library. */
149static void
150dumpname(hte_t *hte)
151{
152	sym_t *sym, *def;
153
154	/* static and undefined symbols are not written */
155	if (hte->h_static || !hte->h_def)
156		return;
157
158	/*
159	 * If there is a definition, write it. Otherwise, write a tentative
160	 * definition. This is necessary because more than one tentative
161	 * definition is allowed (except with sflag).
162	 */
163	def = NULL;
164	for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
165		if (sym->s_def == DEF) {
166			def = sym;
167			break;
168		}
169		if (sym->s_def == TDEF && def == NULL)
170			def = sym;
171	}
172	if (def == NULL)
173		errx(1, "internal error: dumpname %s", hte->h_name);
174
175	outdef(hte, def);
176}
177
178/* Write a new lint library. */
179void
180outlib(const char *name)
181{
182
183	outopen(name);
184
185	outsrc(name);		/* name of the lint library */
186
187	outint(0);		/* filename index of the lint library */
188	outchar('s');
189	outstrg(name);
190	outchar('\n');
191
192	/* All files referenced by unnamed struct/union/enum declarations. */
193	outfiles();
194
195	/* Write all definitions with external linkage. */
196	symtab_forall_sorted(dumpname);
197
198	outclose();
199}
200
201/* Write out the name of a file referenced by a type. */
202struct outflist {
203	short		ofl_num;
204	struct outflist *ofl_next;
205};
206static struct outflist *outflist;
207
208int
209addoutfile(short num)
210{
211	struct outflist *ofl, **pofl;
212	int i;
213
214	ofl = outflist;
215	pofl = &outflist;
216	i = 1;				/* library is 0 */
217
218	while (ofl != NULL) {
219		if (ofl->ofl_num == num)
220			break;
221
222		pofl = &ofl->ofl_next;
223		ofl = ofl->ofl_next;
224		i++;
225	}
226
227	if (ofl == NULL) {
228		ofl = *pofl = xmalloc(sizeof(**pofl));
229		ofl->ofl_num = num;
230		ofl->ofl_next = NULL;
231	}
232	return i;
233}
234
235static void
236outfiles(void)
237{
238	struct outflist *ofl;
239	int i;
240
241	for (ofl = outflist, i = 1; ofl != NULL; ofl = ofl->ofl_next, i++) {
242		outint(i);
243		outchar('s');
244		outstrg(fnames[ofl->ofl_num]);
245		outchar('\n');
246	}
247}
248