191586Smarkm/* $NetBSD: emit2.c,v 1.8 2002/01/21 19:49:52 tv Exp $ */ 212099Sjoerg 312099Sjoerg/* 491586Smarkm * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 512099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl 612099Sjoerg * All Rights Reserved. 712099Sjoerg * 812099Sjoerg * Redistribution and use in source and binary forms, with or without 912099Sjoerg * modification, are permitted provided that the following conditions 1012099Sjoerg * are met: 1112099Sjoerg * 1. Redistributions of source code must retain the above copyright 1212099Sjoerg * notice, this list of conditions and the following disclaimer. 1312099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1412099Sjoerg * notice, this list of conditions and the following disclaimer in the 1512099Sjoerg * documentation and/or other materials provided with the distribution. 1612099Sjoerg * 3. All advertising materials mentioning features or use of this software 1712099Sjoerg * must display the following acknowledgement: 1812099Sjoerg * This product includes software developed by Jochen Pohl for 1912099Sjoerg * The NetBSD Project. 2012099Sjoerg * 4. The name of the author may not be used to endorse or promote products 2112099Sjoerg * derived from this software without specific prior written permission. 2212099Sjoerg * 2312099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2412099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2512099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2612099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2712099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2812099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2912099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3012099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3112099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3212099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3312099Sjoerg */ 3412099Sjoerg 3591586Smarkm#include <sys/cdefs.h> 3691586Smarkm#if defined(__RCSID) && !defined(lint) 3791586Smarkm__RCSID("$NetBSD: emit2.c,v 1.8 2002/01/21 19:49:52 tv Exp $"); 3812099Sjoerg#endif 39148723Sstefanf__FBSDID("$FreeBSD$"); 4012099Sjoerg 41148723Sstefanf#include <err.h> 42148723Sstefanf 4312099Sjoerg#include "lint2.h" 4412099Sjoerg 4591586Smarkmstatic void outtype(type_t *); 4691586Smarkmstatic void outdef(hte_t *, sym_t *); 4791586Smarkmstatic void dumpname(hte_t *); 4891586Smarkmstatic void outfiles(void); 4912099Sjoerg 5012099Sjoerg/* 5112099Sjoerg * Write type into the output buffer. 5212099Sjoerg */ 5312099Sjoergstatic void 5491586Smarkmouttype(type_t *tp) 5512099Sjoerg{ 5612099Sjoerg int t, s, na; 5712099Sjoerg tspec_t ts; 5812099Sjoerg type_t **ap; 5912099Sjoerg 6012099Sjoerg while (tp != NULL) { 6112099Sjoerg if ((ts = tp->t_tspec) == INT && tp->t_isenum) 6212099Sjoerg ts = ENUM; 6312099Sjoerg switch (ts) { 6412099Sjoerg case CHAR: t = 'C'; s = '\0'; break; 6512099Sjoerg case SCHAR: t = 'C'; s = 's'; break; 6612099Sjoerg case UCHAR: t = 'C'; s = 'u'; break; 6712099Sjoerg case SHORT: t = 'S'; s = '\0'; break; 6812099Sjoerg case USHORT: t = 'S'; s = 'u'; break; 6912099Sjoerg case INT: t = 'I'; s = '\0'; break; 7012099Sjoerg case UINT: t = 'I'; s = 'u'; break; 7112099Sjoerg case LONG: t = 'L'; s = '\0'; break; 7212099Sjoerg case ULONG: t = 'L'; s = 'u'; break; 7312099Sjoerg case QUAD: t = 'Q'; s = '\0'; break; 7412099Sjoerg case UQUAD: t = 'Q'; s = 'u'; break; 7512099Sjoerg case FLOAT: t = 'D'; s = 's'; break; 7612099Sjoerg case DOUBLE: t = 'D'; s = '\0'; break; 7712099Sjoerg case LDOUBLE: t = 'D'; s = 'l'; break; 7812099Sjoerg case VOID: t = 'V'; s = '\0'; break; 7912099Sjoerg case PTR: t = 'P'; s = '\0'; break; 8012099Sjoerg case ARRAY: t = 'A'; s = '\0'; break; 8112099Sjoerg case ENUM: t = 'T'; s = 'e'; break; 8212099Sjoerg case STRUCT: t = 'T'; s = 's'; break; 8312099Sjoerg case UNION: t = 'T'; s = 'u'; break; 8412099Sjoerg case FUNC: 8512099Sjoerg if (tp->t_args != NULL && !tp->t_proto) { 8612099Sjoerg t = 'f'; 8712099Sjoerg } else { 8812099Sjoerg t = 'F'; 8912099Sjoerg } 9012099Sjoerg s = '\0'; 9112099Sjoerg break; 9212099Sjoerg default: 9312099Sjoerg errx(1, "internal error: outtype() 1"); 9412099Sjoerg } 9512099Sjoerg if (tp->t_const) 9612099Sjoerg outchar('c'); 9712099Sjoerg if (tp->t_volatile) 9812099Sjoerg outchar('v'); 9912099Sjoerg if (s != '\0') 10012099Sjoerg outchar(s); 10112099Sjoerg outchar(t); 10212099Sjoerg if (ts == ARRAY) { 10312099Sjoerg outint(tp->t_dim); 10412099Sjoerg } else if (ts == ENUM || ts == STRUCT || ts == UNION) { 10512099Sjoerg if (tp->t_istag) { 10612099Sjoerg outint(1); 10712099Sjoerg outname(tp->t_tag->h_name); 10812099Sjoerg } else if (tp->t_istynam) { 10912099Sjoerg outint(2); 11012099Sjoerg outname(tp->t_tynam->h_name); 11191586Smarkm } else if (tp->t_isuniqpos) { 11291586Smarkm outint(3); 11391586Smarkm outint(tp->t_uniqpos.p_line); 11491586Smarkm outchar('.'); 11591586Smarkm outint(tp->t_uniqpos.p_file); 11691586Smarkm outchar('.'); 11791586Smarkm outint(tp->t_uniqpos.p_uniq); 11891586Smarkm } else 11991586Smarkm errx(1, "internal error: outtype() 2"); 12012099Sjoerg } else if (ts == FUNC && tp->t_args != NULL) { 12112099Sjoerg na = 0; 12212099Sjoerg for (ap = tp->t_args; *ap != NULL; ap++) 12312099Sjoerg na++; 12412099Sjoerg if (tp->t_vararg) 12512099Sjoerg na++; 12612099Sjoerg outint(na); 12712099Sjoerg for (ap = tp->t_args; *ap != NULL; ap++) 12812099Sjoerg outtype(*ap); 12912099Sjoerg if (tp->t_vararg) 13012099Sjoerg outchar('E'); 13112099Sjoerg } 13212099Sjoerg tp = tp->t_subt; 13312099Sjoerg } 13412099Sjoerg} 13512099Sjoerg 13612099Sjoerg/* 13712099Sjoerg * Write a definition. 13812099Sjoerg */ 13912099Sjoergstatic void 14091586Smarkmoutdef(hte_t *hte, sym_t *sym) 14112099Sjoerg{ 14291586Smarkm 14312099Sjoerg /* reset output buffer */ 14412099Sjoerg outclr(); 14512099Sjoerg 14612099Sjoerg /* line number in C source file */ 14712099Sjoerg outint(0); 14812099Sjoerg 14912099Sjoerg /* this is a definition */ 15012099Sjoerg outchar('d'); 15112099Sjoerg 15212099Sjoerg /* index of file where symbol was defined and line number of def. */ 15312099Sjoerg outint(0); 15412099Sjoerg outchar('.'); 15512099Sjoerg outint(0); 15612099Sjoerg 15712099Sjoerg /* flags */ 15812099Sjoerg if (sym->s_va) { 15912099Sjoerg outchar('v'); /* varargs */ 16012099Sjoerg outint(sym->s_nva); 16112099Sjoerg } 16212099Sjoerg if (sym->s_scfl) { 16312099Sjoerg outchar('S'); /* scanflike */ 16412099Sjoerg outint(sym->s_nscfl); 16512099Sjoerg } 16612099Sjoerg if (sym->s_prfl) { 16712099Sjoerg outchar('P'); /* printflike */ 16812099Sjoerg outint(sym->s_nprfl); 16912099Sjoerg } 17012099Sjoerg /* definition or tentative definition */ 17112099Sjoerg outchar(sym->s_def == DEF ? 'd' : 't'); 17212099Sjoerg if (TP(sym->s_type)->t_tspec == FUNC) { 17312099Sjoerg if (sym->s_rval) 17412099Sjoerg outchar('r'); /* fkt. has return value */ 17512099Sjoerg if (sym->s_osdef) 17612099Sjoerg outchar('o'); /* old style definition */ 17712099Sjoerg } 17812099Sjoerg outchar('u'); /* used (no warning if not used) */ 17912099Sjoerg 18012099Sjoerg /* name */ 18112099Sjoerg outname(hte->h_name); 18212099Sjoerg 18312099Sjoerg /* type */ 18412099Sjoerg outtype(TP(sym->s_type)); 18512099Sjoerg} 18612099Sjoerg 18712099Sjoerg/* 18812099Sjoerg * Write the first definition of a name into the lint library. 18912099Sjoerg */ 19012099Sjoergstatic void 19191586Smarkmdumpname(hte_t *hte) 19212099Sjoerg{ 19312099Sjoerg sym_t *sym, *def; 19412099Sjoerg 19512099Sjoerg /* static and undefined symbols are not written */ 19612099Sjoerg if (hte->h_static || !hte->h_def) 19712099Sjoerg return; 19812099Sjoerg 19912099Sjoerg /* 20012099Sjoerg * If there is a definition, write it. Otherwise write a tentative 20191586Smarkm * definition. This is necessary because more than one tentative 20212099Sjoerg * definition is allowed (except with sflag). 20312099Sjoerg */ 20412099Sjoerg def = NULL; 20512099Sjoerg for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { 20612099Sjoerg if (sym->s_def == DEF) { 20712099Sjoerg def = sym; 20812099Sjoerg break; 20912099Sjoerg } 21012099Sjoerg if (sym->s_def == TDEF && def == NULL) 21112099Sjoerg def = sym; 21212099Sjoerg } 21312099Sjoerg if (def == NULL) 21412099Sjoerg errx(1, "internal error: dumpname() %s", hte->h_name); 21512099Sjoerg 21612099Sjoerg outdef(hte, def); 21712099Sjoerg} 21812099Sjoerg 21912099Sjoerg/* 22012099Sjoerg * Write a new lint library. 22112099Sjoerg */ 22212099Sjoergvoid 22391586Smarkmoutlib(const char *name) 22412099Sjoerg{ 22512099Sjoerg /* Open of output file and initialisation of the output buffer */ 22612099Sjoerg outopen(name); 22712099Sjoerg 22812099Sjoerg /* write name of lint library */ 22912099Sjoerg outsrc(name); 23012099Sjoerg 23112099Sjoerg /* name of lint lib has index 0 */ 23212099Sjoerg outclr(); 23312099Sjoerg outint(0); 23412099Sjoerg outchar('s'); 23512099Sjoerg outstrg(name); 23612099Sjoerg 23791586Smarkm /* 23891586Smarkm * print the names of all files references by unnamed 23991586Smarkm * struct/union/enum declarations. 24091586Smarkm */ 24191586Smarkm outfiles(); 24291586Smarkm 24312099Sjoerg /* write all definitions with external linkage */ 24412099Sjoerg forall(dumpname); 24512099Sjoerg 24612099Sjoerg /* close the output */ 24712099Sjoerg outclose(); 24812099Sjoerg} 24991586Smarkm 25091586Smarkm/* 25191586Smarkm * Write out the name of a file referenced by a type. 25291586Smarkm */ 25391586Smarkmstruct outflist { 25491586Smarkm short ofl_num; 25591586Smarkm struct outflist *ofl_next; 25691586Smarkm}; 25791586Smarkmstatic struct outflist *outflist; 25891586Smarkm 25991586Smarkmint 26091586Smarkmaddoutfile(short num) 26191586Smarkm{ 26291586Smarkm struct outflist *ofl, **pofl; 26391586Smarkm int i; 26491586Smarkm 26591586Smarkm ofl = outflist; 26691586Smarkm pofl = &outflist; 26791586Smarkm i = 1; /* library is 0 */ 26891586Smarkm 26991586Smarkm while (ofl != NULL) { 27091586Smarkm if (ofl->ofl_num == num) 27191586Smarkm break; 27291586Smarkm 27391586Smarkm pofl = &ofl->ofl_next; 27491586Smarkm ofl = ofl->ofl_next; 27591586Smarkm i++; 27691586Smarkm } 27791586Smarkm 27891586Smarkm if (ofl == NULL) { 27991586Smarkm ofl = *pofl = xmalloc(sizeof (struct outflist)); 28091586Smarkm ofl->ofl_num = num; 28191586Smarkm ofl->ofl_next = NULL; 28291586Smarkm } 28391586Smarkm return (i); 28491586Smarkm} 28591586Smarkm 28691586Smarkmstatic void 28791586Smarkmoutfiles(void) 28891586Smarkm{ 28991586Smarkm struct outflist *ofl; 29091586Smarkm int i; 29191586Smarkm 29291586Smarkm for (ofl = outflist, i = 1; ofl != NULL; ofl = ofl->ofl_next, i++) { 29391586Smarkm /* reset output buffer */ 29491586Smarkm outclr(); 29591586Smarkm 29691586Smarkm outint(i); 29791586Smarkm outchar('s'); 29891586Smarkm outstrg(fnames[ofl->ofl_num]); 29991586Smarkm } 30091586Smarkm} 301