162587Sitojun/* $NetBSD: emit2.c,v 1.39 2024/05/12 18:49:36 rillig Exp $ */ 262587Sitojun 362587Sitojun/* 453541Sshin * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 553541Sshin * Copyright (c) 1994, 1995 Jochen Pohl 653541Sshin * All Rights Reserved. 753541Sshin * 853541Sshin * Redistribution and use in source and binary forms, with or without 953541Sshin * modification, are permitted provided that the following conditions 1053541Sshin * are met: 1153541Sshin * 1. Redistributions of source code must retain the above copyright 1253541Sshin * notice, this list of conditions and the following disclaimer. 1353541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1453541Sshin * notice, this list of conditions and the following disclaimer in the 1553541Sshin * documentation and/or other materials provided with the distribution. 1653541Sshin * 3. All advertising materials mentioning features or use of this software 1753541Sshin * must display the following acknowledgement: 1853541Sshin * This product includes software developed by Jochen Pohl for 1953541Sshin * The NetBSD Project. 2053541Sshin * 4. The name of the author may not be used to endorse or promote products 2153541Sshin * derived from this software without specific prior written permission. 2253541Sshin * 2353541Sshin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2453541Sshin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2553541Sshin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2653541Sshin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2753541Sshin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2853541Sshin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2953541Sshin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3053541Sshin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3153541Sshin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3253541Sshin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3353541Sshin */ 3453541Sshin 3553541Sshin#include <sys/cdefs.h> 3653541Sshin#if defined(__RCSID) 3753541Sshin__RCSID("$NetBSD: emit2.c,v 1.39 2024/05/12 18:49:36 rillig Exp $"); 3853541Sshin#endif 3953541Sshin 4053541Sshin#include "lint2.h" 4153541Sshin 4253541Sshinstatic void outtype(type_t *); 4353541Sshinstatic void outdef(hte_t *, sym_t *); 4453541Sshinstatic void dumpname(hte_t *); 4553541Sshinstatic void outfiles(void); 4653541Sshin 4753541Sshin/* Write type into the output file. */ 4853541Sshinstatic void 4953541Sshinouttype(type_t *tp) 5053541Sshin{ 5153541Sshin#ifdef INT128_SIZE 5253541Sshin static const char tt[NTSPEC] = "???BCCCSSIILLQQJJDDD?XXXVTTTPAF"; 5353541Sshin static const char ss[NTSPEC] = "??? su u u u u us l?s l sue "; 5453541Sshin#else 5553541Sshin static const char tt[NTSPEC] = "???BCCCSSIILLQQDDD?XXXVTTTPAF"; 5653541Sshin static const char ss[NTSPEC] = "??? su u u u us l?s l sue "; 5753541Sshin#endif 5853541Sshin 5953541Sshin while (tp != NULL) { 6053541Sshin tspec_t ts = tp->t_tspec; 6153541Sshin if (ts == INT && tp->t_is_enum) 6253541Sshin ts = ENUM; 6353541Sshin if (!ch_isupper(tt[ts])) 6453541Sshin errx(1, "internal error: outtype(%d)", ts); 6553541Sshin if (tp->t_const) 6653541Sshin outchar('c'); 6753541Sshin if (tp->t_volatile) 6855679Sshin outchar('v'); 6962587Sitojun if (ss[ts] != ' ') 7055009Sshin outchar(ss[ts]); 7155009Sshin if (ts == FUNC && tp->t_args != NULL && !tp->t_proto) 7253541Sshin outchar('f'); 7353541Sshin else 7453541Sshin outchar(tt[ts]); 7553541Sshin 7653541Sshin if (ts == ARRAY) { 7753541Sshin outint(tp->t_dim); 7853541Sshin } else if (ts == ENUM || ts == STRUCT || ts == UNION) { 7953541Sshin if (tp->t_istag) { 8053541Sshin outint(1); 8153541Sshin outname(tp->t_tag->h_name); 8253541Sshin } else if (tp->t_istynam) { 8353541Sshin outint(2); 8453541Sshin outname(tp->t_tynam->h_name); 8553541Sshin } else if (tp->t_isuniqpos) { 8653541Sshin outint(3); 8753541Sshin outint(tp->t_uniqpos.p_line); 8853541Sshin outchar('.'); 8962587Sitojun outint(tp->t_uniqpos.p_file); 9053541Sshin outchar('.'); 9153541Sshin outint(tp->t_uniqpos.p_uniq); 9262587Sitojun } else 9353541Sshin errx(1, "internal error: outtype"); 9462587Sitojun } else if (ts == FUNC && tp->t_args != NULL) { 9553541Sshin int na = 0; 9653541Sshin for (type_t **ap = tp->t_args; *ap != NULL; ap++) 9753541Sshin na++; 9853541Sshin if (tp->t_vararg) 9953541Sshin na++; 10053541Sshin outint(na); 10153541Sshin for (type_t **ap = tp->t_args; *ap != NULL; ap++) 10262587Sitojun outtype(*ap); 10353541Sshin if (tp->t_vararg) 10453541Sshin outchar('E'); 10553541Sshin } 10653541Sshin tp = tp->t_subt; 10753541Sshin } 10853541Sshin} 10953541Sshin 11053541Sshin/* Write a definition. */ 11153541Sshinstatic void 11262587Sitojunoutdef(hte_t *hte, sym_t *sym) 11355009Sshin{ 11455009Sshin 11553541Sshin outint(0); /* line number in C source file */ 11653541Sshin outchar('d'); /* definition */ 11755009Sshin outint(0); /* index of file where symbol was defined */ 11853541Sshin outchar('.'); 11962587Sitojun outint(0); /* line number of definition */ 12062587Sitojun 12153541Sshin /* flags */ 12253541Sshin if (sym->s_check_only_first_args) { 12353541Sshin outchar('v'); 12453541Sshin outint(sym->s_check_num_args); 12554263Sshin } 12653541Sshin if (sym->s_scanflike) { 12753541Sshin outchar('S'); 12853541Sshin outint(sym->s_scanflike_arg); 12953541Sshin } 13053541Sshin if (sym->s_printflike) { 13153541Sshin outchar('P'); 13253541Sshin outint(sym->s_printflike_arg); 13353541Sshin } 13453541Sshin /* definition or tentative definition */ 13553541Sshin outchar(sym->s_def == DEF ? 'd' : 't'); 13653541Sshin if (TP(sym->s_type)->t_tspec == FUNC) { 13753541Sshin if (sym->s_function_has_return_value) 13862587Sitojun outchar('r'); 13962587Sitojun if (sym->s_old_style_function) 14053541Sshin outchar('o'); 14153541Sshin } 14253541Sshin outchar('u'); /* used (no warning if not used) */ 14353541Sshin outname(hte->h_name); 14453541Sshin outtype(TP(sym->s_type)); 14553541Sshin outchar('\n'); 14653541Sshin} 14753541Sshin 14854263Sshin/* Write the first definition of a name into the lint library. */ 14954263Sshinstatic void 15054263Sshindumpname(hte_t *hte) 15154263Sshin{ 15254263Sshin sym_t *sym, *def; 15354263Sshin 15455679Sshin /* static and undefined symbols are not written */ 15555679Sshin if (hte->h_static || !hte->h_def) 15655679Sshin return; 15755679Sshin 15855679Sshin /* 15955679Sshin * If there is a definition, write it. Otherwise, write a tentative 16062587Sitojun * definition. This is necessary because more than one tentative 16155679Sshin * definition is allowed (except with sflag). 16255679Sshin */ 16355679Sshin def = NULL; 16453541Sshin for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) { 16562587Sitojun if (sym->s_def == DEF) { 16653541Sshin def = sym; 16753541Sshin break; 16853541Sshin } 16953541Sshin if (sym->s_def == TDEF && def == NULL) 17053541Sshin def = sym; 17153541Sshin } 17253541Sshin if (def == NULL) 17353541Sshin errx(1, "internal error: dumpname %s", hte->h_name); 17453541Sshin 17553541Sshin outdef(hte, def); 17653541Sshin} 17753541Sshin 17862587Sitojun/* Write a new lint library. */ 17953541Sshinvoid 18053541Sshinoutlib(const char *name) 18153541Sshin{ 18253541Sshin 18353541Sshin outopen(name); 18462587Sitojun 18553541Sshin outsrc(name); /* name of the lint library */ 18653541Sshin 18753541Sshin outint(0); /* filename index of the lint library */ 18853541Sshin outchar('s'); 18953541Sshin outstrg(name); 19062587Sitojun outchar('\n'); 19153541Sshin 19253541Sshin /* All files referenced by unnamed struct/union/enum declarations. */ 19353541Sshin outfiles(); 19453541Sshin 19553541Sshin /* Write all definitions with external linkage. */ 19653541Sshin symtab_forall_sorted(dumpname); 19762587Sitojun 19853541Sshin outclose(); 19953541Sshin} 20053541Sshin 20153541Sshin/* Write out the name of a file referenced by a type. */ 20253541Sshinstruct outflist { 20353541Sshin short ofl_num; 20462587Sitojun struct outflist *ofl_next; 20553541Sshin}; 20653541Sshinstatic struct outflist *outflist; 20753541Sshin 20853541Sshinint 20962587Sitojunaddoutfile(short num) 21062587Sitojun{ 21162587Sitojun struct outflist *ofl, **pofl; 21262587Sitojun int i; 21362587Sitojun 21462587Sitojun ofl = outflist; 21553541Sshin pofl = &outflist; 21662587Sitojun i = 1; /* library is 0 */ 21753541Sshin 21862587Sitojun while (ofl != NULL) { 21962587Sitojun if (ofl->ofl_num == num) 22053541Sshin break; 22162587Sitojun 22253541Sshin pofl = &ofl->ofl_next; 22362587Sitojun ofl = ofl->ofl_next; 22453541Sshin i++; 22562587Sitojun } 22654263Sshin 22762587Sitojun if (ofl == NULL) { 22862587Sitojun ofl = *pofl = xmalloc(sizeof(**pofl)); 22962587Sitojun ofl->ofl_num = num; 23053541Sshin ofl->ofl_next = NULL; 23162587Sitojun } 23262587Sitojun return i; 23353541Sshin} 23456722Sshin 23562587Sitojunstatic void 23656722Sshinoutfiles(void) 23762587Sitojun{ 23856722Sshin struct outflist *ofl; 23956722Sshin int i; 24053541Sshin 24153541Sshin for (ofl = outflist, i = 1; ofl != NULL; ofl = ofl->ofl_next, i++) { 24253541Sshin outint(i); 24362587Sitojun outchar('s'); 24462587Sitojun outstrg(fnames[ofl->ofl_num]); 24553541Sshin outchar('\n'); 24653541Sshin } 24753541Sshin} 24853541Sshin