emit2.c revision 1.5
1/* $NetBSD: emit2.c,v 1.5 2000/06/14 06:49:23 cgd 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#ifndef lint 37__RCSID("$NetBSD: emit2.c,v 1.5 2000/06/14 06:49:23 cgd Exp $"); 38#endif 39 40#include <err.h> 41 42#include "lint2.h" 43 44static void outtype __P((type_t *)); 45static void outdef __P((hte_t *, sym_t *)); 46static void dumpname __P((hte_t *)); 47static void outfiles __P((void)); 48 49/* 50 * Write type into the output buffer. 51 */ 52static void 53outtype(tp) 54 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, sym) 141 hte_t *hte; 142 sym_t *sym; 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) 193 hte_t *hte; 194{ 195 sym_t *sym, *def; 196 197 /* static and undefined symbols are not written */ 198 if (hte->h_static || !hte->h_def) 199 return; 200 201 /* 202 * If there is a definition, write it. Otherwise write a tentative 203 * definition. This is neccessary because more than one tentative 204 * definition is allowed (except with sflag). 205 */ 206 def = NULL; 207 for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { 208 if (sym->s_def == DEF) { 209 def = sym; 210 break; 211 } 212 if (sym->s_def == TDEF && def == NULL) 213 def = sym; 214 } 215 if (def == NULL) 216 errx(1, "internal error: dumpname() %s", hte->h_name); 217 218 outdef(hte, def); 219} 220 221/* 222 * Write a new lint library. 223 */ 224void 225outlib(name) 226 const char *name; 227{ 228 /* Open of output file and initialisation of the output buffer */ 229 outopen(name); 230 231 /* write name of lint library */ 232 outsrc(name); 233 234 /* name of lint lib has index 0 */ 235 outclr(); 236 outint(0); 237 outchar('s'); 238 outstrg(name); 239 240 /* 241 * print the names of all files references by unnamed 242 * struct/union/enum declarations. 243 */ 244 outfiles(); 245 246 /* write all definitions with external linkage */ 247 forall(dumpname); 248 249 /* close the output */ 250 outclose(); 251} 252 253/* 254 * Write out the name of a file referenced by a type. 255 */ 256struct outflist { 257 short ofl_num; 258 struct outflist *ofl_next; 259}; 260static struct outflist *outflist; 261 262int 263addoutfile(num) 264 short num; 265{ 266 struct outflist *ofl, **pofl; 267 int i; 268 269 ofl = outflist; 270 pofl = &outflist; 271 i = 1; /* library is 0 */ 272 273 while (ofl != NULL) { 274 if (ofl->ofl_num == num) 275 break; 276 277 pofl = &ofl->ofl_next; 278 ofl = ofl->ofl_next; 279 i++; 280 } 281 282 if (ofl == NULL) { 283 ofl = *pofl = xmalloc(sizeof (struct outflist)); 284 ofl->ofl_num = num; 285 ofl->ofl_next = NULL; 286 } 287 return (i); 288} 289 290static void 291outfiles() 292{ 293 struct outflist *ofl; 294 int i; 295 296 for (ofl = outflist, i = 1; ofl != NULL; ofl = ofl->ofl_next, i++) { 297 /* reset output buffer */ 298 outclr(); 299 300 outint(i); 301 outchar('s'); 302 outstrg(fnames[ofl->ofl_num]); 303 } 304} 305