xref: /titanic_44/usr/src/tools/lintdump/lintdump.c (revision 34c989574817eca41f72a5f02c848e51cfef32f0)
1*34c98957Smeem /*
2*34c98957Smeem  * CDDL HEADER START
3*34c98957Smeem  *
4*34c98957Smeem  * The contents of this file are subject to the terms of the
5*34c98957Smeem  * Common Development and Distribution License (the "License").
6*34c98957Smeem  * You may not use this file except in compliance with the License.
7*34c98957Smeem  *
8*34c98957Smeem  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*34c98957Smeem  * or http://www.opensolaris.org/os/licensing.
10*34c98957Smeem  * See the License for the specific language governing permissions
11*34c98957Smeem  * and limitations under the License.
12*34c98957Smeem  *
13*34c98957Smeem  * When distributing Covered Code, include this CDDL HEADER in each
14*34c98957Smeem  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*34c98957Smeem  * If applicable, add the following below this CDDL HEADER, with the
16*34c98957Smeem  * fields enclosed by brackets "[]" replaced with your own identifying
17*34c98957Smeem  * information: Portions Copyright [yyyy] [name of copyright owner]
18*34c98957Smeem  *
19*34c98957Smeem  * CDDL HEADER END
20*34c98957Smeem  */
21*34c98957Smeem 
22*34c98957Smeem /*
23*34c98957Smeem  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*34c98957Smeem  * Use is subject to license terms.
25*34c98957Smeem  */
26*34c98957Smeem 
27*34c98957Smeem #pragma ident	"@(#)lintdump.c	1.6	06/06/04 SMI (from meem)"
28*34c98957Smeem #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*34c98957Smeem 
30*34c98957Smeem /*
31*34c98957Smeem  * Tool for dumping lint libraries.
32*34c98957Smeem  */
33*34c98957Smeem 
34*34c98957Smeem #include <ctype.h>
35*34c98957Smeem #include <errno.h>
36*34c98957Smeem #include <stdarg.h>
37*34c98957Smeem #include <stdio.h>
38*34c98957Smeem #include <stdlib.h>
39*34c98957Smeem #include <string.h>
40*34c98957Smeem #include <sys/types.h>
41*34c98957Smeem 
42*34c98957Smeem #include "lnstuff.h"		/* silly header name from alint */
43*34c98957Smeem 
44*34c98957Smeem typedef struct lsu {
45*34c98957Smeem 	const char	*name;
46*34c98957Smeem 	ATYPE		atype;
47*34c98957Smeem 	struct lsu	*next;
48*34c98957Smeem } lsu_t;
49*34c98957Smeem 
50*34c98957Smeem #define	LSU_HASHSIZE	512
51*34c98957Smeem static lsu_t		*lsu_table[LSU_HASHSIZE];
52*34c98957Smeem 
53*34c98957Smeem static boolean_t	showids = B_TRUE;
54*34c98957Smeem static boolean_t	justrelpaths = B_FALSE;
55*34c98957Smeem static int		justpass = -1;
56*34c98957Smeem static int		indentlevel = 9;
57*34c98957Smeem static const char	*progname;
58*34c98957Smeem 
59*34c98957Smeem static void info(const char *, ...);
60*34c98957Smeem static void infohdr(const char *, const char *, ...);
61*34c98957Smeem static void warn(const char *, ...);
62*34c98957Smeem static void die(const char *, ...);
63*34c98957Smeem static void usage(void);
64*34c98957Smeem static void indent(void);
65*34c98957Smeem static void unindent(void);
66*34c98957Smeem static void print_lintlib(const char *, FILE *, FLENS *);
67*34c98957Smeem static void print_pass(FILE *);
68*34c98957Smeem static void print_atype(ATYPE *, int, ATYPE *, const char *);
69*34c98957Smeem static void print_mods(const char *, ATYPE *, int, ATYPE *, uint_t);
70*34c98957Smeem static void getstr(FILE *, char *, size_t);
71*34c98957Smeem static void lsu_build(FILE *);
72*34c98957Smeem static void lsu_empty(void);
73*34c98957Smeem static int lsu_add(const char *, ATYPE *);
74*34c98957Smeem static lsu_t *lsu_lookup(unsigned long);
75*34c98957Smeem 
76*34c98957Smeem int
77*34c98957Smeem main(int argc, char **argv)
78*34c98957Smeem {
79*34c98957Smeem 	int	i, c;
80*34c98957Smeem 	FILE	*fp;
81*34c98957Smeem 	FLENS	hdr;
82*34c98957Smeem 
83*34c98957Smeem 	progname = strrchr(argv[0], '/');
84*34c98957Smeem 	if (progname == NULL)
85*34c98957Smeem 		progname = argv[0];
86*34c98957Smeem 	else
87*34c98957Smeem 		progname++;
88*34c98957Smeem 
89*34c98957Smeem 	while ((c = getopt(argc, argv, "ip:r")) != EOF) {
90*34c98957Smeem 		switch (c) {
91*34c98957Smeem 		case 'i':
92*34c98957Smeem 			showids = B_FALSE;
93*34c98957Smeem 			break;
94*34c98957Smeem 		case 'p':
95*34c98957Smeem 			justpass = strtoul(optarg, NULL, 0);
96*34c98957Smeem 			if (justpass < 1 || justpass > 3)
97*34c98957Smeem 				usage();
98*34c98957Smeem 			break;
99*34c98957Smeem 		case 'r':
100*34c98957Smeem 			justrelpaths = B_TRUE;
101*34c98957Smeem 			break;
102*34c98957Smeem 		default:
103*34c98957Smeem 			usage();
104*34c98957Smeem 		}
105*34c98957Smeem 	}
106*34c98957Smeem 
107*34c98957Smeem 	if (optind == argc)
108*34c98957Smeem 		usage();
109*34c98957Smeem 
110*34c98957Smeem 	for (i = optind; i < argc; i++) {
111*34c98957Smeem 		fp = fopen(argv[i], "r");
112*34c98957Smeem 		if (fp == NULL) {
113*34c98957Smeem 			warn("cannot open \"%s\"", argv[i]);
114*34c98957Smeem 			continue;
115*34c98957Smeem 		}
116*34c98957Smeem 
117*34c98957Smeem 		if (fread(&hdr, sizeof (hdr), 1, fp) < 1) {
118*34c98957Smeem 			warn("%s: cannot read lint library header\n", argv[i]);
119*34c98957Smeem 			(void) fclose(fp);
120*34c98957Smeem 			continue;
121*34c98957Smeem 		}
122*34c98957Smeem 
123*34c98957Smeem 		if (hdr.ver != LINTVER) {
124*34c98957Smeem 			warn("%s: lint library version %d unsupported\n",
125*34c98957Smeem 			    argv[i], hdr.ver);
126*34c98957Smeem 			(void) fclose(fp);
127*34c98957Smeem 			continue;
128*34c98957Smeem 		}
129*34c98957Smeem 
130*34c98957Smeem 		/*
131*34c98957Smeem 		 * First build the table of structure/union names, then seek
132*34c98957Smeem 		 * back to the start and print the lint library.  Finally,
133*34c98957Smeem 		 * empty the table out before dumping the next library.
134*34c98957Smeem 		 */
135*34c98957Smeem 		lsu_build(fp);
136*34c98957Smeem 		(void) fseek(fp, sizeof (hdr), SEEK_SET);
137*34c98957Smeem 		print_lintlib(argv[i], fp, &hdr);
138*34c98957Smeem 		(void) fclose(fp);
139*34c98957Smeem 		lsu_empty();
140*34c98957Smeem 	}
141*34c98957Smeem 
142*34c98957Smeem 	return (EXIT_SUCCESS);
143*34c98957Smeem }
144*34c98957Smeem 
145*34c98957Smeem /*
146*34c98957Smeem  * Print a lint library.
147*34c98957Smeem  */
148*34c98957Smeem static void
149*34c98957Smeem print_lintlib(const char *lnname, FILE *fp, FLENS *hp)
150*34c98957Smeem {
151*34c98957Smeem 	off_t		passoff = 0;
152*34c98957Smeem 	ulong_t		psizes[4];
153*34c98957Smeem 	uint_t		pass;
154*34c98957Smeem 
155*34c98957Smeem 	psizes[0] = 0;
156*34c98957Smeem 	psizes[1] = hp->f1;
157*34c98957Smeem 	psizes[2] = hp->f2;
158*34c98957Smeem 	psizes[3] = hp->f3;
159*34c98957Smeem 
160*34c98957Smeem 	if (justrelpaths && lnname[0] == '/')
161*34c98957Smeem 		lnname = strrchr(lnname, '/') + 1;
162*34c98957Smeem 
163*34c98957Smeem 	infohdr("LINTLIB", "%s <mid %hu> %lu+%lu+%lu+%lu = %lu bytes\n", lnname,
164*34c98957Smeem 	    hp->mno, hp->f1, hp->f2, hp->f3, hp->f4,
165*34c98957Smeem 	    hp->f1 + hp->f2 + hp->f3 + hp->f4);
166*34c98957Smeem 
167*34c98957Smeem 	for (pass = 1; pass <= 3; pass++) {
168*34c98957Smeem 		if (justpass < 0 || justpass == pass) {
169*34c98957Smeem 			infohdr("SECTION", "PASS%u: %lu bytes\n", pass,
170*34c98957Smeem 			    psizes[pass]);
171*34c98957Smeem 			print_pass(fp);
172*34c98957Smeem 		}
173*34c98957Smeem 		passoff += psizes[pass];
174*34c98957Smeem 		(void) fseek(fp, passoff, SEEK_SET);
175*34c98957Smeem 	}
176*34c98957Smeem }
177*34c98957Smeem 
178*34c98957Smeem /*
179*34c98957Smeem  * Print out a PASS section of a lint library.
180*34c98957Smeem  */
181*34c98957Smeem static void
182*34c98957Smeem print_pass(FILE *fp)
183*34c98957Smeem {
184*34c98957Smeem 	union rec	rec;
185*34c98957Smeem 	int		nargs;
186*34c98957Smeem 	char		name[1024];
187*34c98957Smeem 	ATYPE		atype, *args;
188*34c98957Smeem 	LINE		line;
189*34c98957Smeem 	boolean_t	wasfile = B_FALSE;
190*34c98957Smeem 
191*34c98957Smeem 	for (;;) {
192*34c98957Smeem 		if (fread(&rec, sizeof (rec), 1, fp) != 1)
193*34c98957Smeem 			die("unexpected end of data stream\n");
194*34c98957Smeem 
195*34c98957Smeem 		line = rec.l;
196*34c98957Smeem 		if (line.decflag & LND)		/* end-of-pass marker */
197*34c98957Smeem 			break;
198*34c98957Smeem 
199*34c98957Smeem 		getstr(fp, name, sizeof (name));
200*34c98957Smeem 
201*34c98957Smeem 		/*
202*34c98957Smeem 		 * Check if this is a file record.
203*34c98957Smeem 		 */
204*34c98957Smeem 		if (line.decflag & LFN) {
205*34c98957Smeem 			if (wasfile || !justrelpaths)
206*34c98957Smeem 				infohdr("FILE", "%s\n", name);
207*34c98957Smeem 			wasfile = B_TRUE;
208*34c98957Smeem 			continue;
209*34c98957Smeem 		}
210*34c98957Smeem 		wasfile = B_FALSE;
211*34c98957Smeem 
212*34c98957Smeem 		/*
213*34c98957Smeem 		 * Check if this is a function or variable record.
214*34c98957Smeem 		 */
215*34c98957Smeem 		nargs = line.nargs;
216*34c98957Smeem 		if (line.decflag & (LIB|LDS|LDI|LPR|LDX|LDC|LRV|LUE|LUV|LUM)) {
217*34c98957Smeem 			if (nargs < 0)
218*34c98957Smeem 				nargs = -nargs - 1;
219*34c98957Smeem 
220*34c98957Smeem 			if (line.decflag & LDS)
221*34c98957Smeem 				info("static ");
222*34c98957Smeem 			else if (line.decflag & (LPR|LDX|LDC))
223*34c98957Smeem 				info("extern ");
224*34c98957Smeem 
225*34c98957Smeem 			args = calloc(sizeof (atype), nargs);
226*34c98957Smeem 			if (args == NULL)
227*34c98957Smeem 				die("cannot allocate argument information");
228*34c98957Smeem 
229*34c98957Smeem 			if (fread(args, sizeof (atype), nargs, fp) != nargs)
230*34c98957Smeem 				die("unexpected end of data stream\n");
231*34c98957Smeem 
232*34c98957Smeem 			print_atype(&line.type, line.nargs, args, name);
233*34c98957Smeem 			free(args);
234*34c98957Smeem 
235*34c98957Smeem 			if (line.decflag & LRV)
236*34c98957Smeem 				info(" <returns value>");
237*34c98957Smeem 			if (line.decflag & LUE)
238*34c98957Smeem 				info(" <use: side-effects context>");
239*34c98957Smeem 			if (line.decflag & LUV)
240*34c98957Smeem 				info(" <use: return value context>");
241*34c98957Smeem 			if (line.decflag & LUM)
242*34c98957Smeem 				info(" <use: unspecified context>");
243*34c98957Smeem 
244*34c98957Smeem 			if (line.decflag & LPF)
245*34c98957Smeem 				info(" <PRINTFLIKE%d>", nargs);
246*34c98957Smeem 			else if (line.decflag & LSF)
247*34c98957Smeem 				info(" <SCANFLIKE%d>", nargs);
248*34c98957Smeem 
249*34c98957Smeem 			if (line.decflag & LDI)
250*34c98957Smeem 				info(" { <definition> }");
251*34c98957Smeem 			else if (line.decflag & LDX)
252*34c98957Smeem 				info(" = <definition>");
253*34c98957Smeem 
254*34c98957Smeem 			info(";\n");
255*34c98957Smeem 			continue;
256*34c98957Smeem 		}
257*34c98957Smeem 
258*34c98957Smeem 		/*
259*34c98957Smeem 		 * Check if this is a structure or union record.
260*34c98957Smeem 		 */
261*34c98957Smeem 		if (line.decflag & LSU) {
262*34c98957Smeem 			if (line.decflag & ~(LSU))
263*34c98957Smeem 				info("??? ");
264*34c98957Smeem 
265*34c98957Smeem 			info("struct %s ", name);
266*34c98957Smeem 			if (showids)
267*34c98957Smeem 				info("<tag %lu> ", line.type.extra.ty);
268*34c98957Smeem 			info("{ \n");
269*34c98957Smeem 
270*34c98957Smeem 			indent();
271*34c98957Smeem 			for (; nargs > 0; nargs--) {
272*34c98957Smeem 				if (fread(&atype, sizeof (atype), 1, fp) != 1)
273*34c98957Smeem 					die("unexpected end of data stream\n");
274*34c98957Smeem 
275*34c98957Smeem 				getstr(fp, name, sizeof (name));
276*34c98957Smeem 				print_atype(&atype, 0, NULL, name);
277*34c98957Smeem 				info(";\n");
278*34c98957Smeem 			}
279*34c98957Smeem 			unindent();
280*34c98957Smeem 			info("};\n");
281*34c98957Smeem 			continue;
282*34c98957Smeem 		}
283*34c98957Smeem 
284*34c98957Smeem 		warn("unknown record type 0%o\n", line.decflag);
285*34c98957Smeem 	}
286*34c98957Smeem }
287*34c98957Smeem 
288*34c98957Smeem /*
289*34c98957Smeem  * Print the C datatype or function `atp' named `name'.  If `name' is a
290*34c98957Smeem  * function, then `nargs' indicates the number of C datatypes pointed to
291*34c98957Smeem  * by `args'.
292*34c98957Smeem  */
293*34c98957Smeem static void
294*34c98957Smeem print_atype(ATYPE *atp, int nargs, ATYPE *args, const char *name)
295*34c98957Smeem {
296*34c98957Smeem 	static const char *basetypes[] = {		"",
297*34c98957Smeem 		"char",		"unsigned char",	"signed char",
298*34c98957Smeem 		"short",	"unsigned short",	"signed short",
299*34c98957Smeem 		"int",		"unsigned int",		"signed int",
300*34c98957Smeem 		"long",		"unsigned long",	"signed long",
301*34c98957Smeem 		"long long",	"unsigned long long",	"signed long long",
302*34c98957Smeem 		"enum",		"float",		"double",
303*34c98957Smeem 		"long double",	"void",			"struct",
304*34c98957Smeem 		"union",	"_Bool",		"<genchar>",
305*34c98957Smeem 		"<genshort>",	"<genint>",		"<genlong>",
306*34c98957Smeem 		"<genlonglong>"
307*34c98957Smeem 	};
308*34c98957Smeem 	uint16_t basetype = atp->aty & LNQUAL;
309*34c98957Smeem 	lsu_t *lsup;
310*34c98957Smeem 
311*34c98957Smeem 	if (atp->aty & LCON)
312*34c98957Smeem 		info("const ");
313*34c98957Smeem 	if (atp->aty & LVOL)
314*34c98957Smeem 		info("volatile ");
315*34c98957Smeem 	if (atp->aty & LCONV)
316*34c98957Smeem 		info("integer const ");
317*34c98957Smeem 
318*34c98957Smeem 	if (basetype < 1 ||
319*34c98957Smeem 	    basetype > (sizeof (basetypes) / sizeof (*basetypes)))
320*34c98957Smeem 		info("<unknown type %x>", basetype);
321*34c98957Smeem 
322*34c98957Smeem 	switch (basetype) {
323*34c98957Smeem 	case LN_UNION:
324*34c98957Smeem 	case LN_STRUCT:
325*34c98957Smeem 		lsup = lsu_lookup(atp->extra.ty);
326*34c98957Smeem 		if (lsup != NULL && lsup->name[0] != '.') {
327*34c98957Smeem 			info("%s %s", basetypes[basetype], lsup->name);
328*34c98957Smeem 		} else {
329*34c98957Smeem 			info("%s", basetypes[basetype]);
330*34c98957Smeem 			if (showids)
331*34c98957Smeem 				info(" <tag %lu>", atp->extra.ty);
332*34c98957Smeem 			else
333*34c98957Smeem 				info(" <anon>");
334*34c98957Smeem 		}
335*34c98957Smeem 		break;
336*34c98957Smeem 	default:
337*34c98957Smeem 		info(basetypes[basetype]);
338*34c98957Smeem 	};
339*34c98957Smeem 
340*34c98957Smeem 	print_mods(name, atp, nargs, args, 14);
341*34c98957Smeem }
342*34c98957Smeem 
343*34c98957Smeem /*
344*34c98957Smeem  * Recursively print type modifiers.
345*34c98957Smeem  */
346*34c98957Smeem static void
347*34c98957Smeem print_mods(const char *name, ATYPE *atp, int nargs, ATYPE *args, uint_t pos)
348*34c98957Smeem {
349*34c98957Smeem 	int arg;
350*34c98957Smeem 	int mods = atp->dcl_mod >> (pos * 2);
351*34c98957Smeem 	int lastmods = atp->dcl_mod >> ((pos + 1) * 2);
352*34c98957Smeem 	boolean_t isvarargs = B_FALSE;
353*34c98957Smeem 
354*34c98957Smeem 	if (LN_ISPTR(mods)) {
355*34c98957Smeem 		if (!LN_ISPTR(lastmods) && !LN_ISFTN(lastmods))
356*34c98957Smeem 			info(" ");
357*34c98957Smeem 		info("*");
358*34c98957Smeem 	}
359*34c98957Smeem 
360*34c98957Smeem 	if (atp->dcl_con & (1 << pos))
361*34c98957Smeem 		info(" const ");
362*34c98957Smeem 	if (atp->dcl_vol & (1 << pos))
363*34c98957Smeem 		info(" volatile ");
364*34c98957Smeem 
365*34c98957Smeem 	if (pos != 0) {
366*34c98957Smeem 		if (LN_ISFTN(mods))
367*34c98957Smeem 			info(" (");
368*34c98957Smeem 		print_mods(name, atp, nargs, args, pos - 1);
369*34c98957Smeem 		if (LN_ISFTN(mods))
370*34c98957Smeem 			info(")()");
371*34c98957Smeem 		return;
372*34c98957Smeem 	}
373*34c98957Smeem 
374*34c98957Smeem 	if (name[0] == '\0')
375*34c98957Smeem 		return;
376*34c98957Smeem 
377*34c98957Smeem 	if (!LN_ISPTR(lastmods) && !LN_ISPTR(mods))
378*34c98957Smeem 		info(" ");
379*34c98957Smeem 	info("%s", name);
380*34c98957Smeem 
381*34c98957Smeem 	if (LN_ISARY(mods)) {
382*34c98957Smeem 		info("[]");
383*34c98957Smeem 	} else if (LN_ISFTN(mods)) {
384*34c98957Smeem 		info("(");
385*34c98957Smeem 
386*34c98957Smeem 		if (nargs < 0) {
387*34c98957Smeem 			nargs = -nargs - 1;
388*34c98957Smeem 			isvarargs = B_TRUE;
389*34c98957Smeem 		}
390*34c98957Smeem 
391*34c98957Smeem 		if (nargs == 0) {
392*34c98957Smeem 			info("void");
393*34c98957Smeem 		} else {
394*34c98957Smeem 			for (arg = 0; arg < nargs; arg++) {
395*34c98957Smeem 				print_atype(&args[arg], 0, NULL, "");
396*34c98957Smeem 				if ((arg + 1) < nargs)
397*34c98957Smeem 					info(", ");
398*34c98957Smeem 				else if (isvarargs)
399*34c98957Smeem 					info(", ...");
400*34c98957Smeem 			}
401*34c98957Smeem 		}
402*34c98957Smeem 		info(")");
403*34c98957Smeem 	}
404*34c98957Smeem }
405*34c98957Smeem 
406*34c98957Smeem /*
407*34c98957Smeem  * Add an LSU entry to the LSU table.
408*34c98957Smeem  */
409*34c98957Smeem static int
410*34c98957Smeem lsu_add(const char *name, ATYPE *atp)
411*34c98957Smeem {
412*34c98957Smeem 	unsigned int	i = atp->extra.ty % LSU_HASHSIZE;
413*34c98957Smeem 	lsu_t		*lsup;
414*34c98957Smeem 
415*34c98957Smeem 	lsup = malloc(sizeof (lsu_t));
416*34c98957Smeem 	if (lsup == NULL)
417*34c98957Smeem 		return (ENOMEM);
418*34c98957Smeem 
419*34c98957Smeem 	lsup->atype = *atp;
420*34c98957Smeem 	lsup->next = lsu_table[i];
421*34c98957Smeem 	lsup->name = strdup(name);
422*34c98957Smeem 	if (lsup->name == NULL) {
423*34c98957Smeem 		free(lsup);
424*34c98957Smeem 		return (ENOMEM);
425*34c98957Smeem 	}
426*34c98957Smeem 
427*34c98957Smeem 	lsu_table[i] = lsup;
428*34c98957Smeem 	return (0);
429*34c98957Smeem }
430*34c98957Smeem 
431*34c98957Smeem /*
432*34c98957Smeem  * Lookup an LSU entry by ID.
433*34c98957Smeem  */
434*34c98957Smeem static lsu_t *
435*34c98957Smeem lsu_lookup(T1WORD ty)
436*34c98957Smeem {
437*34c98957Smeem 	unsigned int	i = ty % LSU_HASHSIZE;
438*34c98957Smeem 	lsu_t		*lsup;
439*34c98957Smeem 
440*34c98957Smeem 	for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup->next) {
441*34c98957Smeem 		if (lsup->atype.extra.ty == ty)
442*34c98957Smeem 			return (lsup);
443*34c98957Smeem 	}
444*34c98957Smeem 
445*34c98957Smeem 	return (NULL);
446*34c98957Smeem }
447*34c98957Smeem 
448*34c98957Smeem /*
449*34c98957Smeem  * Read all LSU (structure and union definition) records in order to
450*34c98957Smeem  * build a structure and union name table, called the LSU table.
451*34c98957Smeem  */
452*34c98957Smeem static void
453*34c98957Smeem lsu_build(FILE *fp)
454*34c98957Smeem {
455*34c98957Smeem 	union rec	rec;
456*34c98957Smeem 	char		name[1024];
457*34c98957Smeem 	int		nargs;
458*34c98957Smeem 
459*34c98957Smeem 	for (;;) {
460*34c98957Smeem 		if (fread(&rec, sizeof (rec), 1, fp) != 1)
461*34c98957Smeem 			return;
462*34c98957Smeem 
463*34c98957Smeem 		if (rec.l.decflag & LND)	/* end-of-pass marker */
464*34c98957Smeem 			break;
465*34c98957Smeem 
466*34c98957Smeem 		getstr(fp, name, sizeof (name));
467*34c98957Smeem 		nargs = rec.l.nargs;
468*34c98957Smeem 
469*34c98957Smeem 		if (rec.l.decflag & (LIB|LDS|LDI)) {
470*34c98957Smeem 			if (nargs < 0)
471*34c98957Smeem 				nargs = -nargs - 1;
472*34c98957Smeem 
473*34c98957Smeem 			(void) fseek(fp, sizeof (ATYPE) * nargs, SEEK_CUR);
474*34c98957Smeem 			continue;
475*34c98957Smeem 		}
476*34c98957Smeem 
477*34c98957Smeem 		if (rec.l.decflag & LSU) {
478*34c98957Smeem 			if (lsu_add(name, &rec.l.type) != 0)
479*34c98957Smeem 				warn("cannot allocate struct `%s' info", name);
480*34c98957Smeem 
481*34c98957Smeem 			for (; nargs > 0; nargs--) {
482*34c98957Smeem 				(void) fseek(fp, sizeof (ATYPE), SEEK_CUR);
483*34c98957Smeem 				getstr(fp, name, sizeof (name));
484*34c98957Smeem 			}
485*34c98957Smeem 		}
486*34c98957Smeem 	}
487*34c98957Smeem }
488*34c98957Smeem 
489*34c98957Smeem /*
490*34c98957Smeem  * Empty the LSU table.
491*34c98957Smeem  */
492*34c98957Smeem static void
493*34c98957Smeem lsu_empty(void)
494*34c98957Smeem {
495*34c98957Smeem 	lsu_t		*lsup, *lsup_next;
496*34c98957Smeem 	unsigned int	i;
497*34c98957Smeem 
498*34c98957Smeem 	for (i = 0; i < LSU_HASHSIZE; i++) {
499*34c98957Smeem 		for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup_next) {
500*34c98957Smeem 			lsup_next = lsup->next;
501*34c98957Smeem 			free(lsup);
502*34c98957Smeem 		}
503*34c98957Smeem 		lsu_table[i] = NULL;
504*34c98957Smeem 	}
505*34c98957Smeem }
506*34c98957Smeem 
507*34c98957Smeem /*
508*34c98957Smeem  * Read the NUL-terminated string at `fp' into `buf', which is at most
509*34c98957Smeem  * `bufsize' bytes.
510*34c98957Smeem  */
511*34c98957Smeem static void
512*34c98957Smeem getstr(FILE *fp, char *buf, size_t bufsize)
513*34c98957Smeem {
514*34c98957Smeem 	int c;
515*34c98957Smeem 	size_t i;
516*34c98957Smeem 
517*34c98957Smeem 	for (i = 0; i < bufsize - 1; i++) {
518*34c98957Smeem 		c = fgetc(fp);
519*34c98957Smeem 		if (c == EOF || c == '\0' || !isascii(c))
520*34c98957Smeem 			break;
521*34c98957Smeem 		buf[i] = (char)c;
522*34c98957Smeem 	}
523*34c98957Smeem 
524*34c98957Smeem 	buf[i] = '\0';
525*34c98957Smeem }
526*34c98957Smeem 
527*34c98957Smeem static void
528*34c98957Smeem indent(void)
529*34c98957Smeem {
530*34c98957Smeem 	indentlevel += 4;
531*34c98957Smeem }
532*34c98957Smeem 
533*34c98957Smeem static void
534*34c98957Smeem unindent(void)
535*34c98957Smeem {
536*34c98957Smeem 	indentlevel -= 4;
537*34c98957Smeem }
538*34c98957Smeem 
539*34c98957Smeem static void
540*34c98957Smeem usage(void)
541*34c98957Smeem {
542*34c98957Smeem 	(void) fprintf(stderr, "usage: %s [-i] [-p 1|2|3] [-r] lintlib"
543*34c98957Smeem 	    " [ lintlib ... ]\n", progname);
544*34c98957Smeem 	exit(EXIT_FAILURE);
545*34c98957Smeem }
546*34c98957Smeem 
547*34c98957Smeem /* PRINTFLIKE1 */
548*34c98957Smeem static void
549*34c98957Smeem info(const char *format, ...)
550*34c98957Smeem {
551*34c98957Smeem 	va_list alist;
552*34c98957Smeem 	static int complete = 1;
553*34c98957Smeem 
554*34c98957Smeem 	if (complete)
555*34c98957Smeem 		(void) printf("%*s", indentlevel, "");
556*34c98957Smeem 
557*34c98957Smeem 	va_start(alist, format);
558*34c98957Smeem 	(void) vprintf(format, alist);
559*34c98957Smeem 	va_end(alist);
560*34c98957Smeem 
561*34c98957Smeem 	complete = strrchr(format, '\n') != NULL;
562*34c98957Smeem }
563*34c98957Smeem 
564*34c98957Smeem /* PRINTFLIKE2 */
565*34c98957Smeem static void
566*34c98957Smeem infohdr(const char *hdr, const char *format, ...)
567*34c98957Smeem {
568*34c98957Smeem 	va_list alist;
569*34c98957Smeem 	static int complete = 1;
570*34c98957Smeem 
571*34c98957Smeem 	if (complete)
572*34c98957Smeem 		(void) printf("%7s: ", hdr);
573*34c98957Smeem 
574*34c98957Smeem 	va_start(alist, format);
575*34c98957Smeem 	(void) vprintf(format, alist);
576*34c98957Smeem 	va_end(alist);
577*34c98957Smeem 
578*34c98957Smeem 	complete = strrchr(format, '\n') != NULL;
579*34c98957Smeem }
580*34c98957Smeem 
581*34c98957Smeem /* PRINTFLIKE1 */
582*34c98957Smeem static void
583*34c98957Smeem warn(const char *format, ...)
584*34c98957Smeem {
585*34c98957Smeem 	va_list alist;
586*34c98957Smeem 	char *errstr = strerror(errno);
587*34c98957Smeem 
588*34c98957Smeem 	(void) fprintf(stderr, "%s: warning: ", progname);
589*34c98957Smeem 
590*34c98957Smeem 	va_start(alist, format);
591*34c98957Smeem 	(void) vfprintf(stderr, format, alist);
592*34c98957Smeem 	va_end(alist);
593*34c98957Smeem 
594*34c98957Smeem 	if (strrchr(format, '\n') == NULL)
595*34c98957Smeem 		(void) fprintf(stderr, ": %s\n", errstr);
596*34c98957Smeem }
597*34c98957Smeem 
598*34c98957Smeem /* PRINTFLIKE1 */
599*34c98957Smeem static void
600*34c98957Smeem die(const char *format, ...)
601*34c98957Smeem {
602*34c98957Smeem 	va_list alist;
603*34c98957Smeem 	char *errstr = strerror(errno);
604*34c98957Smeem 
605*34c98957Smeem 	(void) fprintf(stderr, "%s: fatal: ", progname);
606*34c98957Smeem 
607*34c98957Smeem 	va_start(alist, format);
608*34c98957Smeem 	(void) vfprintf(stderr, format, alist);
609*34c98957Smeem 	va_end(alist);
610*34c98957Smeem 
611*34c98957Smeem 	if (strrchr(format, '\n') == NULL)
612*34c98957Smeem 		(void) fprintf(stderr, ": %s\n", errstr);
613*34c98957Smeem 
614*34c98957Smeem 	exit(EXIT_FAILURE);
615*34c98957Smeem }
616