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*fa5e8906Smeem * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2434c98957Smeem * Use is subject to license terms.
2534c98957Smeem */
2634c98957Smeem
2734c98957Smeem /*
2834c98957Smeem * Tool for dumping lint libraries.
2934c98957Smeem */
3034c98957Smeem
3134c98957Smeem #include <ctype.h>
3234c98957Smeem #include <errno.h>
3334c98957Smeem #include <stdarg.h>
3434c98957Smeem #include <stdio.h>
3534c98957Smeem #include <stdlib.h>
3634c98957Smeem #include <string.h>
3734c98957Smeem #include <sys/types.h>
3834c98957Smeem
3934c98957Smeem #include "lnstuff.h" /* silly header name from alint */
4034c98957Smeem
4134c98957Smeem typedef struct lsu {
4234c98957Smeem const char *name;
4334c98957Smeem ATYPE atype;
4434c98957Smeem struct lsu *next;
4534c98957Smeem } lsu_t;
4634c98957Smeem
4734c98957Smeem #define LSU_HASHSIZE 512
4834c98957Smeem static lsu_t *lsu_table[LSU_HASHSIZE];
4934c98957Smeem
5034c98957Smeem static boolean_t showids = B_TRUE;
5134c98957Smeem static boolean_t justrelpaths = B_FALSE;
5234c98957Smeem static int justpass = -1;
5334c98957Smeem static int indentlevel = 9;
5434c98957Smeem static const char *progname;
5534c98957Smeem
5634c98957Smeem static void info(const char *, ...);
5734c98957Smeem static void infohdr(const char *, const char *, ...);
5834c98957Smeem static void warn(const char *, ...);
5934c98957Smeem static void die(const char *, ...);
6034c98957Smeem static void usage(void);
6134c98957Smeem static void indent(void);
6234c98957Smeem static void unindent(void);
63*fa5e8906Smeem static void print_lintmod(const char *, FILE *, FLENS *);
64b4034a75Smeem static void print_pass(const char *, FILE *);
6534c98957Smeem static void print_atype(ATYPE *, int, ATYPE *, const char *);
6634c98957Smeem static void print_mods(const char *, ATYPE *, int, ATYPE *, uint_t);
6734c98957Smeem static void getstr(FILE *, char *, size_t);
6834c98957Smeem static void lsu_build(FILE *);
6934c98957Smeem static void lsu_empty(void);
7034c98957Smeem static int lsu_add(const char *, ATYPE *);
7134c98957Smeem static lsu_t *lsu_lookup(unsigned long);
7234c98957Smeem
7334c98957Smeem int
main(int argc,char ** argv)7434c98957Smeem main(int argc, char **argv)
7534c98957Smeem {
76*fa5e8906Smeem int i, c, mod;
7734c98957Smeem FILE *fp;
7834c98957Smeem FLENS hdr;
79*fa5e8906Smeem const char *lnname;
8034c98957Smeem
8134c98957Smeem progname = strrchr(argv[0], '/');
8234c98957Smeem if (progname == NULL)
8334c98957Smeem progname = argv[0];
8434c98957Smeem else
8534c98957Smeem progname++;
8634c98957Smeem
8734c98957Smeem while ((c = getopt(argc, argv, "ip:r")) != EOF) {
8834c98957Smeem switch (c) {
8934c98957Smeem case 'i':
9034c98957Smeem showids = B_FALSE;
9134c98957Smeem break;
9234c98957Smeem case 'p':
9334c98957Smeem justpass = strtoul(optarg, NULL, 0);
9434c98957Smeem if (justpass < 1 || justpass > 3)
9534c98957Smeem usage();
9634c98957Smeem break;
9734c98957Smeem case 'r':
9834c98957Smeem justrelpaths = B_TRUE;
9934c98957Smeem break;
10034c98957Smeem default:
10134c98957Smeem usage();
10234c98957Smeem }
10334c98957Smeem }
10434c98957Smeem
10534c98957Smeem if (optind == argc)
10634c98957Smeem usage();
10734c98957Smeem
10834c98957Smeem for (i = optind; i < argc; i++) {
10934c98957Smeem fp = fopen(argv[i], "r");
11034c98957Smeem if (fp == NULL) {
11134c98957Smeem warn("cannot open \"%s\"", argv[i]);
11234c98957Smeem continue;
11334c98957Smeem }
11434c98957Smeem
115*fa5e8906Smeem lnname = argv[i];
116*fa5e8906Smeem if (justrelpaths && lnname[0] == '/')
117*fa5e8906Smeem lnname = strrchr(lnname, '/') + 1;
11834c98957Smeem
11934c98957Smeem /*
120*fa5e8906Smeem * Dump out all of the modules in the lint object.
121*fa5e8906Smeem */
122*fa5e8906Smeem for (mod = 1; fread(&hdr, sizeof (hdr), 1, fp) == 1; mod++) {
123*fa5e8906Smeem if (hdr.ver != LINTVER) {
124*fa5e8906Smeem warn("%s: unsupported lint object version "
125*fa5e8906Smeem "%d\n", argv[i], hdr.ver);
126*fa5e8906Smeem break;
127*fa5e8906Smeem }
128*fa5e8906Smeem
129*fa5e8906Smeem if (mod == 1)
130*fa5e8906Smeem infohdr("LINTOBJ", "%s\n", lnname);
131*fa5e8906Smeem
132*fa5e8906Smeem /*
133*fa5e8906Smeem * First build the table of structure/union names,
134*fa5e8906Smeem * then print the lint module. Finally, empty the
135*fa5e8906Smeem * table out before dumping the next module.
13634c98957Smeem */
13734c98957Smeem lsu_build(fp);
138*fa5e8906Smeem print_lintmod(lnname, fp, &hdr);
13934c98957Smeem lsu_empty();
14034c98957Smeem }
141*fa5e8906Smeem (void) fclose(fp);
142*fa5e8906Smeem }
14334c98957Smeem
14434c98957Smeem return (EXIT_SUCCESS);
14534c98957Smeem }
14634c98957Smeem
14734c98957Smeem /*
148*fa5e8906Smeem * Print a lint module and advance past it in the stream.
14934c98957Smeem */
15034c98957Smeem static void
print_lintmod(const char * lnname,FILE * fp,FLENS * hp)151*fa5e8906Smeem print_lintmod(const char *lnname, FILE *fp, FLENS *hp)
15234c98957Smeem {
153*fa5e8906Smeem ulong_t psizes[5];
15434c98957Smeem uint_t pass;
15534c98957Smeem
15634c98957Smeem psizes[0] = 0;
15734c98957Smeem psizes[1] = hp->f1;
15834c98957Smeem psizes[2] = hp->f2;
15934c98957Smeem psizes[3] = hp->f3;
160*fa5e8906Smeem psizes[4] = hp->f4;
16134c98957Smeem
162*fa5e8906Smeem infohdr("LINTMOD", "%hu: %lu+%lu+%lu+%lu = %lu bytes\n", hp->mno,
163*fa5e8906Smeem hp->f1, hp->f2, hp->f3, hp->f4, hp->f1 + hp->f2 + hp->f3 + hp->f4);
16434c98957Smeem
165*fa5e8906Smeem for (pass = 1; pass <= 4; pass++) {
166*fa5e8906Smeem if ((justpass < 0 || justpass == pass) && pass < 4) {
16734c98957Smeem infohdr("SECTION", "PASS%u: %lu bytes\n", pass,
16834c98957Smeem psizes[pass]);
169b4034a75Smeem print_pass(lnname, fp);
170*fa5e8906Smeem } else {
171*fa5e8906Smeem (void) fseek(fp, psizes[pass], SEEK_CUR);
17234c98957Smeem }
17334c98957Smeem }
17434c98957Smeem }
17534c98957Smeem
17634c98957Smeem /*
177*fa5e8906Smeem * Print out a PASS section of a lint module.
17834c98957Smeem */
17934c98957Smeem static void
print_pass(const char * lnname,FILE * fp)180b4034a75Smeem print_pass(const char *lnname, FILE *fp)
18134c98957Smeem {
18234c98957Smeem union rec rec;
18334c98957Smeem int nargs;
18434c98957Smeem char name[1024];
18534c98957Smeem ATYPE atype, *args;
18634c98957Smeem LINE line;
18734c98957Smeem boolean_t wasfile = B_FALSE;
18834c98957Smeem
18934c98957Smeem for (;;) {
19034c98957Smeem if (fread(&rec, sizeof (rec), 1, fp) != 1)
191b4034a75Smeem die("%s: unexpected end of file\n", lnname);
19234c98957Smeem
19334c98957Smeem line = rec.l;
19434c98957Smeem if (line.decflag & LND) /* end-of-pass marker */
19534c98957Smeem break;
19634c98957Smeem
19734c98957Smeem getstr(fp, name, sizeof (name));
19834c98957Smeem
19934c98957Smeem /*
20034c98957Smeem * Check if this is a file record.
20134c98957Smeem */
20234c98957Smeem if (line.decflag & LFN) {
20334c98957Smeem if (wasfile || !justrelpaths)
20434c98957Smeem infohdr("FILE", "%s\n", name);
20534c98957Smeem wasfile = B_TRUE;
20634c98957Smeem continue;
20734c98957Smeem }
20834c98957Smeem wasfile = B_FALSE;
20934c98957Smeem
21034c98957Smeem /*
21134c98957Smeem * Check if this is a function or variable record.
21234c98957Smeem */
21334c98957Smeem nargs = line.nargs;
21434c98957Smeem if (line.decflag & (LIB|LDS|LDI|LPR|LDX|LDC|LRV|LUE|LUV|LUM)) {
21534c98957Smeem if (nargs < 0)
21634c98957Smeem nargs = -nargs - 1;
21734c98957Smeem
21834c98957Smeem if (line.decflag & LDS)
21934c98957Smeem info("static ");
22034c98957Smeem else if (line.decflag & (LPR|LDX|LDC))
22134c98957Smeem info("extern ");
22234c98957Smeem
22334c98957Smeem args = calloc(sizeof (atype), nargs);
22434c98957Smeem if (args == NULL)
22534c98957Smeem die("cannot allocate argument information");
22634c98957Smeem
22734c98957Smeem if (fread(args, sizeof (atype), nargs, fp) != nargs)
228b4034a75Smeem die("%s: unexpected end of file\n", lnname);
22934c98957Smeem
23034c98957Smeem print_atype(&line.type, line.nargs, args, name);
23134c98957Smeem free(args);
23234c98957Smeem
23334c98957Smeem if (line.decflag & LRV)
23434c98957Smeem info(" <returns value>");
23534c98957Smeem if (line.decflag & LUE)
23634c98957Smeem info(" <use: side-effects context>");
23734c98957Smeem if (line.decflag & LUV)
23834c98957Smeem info(" <use: return value context>");
23934c98957Smeem if (line.decflag & LUM)
24034c98957Smeem info(" <use: unspecified context>");
24134c98957Smeem
24234c98957Smeem if (line.decflag & LPF)
24334c98957Smeem info(" <PRINTFLIKE%d>", nargs);
24434c98957Smeem else if (line.decflag & LSF)
24534c98957Smeem info(" <SCANFLIKE%d>", nargs);
24634c98957Smeem
24734c98957Smeem if (line.decflag & LDI)
24834c98957Smeem info(" { <definition> }");
24934c98957Smeem else if (line.decflag & LDX)
25034c98957Smeem info(" = <definition>");
25134c98957Smeem
25234c98957Smeem info(";\n");
25334c98957Smeem continue;
25434c98957Smeem }
25534c98957Smeem
25634c98957Smeem /*
25734c98957Smeem * Check if this is a structure or union record.
25834c98957Smeem */
25934c98957Smeem if (line.decflag & LSU) {
26034c98957Smeem if (line.decflag & ~(LSU))
26134c98957Smeem info("??? ");
26234c98957Smeem
2635cb4fc81Smeem info("struct ");
2645cb4fc81Smeem if (name[0] != '.')
2655cb4fc81Smeem info("%s ", name);
26634c98957Smeem if (showids)
26734c98957Smeem info("<tag %lu> ", line.type.extra.ty);
26834c98957Smeem info("{ \n");
26934c98957Smeem
27034c98957Smeem indent();
27134c98957Smeem for (; nargs > 0; nargs--) {
272b4034a75Smeem if (fread(&atype, sizeof (atype), 1, fp) != 1) {
273b4034a75Smeem die("%s: unexpected end of file\n",
274b4034a75Smeem lnname);
275b4034a75Smeem }
27634c98957Smeem getstr(fp, name, sizeof (name));
27734c98957Smeem print_atype(&atype, 0, NULL, name);
27834c98957Smeem info(";\n");
27934c98957Smeem }
28034c98957Smeem unindent();
28134c98957Smeem info("};\n");
28234c98957Smeem continue;
28334c98957Smeem }
28434c98957Smeem
285b4034a75Smeem warn("%s: unknown record type 0%o\n", lnname, line.decflag);
28634c98957Smeem }
28734c98957Smeem }
28834c98957Smeem
28934c98957Smeem /*
29034c98957Smeem * Print the C datatype or function `atp' named `name'. If `name' is a
29134c98957Smeem * function, then `nargs' indicates the number of C datatypes pointed to
29234c98957Smeem * by `args'.
29334c98957Smeem */
29434c98957Smeem static void
print_atype(ATYPE * atp,int nargs,ATYPE * args,const char * name)29534c98957Smeem print_atype(ATYPE *atp, int nargs, ATYPE *args, const char *name)
29634c98957Smeem {
29734c98957Smeem static const char *basetypes[] = { "",
29834c98957Smeem "char", "unsigned char", "signed char",
29934c98957Smeem "short", "unsigned short", "signed short",
30034c98957Smeem "int", "unsigned int", "signed int",
30134c98957Smeem "long", "unsigned long", "signed long",
30234c98957Smeem "long long", "unsigned long long", "signed long long",
30334c98957Smeem "enum", "float", "double",
30434c98957Smeem "long double", "void", "struct",
30534c98957Smeem "union", "_Bool", "<genchar>",
30634c98957Smeem "<genshort>", "<genint>", "<genlong>",
30734c98957Smeem "<genlonglong>"
30834c98957Smeem };
30934c98957Smeem uint16_t basetype = atp->aty & LNQUAL;
31034c98957Smeem lsu_t *lsup;
31134c98957Smeem
31234c98957Smeem if (atp->aty & LCON)
31334c98957Smeem info("const ");
31434c98957Smeem if (atp->aty & LVOL)
31534c98957Smeem info("volatile ");
31634c98957Smeem if (atp->aty & LCONV)
31734c98957Smeem info("integer const ");
31834c98957Smeem
31934c98957Smeem if (basetype < 1 ||
32034c98957Smeem basetype > (sizeof (basetypes) / sizeof (*basetypes)))
32134c98957Smeem info("<unknown type %x>", basetype);
32234c98957Smeem
32334c98957Smeem switch (basetype) {
32434c98957Smeem case LN_UNION:
32534c98957Smeem case LN_STRUCT:
32634c98957Smeem lsup = lsu_lookup(atp->extra.ty);
32734c98957Smeem if (lsup != NULL && lsup->name[0] != '.') {
32834c98957Smeem info("%s %s", basetypes[basetype], lsup->name);
32934c98957Smeem } else {
33034c98957Smeem info("%s", basetypes[basetype]);
33134c98957Smeem if (showids)
33234c98957Smeem info(" <tag %lu>", atp->extra.ty);
33334c98957Smeem else
33434c98957Smeem info(" <anon>");
33534c98957Smeem }
33634c98957Smeem break;
33734c98957Smeem default:
3385cb4fc81Smeem info("%s", basetypes[basetype]);
33934c98957Smeem };
34034c98957Smeem
34134c98957Smeem print_mods(name, atp, nargs, args, 14);
34234c98957Smeem }
34334c98957Smeem
34434c98957Smeem /*
34534c98957Smeem * Recursively print type modifiers.
34634c98957Smeem */
34734c98957Smeem static void
print_mods(const char * name,ATYPE * atp,int nargs,ATYPE * args,uint_t pos)34834c98957Smeem print_mods(const char *name, ATYPE *atp, int nargs, ATYPE *args, uint_t pos)
34934c98957Smeem {
35034c98957Smeem int arg;
35134c98957Smeem int mods = atp->dcl_mod >> (pos * 2);
35234c98957Smeem int lastmods = atp->dcl_mod >> ((pos + 1) * 2);
35334c98957Smeem boolean_t isvarargs = B_FALSE;
35434c98957Smeem
35534c98957Smeem if (LN_ISPTR(mods)) {
35634c98957Smeem if (!LN_ISPTR(lastmods) && !LN_ISFTN(lastmods))
35734c98957Smeem info(" ");
35834c98957Smeem info("*");
35934c98957Smeem }
36034c98957Smeem
36134c98957Smeem if (atp->dcl_con & (1 << pos))
36234c98957Smeem info(" const ");
36334c98957Smeem if (atp->dcl_vol & (1 << pos))
36434c98957Smeem info(" volatile ");
36534c98957Smeem
36634c98957Smeem if (pos != 0) {
36734c98957Smeem if (LN_ISFTN(mods))
36834c98957Smeem info(" (");
36934c98957Smeem print_mods(name, atp, nargs, args, pos - 1);
37034c98957Smeem if (LN_ISFTN(mods))
37134c98957Smeem info(")()");
37234c98957Smeem return;
37334c98957Smeem }
37434c98957Smeem
37534c98957Smeem if (name[0] == '\0')
37634c98957Smeem return;
37734c98957Smeem
37834c98957Smeem if (!LN_ISPTR(lastmods) && !LN_ISPTR(mods))
37934c98957Smeem info(" ");
38034c98957Smeem info("%s", name);
38134c98957Smeem
38234c98957Smeem if (LN_ISARY(mods)) {
38334c98957Smeem info("[]");
38434c98957Smeem } else if (LN_ISFTN(mods)) {
38534c98957Smeem info("(");
38634c98957Smeem
38734c98957Smeem if (nargs < 0) {
38834c98957Smeem nargs = -nargs - 1;
38934c98957Smeem isvarargs = B_TRUE;
39034c98957Smeem }
39134c98957Smeem
39234c98957Smeem if (nargs == 0) {
39334c98957Smeem info("void");
39434c98957Smeem } else {
39534c98957Smeem for (arg = 0; arg < nargs; arg++) {
39634c98957Smeem print_atype(&args[arg], 0, NULL, "");
39734c98957Smeem if ((arg + 1) < nargs)
39834c98957Smeem info(", ");
39934c98957Smeem else if (isvarargs)
40034c98957Smeem info(", ...");
40134c98957Smeem }
40234c98957Smeem }
40334c98957Smeem info(")");
40434c98957Smeem }
40534c98957Smeem }
40634c98957Smeem
40734c98957Smeem /*
40834c98957Smeem * Add an LSU entry to the LSU table.
40934c98957Smeem */
41034c98957Smeem static int
lsu_add(const char * name,ATYPE * atp)41134c98957Smeem lsu_add(const char *name, ATYPE *atp)
41234c98957Smeem {
41334c98957Smeem unsigned int i = atp->extra.ty % LSU_HASHSIZE;
41434c98957Smeem lsu_t *lsup;
41534c98957Smeem
41634c98957Smeem lsup = malloc(sizeof (lsu_t));
41734c98957Smeem if (lsup == NULL)
41834c98957Smeem return (ENOMEM);
41934c98957Smeem
42034c98957Smeem lsup->atype = *atp;
42134c98957Smeem lsup->next = lsu_table[i];
42234c98957Smeem lsup->name = strdup(name);
42334c98957Smeem if (lsup->name == NULL) {
42434c98957Smeem free(lsup);
42534c98957Smeem return (ENOMEM);
42634c98957Smeem }
42734c98957Smeem
42834c98957Smeem lsu_table[i] = lsup;
42934c98957Smeem return (0);
43034c98957Smeem }
43134c98957Smeem
43234c98957Smeem /*
43334c98957Smeem * Lookup an LSU entry by ID.
43434c98957Smeem */
43534c98957Smeem static lsu_t *
lsu_lookup(T1WORD ty)43634c98957Smeem lsu_lookup(T1WORD ty)
43734c98957Smeem {
43834c98957Smeem unsigned int i = ty % LSU_HASHSIZE;
43934c98957Smeem lsu_t *lsup;
44034c98957Smeem
44134c98957Smeem for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup->next) {
44234c98957Smeem if (lsup->atype.extra.ty == ty)
44334c98957Smeem return (lsup);
44434c98957Smeem }
44534c98957Smeem
44634c98957Smeem return (NULL);
44734c98957Smeem }
44834c98957Smeem
44934c98957Smeem /*
45034c98957Smeem * Read all LSU (structure and union definition) records in order to
45134c98957Smeem * build a structure and union name table, called the LSU table.
452*fa5e8906Smeem * Although `fp' is read from, the original file offset is preserved.
45334c98957Smeem */
45434c98957Smeem static void
lsu_build(FILE * fp)45534c98957Smeem lsu_build(FILE *fp)
45634c98957Smeem {
45734c98957Smeem union rec rec;
45834c98957Smeem char name[1024];
45934c98957Smeem int nargs;
460*fa5e8906Smeem off_t curoff = ftello(fp);
46134c98957Smeem
46234c98957Smeem for (;;) {
46334c98957Smeem if (fread(&rec, sizeof (rec), 1, fp) != 1)
464*fa5e8906Smeem break;
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 }
490*fa5e8906Smeem
491*fa5e8906Smeem (void) fseek(fp, curoff, SEEK_SET);
49234c98957Smeem }
49334c98957Smeem
49434c98957Smeem /*
49534c98957Smeem * Empty the LSU table.
49634c98957Smeem */
49734c98957Smeem static void
lsu_empty(void)49834c98957Smeem lsu_empty(void)
49934c98957Smeem {
50034c98957Smeem lsu_t *lsup, *lsup_next;
50134c98957Smeem unsigned int i;
50234c98957Smeem
50334c98957Smeem for (i = 0; i < LSU_HASHSIZE; i++) {
50434c98957Smeem for (lsup = lsu_table[i]; lsup != NULL; lsup = lsup_next) {
50534c98957Smeem lsup_next = lsup->next;
50634c98957Smeem free(lsup);
50734c98957Smeem }
50834c98957Smeem lsu_table[i] = NULL;
50934c98957Smeem }
51034c98957Smeem }
51134c98957Smeem
51234c98957Smeem /*
51334c98957Smeem * Read the NUL-terminated string at `fp' into `buf', which is at most
51434c98957Smeem * `bufsize' bytes.
51534c98957Smeem */
51634c98957Smeem static void
getstr(FILE * fp,char * buf,size_t bufsize)51734c98957Smeem getstr(FILE *fp, char *buf, size_t bufsize)
51834c98957Smeem {
51934c98957Smeem int c;
52034c98957Smeem size_t i;
52134c98957Smeem
52234c98957Smeem for (i = 0; i < bufsize - 1; i++) {
52334c98957Smeem c = fgetc(fp);
52434c98957Smeem if (c == EOF || c == '\0' || !isascii(c))
52534c98957Smeem break;
52634c98957Smeem buf[i] = (char)c;
52734c98957Smeem }
52834c98957Smeem
52934c98957Smeem buf[i] = '\0';
53034c98957Smeem }
53134c98957Smeem
53234c98957Smeem static void
indent(void)53334c98957Smeem indent(void)
53434c98957Smeem {
53534c98957Smeem indentlevel += 4;
53634c98957Smeem }
53734c98957Smeem
53834c98957Smeem static void
unindent(void)53934c98957Smeem unindent(void)
54034c98957Smeem {
54134c98957Smeem indentlevel -= 4;
54234c98957Smeem }
54334c98957Smeem
54434c98957Smeem static void
usage(void)54534c98957Smeem usage(void)
54634c98957Smeem {
547*fa5e8906Smeem (void) fprintf(stderr, "usage: %s [-i] [-p 1|2|3] [-r] lintobj"
548*fa5e8906Smeem " [ lintobj ... ]\n", progname);
54934c98957Smeem exit(EXIT_FAILURE);
55034c98957Smeem }
55134c98957Smeem
55234c98957Smeem /* PRINTFLIKE1 */
55334c98957Smeem static void
info(const char * format,...)55434c98957Smeem info(const char *format, ...)
55534c98957Smeem {
55634c98957Smeem va_list alist;
55734c98957Smeem static int complete = 1;
55834c98957Smeem
55934c98957Smeem if (complete)
56034c98957Smeem (void) printf("%*s", indentlevel, "");
56134c98957Smeem
56234c98957Smeem va_start(alist, format);
56334c98957Smeem (void) vprintf(format, alist);
56434c98957Smeem va_end(alist);
56534c98957Smeem
56634c98957Smeem complete = strrchr(format, '\n') != NULL;
56734c98957Smeem }
56834c98957Smeem
56934c98957Smeem /* PRINTFLIKE2 */
57034c98957Smeem static void
infohdr(const char * hdr,const char * format,...)57134c98957Smeem infohdr(const char *hdr, const char *format, ...)
57234c98957Smeem {
57334c98957Smeem va_list alist;
57434c98957Smeem static int complete = 1;
57534c98957Smeem
57634c98957Smeem if (complete)
57734c98957Smeem (void) printf("%7s: ", hdr);
57834c98957Smeem
57934c98957Smeem va_start(alist, format);
58034c98957Smeem (void) vprintf(format, alist);
58134c98957Smeem va_end(alist);
58234c98957Smeem
58334c98957Smeem complete = strrchr(format, '\n') != NULL;
58434c98957Smeem }
58534c98957Smeem
58634c98957Smeem /* PRINTFLIKE1 */
58734c98957Smeem static void
warn(const char * format,...)58834c98957Smeem warn(const char *format, ...)
58934c98957Smeem {
59034c98957Smeem va_list alist;
59134c98957Smeem char *errstr = strerror(errno);
59234c98957Smeem
59334c98957Smeem (void) fprintf(stderr, "%s: warning: ", progname);
59434c98957Smeem
59534c98957Smeem va_start(alist, format);
59634c98957Smeem (void) vfprintf(stderr, format, alist);
59734c98957Smeem va_end(alist);
59834c98957Smeem
59934c98957Smeem if (strrchr(format, '\n') == NULL)
60034c98957Smeem (void) fprintf(stderr, ": %s\n", errstr);
60134c98957Smeem }
60234c98957Smeem
60334c98957Smeem /* PRINTFLIKE1 */
60434c98957Smeem static void
die(const char * format,...)60534c98957Smeem die(const char *format, ...)
60634c98957Smeem {
60734c98957Smeem va_list alist;
60834c98957Smeem char *errstr = strerror(errno);
60934c98957Smeem
61034c98957Smeem (void) fprintf(stderr, "%s: fatal: ", progname);
61134c98957Smeem
61234c98957Smeem va_start(alist, format);
61334c98957Smeem (void) vfprintf(stderr, format, alist);
61434c98957Smeem va_end(alist);
61534c98957Smeem
61634c98957Smeem if (strrchr(format, '\n') == NULL)
61734c98957Smeem (void) fprintf(stderr, ": %s\n", errstr);
61834c98957Smeem
61934c98957Smeem exit(EXIT_FAILURE);
62034c98957Smeem }
621