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