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