xlint.c revision 100364
1192067Snwhitehorn/* $NetBSD: xlint.c,v 1.27 2002/01/31 19:09:33 tv Exp $ */ 2192067Snwhitehorn 3192067Snwhitehorn/* 4192067Snwhitehorn * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 5192067Snwhitehorn * Copyright (c) 1994, 1995 Jochen Pohl 6192067Snwhitehorn * All Rights Reserved. 7192067Snwhitehorn * 8192067Snwhitehorn * Redistribution and use in source and binary forms, with or without 9192067Snwhitehorn * modification, are permitted provided that the following conditions 10192067Snwhitehorn * are met: 11192067Snwhitehorn * 1. Redistributions of source code must retain the above copyright 12192067Snwhitehorn * notice, this list of conditions and the following disclaimer. 13192067Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 14192067Snwhitehorn * notice, this list of conditions and the following disclaimer in the 15192067Snwhitehorn * documentation and/or other materials provided with the distribution. 16192067Snwhitehorn * 3. All advertising materials mentioning features or use of this software 17192067Snwhitehorn * must display the following acknowledgement: 18192067Snwhitehorn * This product includes software developed by Jochen Pohl for 19192067Snwhitehorn * The NetBSD Project. 20192067Snwhitehorn * 4. The name of the author may not be used to endorse or promote products 21192067Snwhitehorn * derived from this software without specific prior written permission. 22192067Snwhitehorn * 23192067Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24192067Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25192067Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26192067Snwhitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27192067Snwhitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28192067Snwhitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29192067Snwhitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30192067Snwhitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31192067Snwhitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32192067Snwhitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33192067Snwhitehorn */ 34192067Snwhitehorn 35192067Snwhitehorn#include <sys/cdefs.h> 36192067Snwhitehorn#if defined(__RCSID) && !defined(lint) 37192067Snwhitehorn__RCSID("$NetBSD: xlint.c,v 1.27 2002/01/31 19:09:33 tv Exp $"); 38198212Snwhitehorn#endif 39198212Snwhitehorn__FBSDID("$FreeBSD: head/usr.bin/xlint/xlint/xlint.c 100364 2002-07-19 16:38:21Z markm $"); 40192067Snwhitehorn 41262675Sjhibbits#include <sys/param.h> 42192067Snwhitehorn#include <sys/wait.h> 43192067Snwhitehorn#include <sys/stat.h> 44262675Sjhibbits#include <sys/utsname.h> 45192067Snwhitehorn#include <errno.h> 46192067Snwhitehorn#include <fcntl.h> 47198212Snwhitehorn#include <paths.h> 48262675Sjhibbits#include <signal.h> 49192067Snwhitehorn#include <stdio.h> 50192067Snwhitehorn#include <stdlib.h> 51192067Snwhitehorn#include <string.h> 52192067Snwhitehorn#include <unistd.h> 53192067Snwhitehorn 54192067Snwhitehorn#include "lint.h" 55192067Snwhitehorn#include "pathnames.h" 56192067Snwhitehorn 57192067Snwhitehorn#define DEFAULT_PATH _PATH_DEFPATH 58192067Snwhitehorn 59212054Snwhitehornint main(int, char *[]); 60255910Snwhitehorn 61266020Sian/* directory for temporary files */ 62266020Sianstatic const char *tmpdir; 63212054Snwhitehorn 64212054Snwhitehorn/* path name for cpp output */ 65212054Snwhitehornstatic char *cppout; 66212054Snwhitehorn 67212054Snwhitehorn/* file descriptor for cpp output */ 68212054Snwhitehornstatic int cppoutfd = -1; 69262675Sjhibbits 70192067Snwhitehorn/* files created by 1st pass */ 71212054Snwhitehornstatic char **p1out; 72212054Snwhitehorn 73255910Snwhitehorn/* input files for 2nd pass (without libraries) */ 74212054Snwhitehornstatic char **p2in; 75212054Snwhitehorn 76192067Snwhitehorn/* library which will be created by 2nd pass */ 77212054Snwhitehornstatic char *p2out; 78212054Snwhitehorn 79212054Snwhitehorn/* flags always passed to cc(1) */ 80212054Snwhitehornstatic char **cflags; 81192067Snwhitehorn 82212054Snwhitehorn/* flags for cc(1), controled by sflag/tflag */ 83262675Sjhibbitsstatic char **lcflags; 84212054Snwhitehorn 85246732Srpaulo/* flags for lint1 */ 86192067Snwhitehornstatic char **l1flags; 87192067Snwhitehorn 88212054Snwhitehorn/* flags for lint2 */ 89212054Snwhitehornstatic char **l2flags; 90212054Snwhitehorn 91192067Snwhitehorn/* libraries for lint2 */ 92192067Snwhitehornstatic char **l2libs; 93192067Snwhitehorn 94212054Snwhitehorn/* default libraries */ 95192067Snwhitehornstatic char **deflibs; 96192067Snwhitehorn 97212054Snwhitehorn/* additional libraries */ 98192067Snwhitehornstatic char **libs; 99255420Snwhitehorn 100255420Snwhitehorn/* search path for libraries */ 101255420Snwhitehornstatic char **libsrchpath; 102255420Snwhitehorn 103192067Snwhitehornstatic char *libexec_path; 104255420Snwhitehorn 105255420Snwhitehorn/* flags */ 106255420Snwhitehornstatic int iflag, oflag, Cflag, sflag, tflag, Fflag, dflag, Bflag; 107255420Snwhitehorn 108255420Snwhitehorn/* print the commands executed to run the stages of compilation */ 109255420Snwhitehornstatic int Vflag; 110255420Snwhitehorn 111255420Snwhitehorn/* filename for oflag */ 112255420Snwhitehornstatic char *outputfn; 113255420Snwhitehorn 114255420Snwhitehorn/* reset after first .c source has been processed */ 115255420Snwhitehornstatic int first = 1; 116192067Snwhitehorn 117192067Snwhitehorn/* 118192067Snwhitehorn * name of a file which is currently written by a child and should 119192067Snwhitehorn * be removed after abnormal termination of the child 120266020Sian */ 121266020Sianstatic const char *currfn; 122192067Snwhitehorn 123266020Sian#if !defined(TARGET_PREFIX) 124266020Sian#define TARGET_PREFIX "" 125266020Sian#endif 126266020Sianstatic const char target_prefix[] = TARGET_PREFIX; 127266020Sian 128266020Sianstatic void appstrg(char ***, char *); 129266020Sianstatic void appcstrg(char ***, const char *); 130266020Sianstatic void applst(char ***, char *const *); 131266020Sianstatic void freelst(char ***); 132266020Sianstatic char *concat2(const char *, const char *); 133266020Sianstatic char *concat3(const char *, const char *, const char *); 134266020Sianstatic void terminate(int) __attribute__((__noreturn__)); 135266020Sianstatic const char *lbasename(const char *, int); 136266020Sianstatic void appdef(char ***, const char *); 137266020Sianstatic void usage(void); 138266020Sianstatic void fname(const char *); 139266020Sianstatic void runchild(const char *, char *const *, const char *, int); 140266020Sianstatic void findlibs(char *const *); 141266020Sianstatic int rdok(const char *); 142266020Sianstatic void lint2(void); 143266020Sianstatic void cat(char *const *, const char *); 144266020Sian 145266020Sian/* 146266020Sian * Some functions to deal with lists of strings. 147266020Sian * Take care that we get no surprises in case of asyncron signals. 148266020Sian */ 149266020Sianstatic void 150266020Sianappstrg(char ***lstp, char *s) 151266020Sian{ 152266020Sian char **lst, **olst; 153266020Sian int i; 154266020Sian 155266020Sian olst = *lstp; 156266020Sian for (i = 0; olst[i] != NULL; i++) 157266020Sian continue; 158266020Sian lst = xrealloc(olst, (i + 2) * sizeof (char *)); 159266020Sian lst[i] = s; 160266020Sian lst[i + 1] = NULL; 161266020Sian *lstp = lst; 162266020Sian} 163266020Sian 164266020Sianstatic void 165266020Sianappcstrg(char ***lstp, const char *s) 166266020Sian{ 167266020Sian 168266020Sian appstrg(lstp, xstrdup(s)); 169266020Sian} 170266020Sian 171266020Sianstatic void 172266020Sianapplst(char ***destp, char *const *src) 173266020Sian{ 174192067Snwhitehorn int i, k; 175192067Snwhitehorn char **dest, **odest; 176255910Snwhitehorn 177255910Snwhitehorn odest = *destp; 178255910Snwhitehorn for (i = 0; odest[i] != NULL; i++) 179255910Snwhitehorn continue; 180255910Snwhitehorn for (k = 0; src[k] != NULL; k++) 181255910Snwhitehorn continue; 182255910Snwhitehorn dest = xrealloc(odest, (i + k + 1) * sizeof (char *)); 183255910Snwhitehorn for (k = 0; src[k] != NULL; k++) 184255910Snwhitehorn dest[i + k] = xstrdup(src[k]); 185255910Snwhitehorn dest[i + k] = NULL; 186255910Snwhitehorn *destp = dest; 187255910Snwhitehorn} 188255910Snwhitehorn 189255910Snwhitehornstatic void 190255910Snwhitehornfreelst(char ***lstp) 191255910Snwhitehorn{ 192255910Snwhitehorn char *s; 193255910Snwhitehorn int i; 194255910Snwhitehorn 195255910Snwhitehorn for (i = 0; (*lstp)[i] != NULL; i++) 196255910Snwhitehorn continue; 197255910Snwhitehorn while (i-- > 0) { 198255910Snwhitehorn s = (*lstp)[i]; 199255910Snwhitehorn (*lstp)[i] = NULL; 200255910Snwhitehorn free(s); 201255910Snwhitehorn } 202255910Snwhitehorn} 203255910Snwhitehorn 204255910Snwhitehornstatic char * 205192067Snwhitehornconcat2(const char *s1, const char *s2) 206212054Snwhitehorn{ 207192067Snwhitehorn char *s; 208192067Snwhitehorn 209209851Snwhitehorn s = xmalloc(strlen(s1) + strlen(s2) + 1); 210192067Snwhitehorn (void)strcpy(s, s1); 211192067Snwhitehorn (void)strcat(s, s2); 212192067Snwhitehorn 213192067Snwhitehorn return (s); 214192067Snwhitehorn} 215192067Snwhitehorn 216192067Snwhitehornstatic char * 217192067Snwhitehornconcat3(const char *s1, const char *s2, const char *s3) 218192067Snwhitehorn{ 219192067Snwhitehorn char *s; 220192067Snwhitehorn 221192067Snwhitehorn s = xmalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1); 222192067Snwhitehorn (void)strcpy(s, s1); 223212054Snwhitehorn (void)strcat(s, s2); 224192067Snwhitehorn (void)strcat(s, s3); 225260673Sjhibbits 226260673Sjhibbits return (s); 227192067Snwhitehorn} 228192067Snwhitehorn 229192067Snwhitehorn/* 230192067Snwhitehorn * Clean up after a signal. 231193909Sgrehan */ 232193909Sgrehanstatic void 233193909Sgrehanterminate(int signo) 234193909Sgrehan{ 235193909Sgrehan int i; 236193909Sgrehan 237193909Sgrehan if (cppoutfd != -1) 238193909Sgrehan (void)close(cppoutfd); 239192067Snwhitehorn if (cppout != NULL) 240192067Snwhitehorn (void)remove(cppout); 241192067Snwhitehorn 242192067Snwhitehorn if (p1out != NULL) { 243192067Snwhitehorn for (i = 0; p1out[i] != NULL; i++) 244212054Snwhitehorn (void)remove(p1out[i]); 245192067Snwhitehorn } 246192067Snwhitehorn 247192067Snwhitehorn if (p2out != NULL) 248192067Snwhitehorn (void)remove(p2out); 249192067Snwhitehorn 250192067Snwhitehorn if (currfn != NULL) 251192067Snwhitehorn (void)remove(currfn); 252192067Snwhitehorn 253192067Snwhitehorn exit(signo != 0 ? 1 : 0); 254192067Snwhitehorn} 255192067Snwhitehorn 256192067Snwhitehorn/* 257192067Snwhitehorn * Returns a pointer to the last component of strg after delim. 258192067Snwhitehorn * Returns strg if the string does not contain delim. 259193909Sgrehan */ 260193909Sgrehanstatic const char * 261193909Sgrehanlbasename(const char *strg, int delim) 262193909Sgrehan{ 263193909Sgrehan const char *cp, *cp1, *cp2; 264193909Sgrehan 265228201Sjchandra cp = cp1 = cp2 = strg; 266193909Sgrehan while (*cp != '\0') { 267193909Sgrehan if (*cp++ == delim) { 268192067Snwhitehorn cp2 = cp1; 269192067Snwhitehorn cp1 = cp; 270193909Sgrehan } 271192067Snwhitehorn } 272192067Snwhitehorn return (*cp1 == '\0' ? cp2 : cp1); 273192067Snwhitehorn} 274192067Snwhitehorn 275192067Snwhitehornstatic void 276192067Snwhitehornappdef(char ***lstp, const char *def) 277192067Snwhitehorn{ 278192067Snwhitehorn 279192067Snwhitehorn appstrg(lstp, concat2("-D__", def)); 280212054Snwhitehorn appstrg(lstp, concat3("-D__", def, "__")); 281192067Snwhitehorn} 282192067Snwhitehorn 283192067Snwhitehornstatic void 284212054Snwhitehornusage(void) 285192067Snwhitehorn{ 286192067Snwhitehorn 287192067Snwhitehorn (void)fprintf(stderr, 288192067Snwhitehorn "usage: lint [-abceghprvwxzHF] [-s|-t] [-i|-nu] [-Dname[=def]]" 289192067Snwhitehorn " [-Uname] [-X <id>[,<id>]...\n"); 290192067Snwhitehorn (void)fprintf(stderr, 291192067Snwhitehorn "\t[-Idirectory] [-Ldirectory] [-llibrary] [-ooutputfile]" 292192067Snwhitehorn " file...\n"); 293192067Snwhitehorn (void)fprintf(stderr, 294192067Snwhitehorn " lint [-abceghprvwzHF] [-s|-t] -Clibrary [-Dname[=def]]\n" 295192067Snwhitehorn " [-X <id>[,<id>]...\n"); 296192067Snwhitehorn (void)fprintf(stderr, "\t[-Idirectory] [-Uname] [-Bpath] file" 297192067Snwhitehorn " ...\n"); 298192067Snwhitehorn terminate(-1); 299192067Snwhitehorn} 300212054Snwhitehorn 301192067Snwhitehorn 302192067Snwhitehornint 303192067Snwhitehornmain(int argc, char *argv[]) 304212054Snwhitehorn{ 305192067Snwhitehorn int c; 306192067Snwhitehorn char flgbuf[3], *tmp, *s; 307192067Snwhitehorn size_t len; 308192067Snwhitehorn 309192067Snwhitehorn if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) { 310192067Snwhitehorn tmpdir = xstrdup(_PATH_TMP); 311228201Sjchandra } else { 312192067Snwhitehorn s = xmalloc(len + 2); 313192067Snwhitehorn (void)sprintf(s, "%s%s", tmp, tmp[len - 1] == '/' ? "" : "/"); 314192067Snwhitehorn tmpdir = s; 315192067Snwhitehorn } 316192067Snwhitehorn 317192067Snwhitehorn cppout = xmalloc(strlen(tmpdir) + sizeof ("lint0.XXXXXX")); 318192067Snwhitehorn (void)sprintf(cppout, "%slint0.XXXXXX", tmpdir); 319212054Snwhitehorn cppoutfd = mkstemp(cppout); 320192067Snwhitehorn if (cppoutfd == -1) { 321192067Snwhitehorn warn("can't make temp"); 322192067Snwhitehorn terminate(-1); 323212054Snwhitehorn } 324192067Snwhitehorn 325192067Snwhitehorn p1out = xcalloc(1, sizeof (char *)); 326192067Snwhitehorn p2in = xcalloc(1, sizeof (char *)); 327192067Snwhitehorn cflags = xcalloc(1, sizeof (char *)); 328198212Snwhitehorn lcflags = xcalloc(1, sizeof (char *)); 329192067Snwhitehorn l1flags = xcalloc(1, sizeof (char *)); 330192067Snwhitehorn l2flags = xcalloc(1, sizeof (char *)); 331192067Snwhitehorn l2libs = xcalloc(1, sizeof (char *)); 332192067Snwhitehorn deflibs = xcalloc(1, sizeof (char *)); 333209114Snwhitehorn libs = xcalloc(1, sizeof (char *)); 334209114Snwhitehorn libsrchpath = xcalloc(1, sizeof (char *)); 335192067Snwhitehorn 336209114Snwhitehorn appcstrg(&cflags, "-E"); 337209114Snwhitehorn appcstrg(&cflags, "-x"); 338209114Snwhitehorn appcstrg(&cflags, "c"); 339209114Snwhitehorn#if 0 340209114Snwhitehorn appcstrg(&cflags, "-D__attribute__(x)="); 341209114Snwhitehorn appcstrg(&cflags, "-D__extension__(x)=/*NOSTRICT*/0"); 342209114Snwhitehorn#else 343209114Snwhitehorn appcstrg(&cflags, "-U__GNUC__"); 344209114Snwhitehorn appcstrg(&cflags, "-undef"); 345209114Snwhitehorn#endif 346209853Snwhitehorn appcstrg(&cflags, "-Wp,-$"); 347209114Snwhitehorn appcstrg(&cflags, "-Wp,-C"); 348209114Snwhitehorn appcstrg(&cflags, "-Wcomment"); 349209114Snwhitehorn appcstrg(&cflags, "-D__LINT__"); 350209114Snwhitehorn appcstrg(&cflags, "-Dlint"); /* XXX don't def. with -s */ 351209114Snwhitehorn 352209114Snwhitehorn appdef(&cflags, "lint"); 353209114Snwhitehorn 354192067Snwhitehorn appcstrg(&lcflags, "-Wtraditional"); 355192067Snwhitehorn 356198212Snwhitehorn appcstrg(&deflibs, "c"); 357198212Snwhitehorn 358192067Snwhitehorn if (signal(SIGHUP, terminate) == SIG_IGN) 359198212Snwhitehorn (void)signal(SIGHUP, SIG_IGN); 360198212Snwhitehorn (void)signal(SIGINT, terminate); 361192067Snwhitehorn (void)signal(SIGQUIT, terminate); 362209114Snwhitehorn (void)signal(SIGTERM, terminate); 363198378Snwhitehorn 364192067Snwhitehorn while ((c = getopt(argc, argv, "abcd:eghil:no:prstuvwxzB:C:D:FHI:L:U:VX:")) != -1) { 365192067Snwhitehorn switch (c) { 366192067Snwhitehorn 367209114Snwhitehorn case 'a': 368198378Snwhitehorn case 'b': 369192067Snwhitehorn case 'c': 370192067Snwhitehorn case 'e': 371198378Snwhitehorn case 'g': 372192067Snwhitehorn case 'r': 373192067Snwhitehorn case 'v': 374192067Snwhitehorn case 'w': 375192067Snwhitehorn case 'z': 376192067Snwhitehorn (void)sprintf(flgbuf, "-%c", c); 377192067Snwhitehorn appcstrg(&l1flags, flgbuf); 378192067Snwhitehorn break; 379192067Snwhitehorn 380192067Snwhitehorn case 'F': 381192067Snwhitehorn Fflag = 1; 382212054Snwhitehorn /* FALLTHROUGH */ 383212054Snwhitehorn case 'u': 384212054Snwhitehorn case 'h': 385212054Snwhitehorn (void)sprintf(flgbuf, "-%c", c); 386212054Snwhitehorn appcstrg(&l1flags, flgbuf); 387212054Snwhitehorn appcstrg(&l2flags, flgbuf); 388262675Sjhibbits break; 389262675Sjhibbits 390262675Sjhibbits case 'X': 391262675Sjhibbits (void)sprintf(flgbuf, "-%c", c); 392262675Sjhibbits appcstrg(&l1flags, flgbuf); 393262675Sjhibbits appcstrg(&l1flags, optarg); 394262675Sjhibbits break; 395262675Sjhibbits 396 case 'i': 397 if (Cflag) 398 usage(); 399 iflag = 1; 400 break; 401 402 case 'n': 403 freelst(&deflibs); 404 break; 405 406 case 'p': 407 appcstrg(&l1flags, "-p"); 408 appcstrg(&l2flags, "-p"); 409 if (*deflibs != NULL) { 410 freelst(&deflibs); 411 appcstrg(&deflibs, "c"); 412 } 413 break; 414 415 case 's': 416 if (tflag) 417 usage(); 418 freelst(&lcflags); 419 appcstrg(&lcflags, "-trigraphs"); 420 appcstrg(&lcflags, "-Wtrigraphs"); 421 appcstrg(&lcflags, "-pedantic"); 422 appcstrg(&lcflags, "-D__STRICT_ANSI__"); 423 appcstrg(&l1flags, "-s"); 424 appcstrg(&l2flags, "-s"); 425 sflag = 1; 426 break; 427 428#if !HAVE_CONFIG_H 429 case 't': 430 if (sflag) 431 usage(); 432 freelst(&lcflags); 433 appcstrg(&lcflags, "-traditional"); 434 appstrg(&lcflags, concat2("-D", MACHINE)); 435 appstrg(&lcflags, concat2("-D", MACHINE_ARCH)); 436 appcstrg(&l1flags, "-t"); 437 appcstrg(&l2flags, "-t"); 438 tflag = 1; 439 break; 440#endif 441 442 case 'x': 443 appcstrg(&l2flags, "-x"); 444 break; 445 446 case 'C': 447 if (Cflag || oflag || iflag) 448 usage(); 449 Cflag = 1; 450 appstrg(&l2flags, concat2("-C", optarg)); 451 p2out = xmalloc(sizeof ("llib-l.ln") + strlen(optarg)); 452 (void)sprintf(p2out, "llib-l%s.ln", optarg); 453 freelst(&deflibs); 454 break; 455 456 case 'd': 457 if (dflag) 458 usage(); 459 dflag = 1; 460 appcstrg(&cflags, "-nostdinc"); 461 appcstrg(&cflags, "-idirafter"); 462 appcstrg(&cflags, optarg); 463 break; 464 465 case 'D': 466 case 'I': 467 case 'U': 468 (void)sprintf(flgbuf, "-%c", c); 469 appstrg(&cflags, concat2(flgbuf, optarg)); 470 break; 471 472 case 'l': 473 appcstrg(&libs, optarg); 474 break; 475 476 case 'o': 477 if (Cflag || oflag) 478 usage(); 479 oflag = 1; 480 outputfn = xstrdup(optarg); 481 break; 482 483 case 'L': 484 appcstrg(&libsrchpath, optarg); 485 break; 486 487 case 'H': 488 appcstrg(&l2flags, "-H"); 489 break; 490 491 case 'B': 492 Bflag = 1; 493 libexec_path = xstrdup(optarg); 494 break; 495 496 case 'V': 497 Vflag = 1; 498 break; 499 500 default: 501 usage(); 502 /* NOTREACHED */ 503 } 504 } 505 argc -= optind; 506 argv += optind; 507 508 /* 509 * To avoid modifying getopt(3)'s state engine midstream, we 510 * explicitly accept just a few options after the first source file. 511 * 512 * In particular, only -l<lib> and -L<libdir> (and these with a space 513 * after -l or -L) are allowed. 514 */ 515 while (argc > 0) { 516 const char *arg = argv[0]; 517 518 if (arg[0] == '-') { 519 char ***list; 520 521 /* option */ 522 switch (arg[1]) { 523 case 'l': 524 list = &libs; 525 break; 526 527 case 'L': 528 list = &libsrchpath; 529 break; 530 531 default: 532 usage(); 533 /* NOTREACHED */ 534 } 535 if (arg[2]) 536 appcstrg(list, arg + 2); 537 else if (argc > 1) { 538 argc--; 539 appcstrg(list, *++argv); 540 } else 541 usage(); 542 } else { 543 /* filename */ 544 fname(arg); 545 first = 0; 546 } 547 argc--; 548 argv++; 549 } 550 551 if (first) 552 usage(); 553 554 if (iflag) 555 terminate(0); 556 557 if (!oflag) { 558 if ((s = getenv("LIBDIR")) == NULL || strlen(s) == 0) 559 s = PATH_LINTLIB; 560 appcstrg(&libsrchpath, s); 561 findlibs(libs); 562 findlibs(deflibs); 563 } 564 565 (void)printf("Lint pass2:\n"); 566 lint2(); 567 568 if (oflag) 569 cat(p2in, outputfn); 570 571 if (Cflag) 572 p2out = NULL; 573 574 terminate(0); 575 /* NOTREACHED */ 576} 577 578/* 579 * Read a file name from the command line 580 * and pass it through lint1 if it is a C source. 581 */ 582static void 583fname(const char *name) 584{ 585 const char *bn, *suff; 586 char **args, *ofn, *pathname, *CC; 587 size_t len; 588 int is_stdin; 589 int fd; 590 591 is_stdin = (strcmp(name, "-") == 0); 592 bn = lbasename(name, '/'); 593 suff = lbasename(bn, '.'); 594 595 if (strcmp(suff, "ln") == 0) { 596 /* only for lint2 */ 597 if (!iflag) 598 appcstrg(&p2in, name); 599 return; 600 } 601 602 if (!is_stdin && strcmp(suff, "c") != 0 && 603 (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) { 604 warnx("unknown file type: %s\n", name); 605 return; 606 } 607 608 if (!iflag || !first) 609 (void)printf("%s:\n", 610 is_stdin ? "{standard input}" : Fflag ? name : bn); 611 612 /* build the name of the output file of lint1 */ 613 if (oflag) { 614 ofn = outputfn; 615 outputfn = NULL; 616 oflag = 0; 617 } else if (iflag) { 618 if (is_stdin) { 619 warnx("-i not supported without -o for standard input"); 620 return; 621 } 622 ofn = xmalloc(strlen(bn) + (bn == suff ? 4 : 2)); 623 len = bn == suff ? strlen(bn) : (suff - 1) - bn; 624 (void)sprintf(ofn, "%.*s", (int)len, bn); 625 (void)strcat(ofn, ".ln"); 626 } else { 627 ofn = xmalloc(strlen(tmpdir) + sizeof ("lint1.XXXXXX")); 628 (void)sprintf(ofn, "%slint1.XXXXXX", tmpdir); 629 fd = mkstemp(ofn); 630 if (fd == -1) { 631 warn("can't make temp"); 632 terminate(-1); 633 } 634 close(fd); 635 } 636 if (!iflag) 637 appcstrg(&p1out, ofn); 638 639 args = xcalloc(1, sizeof (char *)); 640 641 /* run cc */ 642 643 if (getenv("CC") == NULL) { 644 pathname = xmalloc(strlen(PATH_USRBIN) + sizeof ("/cc")); 645 (void)sprintf(pathname, "%s/cc", PATH_USRBIN); 646 } else 647 pathname = strdup(getenv("CC")); 648 649 appcstrg(&args, pathname); 650 applst(&args, cflags); 651 applst(&args, lcflags); 652 appcstrg(&args, name); 653 654 /* we reuse the same tmp file for cpp output, so rewind and truncate */ 655 if (lseek(cppoutfd, SEEK_SET, (off_t)0) != 0) { 656 warn("lseek"); 657 terminate(-1); 658 } 659 if (ftruncate(cppoutfd, (off_t)0) != 0) { 660 warn("ftruncate"); 661 terminate(-1); 662 } 663 664 runchild(pathname, args, cppout, cppoutfd); 665 free(pathname); 666 freelst(&args); 667 668 /* run lint1 */ 669 670 if (!Bflag) { 671 pathname = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint1") + 672 strlen(target_prefix)); 673 (void)sprintf(pathname, "%s/%slint1", PATH_LIBEXEC, 674 target_prefix); 675 } else { 676 /* 677 * XXX Unclear whether we should be using target_prefix 678 * XXX here. --thorpej@wasabisystems.com 679 */ 680 pathname = xmalloc(strlen(libexec_path) + sizeof ("/lint1")); 681 (void)sprintf(pathname, "%s/lint1", libexec_path); 682 } 683 684 appcstrg(&args, pathname); 685 applst(&args, l1flags); 686 appcstrg(&args, cppout); 687 appcstrg(&args, ofn); 688 689 runchild(pathname, args, ofn, -1); 690 free(pathname); 691 freelst(&args); 692 693 appcstrg(&p2in, ofn); 694 free(ofn); 695 696 free(args); 697} 698 699static void 700runchild(const char *path, char *const *args, const char *crfn, int fdout) 701{ 702 int status, rv, signo, i; 703 704 if (Vflag) { 705 for (i = 0; args[i] != NULL; i++) 706 (void)printf("%s ", args[i]); 707 (void)printf("\n"); 708 } 709 710 currfn = crfn; 711 712 (void)fflush(stdout); 713 714 switch (vfork()) { 715 case -1: 716 warn("cannot fork"); 717 terminate(-1); 718 /* NOTREACHED */ 719 default: 720 /* parent */ 721 break; 722 case 0: 723 /* child */ 724 725 /* setup the standard output if necessary */ 726 if (fdout != -1) { 727 dup2(fdout, STDOUT_FILENO); 728 close(fdout); 729 } 730 (void)execvp(path, args); 731 warn("cannot exec %s", path); 732 _exit(1); 733 /* NOTREACHED */ 734 } 735 736 while ((rv = wait(&status)) == -1 && errno == EINTR) ; 737 if (rv == -1) { 738 warn("wait"); 739 terminate(-1); 740 } 741 if (WIFSIGNALED(status)) { 742 signo = WTERMSIG(status); 743#if HAVE_DECL_SYS_SIGNAME 744 warnx("%s got SIG%s", path, sys_signame[signo]); 745#else 746 warnx("%s got signal %d", path, signo); 747#endif 748 terminate(-1); 749 } 750 if (WEXITSTATUS(status) != 0) 751 terminate(-1); 752 currfn = NULL; 753} 754 755static void 756findlibs(char *const *liblst) 757{ 758 int i, k; 759 const char *lib, *path; 760 char *lfn; 761 size_t len; 762 763 lfn = NULL; 764 765 for (i = 0; (lib = liblst[i]) != NULL; i++) { 766 for (k = 0; (path = libsrchpath[k]) != NULL; k++) { 767 len = strlen(path) + strlen(lib); 768 lfn = xrealloc(lfn, len + sizeof ("/llib-l.ln")); 769 (void)sprintf(lfn, "%s/llib-l%s.ln", path, lib); 770 if (rdok(lfn)) 771 break; 772 lfn = xrealloc(lfn, len + sizeof ("/lint/llib-l.ln")); 773 (void)sprintf(lfn, "%s/lint/llib-l%s.ln", path, lib); 774 if (rdok(lfn)) 775 break; 776 } 777 if (path != NULL) { 778 appstrg(&l2libs, concat2("-l", lfn)); 779 } else { 780 warnx("cannot find llib-l%s.ln", lib); 781 } 782 } 783 784 free(lfn); 785} 786 787static int 788rdok(const char *path) 789{ 790 struct stat sbuf; 791 792 if (stat(path, &sbuf) == -1) 793 return (0); 794 if (!S_ISREG(sbuf.st_mode)) 795 return (0); 796 if (access(path, R_OK) == -1) 797 return (0); 798 return (1); 799} 800 801static void 802lint2(void) 803{ 804 char *path, **args; 805 806 args = xcalloc(1, sizeof (char *)); 807 808 if (!Bflag) { 809 path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint2") + 810 strlen(target_prefix)); 811 (void)sprintf(path, "%s/%slint2", PATH_LIBEXEC, 812 target_prefix); 813 } else { 814 /* 815 * XXX Unclear whether we should be using target_prefix 816 * XXX here. --thorpej@wasabisystems.com 817 */ 818 path = xmalloc(strlen(libexec_path) + sizeof ("/lint2")); 819 (void)sprintf(path, "%s/lint2", libexec_path); 820 } 821 822 appcstrg(&args, path); 823 applst(&args, l2flags); 824 applst(&args, l2libs); 825 applst(&args, p2in); 826 827 runchild(path, args, p2out, -1); 828 free(path); 829 freelst(&args); 830 free(args); 831} 832 833static void 834cat(char *const *srcs, const char *dest) 835{ 836 int ifd, ofd, i; 837 char *src, *buf; 838 ssize_t rlen; 839 840 if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { 841 warn("cannot open %s", dest); 842 terminate(-1); 843 } 844 845 buf = xmalloc(MBLKSIZ); 846 847 for (i = 0; (src = srcs[i]) != NULL; i++) { 848 if ((ifd = open(src, O_RDONLY)) == -1) { 849 free(buf); 850 warn("cannot open %s", src); 851 terminate(-1); 852 } 853 do { 854 if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) { 855 free(buf); 856 warn("read error on %s", src); 857 terminate(-1); 858 } 859 if (write(ofd, buf, (size_t)rlen) == -1) { 860 free(buf); 861 warn("write error on %s", dest); 862 terminate(-1); 863 } 864 } while (rlen == MBLKSIZ); 865 (void)close(ifd); 866 } 867 (void)close(ofd); 868 free(buf); 869} 870