xlint.c revision 92089
191592Smarkm/* $NetBSD: xlint.c,v 1.26 2002/01/22 01:14:03 thorpej Exp $ */ 212099Sjoerg 312099Sjoerg/* 491592Smarkm * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 512099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl 612099Sjoerg * All Rights Reserved. 712099Sjoerg * 812099Sjoerg * Redistribution and use in source and binary forms, with or without 912099Sjoerg * modification, are permitted provided that the following conditions 1012099Sjoerg * are met: 1112099Sjoerg * 1. Redistributions of source code must retain the above copyright 1212099Sjoerg * notice, this list of conditions and the following disclaimer. 1312099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1412099Sjoerg * notice, this list of conditions and the following disclaimer in the 1512099Sjoerg * documentation and/or other materials provided with the distribution. 1612099Sjoerg * 3. All advertising materials mentioning features or use of this software 1712099Sjoerg * must display the following acknowledgement: 1812099Sjoerg * This product includes software developed by Jochen Pohl for 1912099Sjoerg * The NetBSD Project. 2012099Sjoerg * 4. The name of the author may not be used to endorse or promote products 2112099Sjoerg * derived from this software without specific prior written permission. 2212099Sjoerg * 2312099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2412099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2512099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2612099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2712099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2812099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2912099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3012099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3112099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3212099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3312099Sjoerg */ 3412099Sjoerg 3591592Smarkm#include <sys/cdefs.h> 3691592Smarkm#if defined(__RCSID) && !defined(lint) 3791592Smarkm__RCSID("$NetBSD: xlint.c,v 1.26 2002/01/22 01:14:03 thorpej Exp $"); 3812099Sjoerg#endif 3991592Smarkm__FBSDID("$FreeBSD: head/usr.bin/xlint/xlint/xlint.c 92089 2002-03-11 11:32:55Z markm $"); 4012099Sjoerg 4112099Sjoerg#include <sys/param.h> 4212099Sjoerg#include <sys/wait.h> 4312099Sjoerg#include <sys/stat.h> 4412099Sjoerg#include <sys/utsname.h> 4591592Smarkm#include <errno.h> 4691592Smarkm#include <fcntl.h> 4791592Smarkm#include <paths.h> 4891592Smarkm#include <signal.h> 4912099Sjoerg#include <stdio.h> 5012099Sjoerg#include <stdlib.h> 5112099Sjoerg#include <string.h> 5212099Sjoerg#include <unistd.h> 5312099Sjoerg 5412099Sjoerg#include "lint.h" 5512099Sjoerg#include "pathnames.h" 5612099Sjoerg 5791592Smarkmint main(int, char *[]); 5891592Smarkm 5912099Sjoerg/* directory for temporary files */ 6012099Sjoergstatic const char *tmpdir; 6112099Sjoerg 6212099Sjoerg/* path name for cpp output */ 6312099Sjoergstatic char *cppout; 6412099Sjoerg 6591592Smarkm/* file descriptor for cpp output */ 6675710Sasmodaistatic int cppoutfd = -1; 6775710Sasmodai 6812099Sjoerg/* files created by 1st pass */ 6912099Sjoergstatic char **p1out; 7012099Sjoerg 7112099Sjoerg/* input files for 2nd pass (without libraries) */ 7212099Sjoergstatic char **p2in; 7312099Sjoerg 7412099Sjoerg/* library which will be created by 2nd pass */ 7512099Sjoergstatic char *p2out; 7612099Sjoerg 7775710Sasmodai/* flags always passed to cc(1) */ 7875710Sasmodaistatic char **cflags; 7912099Sjoerg 8075710Sasmodai/* flags for cc(1), controled by sflag/tflag */ 8175710Sasmodaistatic char **lcflags; 8212099Sjoerg 8312099Sjoerg/* flags for lint1 */ 8412099Sjoergstatic char **l1flags; 8512099Sjoerg 8612099Sjoerg/* flags for lint2 */ 8712099Sjoergstatic char **l2flags; 8812099Sjoerg 8912099Sjoerg/* libraries for lint2 */ 9012099Sjoergstatic char **l2libs; 9112099Sjoerg 9212099Sjoerg/* default libraries */ 9312099Sjoergstatic char **deflibs; 9412099Sjoerg 9512099Sjoerg/* additional libraries */ 9612099Sjoergstatic char **libs; 9712099Sjoerg 9812099Sjoerg/* search path for libraries */ 9912099Sjoergstatic char **libsrchpath; 10012099Sjoerg 10191592Smarkmstatic char *libexec_path; 10291592Smarkm 10312099Sjoerg/* flags */ 10491592Smarkmstatic int iflag, oflag, Cflag, sflag, tflag, Fflag, dflag, Bflag; 10512099Sjoerg 10612099Sjoerg/* print the commands executed to run the stages of compilation */ 10712099Sjoergstatic int Vflag; 10812099Sjoerg 10912099Sjoerg/* filename for oflag */ 11012099Sjoergstatic char *outputfn; 11112099Sjoerg 11212099Sjoerg/* reset after first .c source has been processed */ 11312099Sjoergstatic int first = 1; 11412099Sjoerg 11512099Sjoerg/* 11612099Sjoerg * name of a file which is currently written by a child and should 11712099Sjoerg * be removed after abnormal termination of the child 11812099Sjoerg */ 11912099Sjoergstatic const char *currfn; 12012099Sjoerg 12191592Smarkm#if !defined(TARGET_PREFIX) 12291592Smarkm#define TARGET_PREFIX "" 12391592Smarkm#endif 12491592Smarkmstatic const char target_prefix[] = TARGET_PREFIX; 12512099Sjoerg 12691592Smarkmstatic void appstrg(char ***, char *); 12791592Smarkmstatic void appcstrg(char ***, const char *); 12891592Smarkmstatic void applst(char ***, char *const *); 12991592Smarkmstatic void freelst(char ***); 13091592Smarkmstatic char *concat2(const char *, const char *); 13191592Smarkmstatic char *concat3(const char *, const char *, const char *); 13291592Smarkmstatic void terminate(int) __attribute__((__noreturn__)); 13391592Smarkmstatic const char *lbasename(const char *, int); 13491592Smarkmstatic void appdef(char ***, const char *); 13591592Smarkmstatic void usage(void); 13691592Smarkmstatic void fname(const char *); 13791592Smarkmstatic void runchild(const char *, char *const *, const char *, int); 13891592Smarkmstatic void findlibs(char *const *); 13991592Smarkmstatic int rdok(const char *); 14091592Smarkmstatic void lint2(void); 14191592Smarkmstatic void cat(char *const *, const char *); 14212099Sjoerg 14312099Sjoerg/* 14412099Sjoerg * Some functions to deal with lists of strings. 14512099Sjoerg * Take care that we get no surprises in case of asyncron signals. 14612099Sjoerg */ 14712099Sjoergstatic void 14891592Smarkmappstrg(char ***lstp, char *s) 14912099Sjoerg{ 15012099Sjoerg char **lst, **olst; 15112099Sjoerg int i; 15212099Sjoerg 15312099Sjoerg olst = *lstp; 15491592Smarkm for (i = 0; olst[i] != NULL; i++) 15591592Smarkm continue; 15691592Smarkm lst = xrealloc(olst, (i + 2) * sizeof (char *)); 15712099Sjoerg lst[i] = s; 15812099Sjoerg lst[i + 1] = NULL; 15912099Sjoerg *lstp = lst; 16091592Smarkm} 16112099Sjoerg 16212099Sjoergstatic void 16391592Smarkmappcstrg(char ***lstp, const char *s) 16412099Sjoerg{ 16580284Sobrien 16691592Smarkm appstrg(lstp, xstrdup(s)); 16712099Sjoerg} 16812099Sjoerg 16912099Sjoergstatic void 17091592Smarkmapplst(char ***destp, char *const *src) 17112099Sjoerg{ 17212099Sjoerg int i, k; 17312099Sjoerg char **dest, **odest; 17412099Sjoerg 17512099Sjoerg odest = *destp; 17691592Smarkm for (i = 0; odest[i] != NULL; i++) 17791592Smarkm continue; 17812099Sjoerg for (k = 0; src[k] != NULL; k++) 17991592Smarkm continue; 18091592Smarkm dest = xrealloc(odest, (i + k + 1) * sizeof (char *)); 18191592Smarkm for (k = 0; src[k] != NULL; k++) 18291818Smarkm dest[i + k] = xstrdup(src[k]); 18312099Sjoerg dest[i + k] = NULL; 18412099Sjoerg *destp = dest; 18512099Sjoerg} 18612099Sjoerg 18712099Sjoergstatic void 18891592Smarkmfreelst(char ***lstp) 18912099Sjoerg{ 19012099Sjoerg char *s; 19112099Sjoerg int i; 19212099Sjoerg 19391592Smarkm for (i = 0; (*lstp)[i] != NULL; i++) 19491592Smarkm continue; 19512099Sjoerg while (i-- > 0) { 19612099Sjoerg s = (*lstp)[i]; 19712099Sjoerg (*lstp)[i] = NULL; 19812099Sjoerg free(s); 19912099Sjoerg } 20012099Sjoerg} 20112099Sjoerg 20212099Sjoergstatic char * 20391592Smarkmconcat2(const char *s1, const char *s2) 20412099Sjoerg{ 20512099Sjoerg char *s; 20612099Sjoerg 20791818Smarkm s = xmalloc(strlen(s1) + strlen(s2) + 1); 20812099Sjoerg (void)strcpy(s, s1); 20912099Sjoerg (void)strcat(s, s2); 21012099Sjoerg 21112099Sjoerg return (s); 21212099Sjoerg} 21312099Sjoerg 21412099Sjoergstatic char * 21591592Smarkmconcat3(const char *s1, const char *s2, const char *s3) 21612099Sjoerg{ 21712099Sjoerg char *s; 21812099Sjoerg 21991818Smarkm s = xmalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1); 22012099Sjoerg (void)strcpy(s, s1); 22112099Sjoerg (void)strcat(s, s2); 22212099Sjoerg (void)strcat(s, s3); 22312099Sjoerg 22412099Sjoerg return (s); 22512099Sjoerg} 22612099Sjoerg 22712099Sjoerg/* 22812099Sjoerg * Clean up after a signal. 22912099Sjoerg */ 23012099Sjoergstatic void 23191592Smarkmterminate(int signo) 23212099Sjoerg{ 23312099Sjoerg int i; 23412099Sjoerg 23575710Sasmodai if (cppoutfd != -1) 23675710Sasmodai (void)close(cppoutfd); 23712099Sjoerg if (cppout != NULL) 23812099Sjoerg (void)remove(cppout); 23912099Sjoerg 24012099Sjoerg if (p1out != NULL) { 24112099Sjoerg for (i = 0; p1out[i] != NULL; i++) 24212099Sjoerg (void)remove(p1out[i]); 24312099Sjoerg } 24412099Sjoerg 24512099Sjoerg if (p2out != NULL) 24612099Sjoerg (void)remove(p2out); 24712099Sjoerg 24812099Sjoerg if (currfn != NULL) 24912099Sjoerg (void)remove(currfn); 25012099Sjoerg 25112099Sjoerg exit(signo != 0 ? 1 : 0); 25212099Sjoerg} 25312099Sjoerg 25412099Sjoerg/* 25512099Sjoerg * Returns a pointer to the last component of strg after delim. 25612099Sjoerg * Returns strg if the string does not contain delim. 25712099Sjoerg */ 25812099Sjoergstatic const char * 25991592Smarkmlbasename(const char *strg, int delim) 26012099Sjoerg{ 26112099Sjoerg const char *cp, *cp1, *cp2; 26212099Sjoerg 26312099Sjoerg cp = cp1 = cp2 = strg; 26412099Sjoerg while (*cp != '\0') { 26512099Sjoerg if (*cp++ == delim) { 26612099Sjoerg cp2 = cp1; 26712099Sjoerg cp1 = cp; 26812099Sjoerg } 26912099Sjoerg } 27012099Sjoerg return (*cp1 == '\0' ? cp2 : cp1); 27112099Sjoerg} 27212099Sjoerg 27312099Sjoergstatic void 27491592Smarkmappdef(char ***lstp, const char *def) 27512099Sjoerg{ 27691592Smarkm 27712099Sjoerg appstrg(lstp, concat2("-D__", def)); 27812099Sjoerg appstrg(lstp, concat3("-D__", def, "__")); 27912099Sjoerg} 28012099Sjoerg 28112099Sjoergstatic void 28291592Smarkmusage(void) 28312099Sjoerg{ 28491592Smarkm 28591592Smarkm (void)fprintf(stderr, 28691592Smarkm "Usage: %s [-abceghprvwxzHF] [-s|-t] [-i|-nu] [-Dname[=def]]" 28791592Smarkm " [-Uname] [-X <id>[,<id>]...\n", getprogname()); 28891592Smarkm (void)fprintf(stderr, 28991592Smarkm "\t[-Idirectory] [-Ldirectory] [-llibrary] [-ooutputfile]" 29091592Smarkm " file...\n"); 29191592Smarkm (void)fprintf(stderr, 29291592Smarkm " %s [-abceghprvwzHF] [-s|-t] -Clibrary [-Dname[=def]]\n" 29391592Smarkm " [-X <id>[,<id>]...\n", getprogname()); 29491592Smarkm (void)fprintf(stderr, "\t[-Idirectory] [-Uname] [-Bpath] file" 29591592Smarkm " ...\n"); 29612099Sjoerg terminate(-1); 29712099Sjoerg} 29812099Sjoerg 29991592Smarkm 30012099Sjoergint 30191592Smarkmmain(int argc, char *argv[]) 30212099Sjoerg{ 30312099Sjoerg int c; 30412099Sjoerg char flgbuf[3], *tmp, *s; 30512099Sjoerg size_t len; 30612099Sjoerg 30791592Smarkm setprogname(argv[0]); 30891592Smarkm 30912099Sjoerg if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) { 31091818Smarkm tmpdir = xstrdup(_PATH_TMP); 31112099Sjoerg } else { 31291818Smarkm s = xmalloc(len + 2); 31312099Sjoerg (void)sprintf(s, "%s%s", tmp, tmp[len - 1] == '/' ? "" : "/"); 31412099Sjoerg tmpdir = s; 31512099Sjoerg } 31612099Sjoerg 31791818Smarkm cppout = xmalloc(strlen(tmpdir) + sizeof ("lint0.XXXXXX")); 31812099Sjoerg (void)sprintf(cppout, "%slint0.XXXXXX", tmpdir); 31975710Sasmodai cppoutfd = mkstemp(cppout); 32075710Sasmodai if (cppoutfd == -1) { 32112099Sjoerg warn("can't make temp"); 32212099Sjoerg terminate(-1); 32312099Sjoerg } 32412099Sjoerg 32591592Smarkm p1out = xcalloc(1, sizeof (char *)); 32691592Smarkm p2in = xcalloc(1, sizeof (char *)); 32791592Smarkm cflags = xcalloc(1, sizeof (char *)); 32891592Smarkm lcflags = xcalloc(1, sizeof (char *)); 32991592Smarkm l1flags = xcalloc(1, sizeof (char *)); 33091592Smarkm l2flags = xcalloc(1, sizeof (char *)); 33191592Smarkm l2libs = xcalloc(1, sizeof (char *)); 33291592Smarkm deflibs = xcalloc(1, sizeof (char *)); 33391592Smarkm libs = xcalloc(1, sizeof (char *)); 33491592Smarkm libsrchpath = xcalloc(1, sizeof (char *)); 33512099Sjoerg 33675710Sasmodai appcstrg(&cflags, "-E"); 33775710Sasmodai appcstrg(&cflags, "-x"); 33875710Sasmodai appcstrg(&cflags, "c"); 33991592Smarkm#if 0 34075710Sasmodai appcstrg(&cflags, "-D__attribute__(x)="); 34191592Smarkm appcstrg(&cflags, "-D__extension__(x)=/*NOSTRICT*/0"); 34291592Smarkm#else 34391592Smarkm appcstrg(&cflags, "-U__GNUC__"); 34492089Smarkm appcstrg(&cflags, "-undef"); 34591592Smarkm#endif 34675710Sasmodai appcstrg(&cflags, "-Wp,-$"); 34791592Smarkm appcstrg(&cflags, "-Wp,-CC"); 34875710Sasmodai appcstrg(&cflags, "-Wcomment"); 34991592Smarkm appcstrg(&cflags, "-D__LINT__"); 35075710Sasmodai appcstrg(&cflags, "-Dlint"); /* XXX don't def. with -s */ 35112099Sjoerg 35275710Sasmodai appdef(&cflags, "lint"); 35312099Sjoerg 35475710Sasmodai appcstrg(&lcflags, "-Wtraditional"); 35512099Sjoerg 35612099Sjoerg appcstrg(&deflibs, "c"); 35712099Sjoerg 35812099Sjoerg if (signal(SIGHUP, terminate) == SIG_IGN) 35912099Sjoerg (void)signal(SIGHUP, SIG_IGN); 36012099Sjoerg (void)signal(SIGINT, terminate); 36112099Sjoerg (void)signal(SIGQUIT, terminate); 36212099Sjoerg (void)signal(SIGTERM, terminate); 36312099Sjoerg 36491592Smarkm while ((c = getopt(argc, argv, "abcd:eghil:no:prstuvwxzB:C:D:FHI:L:U:VX:")) != -1) { 36512099Sjoerg switch (c) { 36612099Sjoerg 36712099Sjoerg case 'a': 36812099Sjoerg case 'b': 36912099Sjoerg case 'c': 37012099Sjoerg case 'e': 37112099Sjoerg case 'g': 37212099Sjoerg case 'r': 37312099Sjoerg case 'v': 37491592Smarkm case 'w': 37512099Sjoerg case 'z': 37612099Sjoerg (void)sprintf(flgbuf, "-%c", c); 37712099Sjoerg appcstrg(&l1flags, flgbuf); 37812099Sjoerg break; 37912099Sjoerg 38012099Sjoerg case 'F': 38112099Sjoerg Fflag = 1; 38212099Sjoerg /* FALLTHROUGH */ 38312099Sjoerg case 'u': 38412099Sjoerg case 'h': 38512099Sjoerg (void)sprintf(flgbuf, "-%c", c); 38612099Sjoerg appcstrg(&l1flags, flgbuf); 38712099Sjoerg appcstrg(&l2flags, flgbuf); 38812099Sjoerg break; 38912099Sjoerg 39091592Smarkm case 'X': 39191592Smarkm (void)sprintf(flgbuf, "-%c", c); 39291592Smarkm appcstrg(&l1flags, flgbuf); 39391592Smarkm appcstrg(&l1flags, optarg); 39491592Smarkm break; 39591592Smarkm 39612099Sjoerg case 'i': 39712099Sjoerg if (Cflag) 39812099Sjoerg usage(); 39912099Sjoerg iflag = 1; 40012099Sjoerg break; 40112099Sjoerg 40212099Sjoerg case 'n': 40312099Sjoerg freelst(&deflibs); 40412099Sjoerg break; 40512099Sjoerg 40612099Sjoerg case 'p': 40712099Sjoerg appcstrg(&l1flags, "-p"); 40812099Sjoerg appcstrg(&l2flags, "-p"); 40912099Sjoerg if (*deflibs != NULL) { 41012099Sjoerg freelst(&deflibs); 41112099Sjoerg appcstrg(&deflibs, "c"); 41212099Sjoerg } 41312099Sjoerg break; 41412099Sjoerg 41512099Sjoerg case 's': 41612099Sjoerg if (tflag) 41712099Sjoerg usage(); 41875710Sasmodai freelst(&lcflags); 41975710Sasmodai appcstrg(&lcflags, "-trigraphs"); 42075710Sasmodai appcstrg(&lcflags, "-Wtrigraphs"); 42175710Sasmodai appcstrg(&lcflags, "-pedantic"); 42275710Sasmodai appcstrg(&lcflags, "-D__STRICT_ANSI__"); 42312099Sjoerg appcstrg(&l1flags, "-s"); 42412099Sjoerg appcstrg(&l2flags, "-s"); 42512099Sjoerg sflag = 1; 42612099Sjoerg break; 42712099Sjoerg 42891592Smarkm#if !HAVE_CONFIG_H 42912099Sjoerg case 't': 43012099Sjoerg if (sflag) 43112099Sjoerg usage(); 43275710Sasmodai freelst(&lcflags); 43375710Sasmodai appcstrg(&lcflags, "-traditional"); 43475710Sasmodai appstrg(&lcflags, concat2("-D", MACHINE)); 43575710Sasmodai appstrg(&lcflags, concat2("-D", MACHINE_ARCH)); 43612099Sjoerg appcstrg(&l1flags, "-t"); 43712099Sjoerg appcstrg(&l2flags, "-t"); 43812099Sjoerg tflag = 1; 43912099Sjoerg break; 44091592Smarkm#endif 44112099Sjoerg 44212099Sjoerg case 'x': 44312099Sjoerg appcstrg(&l2flags, "-x"); 44412099Sjoerg break; 44512099Sjoerg 44612099Sjoerg case 'C': 44712099Sjoerg if (Cflag || oflag || iflag) 44812099Sjoerg usage(); 44912099Sjoerg Cflag = 1; 45012099Sjoerg appstrg(&l2flags, concat2("-C", optarg)); 45191818Smarkm p2out = xmalloc(sizeof ("llib-l.ln") + strlen(optarg)); 45212099Sjoerg (void)sprintf(p2out, "llib-l%s.ln", optarg); 45312099Sjoerg freelst(&deflibs); 45412099Sjoerg break; 45512099Sjoerg 45691592Smarkm case 'd': 45791592Smarkm if (dflag) 45891592Smarkm usage(); 45991592Smarkm dflag = 1; 46091592Smarkm appcstrg(&cflags, "-nostdinc"); 46191592Smarkm appcstrg(&cflags, "-idirafter"); 46291592Smarkm appcstrg(&cflags, optarg); 46391592Smarkm break; 46491592Smarkm 46512099Sjoerg case 'D': 46612099Sjoerg case 'I': 46712099Sjoerg case 'U': 46812099Sjoerg (void)sprintf(flgbuf, "-%c", c); 46975710Sasmodai appstrg(&cflags, concat2(flgbuf, optarg)); 47012099Sjoerg break; 47112099Sjoerg 47212099Sjoerg case 'l': 47312099Sjoerg appcstrg(&libs, optarg); 47412099Sjoerg break; 47512099Sjoerg 47612099Sjoerg case 'o': 47712099Sjoerg if (Cflag || oflag) 47812099Sjoerg usage(); 47912099Sjoerg oflag = 1; 48091818Smarkm outputfn = xstrdup(optarg); 48112099Sjoerg break; 48212099Sjoerg 48312099Sjoerg case 'L': 48412099Sjoerg appcstrg(&libsrchpath, optarg); 48512099Sjoerg break; 48612099Sjoerg 48712099Sjoerg case 'H': 48812099Sjoerg appcstrg(&l2flags, "-H"); 48912099Sjoerg break; 49012099Sjoerg 49191592Smarkm case 'B': 49291592Smarkm Bflag = 1; 49391592Smarkm libexec_path = xstrdup(optarg); 49491592Smarkm break; 49591592Smarkm 49612099Sjoerg case 'V': 49712099Sjoerg Vflag = 1; 49812099Sjoerg break; 49912099Sjoerg 50091592Smarkm default: 50112099Sjoerg usage(); 50212099Sjoerg /* NOTREACHED */ 50391592Smarkm } 50491592Smarkm } 50591592Smarkm argc -= optind; 50691592Smarkm argv += optind; 50712099Sjoerg 50891592Smarkm /* 50991592Smarkm * To avoid modifying getopt(3)'s state engine midstream, we 51091592Smarkm * explicitly accept just a few options after the first source file. 51191592Smarkm * 51291592Smarkm * In particular, only -l<lib> and -L<libdir> (and these with a space 51391592Smarkm * after -l or -L) are allowed. 51491592Smarkm */ 51591592Smarkm while (argc > 0) { 51691592Smarkm const char *arg = argv[0]; 51791592Smarkm 51891592Smarkm if (arg[0] == '-') { 51991592Smarkm char ***list; 52091592Smarkm 52191592Smarkm /* option */ 52291592Smarkm switch (arg[1]) { 52391592Smarkm case 'l': 52491592Smarkm list = &libs; 52591592Smarkm break; 52691592Smarkm 52791592Smarkm case 'L': 52891592Smarkm list = &libsrchpath; 52991592Smarkm break; 53091592Smarkm 53191592Smarkm default: 53291592Smarkm usage(); 53391592Smarkm /* NOTREACHED */ 53491592Smarkm } 53591592Smarkm if (arg[2]) 53691592Smarkm appcstrg(list, arg + 2); 53791592Smarkm else if (argc > 1) { 53891592Smarkm argc--; 53991592Smarkm appcstrg(list, *++argv); 54091592Smarkm } else 54191592Smarkm usage(); 54291592Smarkm } else { 54312099Sjoerg /* filename */ 54491592Smarkm fname(arg); 54512099Sjoerg first = 0; 54612099Sjoerg } 54791592Smarkm argc--; 54891592Smarkm argv++; 54912099Sjoerg } 55012099Sjoerg 55112099Sjoerg if (first) 55212099Sjoerg usage(); 55312099Sjoerg 55412099Sjoerg if (iflag) 55512099Sjoerg terminate(0); 55612099Sjoerg 55712099Sjoerg if (!oflag) { 55812099Sjoerg if ((s = getenv("LIBDIR")) == NULL || strlen(s) == 0) 55991818Smarkm s = PATH_LINTLIB; 56012099Sjoerg appcstrg(&libsrchpath, s); 56112099Sjoerg findlibs(libs); 56212099Sjoerg findlibs(deflibs); 56312099Sjoerg } 56412099Sjoerg 56512099Sjoerg (void)printf("Lint pass2:\n"); 56612099Sjoerg lint2(); 56712099Sjoerg 56812099Sjoerg if (oflag) 56912099Sjoerg cat(p2in, outputfn); 57012099Sjoerg 57112099Sjoerg if (Cflag) 57212099Sjoerg p2out = NULL; 57312099Sjoerg 57412099Sjoerg terminate(0); 57512099Sjoerg /* NOTREACHED */ 57612099Sjoerg} 57712099Sjoerg 57812099Sjoerg/* 57912099Sjoerg * Read a file name from the command line 58012099Sjoerg * and pass it through lint1 if it is a C source. 58112099Sjoerg */ 58212099Sjoergstatic void 58391592Smarkmfname(const char *name) 58412099Sjoerg{ 58512099Sjoerg const char *bn, *suff; 58612099Sjoerg char **args, *ofn, *path; 58712099Sjoerg size_t len; 58891592Smarkm int is_stdin; 58975710Sasmodai int fd; 59012099Sjoerg 59191592Smarkm is_stdin = (strcmp(name, "-") == 0); 59291592Smarkm bn = lbasename(name, '/'); 59391592Smarkm suff = lbasename(bn, '.'); 59412099Sjoerg 59512099Sjoerg if (strcmp(suff, "ln") == 0) { 59612099Sjoerg /* only for lint2 */ 59712099Sjoerg if (!iflag) 59812099Sjoerg appcstrg(&p2in, name); 59912099Sjoerg return; 60012099Sjoerg } 60112099Sjoerg 60291592Smarkm if (!is_stdin && strcmp(suff, "c") != 0 && 60312099Sjoerg (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) { 60412099Sjoerg warnx("unknown file type: %s\n", name); 60512099Sjoerg return; 60612099Sjoerg } 60712099Sjoerg 60891592Smarkm if (!iflag || !first) 60991592Smarkm (void)printf("%s:\n", 61091592Smarkm is_stdin ? "{standard input}" : Fflag ? name : bn); 61112099Sjoerg 61212099Sjoerg /* build the name of the output file of lint1 */ 61312099Sjoerg if (oflag) { 61412099Sjoerg ofn = outputfn; 61512099Sjoerg outputfn = NULL; 61612099Sjoerg oflag = 0; 61712099Sjoerg } else if (iflag) { 61891592Smarkm if (is_stdin) { 61991592Smarkm warnx("-i not supported without -o for standard input"); 62091592Smarkm return; 62191592Smarkm } 62291592Smarkm ofn = xmalloc(strlen(bn) + (bn == suff ? 4 : 2)); 62312099Sjoerg len = bn == suff ? strlen(bn) : (suff - 1) - bn; 62412099Sjoerg (void)sprintf(ofn, "%.*s", (int)len, bn); 62512099Sjoerg (void)strcat(ofn, ".ln"); 62612099Sjoerg } else { 62791818Smarkm ofn = xmalloc(strlen(tmpdir) + sizeof ("lint1.XXXXXX")); 62812099Sjoerg (void)sprintf(ofn, "%slint1.XXXXXX", tmpdir); 62975710Sasmodai fd = mkstemp(ofn); 63075710Sasmodai if (fd == -1) { 63112099Sjoerg warn("can't make temp"); 63212099Sjoerg terminate(-1); 63312099Sjoerg } 63475710Sasmodai close(fd); 63512099Sjoerg } 63612099Sjoerg if (!iflag) 63712099Sjoerg appcstrg(&p1out, ofn); 63812099Sjoerg 63991818Smarkm args = xcalloc(1, sizeof (char *)); 64012099Sjoerg 64175710Sasmodai /* run cc */ 64212099Sjoerg 64391592Smarkm if (getenv("CC") == NULL) { 64491592Smarkm path = xmalloc(strlen(PATH_USRBIN) + sizeof ("/cc")); 64591592Smarkm (void)sprintf(path, "%s/cc", PATH_USRBIN); 64691592Smarkm } else { 64791592Smarkm path = strdup(getenv("CC")); 64891592Smarkm } 64912099Sjoerg 65012099Sjoerg appcstrg(&args, path); 65175710Sasmodai applst(&args, cflags); 65275710Sasmodai applst(&args, lcflags); 65312099Sjoerg appcstrg(&args, name); 65412099Sjoerg 65575710Sasmodai /* we reuse the same tmp file for cpp output, so rewind and truncate */ 65675710Sasmodai if (lseek(cppoutfd, SEEK_SET, (off_t)0) != 0) { 65775710Sasmodai warn("lseek"); 65875710Sasmodai terminate(-1); 65975710Sasmodai } 66075710Sasmodai if (ftruncate(cppoutfd, (off_t)0) != 0) { 66175710Sasmodai warn("ftruncate"); 66275710Sasmodai terminate(-1); 66375710Sasmodai } 66475710Sasmodai 66575710Sasmodai runchild(path, args, cppout, cppoutfd); 66612099Sjoerg free(path); 66712099Sjoerg freelst(&args); 66812099Sjoerg 66912099Sjoerg /* run lint1 */ 67012099Sjoerg 67191592Smarkm if (!Bflag) { 67291592Smarkm path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint1") + 67391592Smarkm strlen(target_prefix)); 67491592Smarkm (void)sprintf(path, "%s/%slint1", PATH_LIBEXEC, 67591592Smarkm target_prefix); 67691592Smarkm } else { 67791592Smarkm /* 67891592Smarkm * XXX Unclear whether we should be using target_prefix 67991592Smarkm * XXX here. --thorpej@wasabisystems.com 68091592Smarkm */ 68191592Smarkm path = xmalloc(strlen(libexec_path) + sizeof ("/lint1")); 68291592Smarkm (void)sprintf(path, "%s/lint1", libexec_path); 68391592Smarkm } 68412099Sjoerg 68512099Sjoerg appcstrg(&args, path); 68612099Sjoerg applst(&args, l1flags); 68712099Sjoerg appcstrg(&args, cppout); 68812099Sjoerg appcstrg(&args, ofn); 68912099Sjoerg 69075710Sasmodai runchild(path, args, ofn, -1); 69112099Sjoerg free(path); 69212099Sjoerg freelst(&args); 69312099Sjoerg 69412099Sjoerg appcstrg(&p2in, ofn); 69512099Sjoerg free(ofn); 69612099Sjoerg 69712099Sjoerg free(args); 69812099Sjoerg} 69912099Sjoerg 70012099Sjoergstatic void 70191592Smarkmrunchild(const char *path, char *const *args, const char *crfn, int fdout) 70212099Sjoerg{ 70312099Sjoerg int status, rv, signo, i; 70412099Sjoerg 70512099Sjoerg if (Vflag) { 70612099Sjoerg for (i = 0; args[i] != NULL; i++) 70712099Sjoerg (void)printf("%s ", args[i]); 70812099Sjoerg (void)printf("\n"); 70912099Sjoerg } 71012099Sjoerg 71112099Sjoerg currfn = crfn; 71212099Sjoerg 71312099Sjoerg (void)fflush(stdout); 71412099Sjoerg 71575710Sasmodai switch (vfork()) { 71612099Sjoerg case -1: 71712099Sjoerg warn("cannot fork"); 71812099Sjoerg terminate(-1); 71912099Sjoerg /* NOTREACHED */ 72012099Sjoerg default: 72112099Sjoerg /* parent */ 72212099Sjoerg break; 72312099Sjoerg case 0: 72412099Sjoerg /* child */ 72575710Sasmodai 72675710Sasmodai /* setup the standard output if necessary */ 72775710Sasmodai if (fdout != -1) { 72875710Sasmodai dup2(fdout, STDOUT_FILENO); 72975710Sasmodai close(fdout); 73075710Sasmodai } 73191592Smarkm (void)execvp(path, args); 73212099Sjoerg warn("cannot exec %s", path); 73375710Sasmodai _exit(1); 73412099Sjoerg /* NOTREACHED */ 73512099Sjoerg } 73612099Sjoerg 73712099Sjoerg while ((rv = wait(&status)) == -1 && errno == EINTR) ; 73812099Sjoerg if (rv == -1) { 73912099Sjoerg warn("wait"); 74012099Sjoerg terminate(-1); 74112099Sjoerg } 74212099Sjoerg if (WIFSIGNALED(status)) { 74312099Sjoerg signo = WTERMSIG(status); 74491592Smarkm#if HAVE_DECL_SYS_SIGNAME 74512099Sjoerg warnx("%s got SIG%s", path, sys_signame[signo]); 74691592Smarkm#else 74791592Smarkm warnx("%s got signal %d", path, signo); 74891592Smarkm#endif 74912099Sjoerg terminate(-1); 75012099Sjoerg } 75112099Sjoerg if (WEXITSTATUS(status) != 0) 75212099Sjoerg terminate(-1); 75312099Sjoerg currfn = NULL; 75412099Sjoerg} 75512099Sjoerg 75612099Sjoergstatic void 75791592Smarkmfindlibs(char *const *liblst) 75812099Sjoerg{ 75912099Sjoerg int i, k; 76012099Sjoerg const char *lib, *path; 76112099Sjoerg char *lfn; 76212099Sjoerg size_t len; 76312099Sjoerg 76412099Sjoerg lfn = NULL; 76512099Sjoerg 76612099Sjoerg for (i = 0; (lib = liblst[i]) != NULL; i++) { 76712099Sjoerg for (k = 0; (path = libsrchpath[k]) != NULL; k++) { 76812099Sjoerg len = strlen(path) + strlen(lib); 76991818Smarkm lfn = xrealloc(lfn, len + sizeof ("/llib-l.ln")); 77012099Sjoerg (void)sprintf(lfn, "%s/llib-l%s.ln", path, lib); 77112099Sjoerg if (rdok(lfn)) 77212099Sjoerg break; 77391818Smarkm lfn = xrealloc(lfn, len + sizeof ("/lint/llib-l.ln")); 77412099Sjoerg (void)sprintf(lfn, "%s/lint/llib-l%s.ln", path, lib); 77512099Sjoerg if (rdok(lfn)) 77612099Sjoerg break; 77712099Sjoerg } 77812099Sjoerg if (path != NULL) { 77912099Sjoerg appstrg(&l2libs, concat2("-l", lfn)); 78012099Sjoerg } else { 78112099Sjoerg warnx("cannot find llib-l%s.ln", lib); 78212099Sjoerg } 78312099Sjoerg } 78412099Sjoerg 78512099Sjoerg free(lfn); 78612099Sjoerg} 78712099Sjoerg 78812099Sjoergstatic int 78991592Smarkmrdok(const char *path) 79012099Sjoerg{ 79112099Sjoerg struct stat sbuf; 79212099Sjoerg 79312099Sjoerg if (stat(path, &sbuf) == -1) 79412099Sjoerg return (0); 79591592Smarkm if (!S_ISREG(sbuf.st_mode)) 79612099Sjoerg return (0); 79712099Sjoerg if (access(path, R_OK) == -1) 79812099Sjoerg return (0); 79912099Sjoerg return (1); 80012099Sjoerg} 80112099Sjoerg 80212099Sjoergstatic void 80391592Smarkmlint2(void) 80412099Sjoerg{ 80512099Sjoerg char *path, **args; 80612099Sjoerg 80791818Smarkm args = xcalloc(1, sizeof (char *)); 80812099Sjoerg 80991592Smarkm if (!Bflag) { 81091592Smarkm path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint2") + 81191592Smarkm strlen(target_prefix)); 81291592Smarkm (void)sprintf(path, "%s/%slint2", PATH_LIBEXEC, 81391592Smarkm target_prefix); 81491592Smarkm } else { 81591592Smarkm /* 81691592Smarkm * XXX Unclear whether we should be using target_prefix 81791592Smarkm * XXX here. --thorpej@wasabisystems.com 81891592Smarkm */ 81991592Smarkm path = xmalloc(strlen(libexec_path) + sizeof ("/lint2")); 82091592Smarkm (void)sprintf(path, "%s/lint2", libexec_path); 82191592Smarkm } 82291592Smarkm 82312099Sjoerg appcstrg(&args, path); 82412099Sjoerg applst(&args, l2flags); 82512099Sjoerg applst(&args, l2libs); 82612099Sjoerg applst(&args, p2in); 82712099Sjoerg 82875710Sasmodai runchild(path, args, p2out, -1); 82912099Sjoerg free(path); 83012099Sjoerg freelst(&args); 83112099Sjoerg free(args); 83212099Sjoerg} 83312099Sjoerg 83412099Sjoergstatic void 83591592Smarkmcat(char *const *srcs, const char *dest) 83612099Sjoerg{ 83712099Sjoerg int ifd, ofd, i; 83812099Sjoerg char *src, *buf; 83912099Sjoerg ssize_t rlen; 84012099Sjoerg 84112099Sjoerg if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { 84212099Sjoerg warn("cannot open %s", dest); 84312099Sjoerg terminate(-1); 84412099Sjoerg } 84512099Sjoerg 84691818Smarkm buf = xmalloc(MBLKSIZ); 84712099Sjoerg 84812099Sjoerg for (i = 0; (src = srcs[i]) != NULL; i++) { 84912099Sjoerg if ((ifd = open(src, O_RDONLY)) == -1) { 85012099Sjoerg free(buf); 85112099Sjoerg warn("cannot open %s", src); 85212099Sjoerg terminate(-1); 85312099Sjoerg } 85412099Sjoerg do { 85512099Sjoerg if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) { 85612099Sjoerg free(buf); 85712099Sjoerg warn("read error on %s", src); 85812099Sjoerg terminate(-1); 85912099Sjoerg } 86012099Sjoerg if (write(ofd, buf, (size_t)rlen) == -1) { 86112099Sjoerg free(buf); 86212099Sjoerg warn("write error on %s", dest); 86312099Sjoerg terminate(-1); 86412099Sjoerg } 86512099Sjoerg } while (rlen == MBLKSIZ); 86612099Sjoerg (void)close(ifd); 86712099Sjoerg } 86812099Sjoerg (void)close(ofd); 86912099Sjoerg free(buf); 87012099Sjoerg} 871