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