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