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