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