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