xref: /titanic_52/usr/src/tools/lintdump/lintdump.c (revision 5cb4fc8151d97cf08a87f2d1011efed091d169ea)
134c98957Smeem /*
234c98957Smeem  * CDDL HEADER START
334c98957Smeem  *
434c98957Smeem  * The contents of this file are subject to the terms of the
534c98957Smeem  * Common Development and Distribution License (the "License").
634c98957Smeem  * You may not use this file except in compliance with the License.
734c98957Smeem  *
834c98957Smeem  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
934c98957Smeem  * or http://www.opensolaris.org/os/licensing.
1034c98957Smeem  * See the License for the specific language governing permissions
1134c98957Smeem  * and limitations under the License.
1234c98957Smeem  *
1334c98957Smeem  * When distributing Covered Code, include this CDDL HEADER in each
1434c98957Smeem  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1534c98957Smeem  * If applicable, add the following below this CDDL HEADER, with the
1634c98957Smeem  * fields enclosed by brackets "[]" replaced with your own identifying
1734c98957Smeem  * information: Portions Copyright [yyyy] [name of copyright owner]
1834c98957Smeem  *
1934c98957Smeem  * CDDL HEADER END
2034c98957Smeem  */
2134c98957Smeem 
2234c98957Smeem /*
23*5cb4fc81Smeem  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2434c98957Smeem  * Use is subject to license terms.
2534c98957Smeem  */
2634c98957Smeem 
2734c98957Smeem #pragma ident	"@(#)lintdump.c	1.6	06/06/04 SMI (from meem)"
2834c98957Smeem #pragma ident	"%Z%%M%	%I%	%E% SMI"
2934c98957Smeem 
3034c98957Smeem /*
3134c98957Smeem  * Tool for dumping lint libraries.
3234c98957Smeem  */
3334c98957Smeem 
3434c98957Smeem #include <ctype.h>
3534c98957Smeem #include <errno.h>
3634c98957Smeem #include <stdarg.h>
3734c98957Smeem #include <stdio.h>
3834c98957Smeem #include <stdlib.h>
3934c98957Smeem #include <string.h>
4034c98957Smeem #include <sys/types.h>
4134c98957Smeem 
4234c98957Smeem #include "lnstuff.h"		/* silly header name from alint */
4334c98957Smeem 
4434c98957Smeem typedef struct lsu {
4534c98957Smeem 	const char	*name;
4634c98957Smeem 	ATYPE		atype;
4734c98957Smeem 	struct lsu	*next;
4834c98957Smeem } lsu_t;
4934c98957Smeem 
5034c98957Smeem #define	LSU_HASHSIZE	512
5134c98957Smeem static lsu_t		*lsu_table[LSU_HASHSIZE];
5234c98957Smeem 
5334c98957Smeem static boolean_t	showids = B_TRUE;
5434c98957Smeem static boolean_t	justrelpaths = B_FALSE;
5534c98957Smeem static int		justpass = -1;
5634c98957Smeem static int		indentlevel = 9;
5734c98957Smeem static const char	*progname;
5834c98957Smeem 
5934c98957Smeem static void info(const char *, ...);
6034c98957Smeem static void infohdr(const char *, const char *, ...);
6134c98957Smeem static void warn(const char *, ...);
6234c98957Smeem static void die(const char *, ...);
6334c98957Smeem static void usage(void);
6434c98957Smeem static void indent(void);
6534c98957Smeem static void unindent(void);
6634c98957Smeem static void print_lintlib(const char *, FILE *, FLENS *);
67b4034a75Smeem static void print_pass(const char *, FILE *);
6834c98957Smeem static void print_atype(ATYPE *, int, ATYPE *, const char *);
6934c98957Smeem static void print_mods(const char *, ATYPE *, int, ATYPE *, uint_t);
7034c98957Smeem static void getstr(FILE *, char *, size_t);
7134c98957Smeem static void lsu_build(FILE *);
7234c98957Smeem static void lsu_empty(void);
7334c98957Smeem static int lsu_add(const char *, ATYPE *);
7434c98957Smeem static lsu_t *lsu_lookup(unsigned long);
7534c98957Smeem 
7634c98957Smeem int
7734c98957Smeem main(int argc, char **argv)
7834c98957Smeem {
7934c98957Smeem 	int	i, c;
8034c98957Smeem 	FILE	*fp;
8134c98957Smeem 	FLENS	hdr;
8234c98957Smeem 
8334c98957Smeem 	progname = strrchr(argv[0], '/');
8434c98957Smeem 	if (progname == NULL)
8534c98957Smeem 		progname = argv[0];
8634c98957Smeem 	else
8734c98957Smeem 		progname++;
8834c98957Smeem 
8934c98957Smeem 	while ((c = getopt(argc, argv, "ip:r")) != EOF) {
9034c98957Smeem 		switch (c) {
9134c98957Smeem 		case 'i':
9234c98957Smeem 			showids = B_FALSE;
9334c98957Smeem 			break;
9434c98957Smeem 		case 'p':
9534c98957Smeem 			justpass = strtoul(optarg, NULL, 0);
9634c98957Smeem 			if (justpass < 1 || justpass > 3)
9734c98957Smeem 				usage();
9834c98957Smeem 			break;
9934c98957Smeem 		case 'r':
10034c98957Smeem 			justrelpaths = B_TRUE;
10134c98957Smeem 			break;
10234c98957Smeem 		default:
10334c98957Smeem 			usage();
10434c98957Smeem 		}
10534c98957Smeem 	}
10634c98957Smeem 
10734c98957Smeem 	if (optind == argc)
10834c98957Smeem 		usage();
10934c98957Smeem 
11034c98957Smeem 	for (i = optind; i < argc; i++) {
11134c98957Smeem 		fp = fopen(argv[i], "r");
11234c98957Smeem 		if (fp == NULL) {
11334c98957Smeem 			warn("cannot open \"%s\"", argv[i]);
11434c98957Smeem 			continue;
11534c98957Smeem 		}
11634c98957Smeem 
11734c98957Smeem 		if (fread(&hdr, sizeof (hdr), 1, fp) < 1) {
11834c98957Smeem 			warn("%s: cannot read lint library header\n", argv[i]);
11934c98957Smeem 			(void) fclose(fp);
12034c98957Smeem 			continue;
12134c98957Smeem 		}
12234c98957Smeem 
12334c98957Smeem 		if (hdr.ver != LINTVER) {
12434c98957Smeem 			warn("%s: lint library version %d unsupported\n",
12534c98957Smeem 			    argv[i], hdr.ver);
12634c98957Smeem 			(void) fclose(fp);
12734c98957Smeem 			continue;
12834c98957Smeem 		}
12934c98957Smeem 
13034c98957Smeem 		/*
13134c98957Smeem 		 * First build the table of structure/union names, then seek
13234c98957Smeem 		 * back to the start and print the lint library.  Finally,
13334c98957Smeem 		 * empty the table out before dumping the next library.
13434c98957Smeem 		 */
13534c98957Smeem 		lsu_build(fp);
13634c98957Smeem 		(void) fseek(fp, sizeof (hdr), SEEK_SET);
13734c98957Smeem 		print_lintlib(argv[i], fp, &hdr);
13834c98957Smeem 		(void) fclose(fp);
13934c98957Smeem 		lsu_empty();
14034c98957Smeem 	}
14134c98957Smeem 
14234c98957Smeem 	return (EXIT_SUCCESS);
14334c98957Smeem }
14434c98957Smeem 
14534c98957Smeem /*
14634c98957Smeem  * Print a lint library.
14734c98957Smeem  */
14834c98957Smeem static void
14934c98957Smeem print_lintlib(const char *lnname, FILE *fp, FLENS *hp)
15034c98957Smeem {
15134c98957Smeem 	off_t		passoff = 0;
15234c98957Smeem 	ulong_t		psizes[4];
15334c98957Smeem 	uint_t		pass;
15434c98957Smeem 
15534c98957Smeem 	psizes[0] = 0;
15634c98957Smeem 	psizes[1] = hp->f1;
15734c98957Smeem 	psizes[2] = hp->f2;
15834c98957Smeem 	psizes[3] = hp->f3;
15934c98957Smeem 
16034c98957Smeem 	if (justrelpaths && lnname[0] == '/')
16134c98957Smeem 		lnname = strrchr(lnname, '/') + 1;
16234c98957Smeem 
16334c98957Smeem 	infohdr("LINTLIB", "%s <mid %hu> %lu+%lu+%lu+%lu = %lu bytes\n", lnname,
16434c98957Smeem 	    hp->mno, hp->f1, hp->f2, hp->f3, hp->f4,
16534c98957Smeem 	    hp->f1 + hp->f2 + hp->f3 + hp->f4);
16634c98957Smeem 
16734c98957Smeem 	for (pass = 1; pass <= 3; pass++) {
16834c98957Smeem 		if (justpass < 0 || justpass == pass) {
16934c98957Smeem 			infohdr("SECTION", "PASS%u: %lu bytes\n", pass,
17034c98957Smeem 			    psizes[pass]);
171b4034a75Smeem 			print_pass(lnname, fp);
17234c98957Smeem 		}
17334c98957Smeem 		passoff += psizes[pass];
17434c98957Smeem 		(void) fseek(fp, passoff, SEEK_SET);
17534c98957Smeem 	}
17634c98957Smeem }
17734c98957Smeem 
17834c98957Smeem /*
17934c98957Smeem  * Print out a PASS section of a lint library.
18034c98957Smeem  */
18134c98957Smeem static void
182b4034a75Smeem print_pass(const char *lnname, FILE *fp)
18334c98957Smeem {
18434c98957Smeem 	union rec	rec;
18534c98957Smeem 	int		nargs;
18634c98957Smeem 	char		name[1024];
18734c98957Smeem 	ATYPE		atype, *args;
18834c98957Smeem 	LINE		line;
18934c98957Smeem 	boolean_t	wasfile = B_FALSE;
19034c98957Smeem 
19134c98957Smeem 	for (;;) {
19234c98957Smeem 		if (fread(&rec, sizeof (rec), 1, fp) != 1)
193b4034a75Smeem 			die("%s: unexpected end of file\n", lnname);
19434c98957Smeem 
19534c98957Smeem 		line = rec.l;
19634c98957Smeem 		if (line.decflag & LND)		/* end-of-pass marker */
19734c98957Smeem 			break;
19834c98957Smeem 
19934c98957Smeem 		getstr(fp, name, sizeof (name));
20034c98957Smeem 
20134c98957Smeem 		/*
20234c98957Smeem 		 * Check if this is a file record.
20334c98957Smeem 		 */
20434c98957Smeem 		if (line.decflag & LFN) {
20534c98957Smeem 			if (wasfile || !justrelpaths)
20634c98957Smeem 				infohdr("FILE", "%s\n", name);
20734c98957Smeem 			wasfile = B_TRUE;
20834c98957Smeem 			continue;
20934c98957Smeem 		}
21034c98957Smeem 		wasfile = B_FALSE;
21134c98957Smeem 
21234c98957Smeem 		/*
21334c98957Smeem 		 * Check if this is a function or variable record.
21434c98957Smeem 		 */
21534c98957Smeem 		nargs = line.nargs;
21634c98957Smeem 		if (line.decflag & (LIB|LDS|LDI|LPR|LDX|LDC|LRV|LUE|LUV|LUM)) {
21734c98957Smeem 			if (nargs < 0)
21834c98957Smeem 				nargs = -nargs - 1;
21934c98957Smeem 
22034c98957Smeem 			if (line.decflag & LDS)
22134c98957Smeem 				info("static ");
22234c98957Smeem 			else if (line.decflag & (LPR|LDX|LDC))
22334c98957Smeem 				info("extern ");
22434c98957Smeem 
22534c98957Smeem 			args = calloc(sizeof (atype), nargs);
22634c98957Smeem 			if (args == NULL)
22734c98957Smeem 				die("cannot allocate argument information");
22834c98957Smeem 
22934c98957Smeem 			if (fread(args, sizeof (atype), nargs, fp) != nargs)
230b4034a75Smeem 				die("%s: unexpected end of file\n", lnname);
23134c98957Smeem 
23234c98957Smeem 			print_atype(&line.type, line.nargs, args, name);
23334c98957Smeem 			free(args);
23434c98957Smeem 
23534c98957Smeem 			if (line.decflag & LRV)
23634c98957Smeem 				info(" <returns value>");
23734c98957Smeem 			if (line.decflag & LUE)
23834c98957Smeem 				info(" <use: side-effects context>");
23934c98957Smeem 			if (line.decflag & LUV)
24034c98957Smeem 				info(" <use: return value context>");
24134c98957Smeem 			if (line.decflag & LUM)
24234c98957Smeem 				info(" <use: unspecified context>");
24334c98957Smeem 
24434c98957Smeem 			if (line.decflag & LPF)
24534c98957Smeem 				info(" <PRINTFLIKE%d>", nargs);
24634c98957Smeem 			else if (line.decflag & LSF)
24734c98957Smeem 				info(" <SCANFLIKE%d>", nargs);
24834c98957Smeem 
24934c98957Smeem 			if (line.decflag & LDI)
25034c98957Smeem 				info(" { <definition> }");
25134c98957Smeem 			else if (line.decflag & LDX)
25234c98957Smeem 				info(" = <definition>");
25334c98957Smeem 
25434c98957Smeem 			info(";\n");
25534c98957Smeem 			continue;
25634c98957Smeem 		}
25734c98957Smeem 
25834c98957Smeem 		/*
25934c98957Smeem 		 * Check if this is a structure or union record.
26034c98957Smeem 		 */
26134c98957Smeem 		if (line.decflag & LSU) {
26234c98957Smeem 			if (line.decflag & ~(LSU))
26334c98957Smeem 				info("??? ");
26434c98957Smeem 
265*5cb4fc81Smeem 			info("struct ");
266*5cb4fc81Smeem 			if (name[0] != '.')
267*5cb4fc81Smeem 				info("%s ", name);
26834c98957Smeem 			if (showids)
26934c98957Smeem 				info("<tag %lu> ", line.type.extra.ty);
27034c98957Smeem 			info("{ \n");
27134c98957Smeem 
27234c98957Smeem 			indent();
27334c98957Smeem 			for (; nargs > 0; nargs--) {
274b4034a75Smeem 				if (fread(&atype, sizeof (atype), 1, fp) != 1) {
275b4034a75Smeem 					die("%s: unexpected end of file\n",
276b4034a75Smeem 					    lnname);
277b4034a75Smeem 				}
27834c98957Smeem 				getstr(fp, name, sizeof (name));
27934c98957Smeem 				print_atype(&atype, 0, NULL, name);
28034c98957Smeem 				info(";\n");
28134c98957Smeem 			}
28234c98957Smeem 			unindent();
28334c98957Smeem 			info("};\n");
28434c98957Smeem 			continue;
28534c98957Smeem 		}
28634c98957Smeem 
287b4034a75Smeem 		warn("%s: unknown record type 0%o\n", lnname, line.decflag);
28834c98957Smeem 	}
28934c98957Smeem }
29034c98957Smeem 
29134c98957Smeem /*
29234c98957Smeem  * Print the C datatype or function `atp' named `name'.  If `name' is a
29334c98957Smeem  * function, then `nargs' indicates the number of C datatypes pointed to
29434c98957Smeem  * by `args'.
29534c98957Smeem  */
29634c98957Smeem static void
29734c98957Smeem print_atype(ATYPE *atp, int nargs, ATYPE *args, const char *name)
29834c98957Smeem {
29934c98957Smeem 	static const char *basetypes[] = {		"",
30034c98957Smeem 		"char",		"unsigned char",	"signed char",
30134c98957Smeem 		"short",	"unsigned short",	"signed short",
30234c98957Smeem 		"int",		"unsigned int",		"signed int",
30334c98957Smeem 		"long",		"unsigned long",	"signed long",
30434c98957Smeem 		"long long",	"unsigned long long",	"signed long long",
30534c98957Smeem 		"enum",		"float",		"double",
30634c98957Smeem 		"long double",	"void",			"struct",
30734c98957Smeem 		"union",	"_Bool",		"<genchar>",
30834c98957Smeem 		"<genshort>",	"<genint>",		"<genlong>",
30934c98957Smeem 		"<genlonglong>"
31034c98957Smeem 	};
31134c98957Smeem 	uint16_t basetype = atp->aty & LNQUAL;
31234c98957Smeem 	lsu_t *lsup;
31334c98957Smeem 
31434c98957Smeem 	if (atp->aty & LCON)
31534c98957Smeem 		info("const ");
31634c98957Smeem 	if (atp->aty & LVOL)
31734c98957Smeem 		info("volatile ");
31834c98957Smeem 	if (atp->aty & LCONV)
31934c98957Smeem 		info("integer const ");
32034c98957Smeem 
32134c98957Smeem 	if (basetype < 1 ||
32234c98957Smeem 	    basetype > (sizeof (basetypes) / sizeof (*basetypes)))
32334c98957Smeem 		info("<unknown type %x>", basetype);
32434c98957Smeem 
32534c98957Smeem 	switch (basetype) {
32634c98957Smeem 	case LN_UNION:
32734c98957Smeem 	case LN_STRUCT:
32834c98957Smeem 		lsup = lsu_lookup(atp->extra.ty);
32934c98957Smeem 		if (lsup != NULL && lsup->name[0] != '.') {
33034c98957Smeem 			info("%s %s", basetypes[basetype], lsup->name);
33134c98957Smeem 		} else {
33234c98957Smeem 			info("%s", basetypes[basetype]);
33334c98957Smeem 			if (showids)
33434c98957Smeem 				info(" <tag %lu>", atp->extra.ty);
33534c98957Smeem 			else
33634c98957Smeem 				info(" <anon>");
33734c98957Smeem 		}
33834c98957Smeem 		break;
33934c98957Smeem 	default:
340*5cb4fc81Smeem 		info("%s", basetypes[basetype]);
34134c98957Smeem 	};
34234c98957Smeem 
34334c98957Smeem 	print_mods(name, atp, nargs, args, 14);
34434c98957Smeem }
34534c98957Smeem 
34634c98957Smeem /*
34734c98957Smeem  * Recursively print type modifiers.
34834c98957Smeem  */
34934c98957Smeem static void
35034c98957Smeem print_mods(const char *name, ATYPE *atp, int nargs, ATYPE *args, uint_t pos)
35134c98957Smeem {
35234c98957Smeem 	int arg;
35334c98957Smeem 	int mods = atp->dcl_mod >> (pos * 2);
35434c98957Smeem 	int lastmods = atp->dcl_mod >> ((pos + 1) * 2);
35534c98957Smeem 	boolean_t isvarargs = B_FALSE;
35634c98957Smeem 
35734c98957Smeem 	if (LN_ISPTR(mods)) {
35834c98957Smeem 		if (!LN_ISPTR(lastmods) && !LN_ISFTN(lastmods))
35934c98957Smeem 			info(" ");
36034c98957Smeem 		info("*");
36134c98957Smeem 	}
36234c98957Smeem 
36334c98957Smeem 	if (atp->dcl_con & (1 << pos))
36434c98957Smeem 		info(" const ");
36534c98957Smeem 	if (atp->dcl_vol & (1 << pos))
36634c98957Smeem 		info(" volatile ");
36734c98957Smeem 
36834c98957Smeem 	if (pos != 0) {
36934c98957Smeem 		if (LN_ISFTN(mods))
37034c98957Smeem 			info(" (");
37134c98957Smeem 		print_mods(name, atp, nargs, args, pos - 1);
37234c98957Smeem 		if (LN_ISFTN(mods))
37334c98957Smeem 			info(")()");
37434c98957Smeem 		return;
37534c98957Smeem 	}
37634c98957Smeem 
37734c98957Smeem 	if (name[0] == '\0')
37834c98957Smeem 		return;
37934c98957Smeem 
38034c98957Smeem 	if (!LN_ISPTR(lastmods) && !LN_ISPTR(mods))
38134c98957Smeem 		info(" ");
38234c98957Smeem 	info("%s", name);
38334c98957Smeem 
38434c98957Smeem 	if (LN_ISARY(mods)) {
38534c98957Smeem 		info("[]");
38634c98957Smeem 	} else if (LN_ISFTN(mods)) {
38734c98957Smeem 		info("(");
38834c98957Smeem 
38934c98957Smeem 		if (nargs < 0) {
39034c98957Smeem 			nargs = -nargs - 1;
39134c98957Smeem 			isvarargs = B_TRUE;
39234c98957Smeem 		}
39334c98957Smeem 
39434c98957Smeem 		if (nargs == 0) {
39534c98957Smeem 			info("void");
39634c98957Smeem 		} else {
39734c98957Smeem 			for (arg = 0; arg < nargs; arg++) {
39834c98957Smeem 				print_atype(&args[arg], 0, NULL, "");
39934c98957Smeem 				if ((arg + 1) < nargs)
40034c98957Smeem 					info(", ");
40134c98957Smeem 				else if (isvarargs)
40234c98957Smeem 					info(", ...");
40334c98957Smeem 			}
40434c98957Smeem 		}
40534c98957Smeem 		info(")");
40634c98957Smeem 	}
40734c98957Smeem }
40834c98957Smeem 
40934c98957Smeem /*
41034c98957Smeem  * Add an LSU entry to the LSU table.
41134c98957Smeem  */
41234c98957Smeem static int
41334c98957Smeem lsu_add(const char *name, ATYPE *atp)
41434c98957Smeem {
41534c98957Smeem 	unsigned int	i = atp->extra.ty % LSU_HASHSIZE;
41634c98957Smeem 	lsu_t		*lsup;
41734c98957Smeem 
41834c98957Smeem 	lsup = malloc(sizeof (lsu_t));
41934c98957Smeem 	if (lsup == NULL)
42034c98957Smeem 		return (ENOMEM);
42134c98957Smeem 
42234c98957Smeem 	lsup->atype = *atp;
42334c98957Smeem 	lsup->next = lsu_table[i];
42434c98957Smeem 	lsup->name = strdup(name);
42534c98957Smeem 	if (lsup->name == NULL) {
42634c98957Smeem 		free(lsup);
42734c98957Smeem 		return (ENOMEM);
42834c98957Smeem 	}
42934c98957Smeem 
43034c98957Smeem 	lsu_table[i] = lsup;
43134c98957Smeem 	return (0);
43234c98957Smeem }
43334c98957Smeem 
43434c98957Smeem /*
43534c98957Smeem  * Lookup an LSU entry by ID.
43634c98957Smeem  */
43734c98957Smeem static lsu_t *
43834c98957Smeem lsu_lookup(T1WORD ty)
43934c98957Smeem {
44034c98957Smeem 	unsigned int	i = ty % LSU_HASHSIZE;
44134c98957Smeem 	lsu_t		*lsup;
44234c98957Smeem 
44334c98957Smeem 	for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup->next) {
44434c98957Smeem 		if (lsup->atype.extra.ty == ty)
44534c98957Smeem 			return (lsup);
44634c98957Smeem 	}
44734c98957Smeem 
44834c98957Smeem 	return (NULL);
44934c98957Smeem }
45034c98957Smeem 
45134c98957Smeem /*
45234c98957Smeem  * Read all LSU (structure and union definition) records in order to
45334c98957Smeem  * build a structure and union name table, called the LSU table.
45434c98957Smeem  */
45534c98957Smeem static void
45634c98957Smeem lsu_build(FILE *fp)
45734c98957Smeem {
45834c98957Smeem 	union rec	rec;
45934c98957Smeem 	char		name[1024];
46034c98957Smeem 	int		nargs;
46134c98957Smeem 
46234c98957Smeem 	for (;;) {
46334c98957Smeem 		if (fread(&rec, sizeof (rec), 1, fp) != 1)
46434c98957Smeem 			return;
46534c98957Smeem 
46634c98957Smeem 		if (rec.l.decflag & LND)	/* end-of-pass marker */
46734c98957Smeem 			break;
46834c98957Smeem 
46934c98957Smeem 		getstr(fp, name, sizeof (name));
47034c98957Smeem 		nargs = rec.l.nargs;
47134c98957Smeem 
47234c98957Smeem 		if (rec.l.decflag & (LIB|LDS|LDI)) {
47334c98957Smeem 			if (nargs < 0)
47434c98957Smeem 				nargs = -nargs - 1;
47534c98957Smeem 
47634c98957Smeem 			(void) fseek(fp, sizeof (ATYPE) * nargs, SEEK_CUR);
47734c98957Smeem 			continue;
47834c98957Smeem 		}
47934c98957Smeem 
48034c98957Smeem 		if (rec.l.decflag & LSU) {
48134c98957Smeem 			if (lsu_add(name, &rec.l.type) != 0)
48234c98957Smeem 				warn("cannot allocate struct `%s' info", name);
48334c98957Smeem 
48434c98957Smeem 			for (; nargs > 0; nargs--) {
48534c98957Smeem 				(void) fseek(fp, sizeof (ATYPE), SEEK_CUR);
48634c98957Smeem 				getstr(fp, name, sizeof (name));
48734c98957Smeem 			}
48834c98957Smeem 		}
48934c98957Smeem 	}
49034c98957Smeem }
49134c98957Smeem 
49234c98957Smeem /*
49334c98957Smeem  * Empty the LSU table.
49434c98957Smeem  */
49534c98957Smeem static void
49634c98957Smeem lsu_empty(void)
49734c98957Smeem {
49834c98957Smeem 	lsu_t		*lsup, *lsup_next;
49934c98957Smeem 	unsigned int	i;
50034c98957Smeem 
50134c98957Smeem 	for (i = 0; i < LSU_HASHSIZE; i++) {
50234c98957Smeem 		for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup_next) {
50334c98957Smeem 			lsup_next = lsup->next;
50434c98957Smeem 			free(lsup);
50534c98957Smeem 		}
50634c98957Smeem 		lsu_table[i] = NULL;
50734c98957Smeem 	}
50834c98957Smeem }
50934c98957Smeem 
51034c98957Smeem /*
51134c98957Smeem  * Read the NUL-terminated string at `fp' into `buf', which is at most
51234c98957Smeem  * `bufsize' bytes.
51334c98957Smeem  */
51434c98957Smeem static void
51534c98957Smeem getstr(FILE *fp, char *buf, size_t bufsize)
51634c98957Smeem {
51734c98957Smeem 	int c;
51834c98957Smeem 	size_t i;
51934c98957Smeem 
52034c98957Smeem 	for (i = 0; i < bufsize - 1; i++) {
52134c98957Smeem 		c = fgetc(fp);
52234c98957Smeem 		if (c == EOF || c == '\0' || !isascii(c))
52334c98957Smeem 			break;
52434c98957Smeem 		buf[i] = (char)c;
52534c98957Smeem 	}
52634c98957Smeem 
52734c98957Smeem 	buf[i] = '\0';
52834c98957Smeem }
52934c98957Smeem 
53034c98957Smeem static void
53134c98957Smeem indent(void)
53234c98957Smeem {
53334c98957Smeem 	indentlevel += 4;
53434c98957Smeem }
53534c98957Smeem 
53634c98957Smeem static void
53734c98957Smeem unindent(void)
53834c98957Smeem {
53934c98957Smeem 	indentlevel -= 4;
54034c98957Smeem }
54134c98957Smeem 
54234c98957Smeem static void
54334c98957Smeem usage(void)
54434c98957Smeem {
54534c98957Smeem 	(void) fprintf(stderr, "usage: %s [-i] [-p 1|2|3] [-r] lintlib"
54634c98957Smeem 	    " [ lintlib ... ]\n", progname);
54734c98957Smeem 	exit(EXIT_FAILURE);
54834c98957Smeem }
54934c98957Smeem 
55034c98957Smeem /* PRINTFLIKE1 */
55134c98957Smeem static void
55234c98957Smeem info(const char *format, ...)
55334c98957Smeem {
55434c98957Smeem 	va_list alist;
55534c98957Smeem 	static int complete = 1;
55634c98957Smeem 
55734c98957Smeem 	if (complete)
55834c98957Smeem 		(void) printf("%*s", indentlevel, "");
55934c98957Smeem 
56034c98957Smeem 	va_start(alist, format);
56134c98957Smeem 	(void) vprintf(format, alist);
56234c98957Smeem 	va_end(alist);
56334c98957Smeem 
56434c98957Smeem 	complete = strrchr(format, '\n') != NULL;
56534c98957Smeem }
56634c98957Smeem 
56734c98957Smeem /* PRINTFLIKE2 */
56834c98957Smeem static void
56934c98957Smeem infohdr(const char *hdr, const char *format, ...)
57034c98957Smeem {
57134c98957Smeem 	va_list alist;
57234c98957Smeem 	static int complete = 1;
57334c98957Smeem 
57434c98957Smeem 	if (complete)
57534c98957Smeem 		(void) printf("%7s: ", hdr);
57634c98957Smeem 
57734c98957Smeem 	va_start(alist, format);
57834c98957Smeem 	(void) vprintf(format, alist);
57934c98957Smeem 	va_end(alist);
58034c98957Smeem 
58134c98957Smeem 	complete = strrchr(format, '\n') != NULL;
58234c98957Smeem }
58334c98957Smeem 
58434c98957Smeem /* PRINTFLIKE1 */
58534c98957Smeem static void
58634c98957Smeem warn(const char *format, ...)
58734c98957Smeem {
58834c98957Smeem 	va_list alist;
58934c98957Smeem 	char *errstr = strerror(errno);
59034c98957Smeem 
59134c98957Smeem 	(void) fprintf(stderr, "%s: warning: ", progname);
59234c98957Smeem 
59334c98957Smeem 	va_start(alist, format);
59434c98957Smeem 	(void) vfprintf(stderr, format, alist);
59534c98957Smeem 	va_end(alist);
59634c98957Smeem 
59734c98957Smeem 	if (strrchr(format, '\n') == NULL)
59834c98957Smeem 		(void) fprintf(stderr, ": %s\n", errstr);
59934c98957Smeem }
60034c98957Smeem 
60134c98957Smeem /* PRINTFLIKE1 */
60234c98957Smeem static void
60334c98957Smeem die(const char *format, ...)
60434c98957Smeem {
60534c98957Smeem 	va_list alist;
60634c98957Smeem 	char *errstr = strerror(errno);
60734c98957Smeem 
60834c98957Smeem 	(void) fprintf(stderr, "%s: fatal: ", progname);
60934c98957Smeem 
61034c98957Smeem 	va_start(alist, format);
61134c98957Smeem 	(void) vfprintf(stderr, format, alist);
61234c98957Smeem 	va_end(alist);
61334c98957Smeem 
61434c98957Smeem 	if (strrchr(format, '\n') == NULL)
61534c98957Smeem 		(void) fprintf(stderr, ": %s\n", errstr);
61634c98957Smeem 
61734c98957Smeem 	exit(EXIT_FAILURE);
61834c98957Smeem }
619