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