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