xref: /onnv-gate/usr/src/tools/lintdump/lintdump.c (revision 6362:fbd98ce7728f)
12217Smeem /*
22217Smeem  * CDDL HEADER START
32217Smeem  *
42217Smeem  * The contents of this file are subject to the terms of the
52217Smeem  * Common Development and Distribution License (the "License").
62217Smeem  * You may not use this file except in compliance with the License.
72217Smeem  *
82217Smeem  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92217Smeem  * or http://www.opensolaris.org/os/licensing.
102217Smeem  * See the License for the specific language governing permissions
112217Smeem  * and limitations under the License.
122217Smeem  *
132217Smeem  * When distributing Covered Code, include this CDDL HEADER in each
142217Smeem  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152217Smeem  * If applicable, add the following below this CDDL HEADER, with the
162217Smeem  * fields enclosed by brackets "[]" replaced with your own identifying
172217Smeem  * information: Portions Copyright [yyyy] [name of copyright owner]
182217Smeem  *
192217Smeem  * CDDL HEADER END
202217Smeem  */
212217Smeem 
222217Smeem /*
23*6362Smeem  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
242217Smeem  * Use is subject to license terms.
252217Smeem  */
262217Smeem 
272217Smeem #pragma ident	"@(#)lintdump.c	1.6	06/06/04 SMI (from meem)"
282217Smeem #pragma ident	"%Z%%M%	%I%	%E% SMI"
292217Smeem 
302217Smeem /*
312217Smeem  * Tool for dumping lint libraries.
322217Smeem  */
332217Smeem 
342217Smeem #include <ctype.h>
352217Smeem #include <errno.h>
362217Smeem #include <stdarg.h>
372217Smeem #include <stdio.h>
382217Smeem #include <stdlib.h>
392217Smeem #include <string.h>
402217Smeem #include <sys/types.h>
412217Smeem 
422217Smeem #include "lnstuff.h"		/* silly header name from alint */
432217Smeem 
442217Smeem typedef struct lsu {
452217Smeem 	const char	*name;
462217Smeem 	ATYPE		atype;
472217Smeem 	struct lsu	*next;
482217Smeem } lsu_t;
492217Smeem 
502217Smeem #define	LSU_HASHSIZE	512
512217Smeem static lsu_t		*lsu_table[LSU_HASHSIZE];
522217Smeem 
532217Smeem static boolean_t	showids = B_TRUE;
542217Smeem static boolean_t	justrelpaths = B_FALSE;
552217Smeem static int		justpass = -1;
562217Smeem static int		indentlevel = 9;
572217Smeem static const char	*progname;
582217Smeem 
592217Smeem static void info(const char *, ...);
602217Smeem static void infohdr(const char *, const char *, ...);
612217Smeem static void warn(const char *, ...);
622217Smeem static void die(const char *, ...);
632217Smeem static void usage(void);
642217Smeem static void indent(void);
652217Smeem static void unindent(void);
66*6362Smeem static void print_lintmod(const char *, FILE *, FLENS *);
673033Smeem static void print_pass(const char *, FILE *);
682217Smeem static void print_atype(ATYPE *, int, ATYPE *, const char *);
692217Smeem static void print_mods(const char *, ATYPE *, int, ATYPE *, uint_t);
702217Smeem static void getstr(FILE *, char *, size_t);
712217Smeem static void lsu_build(FILE *);
722217Smeem static void lsu_empty(void);
732217Smeem static int lsu_add(const char *, ATYPE *);
742217Smeem static lsu_t *lsu_lookup(unsigned long);
752217Smeem 
762217Smeem int
main(int argc,char ** argv)772217Smeem main(int argc, char **argv)
782217Smeem {
79*6362Smeem 	int		i, c, mod;
80*6362Smeem 	FILE		*fp;
81*6362Smeem 	FLENS		hdr;
82*6362Smeem 	const char	*lnname;
832217Smeem 
842217Smeem 	progname = strrchr(argv[0], '/');
852217Smeem 	if (progname == NULL)
862217Smeem 		progname = argv[0];
872217Smeem 	else
882217Smeem 		progname++;
892217Smeem 
902217Smeem 	while ((c = getopt(argc, argv, "ip:r")) != EOF) {
912217Smeem 		switch (c) {
922217Smeem 		case 'i':
932217Smeem 			showids = B_FALSE;
942217Smeem 			break;
952217Smeem 		case 'p':
962217Smeem 			justpass = strtoul(optarg, NULL, 0);
972217Smeem 			if (justpass < 1 || justpass > 3)
982217Smeem 				usage();
992217Smeem 			break;
1002217Smeem 		case 'r':
1012217Smeem 			justrelpaths = B_TRUE;
1022217Smeem 			break;
1032217Smeem 		default:
1042217Smeem 			usage();
1052217Smeem 		}
1062217Smeem 	}
1072217Smeem 
1082217Smeem 	if (optind == argc)
1092217Smeem 		usage();
1102217Smeem 
1112217Smeem 	for (i = optind; i < argc; i++) {
1122217Smeem 		fp = fopen(argv[i], "r");
1132217Smeem 		if (fp == NULL) {
1142217Smeem 			warn("cannot open \"%s\"", argv[i]);
1152217Smeem 			continue;
1162217Smeem 		}
1172217Smeem 
118*6362Smeem 		lnname = argv[i];
119*6362Smeem 		if (justrelpaths && lnname[0] == '/')
120*6362Smeem 			lnname = strrchr(lnname, '/') + 1;
1212217Smeem 
1222217Smeem 		/*
123*6362Smeem 		 * Dump out all of the modules in the lint object.
1242217Smeem 		 */
125*6362Smeem 		for (mod = 1; fread(&hdr, sizeof (hdr), 1, fp) == 1; mod++) {
126*6362Smeem 			if (hdr.ver != LINTVER) {
127*6362Smeem 				warn("%s: unsupported lint object version "
128*6362Smeem 				    "%d\n", argv[i], hdr.ver);
129*6362Smeem 				break;
130*6362Smeem 			}
131*6362Smeem 
132*6362Smeem 			if (mod == 1)
133*6362Smeem 				infohdr("LINTOBJ", "%s\n", lnname);
134*6362Smeem 
135*6362Smeem 			/*
136*6362Smeem 			 * First build the table of structure/union names,
137*6362Smeem 			 * then print the lint module.  Finally, empty the
138*6362Smeem 			 * table out before dumping the next module.
139*6362Smeem 			 */
140*6362Smeem 			lsu_build(fp);
141*6362Smeem 			print_lintmod(lnname, fp, &hdr);
142*6362Smeem 			lsu_empty();
143*6362Smeem 		}
1442217Smeem 		(void) fclose(fp);
1452217Smeem 	}
1462217Smeem 
1472217Smeem 	return (EXIT_SUCCESS);
1482217Smeem }
1492217Smeem 
1502217Smeem /*
151*6362Smeem  * Print a lint module and advance past it in the stream.
1522217Smeem  */
1532217Smeem static void
print_lintmod(const char * lnname,FILE * fp,FLENS * hp)154*6362Smeem print_lintmod(const char *lnname, FILE *fp, FLENS *hp)
1552217Smeem {
156*6362Smeem 	ulong_t		psizes[5];
1572217Smeem 	uint_t		pass;
1582217Smeem 
1592217Smeem 	psizes[0] = 0;
1602217Smeem 	psizes[1] = hp->f1;
1612217Smeem 	psizes[2] = hp->f2;
1622217Smeem 	psizes[3] = hp->f3;
163*6362Smeem 	psizes[4] = hp->f4;
1642217Smeem 
165*6362Smeem 	infohdr("LINTMOD", "%hu: %lu+%lu+%lu+%lu = %lu bytes\n", hp->mno,
166*6362Smeem 	    hp->f1, hp->f2, hp->f3, hp->f4, hp->f1 + hp->f2 + hp->f3 + hp->f4);
1672217Smeem 
168*6362Smeem 	for (pass = 1; pass <= 4; pass++) {
169*6362Smeem 		if ((justpass < 0 || justpass == pass) && pass < 4) {
1702217Smeem 			infohdr("SECTION", "PASS%u: %lu bytes\n", pass,
1712217Smeem 			    psizes[pass]);
1723033Smeem 			print_pass(lnname, fp);
173*6362Smeem 		} else {
174*6362Smeem 			(void) fseek(fp, psizes[pass], SEEK_CUR);
1752217Smeem 		}
1762217Smeem 	}
1772217Smeem }
1782217Smeem 
1792217Smeem /*
180*6362Smeem  * Print out a PASS section of a lint module.
1812217Smeem  */
1822217Smeem static void
print_pass(const char * lnname,FILE * fp)1833033Smeem print_pass(const char *lnname, FILE *fp)
1842217Smeem {
1852217Smeem 	union rec	rec;
1862217Smeem 	int		nargs;
1872217Smeem 	char		name[1024];
1882217Smeem 	ATYPE		atype, *args;
1892217Smeem 	LINE		line;
1902217Smeem 	boolean_t	wasfile = B_FALSE;
1912217Smeem 
1922217Smeem 	for (;;) {
1932217Smeem 		if (fread(&rec, sizeof (rec), 1, fp) != 1)
1943033Smeem 			die("%s: unexpected end of file\n", lnname);
1952217Smeem 
1962217Smeem 		line = rec.l;
1972217Smeem 		if (line.decflag & LND)		/* end-of-pass marker */
1982217Smeem 			break;
1992217Smeem 
2002217Smeem 		getstr(fp, name, sizeof (name));
2012217Smeem 
2022217Smeem 		/*
2032217Smeem 		 * Check if this is a file record.
2042217Smeem 		 */
2052217Smeem 		if (line.decflag & LFN) {
2062217Smeem 			if (wasfile || !justrelpaths)
2072217Smeem 				infohdr("FILE", "%s\n", name);
2082217Smeem 			wasfile = B_TRUE;
2092217Smeem 			continue;
2102217Smeem 		}
2112217Smeem 		wasfile = B_FALSE;
2122217Smeem 
2132217Smeem 		/*
2142217Smeem 		 * Check if this is a function or variable record.
2152217Smeem 		 */
2162217Smeem 		nargs = line.nargs;
2172217Smeem 		if (line.decflag & (LIB|LDS|LDI|LPR|LDX|LDC|LRV|LUE|LUV|LUM)) {
2182217Smeem 			if (nargs < 0)
2192217Smeem 				nargs = -nargs - 1;
2202217Smeem 
2212217Smeem 			if (line.decflag & LDS)
2222217Smeem 				info("static ");
2232217Smeem 			else if (line.decflag & (LPR|LDX|LDC))
2242217Smeem 				info("extern ");
2252217Smeem 
2262217Smeem 			args = calloc(sizeof (atype), nargs);
2272217Smeem 			if (args == NULL)
2282217Smeem 				die("cannot allocate argument information");
2292217Smeem 
2302217Smeem 			if (fread(args, sizeof (atype), nargs, fp) != nargs)
2313033Smeem 				die("%s: unexpected end of file\n", lnname);
2322217Smeem 
2332217Smeem 			print_atype(&line.type, line.nargs, args, name);
2342217Smeem 			free(args);
2352217Smeem 
2362217Smeem 			if (line.decflag & LRV)
2372217Smeem 				info(" <returns value>");
2382217Smeem 			if (line.decflag & LUE)
2392217Smeem 				info(" <use: side-effects context>");
2402217Smeem 			if (line.decflag & LUV)
2412217Smeem 				info(" <use: return value context>");
2422217Smeem 			if (line.decflag & LUM)
2432217Smeem 				info(" <use: unspecified context>");
2442217Smeem 
2452217Smeem 			if (line.decflag & LPF)
2462217Smeem 				info(" <PRINTFLIKE%d>", nargs);
2472217Smeem 			else if (line.decflag & LSF)
2482217Smeem 				info(" <SCANFLIKE%d>", nargs);
2492217Smeem 
2502217Smeem 			if (line.decflag & LDI)
2512217Smeem 				info(" { <definition> }");
2522217Smeem 			else if (line.decflag & LDX)
2532217Smeem 				info(" = <definition>");
2542217Smeem 
2552217Smeem 			info(";\n");
2562217Smeem 			continue;
2572217Smeem 		}
2582217Smeem 
2592217Smeem 		/*
2602217Smeem 		 * Check if this is a structure or union record.
2612217Smeem 		 */
2622217Smeem 		if (line.decflag & LSU) {
2632217Smeem 			if (line.decflag & ~(LSU))
2642217Smeem 				info("??? ");
2652217Smeem 
2664576Smeem 			info("struct ");
2674576Smeem 			if (name[0] != '.')
2684576Smeem 				info("%s ", name);
2692217Smeem 			if (showids)
2702217Smeem 				info("<tag %lu> ", line.type.extra.ty);
2712217Smeem 			info("{ \n");
2722217Smeem 
2732217Smeem 			indent();
2742217Smeem 			for (; nargs > 0; nargs--) {
2753033Smeem 				if (fread(&atype, sizeof (atype), 1, fp) != 1) {
2763033Smeem 					die("%s: unexpected end of file\n",
2773033Smeem 					    lnname);
2783033Smeem 				}
2792217Smeem 				getstr(fp, name, sizeof (name));
2802217Smeem 				print_atype(&atype, 0, NULL, name);
2812217Smeem 				info(";\n");
2822217Smeem 			}
2832217Smeem 			unindent();
2842217Smeem 			info("};\n");
2852217Smeem 			continue;
2862217Smeem 		}
2872217Smeem 
2883033Smeem 		warn("%s: unknown record type 0%o\n", lnname, line.decflag);
2892217Smeem 	}
2902217Smeem }
2912217Smeem 
2922217Smeem /*
2932217Smeem  * Print the C datatype or function `atp' named `name'.  If `name' is a
2942217Smeem  * function, then `nargs' indicates the number of C datatypes pointed to
2952217Smeem  * by `args'.
2962217Smeem  */
2972217Smeem static void
print_atype(ATYPE * atp,int nargs,ATYPE * args,const char * name)2982217Smeem print_atype(ATYPE *atp, int nargs, ATYPE *args, const char *name)
2992217Smeem {
3002217Smeem 	static const char *basetypes[] = {		"",
3012217Smeem 		"char",		"unsigned char",	"signed char",
3022217Smeem 		"short",	"unsigned short",	"signed short",
3032217Smeem 		"int",		"unsigned int",		"signed int",
3042217Smeem 		"long",		"unsigned long",	"signed long",
3052217Smeem 		"long long",	"unsigned long long",	"signed long long",
3062217Smeem 		"enum",		"float",		"double",
3072217Smeem 		"long double",	"void",			"struct",
3082217Smeem 		"union",	"_Bool",		"<genchar>",
3092217Smeem 		"<genshort>",	"<genint>",		"<genlong>",
3102217Smeem 		"<genlonglong>"
3112217Smeem 	};
3122217Smeem 	uint16_t basetype = atp->aty & LNQUAL;
3132217Smeem 	lsu_t *lsup;
3142217Smeem 
3152217Smeem 	if (atp->aty & LCON)
3162217Smeem 		info("const ");
3172217Smeem 	if (atp->aty & LVOL)
3182217Smeem 		info("volatile ");
3192217Smeem 	if (atp->aty & LCONV)
3202217Smeem 		info("integer const ");
3212217Smeem 
3222217Smeem 	if (basetype < 1 ||
3232217Smeem 	    basetype > (sizeof (basetypes) / sizeof (*basetypes)))
3242217Smeem 		info("<unknown type %x>", basetype);
3252217Smeem 
3262217Smeem 	switch (basetype) {
3272217Smeem 	case LN_UNION:
3282217Smeem 	case LN_STRUCT:
3292217Smeem 		lsup = lsu_lookup(atp->extra.ty);
3302217Smeem 		if (lsup != NULL && lsup->name[0] != '.') {
3312217Smeem 			info("%s %s", basetypes[basetype], lsup->name);
3322217Smeem 		} else {
3332217Smeem 			info("%s", basetypes[basetype]);
3342217Smeem 			if (showids)
3352217Smeem 				info(" <tag %lu>", atp->extra.ty);
3362217Smeem 			else
3372217Smeem 				info(" <anon>");
3382217Smeem 		}
3392217Smeem 		break;
3402217Smeem 	default:
3414576Smeem 		info("%s", basetypes[basetype]);
3422217Smeem 	};
3432217Smeem 
3442217Smeem 	print_mods(name, atp, nargs, args, 14);
3452217Smeem }
3462217Smeem 
3472217Smeem /*
3482217Smeem  * Recursively print type modifiers.
3492217Smeem  */
3502217Smeem static void
print_mods(const char * name,ATYPE * atp,int nargs,ATYPE * args,uint_t pos)3512217Smeem print_mods(const char *name, ATYPE *atp, int nargs, ATYPE *args, uint_t pos)
3522217Smeem {
3532217Smeem 	int arg;
3542217Smeem 	int mods = atp->dcl_mod >> (pos * 2);
3552217Smeem 	int lastmods = atp->dcl_mod >> ((pos + 1) * 2);
3562217Smeem 	boolean_t isvarargs = B_FALSE;
3572217Smeem 
3582217Smeem 	if (LN_ISPTR(mods)) {
3592217Smeem 		if (!LN_ISPTR(lastmods) && !LN_ISFTN(lastmods))
3602217Smeem 			info(" ");
3612217Smeem 		info("*");
3622217Smeem 	}
3632217Smeem 
3642217Smeem 	if (atp->dcl_con & (1 << pos))
3652217Smeem 		info(" const ");
3662217Smeem 	if (atp->dcl_vol & (1 << pos))
3672217Smeem 		info(" volatile ");
3682217Smeem 
3692217Smeem 	if (pos != 0) {
3702217Smeem 		if (LN_ISFTN(mods))
3712217Smeem 			info(" (");
3722217Smeem 		print_mods(name, atp, nargs, args, pos - 1);
3732217Smeem 		if (LN_ISFTN(mods))
3742217Smeem 			info(")()");
3752217Smeem 		return;
3762217Smeem 	}
3772217Smeem 
3782217Smeem 	if (name[0] == '\0')
3792217Smeem 		return;
3802217Smeem 
3812217Smeem 	if (!LN_ISPTR(lastmods) && !LN_ISPTR(mods))
3822217Smeem 		info(" ");
3832217Smeem 	info("%s", name);
3842217Smeem 
3852217Smeem 	if (LN_ISARY(mods)) {
3862217Smeem 		info("[]");
3872217Smeem 	} else if (LN_ISFTN(mods)) {
3882217Smeem 		info("(");
3892217Smeem 
3902217Smeem 		if (nargs < 0) {
3912217Smeem 			nargs = -nargs - 1;
3922217Smeem 			isvarargs = B_TRUE;
3932217Smeem 		}
3942217Smeem 
3952217Smeem 		if (nargs == 0) {
3962217Smeem 			info("void");
3972217Smeem 		} else {
3982217Smeem 			for (arg = 0; arg < nargs; arg++) {
3992217Smeem 				print_atype(&args[arg], 0, NULL, "");
4002217Smeem 				if ((arg + 1) < nargs)
4012217Smeem 					info(", ");
4022217Smeem 				else if (isvarargs)
4032217Smeem 					info(", ...");
4042217Smeem 			}
4052217Smeem 		}
4062217Smeem 		info(")");
4072217Smeem 	}
4082217Smeem }
4092217Smeem 
4102217Smeem /*
4112217Smeem  * Add an LSU entry to the LSU table.
4122217Smeem  */
4132217Smeem static int
lsu_add(const char * name,ATYPE * atp)4142217Smeem lsu_add(const char *name, ATYPE *atp)
4152217Smeem {
4162217Smeem 	unsigned int	i = atp->extra.ty % LSU_HASHSIZE;
4172217Smeem 	lsu_t		*lsup;
4182217Smeem 
4192217Smeem 	lsup = malloc(sizeof (lsu_t));
4202217Smeem 	if (lsup == NULL)
4212217Smeem 		return (ENOMEM);
4222217Smeem 
4232217Smeem 	lsup->atype = *atp;
4242217Smeem 	lsup->next = lsu_table[i];
4252217Smeem 	lsup->name = strdup(name);
4262217Smeem 	if (lsup->name == NULL) {
4272217Smeem 		free(lsup);
4282217Smeem 		return (ENOMEM);
4292217Smeem 	}
4302217Smeem 
4312217Smeem 	lsu_table[i] = lsup;
4322217Smeem 	return (0);
4332217Smeem }
4342217Smeem 
4352217Smeem /*
4362217Smeem  * Lookup an LSU entry by ID.
4372217Smeem  */
4382217Smeem static lsu_t *
lsu_lookup(T1WORD ty)4392217Smeem lsu_lookup(T1WORD ty)
4402217Smeem {
4412217Smeem 	unsigned int	i = ty % LSU_HASHSIZE;
4422217Smeem 	lsu_t		*lsup;
4432217Smeem 
4442217Smeem 	for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup->next) {
4452217Smeem 		if (lsup->atype.extra.ty == ty)
4462217Smeem 			return (lsup);
4472217Smeem 	}
4482217Smeem 
4492217Smeem 	return (NULL);
4502217Smeem }
4512217Smeem 
4522217Smeem /*
4532217Smeem  * Read all LSU (structure and union definition) records in order to
4542217Smeem  * build a structure and union name table, called the LSU table.
455*6362Smeem  * Although `fp' is read from, the original file offset is preserved.
4562217Smeem  */
4572217Smeem static void
lsu_build(FILE * fp)4582217Smeem lsu_build(FILE *fp)
4592217Smeem {
4602217Smeem 	union rec	rec;
4612217Smeem 	char		name[1024];
4622217Smeem 	int		nargs;
463*6362Smeem 	off_t		curoff = ftello(fp);
4642217Smeem 
4652217Smeem 	for (;;) {
4662217Smeem 		if (fread(&rec, sizeof (rec), 1, fp) != 1)
467*6362Smeem 			break;
4682217Smeem 
4692217Smeem 		if (rec.l.decflag & LND)	/* end-of-pass marker */
4702217Smeem 			break;
4712217Smeem 
4722217Smeem 		getstr(fp, name, sizeof (name));
4732217Smeem 		nargs = rec.l.nargs;
4742217Smeem 
4752217Smeem 		if (rec.l.decflag & (LIB|LDS|LDI)) {
4762217Smeem 			if (nargs < 0)
4772217Smeem 				nargs = -nargs - 1;
4782217Smeem 
4792217Smeem 			(void) fseek(fp, sizeof (ATYPE) * nargs, SEEK_CUR);
4802217Smeem 			continue;
4812217Smeem 		}
4822217Smeem 
4832217Smeem 		if (rec.l.decflag & LSU) {
4842217Smeem 			if (lsu_add(name, &rec.l.type) != 0)
4852217Smeem 				warn("cannot allocate struct `%s' info", name);
4862217Smeem 
4872217Smeem 			for (; nargs > 0; nargs--) {
4882217Smeem 				(void) fseek(fp, sizeof (ATYPE), SEEK_CUR);
4892217Smeem 				getstr(fp, name, sizeof (name));
4902217Smeem 			}
4912217Smeem 		}
4922217Smeem 	}
493*6362Smeem 
494*6362Smeem 	(void) fseek(fp, curoff, SEEK_SET);
4952217Smeem }
4962217Smeem 
4972217Smeem /*
4982217Smeem  * Empty the LSU table.
4992217Smeem  */
5002217Smeem static void
lsu_empty(void)5012217Smeem lsu_empty(void)
5022217Smeem {
5032217Smeem 	lsu_t		*lsup, *lsup_next;
5042217Smeem 	unsigned int	i;
5052217Smeem 
5062217Smeem 	for (i = 0; i < LSU_HASHSIZE; i++) {
5072217Smeem 		for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup_next) {
5082217Smeem 			lsup_next = lsup->next;
5092217Smeem 			free(lsup);
5102217Smeem 		}
5112217Smeem 		lsu_table[i] = NULL;
5122217Smeem 	}
5132217Smeem }
5142217Smeem 
5152217Smeem /*
5162217Smeem  * Read the NUL-terminated string at `fp' into `buf', which is at most
5172217Smeem  * `bufsize' bytes.
5182217Smeem  */
5192217Smeem static void
getstr(FILE * fp,char * buf,size_t bufsize)5202217Smeem getstr(FILE *fp, char *buf, size_t bufsize)
5212217Smeem {
5222217Smeem 	int c;
5232217Smeem 	size_t i;
5242217Smeem 
5252217Smeem 	for (i = 0; i < bufsize - 1; i++) {
5262217Smeem 		c = fgetc(fp);
5272217Smeem 		if (c == EOF || c == '\0' || !isascii(c))
5282217Smeem 			break;
5292217Smeem 		buf[i] = (char)c;
5302217Smeem 	}
5312217Smeem 
5322217Smeem 	buf[i] = '\0';
5332217Smeem }
5342217Smeem 
5352217Smeem static void
indent(void)5362217Smeem indent(void)
5372217Smeem {
5382217Smeem 	indentlevel += 4;
5392217Smeem }
5402217Smeem 
5412217Smeem static void
unindent(void)5422217Smeem unindent(void)
5432217Smeem {
5442217Smeem 	indentlevel -= 4;
5452217Smeem }
5462217Smeem 
5472217Smeem static void
usage(void)5482217Smeem usage(void)
5492217Smeem {
550*6362Smeem 	(void) fprintf(stderr, "usage: %s [-i] [-p 1|2|3] [-r] lintobj"
551*6362Smeem 	    " [ lintobj ... ]\n", progname);
5522217Smeem 	exit(EXIT_FAILURE);
5532217Smeem }
5542217Smeem 
5552217Smeem /* PRINTFLIKE1 */
5562217Smeem static void
info(const char * format,...)5572217Smeem info(const char *format, ...)
5582217Smeem {
5592217Smeem 	va_list alist;
5602217Smeem 	static int complete = 1;
5612217Smeem 
5622217Smeem 	if (complete)
5632217Smeem 		(void) printf("%*s", indentlevel, "");
5642217Smeem 
5652217Smeem 	va_start(alist, format);
5662217Smeem 	(void) vprintf(format, alist);
5672217Smeem 	va_end(alist);
5682217Smeem 
5692217Smeem 	complete = strrchr(format, '\n') != NULL;
5702217Smeem }
5712217Smeem 
5722217Smeem /* PRINTFLIKE2 */
5732217Smeem static void
infohdr(const char * hdr,const char * format,...)5742217Smeem infohdr(const char *hdr, const char *format, ...)
5752217Smeem {
5762217Smeem 	va_list alist;
5772217Smeem 	static int complete = 1;
5782217Smeem 
5792217Smeem 	if (complete)
5802217Smeem 		(void) printf("%7s: ", hdr);
5812217Smeem 
5822217Smeem 	va_start(alist, format);
5832217Smeem 	(void) vprintf(format, alist);
5842217Smeem 	va_end(alist);
5852217Smeem 
5862217Smeem 	complete = strrchr(format, '\n') != NULL;
5872217Smeem }
5882217Smeem 
5892217Smeem /* PRINTFLIKE1 */
5902217Smeem static void
warn(const char * format,...)5912217Smeem warn(const char *format, ...)
5922217Smeem {
5932217Smeem 	va_list alist;
5942217Smeem 	char *errstr = strerror(errno);
5952217Smeem 
5962217Smeem 	(void) fprintf(stderr, "%s: warning: ", progname);
5972217Smeem 
5982217Smeem 	va_start(alist, format);
5992217Smeem 	(void) vfprintf(stderr, format, alist);
6002217Smeem 	va_end(alist);
6012217Smeem 
6022217Smeem 	if (strrchr(format, '\n') == NULL)
6032217Smeem 		(void) fprintf(stderr, ": %s\n", errstr);
6042217Smeem }
6052217Smeem 
6062217Smeem /* PRINTFLIKE1 */
6072217Smeem static void
die(const char * format,...)6082217Smeem die(const char *format, ...)
6092217Smeem {
6102217Smeem 	va_list alist;
6112217Smeem 	char *errstr = strerror(errno);
6122217Smeem 
6132217Smeem 	(void) fprintf(stderr, "%s: fatal: ", progname);
6142217Smeem 
6152217Smeem 	va_start(alist, format);
6162217Smeem 	(void) vfprintf(stderr, format, alist);
6172217Smeem 	va_end(alist);
6182217Smeem 
6192217Smeem 	if (strrchr(format, '\n') == NULL)
6202217Smeem 		(void) fprintf(stderr, ": %s\n", errstr);
6212217Smeem 
6222217Smeem 	exit(EXIT_FAILURE);
6232217Smeem }
624