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