1 1.42 rillig /* $NetBSD: emit2.c,v 1.42 2025/05/24 07:38:59 rillig Exp $ */ 2 1.2 cgd 3 1.1 cgd /* 4 1.3 cgd * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 5 1.1 cgd * Copyright (c) 1994, 1995 Jochen Pohl 6 1.1 cgd * All Rights Reserved. 7 1.1 cgd * 8 1.1 cgd * Redistribution and use in source and binary forms, with or without 9 1.1 cgd * modification, are permitted provided that the following conditions 10 1.1 cgd * are met: 11 1.1 cgd * 1. Redistributions of source code must retain the above copyright 12 1.1 cgd * notice, this list of conditions and the following disclaimer. 13 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 cgd * notice, this list of conditions and the following disclaimer in the 15 1.1 cgd * documentation and/or other materials provided with the distribution. 16 1.1 cgd * 3. All advertising materials mentioning features or use of this software 17 1.1 cgd * must display the following acknowledgement: 18 1.33 rillig * This product includes software developed by Jochen Pohl for 19 1.1 cgd * The NetBSD Project. 20 1.1 cgd * 4. The name of the author may not be used to endorse or promote products 21 1.1 cgd * derived from this software without specific prior written permission. 22 1.1 cgd * 23 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 1.1 cgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 1.1 cgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 1.1 cgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 1.1 cgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 1.1 cgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 1.1 cgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 1.1 cgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 1.1 cgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 1.1 cgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 1.1 cgd */ 34 1.1 cgd 35 1.4 christos #include <sys/cdefs.h> 36 1.28 rillig #if defined(__RCSID) 37 1.42 rillig __RCSID("$NetBSD: emit2.c,v 1.42 2025/05/24 07:38:59 rillig Exp $"); 38 1.1 cgd #endif 39 1.1 cgd 40 1.1 cgd #include "lint2.h" 41 1.1 cgd 42 1.37 rillig static void outfiles(void); 43 1.1 cgd 44 1.36 rillig /* Write type into the output file. */ 45 1.1 cgd static void 46 1.41 rillig outtype(const type_t *tp) 47 1.1 cgd { 48 1.25 rillig #ifdef INT128_SIZE 49 1.40 rillig static const char tt[NTSPEC] = "???BCCCSSIILLQQJJDDD?XXXV?TTTPAF"; 50 1.40 rillig static const char ss[NTSPEC] = "??? su u u u u us l?s l ?sue "; 51 1.25 rillig #else 52 1.40 rillig static const char tt[NTSPEC] = "???BCCCSSIILLQQDDD?XXXV?TTTPAF"; 53 1.40 rillig static const char ss[NTSPEC] = "??? su u u u us l?s l ?sue "; 54 1.25 rillig #endif 55 1.25 rillig 56 1.1 cgd while (tp != NULL) { 57 1.31 rillig tspec_t ts = tp->t_tspec; 58 1.30 rillig if (ts == INT && tp->t_is_enum) 59 1.1 cgd ts = ENUM; 60 1.39 rillig if (!ch_isupper(tt[ts])) 61 1.25 rillig errx(1, "internal error: outtype(%d)", ts); 62 1.1 cgd if (tp->t_const) 63 1.1 cgd outchar('c'); 64 1.1 cgd if (tp->t_volatile) 65 1.1 cgd outchar('v'); 66 1.26 rillig if (ss[ts] != ' ') 67 1.26 rillig outchar(ss[ts]); 68 1.26 rillig if (ts == FUNC && tp->t_args != NULL && !tp->t_proto) 69 1.26 rillig outchar('f'); 70 1.26 rillig else 71 1.26 rillig outchar(tt[ts]); 72 1.26 rillig 73 1.1 cgd if (ts == ARRAY) { 74 1.1 cgd outint(tp->t_dim); 75 1.1 cgd } else if (ts == ENUM || ts == STRUCT || ts == UNION) { 76 1.1 cgd if (tp->t_istag) { 77 1.1 cgd outint(1); 78 1.1 cgd outname(tp->t_tag->h_name); 79 1.1 cgd } else if (tp->t_istynam) { 80 1.1 cgd outint(2); 81 1.1 cgd outname(tp->t_tynam->h_name); 82 1.3 cgd } else if (tp->t_isuniqpos) { 83 1.3 cgd outint(3); 84 1.3 cgd outint(tp->t_uniqpos.p_line); 85 1.3 cgd outchar('.'); 86 1.3 cgd outint(tp->t_uniqpos.p_file); 87 1.3 cgd outchar('.'); 88 1.3 cgd outint(tp->t_uniqpos.p_uniq); 89 1.3 cgd } else 90 1.29 rillig errx(1, "internal error: outtype"); 91 1.1 cgd } else if (ts == FUNC && tp->t_args != NULL) { 92 1.30 rillig int na = 0; 93 1.42 rillig for (const type_t **ap = tp->t_args; *ap != NULL; ap++) 94 1.1 cgd na++; 95 1.1 cgd if (tp->t_vararg) 96 1.1 cgd na++; 97 1.1 cgd outint(na); 98 1.42 rillig for (const type_t **ap = tp->t_args; *ap != NULL; ap++) 99 1.1 cgd outtype(*ap); 100 1.1 cgd if (tp->t_vararg) 101 1.1 cgd outchar('E'); 102 1.1 cgd } 103 1.1 cgd tp = tp->t_subt; 104 1.1 cgd } 105 1.1 cgd } 106 1.1 cgd 107 1.36 rillig /* Write a definition. */ 108 1.1 cgd static void 109 1.42 rillig outdef(const hte_t *hte, const sym_t *sym) 110 1.1 cgd { 111 1.6 lukem 112 1.35 rillig outint(0); /* line number in C source file */ 113 1.35 rillig outchar('d'); /* definition */ 114 1.35 rillig outint(0); /* index of file where symbol was defined */ 115 1.1 cgd outchar('.'); 116 1.35 rillig outint(0); /* line number of definition */ 117 1.1 cgd 118 1.1 cgd /* flags */ 119 1.23 rillig if (sym->s_check_only_first_args) { 120 1.23 rillig outchar('v'); 121 1.23 rillig outint(sym->s_check_num_args); 122 1.1 cgd } 123 1.23 rillig if (sym->s_scanflike) { 124 1.23 rillig outchar('S'); 125 1.23 rillig outint(sym->s_scanflike_arg); 126 1.1 cgd } 127 1.23 rillig if (sym->s_printflike) { 128 1.23 rillig outchar('P'); 129 1.23 rillig outint(sym->s_printflike_arg); 130 1.1 cgd } 131 1.1 cgd /* definition or tentative definition */ 132 1.1 cgd outchar(sym->s_def == DEF ? 'd' : 't'); 133 1.1 cgd if (TP(sym->s_type)->t_tspec == FUNC) { 134 1.23 rillig if (sym->s_function_has_return_value) 135 1.23 rillig outchar('r'); 136 1.23 rillig if (sym->s_old_style_function) 137 1.23 rillig outchar('o'); 138 1.1 cgd } 139 1.35 rillig outchar('u'); /* used (no warning if not used) */ 140 1.1 cgd outname(hte->h_name); 141 1.1 cgd outtype(TP(sym->s_type)); 142 1.34 rillig outchar('\n'); 143 1.1 cgd } 144 1.1 cgd 145 1.36 rillig /* Write the first definition of a name into the lint library. */ 146 1.1 cgd static void 147 1.42 rillig dumpname(const hte_t *hte) 148 1.1 cgd { 149 1.31 rillig sym_t *sym, *def; 150 1.1 cgd 151 1.1 cgd /* static and undefined symbols are not written */ 152 1.1 cgd if (hte->h_static || !hte->h_def) 153 1.1 cgd return; 154 1.1 cgd 155 1.1 cgd /* 156 1.30 rillig * If there is a definition, write it. Otherwise, write a tentative 157 1.7 wiz * definition. This is necessary because more than one tentative 158 1.1 cgd * definition is allowed (except with sflag). 159 1.1 cgd */ 160 1.1 cgd def = NULL; 161 1.15 rillig for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) { 162 1.1 cgd if (sym->s_def == DEF) { 163 1.1 cgd def = sym; 164 1.1 cgd break; 165 1.1 cgd } 166 1.1 cgd if (sym->s_def == TDEF && def == NULL) 167 1.1 cgd def = sym; 168 1.1 cgd } 169 1.1 cgd if (def == NULL) 170 1.29 rillig errx(1, "internal error: dumpname %s", hte->h_name); 171 1.1 cgd 172 1.1 cgd outdef(hte, def); 173 1.1 cgd } 174 1.1 cgd 175 1.36 rillig /* Write a new lint library. */ 176 1.1 cgd void 177 1.6 lukem outlib(const char *name) 178 1.1 cgd { 179 1.35 rillig 180 1.1 cgd outopen(name); 181 1.1 cgd 182 1.35 rillig outsrc(name); /* name of the lint library */ 183 1.1 cgd 184 1.35 rillig outint(0); /* filename index of the lint library */ 185 1.1 cgd outchar('s'); 186 1.1 cgd outstrg(name); 187 1.34 rillig outchar('\n'); 188 1.1 cgd 189 1.35 rillig /* All files referenced by unnamed struct/union/enum declarations. */ 190 1.3 cgd outfiles(); 191 1.3 cgd 192 1.35 rillig /* Write all definitions with external linkage. */ 193 1.22 rillig symtab_forall_sorted(dumpname); 194 1.1 cgd 195 1.1 cgd outclose(); 196 1.3 cgd } 197 1.3 cgd 198 1.36 rillig /* Write out the name of a file referenced by a type. */ 199 1.3 cgd struct outflist { 200 1.6 lukem short ofl_num; 201 1.3 cgd struct outflist *ofl_next; 202 1.3 cgd }; 203 1.3 cgd static struct outflist *outflist; 204 1.3 cgd 205 1.3 cgd int 206 1.6 lukem addoutfile(short num) 207 1.3 cgd { 208 1.3 cgd struct outflist *ofl, **pofl; 209 1.3 cgd int i; 210 1.3 cgd 211 1.3 cgd ofl = outflist; 212 1.3 cgd pofl = &outflist; 213 1.3 cgd i = 1; /* library is 0 */ 214 1.3 cgd 215 1.3 cgd while (ofl != NULL) { 216 1.3 cgd if (ofl->ofl_num == num) 217 1.3 cgd break; 218 1.6 lukem 219 1.3 cgd pofl = &ofl->ofl_next; 220 1.3 cgd ofl = ofl->ofl_next; 221 1.3 cgd i++; 222 1.3 cgd } 223 1.3 cgd 224 1.3 cgd if (ofl == NULL) { 225 1.19 rillig ofl = *pofl = xmalloc(sizeof(**pofl)); 226 1.3 cgd ofl->ofl_num = num; 227 1.3 cgd ofl->ofl_next = NULL; 228 1.3 cgd } 229 1.14 rillig return i; 230 1.3 cgd } 231 1.3 cgd 232 1.4 christos static void 233 1.6 lukem outfiles(void) 234 1.3 cgd { 235 1.3 cgd struct outflist *ofl; 236 1.3 cgd int i; 237 1.3 cgd 238 1.3 cgd for (ofl = outflist, i = 1; ofl != NULL; ofl = ofl->ofl_next, i++) { 239 1.3 cgd outint(i); 240 1.3 cgd outchar('s'); 241 1.3 cgd outstrg(fnames[ofl->ofl_num]); 242 1.34 rillig outchar('\n'); 243 1.3 cgd } 244 1.1 cgd } 245