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