[BACK]Return to xlint.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / xlint / xlint

Annotation of src/usr.bin/xlint/xlint/xlint.c, Revision 1.60

1.60    ! rillig      1: /* $NetBSD: xlint.c,v 1.59 2021/04/14 19:25:48 rillig Exp $ */
1.2       cgd         2:
1.1       cgd         3: /*
1.4       cgd         4:  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
1.1       cgd         5:  * Copyright (c) 1994, 1995 Jochen Pohl
                      6:  * All Rights Reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *      This product includes software developed by Jochen Pohl for
                     19:  *     The NetBSD Project.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
1.35      jmc        35: #if HAVE_NBTOOL_CONFIG_H
                     36: #include "nbtool_config.h"
                     37: #endif
                     38:
1.6       christos   39: #include <sys/cdefs.h>
1.27      tv         40: #if defined(__RCSID) && !defined(lint)
1.60    ! rillig     41: __RCSID("$NetBSD: xlint.c,v 1.59 2021/04/14 19:25:48 rillig Exp $");
1.1       cgd        42: #endif
                     43:
1.3       jpo        44: #include <sys/param.h>
1.1       cgd        45: #include <sys/wait.h>
                     46: #include <sys/stat.h>
1.3       jpo        47: #include <sys/utsname.h>
1.25      tv         48: #include <errno.h>
                     49: #include <fcntl.h>
                     50: #include <paths.h>
                     51: #include <signal.h>
1.1       cgd        52: #include <stdio.h>
                     53: #include <stdlib.h>
                     54: #include <string.h>
                     55: #include <unistd.h>
1.38      lukem      56: #include <util.h>
1.1       cgd        57:
                     58: #include "lint.h"
                     59: #include "pathnames.h"
1.28      simonb     60: #include "findcc.h"
                     61:
                     62: #define DEFAULT_PATH           _PATH_DEFPATH
1.1       cgd        63:
                     64: /* directory for temporary files */
                     65: static const   char *tmpdir;
                     66:
                     67: /* path name for cpp output */
                     68: static char    *cppout;
                     69:
1.10      mrg        70: /* file descriptor for cpp output */
                     71: static int     cppoutfd = -1;
                     72:
1.1       cgd        73: /* files created by 1st pass */
                     74: static char    **p1out;
                     75:
                     76: /* input files for 2nd pass (without libraries) */
                     77: static char    **p2in;
                     78:
                     79: /* library which will be created by 2nd pass */
                     80: static char    *p2out;
                     81:
1.10      mrg        82: /* flags always passed to cc(1) */
                     83: static char    **cflags;
1.1       cgd        84:
1.52      rillig     85: /* flags for cc(1), controlled by sflag/tflag */
1.10      mrg        86: static char    **lcflags;
1.1       cgd        87:
                     88: /* flags for lint1 */
                     89: static char    **l1flags;
                     90:
                     91: /* flags for lint2 */
                     92: static char    **l2flags;
                     93:
                     94: /* libraries for lint2 */
                     95: static char    **l2libs;
                     96:
                     97: /* default libraries */
                     98: static char    **deflibs;
                     99:
                    100: /* additional libraries */
                    101: static char    **libs;
                    102:
                    103: /* search path for libraries */
                    104: static char    **libsrchpath;
                    105:
1.17      garbled   106: static  char   *libexec_path;
                    107:
1.1       cgd       108: /* flags */
1.54      rillig    109: static bool    iflag, oflag, Cflag, sflag, tflag, Fflag, dflag, Bflag, Sflag;
1.1       cgd       110:
                    111: /* print the commands executed to run the stages of compilation */
1.56      rillig    112: static bool    Vflag;
1.1       cgd       113:
                    114: /* filename for oflag */
                    115: static char    *outputfn;
                    116:
                    117: /* reset after first .c source has been processed */
1.54      rillig    118: static bool    first = true;
1.1       cgd       119:
                    120: /*
                    121:  * name of a file which is currently written by a child and should
                    122:  * be removed after abnormal termination of the child
                    123:  */
                    124: static const   char *currfn;
                    125:
1.24      thorpej   126: #if !defined(TARGET_PREFIX)
                    127: #define        TARGET_PREFIX   ""
                    128: #endif
                    129: static const char target_prefix[] = TARGET_PREFIX;
1.1       cgd       130:
1.23      lukem     131: static void    appstrg(char ***, char *);
                    132: static void    appcstrg(char ***, const char *);
                    133: static void    applst(char ***, char *const *);
                    134: static void    freelst(char ***);
                    135: static char    *concat2(const char *, const char *);
                    136: static char    *concat3(const char *, const char *, const char *);
                    137: static void    terminate(int) __attribute__((__noreturn__));
1.25      tv        138: static const   char *lbasename(const char *, int);
1.23      lukem     139: static void    appdef(char ***, const char *);
                    140: static void    usage(void);
1.27      tv        141: static void    fname(const char *);
1.23      lukem     142: static void    runchild(const char *, char *const *, const char *, int);
                    143: static void    findlibs(char *const *);
1.56      rillig    144: static bool    rdok(const char *);
1.23      lukem     145: static void    lint2(void);
                    146: static void    cat(char *const *, const char *);
1.1       cgd       147:
                    148: /*
                    149:  * Some functions to deal with lists of strings.
1.32      wiz       150:  * Take care that we get no surprises in case of asynchronous signals.
1.1       cgd       151:  */
                    152: static void
1.23      lukem     153: appstrg(char ***lstp, char *s)
1.1       cgd       154: {
                    155:        char    **lst, **olst;
                    156:        int     i;
                    157:
                    158:        olst = *lstp;
1.23      lukem     159:        for (i = 0; olst[i] != NULL; i++)
                    160:                continue;
1.58      rillig    161:        lst = xrealloc(olst, (i + 2) * sizeof(*lst));
1.3       jpo       162:        lst[i] = s;
1.1       cgd       163:        lst[i + 1] = NULL;
                    164:        *lstp = lst;
1.23      lukem     165: }
1.1       cgd       166:
                    167: static void
1.23      lukem     168: appcstrg(char ***lstp, const char *s)
1.1       cgd       169: {
1.23      lukem     170:
1.3       jpo       171:        appstrg(lstp, xstrdup(s));
1.1       cgd       172: }
                    173:
                    174: static void
1.23      lukem     175: applst(char ***destp, char *const *src)
1.1       cgd       176: {
                    177:        int     i, k;
                    178:        char    **dest, **odest;
                    179:
                    180:        odest = *destp;
1.23      lukem     181:        for (i = 0; odest[i] != NULL; i++)
                    182:                continue;
                    183:        for (k = 0; src[k] != NULL; k++)
                    184:                continue;
1.58      rillig    185:        dest = xrealloc(odest, (i + k + 1) * sizeof(*dest));
1.1       cgd       186:        for (k = 0; src[k] != NULL; k++)
                    187:                dest[i + k] = xstrdup(src[k]);
                    188:        dest[i + k] = NULL;
                    189:        *destp = dest;
                    190: }
                    191:
                    192: static void
1.23      lukem     193: freelst(char ***lstp)
1.1       cgd       194: {
                    195:        char    *s;
                    196:        int     i;
                    197:
1.23      lukem     198:        for (i = 0; (*lstp)[i] != NULL; i++)
                    199:                continue;
1.1       cgd       200:        while (i-- > 0) {
                    201:                s = (*lstp)[i];
                    202:                (*lstp)[i] = NULL;
                    203:                free(s);
                    204:        }
                    205: }
                    206:
1.3       jpo       207: static char *
1.23      lukem     208: concat2(const char *s1, const char *s2)
1.3       jpo       209: {
                    210:        char    *s;
                    211:
                    212:        s = xmalloc(strlen(s1) + strlen(s2) + 1);
                    213:        (void)strcpy(s, s1);
                    214:        (void)strcat(s, s2);
                    215:
1.51      rillig    216:        return s;
1.3       jpo       217: }
                    218:
                    219: static char *
1.23      lukem     220: concat3(const char *s1, const char *s2, const char *s3)
1.3       jpo       221: {
                    222:        char    *s;
                    223:
                    224:        s = xmalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1);
                    225:        (void)strcpy(s, s1);
                    226:        (void)strcat(s, s2);
                    227:        (void)strcat(s, s3);
                    228:
1.51      rillig    229:        return s;
1.3       jpo       230: }
                    231:
1.1       cgd       232: /*
                    233:  * Clean up after a signal.
                    234:  */
                    235: static void
1.23      lukem     236: terminate(int signo)
1.1       cgd       237: {
                    238:        int     i;
                    239:
1.10      mrg       240:        if (cppoutfd != -1)
                    241:                (void)close(cppoutfd);
1.1       cgd       242:        if (cppout != NULL)
                    243:                (void)remove(cppout);
                    244:
                    245:        if (p1out != NULL) {
                    246:                for (i = 0; p1out[i] != NULL; i++)
                    247:                        (void)remove(p1out[i]);
                    248:        }
                    249:
                    250:        if (p2out != NULL)
                    251:                (void)remove(p2out);
                    252:
                    253:        if (currfn != NULL)
                    254:                (void)remove(currfn);
                    255:
1.38      lukem     256:        if (signo != 0)
                    257:                (void)raise_default_signal(signo);
1.1       cgd       258:        exit(signo != 0 ? 1 : 0);
                    259: }
                    260:
                    261: /*
                    262:  * Returns a pointer to the last component of strg after delim.
                    263:  * Returns strg if the string does not contain delim.
                    264:  */
                    265: static const char *
1.25      tv        266: lbasename(const char *strg, int delim)
1.1       cgd       267: {
                    268:        const   char *cp, *cp1, *cp2;
                    269:
                    270:        cp = cp1 = cp2 = strg;
                    271:        while (*cp != '\0') {
                    272:                if (*cp++ == delim) {
                    273:                        cp2 = cp1;
                    274:                        cp1 = cp;
                    275:                }
                    276:        }
1.51      rillig    277:        return *cp1 == '\0' ? cp2 : cp1;
1.1       cgd       278: }
                    279:
                    280: static void
1.23      lukem     281: appdef(char ***lstp, const char *def)
1.3       jpo       282: {
1.23      lukem     283:
1.3       jpo       284:        appstrg(lstp, concat2("-D__", def));
                    285:        appstrg(lstp, concat3("-D__", def, "__"));
                    286: }
                    287:
                    288: static void
1.23      lukem     289: usage(void)
1.1       cgd       290: {
1.59      rillig    291:        const char *name;
                    292:        int indent;
1.22      cgd       293:
1.59      rillig    294:        name = getprogname();
                    295:        indent = (int)(strlen("usage: ") + strlen(name));
1.12      christos  296:        (void)fprintf(stderr,
1.59      rillig    297:            "usage: %s [-abceghprvwxzHFST] [-s|-t] [-i|-nu]\n"
                    298:            "%*s [-Dname[=def]] [-Uname] [-Idirectory] [-Z <cpparg>]\n"
                    299:            "%*s [-Ldirectory] [-llibrary] [-ooutputfile]\n"
1.60    ! rillig    300:            "%*s [-X <id>[,<id>]...] [-Ac11] file...\n",
1.59      rillig    301:            name, indent, "", indent, "", indent, "");
1.23      lukem     302:        (void)fprintf(stderr,
1.59      rillig    303:            "       %s [-abceghprvwzHFST] [-s|-t] -Clibrary\n"
                    304:            "%*s [-Dname[=def]] [-Uname] [-Idirectory] [-Z <cpparg>]\n"
                    305:            "%*s [-Bpath] [-X <id>[,<id>]...] [-R old=new] file ...\n",
                    306:            name, indent, "", indent, "");
1.1       cgd       307:        terminate(-1);
                    308: }
1.6       christos  309:
1.1       cgd       310:
                    311: int
1.23      lukem     312: main(int argc, char *argv[])
1.1       cgd       313: {
                    314:        int     c;
1.42      christos  315:        char    flgbuf[3], *tmp;
1.1       cgd       316:        size_t  len;
1.41      lukem     317:        const char *ks;
1.1       cgd       318:
1.27      tv        319:        setprogname(argv[0]);
                    320:
1.1       cgd       321:        if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) {
                    322:                tmpdir = xstrdup(_PATH_TMP);
                    323:        } else {
1.42      christos  324:                char *p = xmalloc(len + 2);
                    325:                (void)sprintf(p, "%s%s", tmp, tmp[len - 1] == '/' ? "" : "/");
                    326:                tmpdir = p;
1.1       cgd       327:        }
                    328:
1.58      rillig    329:        cppout = xmalloc(strlen(tmpdir) + sizeof("lint0.XXXXXX"));
1.1       cgd       330:        (void)sprintf(cppout, "%slint0.XXXXXX", tmpdir);
1.10      mrg       331:        cppoutfd = mkstemp(cppout);
                    332:        if (cppoutfd == -1) {
1.1       cgd       333:                warn("can't make temp");
                    334:                terminate(-1);
                    335:        }
                    336:
1.58      rillig    337:        p1out = xcalloc(1, sizeof(*p1out));
                    338:        p2in = xcalloc(1, sizeof(*p2in));
                    339:        cflags = xcalloc(1, sizeof(*cflags));
                    340:        lcflags = xcalloc(1, sizeof(*lcflags));
                    341:        l1flags = xcalloc(1, sizeof(*l1flags));
                    342:        l2flags = xcalloc(1, sizeof(*l2flags));
                    343:        l2libs = xcalloc(1, sizeof(*l2libs));
                    344:        deflibs = xcalloc(1, sizeof(*deflibs));
                    345:        libs = xcalloc(1, sizeof(*libs));
                    346:        libsrchpath = xcalloc(1, sizeof(*libsrchpath));
1.1       cgd       347:
1.10      mrg       348:        appcstrg(&cflags, "-E");
                    349:        appcstrg(&cflags, "-x");
                    350:        appcstrg(&cflags, "c");
1.12      christos  351: #if 0
1.10      mrg       352:        appcstrg(&cflags, "-D__attribute__(x)=");
1.11      christos  353:        appcstrg(&cflags, "-D__extension__(x)=/*NOSTRICT*/0");
1.12      christos  354: #else
                    355:        appcstrg(&cflags, "-U__GNUC__");
1.40      gmcgarry  356:        appcstrg(&cflags, "-U__PCC__");
1.47      christos  357:        appcstrg(&cflags, "-U__SSE__");
                    358:        appcstrg(&cflags, "-U__SSE4_1__");
1.12      christos  359: #endif
1.31      thorpej   360: #if 0
1.10      mrg       361:        appcstrg(&cflags, "-Wp,-$");
1.31      thorpej   362: #endif
1.10      mrg       363:        appcstrg(&cflags, "-Wp,-CC");
                    364:        appcstrg(&cflags, "-Wcomment");
1.16      kleink    365:        appcstrg(&cflags, "-D__LINT__");
1.10      mrg       366:        appcstrg(&cflags, "-Dlint");            /* XXX don't def. with -s */
                    367:
                    368:        appdef(&cflags, "lint");
                    369:
1.3       jpo       370:        appcstrg(&deflibs, "c");
1.1       cgd       371:
                    372:        if (signal(SIGHUP, terminate) == SIG_IGN)
                    373:                (void)signal(SIGHUP, SIG_IGN);
                    374:        (void)signal(SIGINT, terminate);
                    375:        (void)signal(SIGQUIT, terminate);
                    376:        (void)signal(SIGTERM, terminate);
1.53      rillig    377:        while ((c = getopt(argc, argv,
1.60    ! rillig    378:            "abcd:eghil:no:prstuvwxzA:B:C:D:FHI:L:M:PR:STU:VX:Z:")) != -1) {
1.1       cgd       379:                switch (c) {
                    380:
                    381:                case 'a':
                    382:                case 'b':
                    383:                case 'c':
                    384:                case 'e':
                    385:                case 'g':
                    386:                case 'r':
                    387:                case 'v':
1.20      christos  388:                case 'w':
1.1       cgd       389:                case 'z':
                    390:                        (void)sprintf(flgbuf, "-%c", c);
1.3       jpo       391:                        appcstrg(&l1flags, flgbuf);
1.1       cgd       392:                        break;
                    393:
1.60    ! rillig    394:                case 'A':
        !           395:                        appcstrg(&l1flags, "-A");
        !           396:                        appcstrg(&l1flags, optarg);
        !           397:                        break;
        !           398:
1.1       cgd       399:                case 'F':
1.54      rillig    400:                        Fflag = true;
1.1       cgd       401:                        /* FALLTHROUGH */
                    402:                case 'u':
                    403:                case 'h':
                    404:                        (void)sprintf(flgbuf, "-%c", c);
1.3       jpo       405:                        appcstrg(&l1flags, flgbuf);
                    406:                        appcstrg(&l2flags, flgbuf);
1.20      christos  407:                        break;
                    408:
                    409:                case 'X':
                    410:                        (void)sprintf(flgbuf, "-%c", c);
                    411:                        appcstrg(&l1flags, flgbuf);
                    412:                        appcstrg(&l1flags, optarg);
1.1       cgd       413:                        break;
                    414:
                    415:                case 'i':
                    416:                        if (Cflag)
                    417:                                usage();
1.54      rillig    418:                        iflag = true;
1.1       cgd       419:                        break;
                    420:
                    421:                case 'n':
                    422:                        freelst(&deflibs);
                    423:                        break;
                    424:
                    425:                case 'p':
1.3       jpo       426:                        appcstrg(&l1flags, "-p");
                    427:                        appcstrg(&l2flags, "-p");
1.1       cgd       428:                        if (*deflibs != NULL) {
                    429:                                freelst(&deflibs);
1.3       jpo       430:                                appcstrg(&deflibs, "c");
1.1       cgd       431:                        }
                    432:                        break;
                    433:
1.39      christos  434:                case 'P':
                    435:                        appcstrg(&l1flags, "-P");
                    436:                        break;
                    437:
1.46      christos  438:                case 'R':
                    439:                        appcstrg(&l1flags, concat2("-R", optarg));
                    440:                        break;
                    441:
1.1       cgd       442:                case 's':
                    443:                        if (tflag)
                    444:                                usage();
1.10      mrg       445:                        freelst(&lcflags);
                    446:                        appcstrg(&lcflags, "-trigraphs");
                    447:                        appcstrg(&lcflags, "-Wtrigraphs");
                    448:                        appcstrg(&lcflags, "-pedantic");
                    449:                        appcstrg(&lcflags, "-D__STRICT_ANSI__");
1.3       jpo       450:                        appcstrg(&l1flags, "-s");
                    451:                        appcstrg(&l2flags, "-s");
1.54      rillig    452:                        sflag = true;
1.30      christos  453:                        break;
                    454:
                    455:                case 'S':
                    456:                        if (tflag)
                    457:                                usage();
                    458:                        appcstrg(&l1flags, "-S");
1.54      rillig    459:                        Sflag = true;
1.1       cgd       460:                        break;
                    461:
1.55      rillig    462:                case 'T':
                    463:                        (void)sprintf(flgbuf, "-%c", c);
                    464:                        appcstrg(&cflags, "-I" PATH_STRICT_BOOL_INCLUDE);
                    465:                        appcstrg(&l1flags, flgbuf);
                    466:                        appcstrg(&l2flags, flgbuf);
                    467:                        break;
                    468:
1.33      lukem     469: #if ! HAVE_NBTOOL_CONFIG_H
1.1       cgd       470:                case 't':
                    471:                        if (sflag)
                    472:                                usage();
1.10      mrg       473:                        freelst(&lcflags);
                    474:                        appcstrg(&lcflags, "-traditional");
1.36      dsl       475:                        appcstrg(&lcflags, "-Wtraditional");
1.10      mrg       476:                        appstrg(&lcflags, concat2("-D", MACHINE));
                    477:                        appstrg(&lcflags, concat2("-D", MACHINE_ARCH));
1.3       jpo       478:                        appcstrg(&l1flags, "-t");
                    479:                        appcstrg(&l2flags, "-t");
1.54      rillig    480:                        tflag = true;
1.1       cgd       481:                        break;
1.25      tv        482: #endif
1.1       cgd       483:
                    484:                case 'x':
1.3       jpo       485:                        appcstrg(&l2flags, "-x");
1.1       cgd       486:                        break;
                    487:
                    488:                case 'C':
                    489:                        if (Cflag || oflag || iflag)
                    490:                                usage();
1.54      rillig    491:                        Cflag = true;
1.3       jpo       492:                        appstrg(&l2flags, concat2("-C", optarg));
1.58      rillig    493:                        p2out = xmalloc(sizeof("llib-l.ln") + strlen(optarg));
1.1       cgd       494:                        (void)sprintf(p2out, "llib-l%s.ln", optarg);
                    495:                        freelst(&deflibs);
                    496:                        break;
                    497:
1.7       sommerfe  498:                case 'd':
                    499:                        if (dflag)
                    500:                                usage();
1.54      rillig    501:                        dflag = true;
1.10      mrg       502:                        appcstrg(&cflags, "-nostdinc");
1.43      mrg       503:                        appcstrg(&cflags, "-isystem");
1.10      mrg       504:                        appcstrg(&cflags, optarg);
1.7       sommerfe  505:                        break;
1.23      lukem     506:
1.1       cgd       507:                case 'D':
                    508:                case 'I':
1.34      dsl       509:                case 'M':
1.1       cgd       510:                case 'U':
                    511:                        (void)sprintf(flgbuf, "-%c", c);
1.10      mrg       512:                        appstrg(&cflags, concat2(flgbuf, optarg));
1.1       cgd       513:                        break;
                    514:
                    515:                case 'l':
1.3       jpo       516:                        appcstrg(&libs, optarg);
1.1       cgd       517:                        break;
                    518:
                    519:                case 'o':
                    520:                        if (Cflag || oflag)
                    521:                                usage();
1.54      rillig    522:                        oflag = true;
1.1       cgd       523:                        outputfn = xstrdup(optarg);
                    524:                        break;
                    525:
                    526:                case 'L':
1.3       jpo       527:                        appcstrg(&libsrchpath, optarg);
1.1       cgd       528:                        break;
                    529:
                    530:                case 'H':
1.3       jpo       531:                        appcstrg(&l2flags, "-H");
1.1       cgd       532:                        break;
                    533:
1.17      garbled   534:                case 'B':
1.54      rillig    535:                        Bflag = true;
1.17      garbled   536:                        libexec_path = xstrdup(optarg);
                    537:                        break;
                    538:
1.1       cgd       539:                case 'V':
1.54      rillig    540:                        Vflag = true;
1.1       cgd       541:                        break;
                    542:
1.50      christos  543:                case 'Z':
                    544:                        appcstrg(&cflags, optarg);
                    545:                        break;
                    546:
1.25      tv        547:                default:
                    548:                        usage();
                    549:                        /* NOTREACHED */
1.1       cgd       550:                }
                    551:        }
1.21      wiz       552:        argc -= optind;
                    553:        argv += optind;
1.1       cgd       554:
1.27      tv        555:        /*
                    556:         * To avoid modifying getopt(3)'s state engine midstream, we
                    557:         * explicitly accept just a few options after the first source file.
                    558:         *
                    559:         * In particular, only -l<lib> and -L<libdir> (and these with a space
                    560:         * after -l or -L) are allowed.
                    561:         */
                    562:        while (argc > 0) {
                    563:                const char *arg = argv[0];
                    564:
                    565:                if (arg[0] == '-') {
                    566:                        char ***list;
                    567:
1.37      lukem     568:                        list = NULL;    /* XXXGCC -Wuninitialized */
                    569:
1.27      tv        570:                        /* option */
                    571:                        switch (arg[1]) {
                    572:                        case 'l':
                    573:                                list = &libs;
                    574:                                break;
                    575:
                    576:                        case 'L':
                    577:                                list = &libsrchpath;
                    578:                                break;
                    579:
                    580:                        default:
                    581:                                usage();
                    582:                                /* NOTREACHED */
                    583:                        }
1.56      rillig    584:                        if (arg[2] != '\0')
1.27      tv        585:                                appcstrg(list, arg + 2);
                    586:                        else if (argc > 1) {
                    587:                                argc--;
                    588:                                appcstrg(list, *++argv);
                    589:                        } else
                    590:                                usage();
                    591:                } else {
                    592:                        /* filename */
                    593:                        fname(arg);
1.54      rillig    594:                        first = false;
1.27      tv        595:                }
                    596:                argc--;
                    597:                argv++;
                    598:        }
                    599:
1.1       cgd       600:        if (first)
                    601:                usage();
                    602:
                    603:        if (iflag)
                    604:                terminate(0);
                    605:
                    606:        if (!oflag) {
1.41      lukem     607:                if ((ks = getenv("LIBDIR")) == NULL || strlen(ks) == 0)
                    608:                        ks = PATH_LINTLIB;
                    609:                appcstrg(&libsrchpath, ks);
1.1       cgd       610:                findlibs(libs);
                    611:                findlibs(deflibs);
                    612:        }
                    613:
                    614:        (void)printf("Lint pass2:\n");
                    615:        lint2();
                    616:
                    617:        if (oflag)
                    618:                cat(p2in, outputfn);
                    619:
                    620:        if (Cflag)
                    621:                p2out = NULL;
                    622:
                    623:        terminate(0);
                    624:        /* NOTREACHED */
                    625: }
                    626:
                    627: /*
                    628:  * Read a file name from the command line
                    629:  * and pass it through lint1 if it is a C source.
                    630:  */
                    631: static void
1.27      tv        632: fname(const char *name)
1.1       cgd       633: {
                    634:        const   char *bn, *suff;
1.41      lukem     635:        char    **args, *ofn, *pathname;
                    636:        const char *CC;
1.49      christos  637:        size_t  len;
1.56      rillig    638:        bool    is_stdin;
1.10      mrg       639:        int     fd;
1.1       cgd       640:
1.56      rillig    641:        is_stdin = strcmp(name, "-") == 0;
1.25      tv        642:        bn = lbasename(name, '/');
                    643:        suff = lbasename(bn, '.');
1.1       cgd       644:
                    645:        if (strcmp(suff, "ln") == 0) {
                    646:                /* only for lint2 */
                    647:                if (!iflag)
1.3       jpo       648:                        appcstrg(&p2in, name);
1.1       cgd       649:                return;
                    650:        }
                    651:
1.4       cgd       652:        if (!is_stdin && strcmp(suff, "c") != 0 &&
1.1       cgd       653:            (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) {
1.29      grant     654:                warnx("unknown file type: %s", name);
1.1       cgd       655:                return;
                    656:        }
                    657:
1.27      tv        658:        if (!iflag || !first)
1.4       cgd       659:                (void)printf("%s:\n",
                    660:                    is_stdin ? "{standard input}" : Fflag ? name : bn);
1.1       cgd       661:
                    662:        /* build the name of the output file of lint1 */
                    663:        if (oflag) {
                    664:                ofn = outputfn;
                    665:                outputfn = NULL;
1.54      rillig    666:                oflag = false;
1.1       cgd       667:        } else if (iflag) {
1.4       cgd       668:                if (is_stdin) {
                    669:                        warnx("-i not supported without -o for standard input");
                    670:                        return;
                    671:                }
1.42      christos  672:                len = bn == suff ? strlen(bn) : (size_t)((suff - 1) - bn);
1.49      christos  673:                xasprintf(&ofn, "%.*s.ln", (int)len, bn);
1.1       cgd       674:        } else {
1.49      christos  675:                xasprintf(&ofn, "%slint1.XXXXXX", tmpdir);
1.10      mrg       676:                fd = mkstemp(ofn);
                    677:                if (fd == -1) {
1.1       cgd       678:                        warn("can't make temp");
                    679:                        terminate(-1);
                    680:                }
1.10      mrg       681:                close(fd);
1.1       cgd       682:        }
                    683:        if (!iflag)
1.3       jpo       684:                appcstrg(&p1out, ofn);
1.1       cgd       685:
1.58      rillig    686:        args = xcalloc(1, sizeof(*args));
1.1       cgd       687:
1.10      mrg       688:        /* run cc */
1.28      simonb    689:        if ((CC = getenv("CC")) == NULL)
                    690:                CC = DEFAULT_CC;
                    691:        if ((pathname = findcc(CC)) == NULL)
1.56      rillig    692:                if (setenv("PATH", DEFAULT_PATH, 1) == 0)
1.28      simonb    693:                        pathname = findcc(CC);
                    694:        if (pathname == NULL) {
                    695:                (void)fprintf(stderr, "%s: %s: not found\n", getprogname(), CC);
                    696:                exit(EXIT_FAILURE);
1.17      garbled   697:        }
1.1       cgd       698:
1.28      simonb    699:        appcstrg(&args, pathname);
1.10      mrg       700:        applst(&args, cflags);
                    701:        applst(&args, lcflags);
1.3       jpo       702:        appcstrg(&args, name);
1.1       cgd       703:
1.15      jwise     704:        /* we reuse the same tmp file for cpp output, so rewind and truncate */
1.44      njoly     705:        if (lseek(cppoutfd, (off_t)0, SEEK_SET) != 0) {
1.15      jwise     706:                warn("lseek");
                    707:                terminate(-1);
                    708:        }
                    709:        if (ftruncate(cppoutfd, (off_t)0) != 0) {
                    710:                warn("ftruncate");
                    711:                terminate(-1);
                    712:        }
1.23      lukem     713:
1.28      simonb    714:        runchild(pathname, args, cppout, cppoutfd);
                    715:        free(pathname);
1.1       cgd       716:        freelst(&args);
                    717:
                    718:        /* run lint1 */
                    719:
1.17      garbled   720:        if (!Bflag) {
1.58      rillig    721:                pathname = xmalloc(strlen(PATH_LIBEXEC) + sizeof("/lint1") +
1.24      thorpej   722:                    strlen(target_prefix));
1.28      simonb    723:                (void)sprintf(pathname, "%s/%slint1", PATH_LIBEXEC,
1.24      thorpej   724:                    target_prefix);
1.17      garbled   725:        } else {
1.24      thorpej   726:                /*
                    727:                 * XXX Unclear whether we should be using target_prefix
                    728:                 * XXX here.  --thorpej@wasabisystems.com
                    729:                 */
1.58      rillig    730:                pathname = xmalloc(strlen(libexec_path) + sizeof("/lint1"));
1.28      simonb    731:                (void)sprintf(pathname, "%s/lint1", libexec_path);
1.17      garbled   732:        }
1.1       cgd       733:
1.28      simonb    734:        appcstrg(&args, pathname);
1.1       cgd       735:        applst(&args, l1flags);
1.3       jpo       736:        appcstrg(&args, cppout);
                    737:        appcstrg(&args, ofn);
1.1       cgd       738:
1.28      simonb    739:        runchild(pathname, args, ofn, -1);
                    740:        free(pathname);
1.1       cgd       741:        freelst(&args);
                    742:
1.3       jpo       743:        appcstrg(&p2in, ofn);
1.1       cgd       744:        free(ofn);
                    745:
                    746:        free(args);
                    747: }
                    748:
                    749: static void
1.23      lukem     750: runchild(const char *path, char *const *args, const char *crfn, int fdout)
1.1       cgd       751: {
                    752:        int     status, rv, signo, i;
                    753:
                    754:        if (Vflag) {
                    755:                for (i = 0; args[i] != NULL; i++)
                    756:                        (void)printf("%s ", args[i]);
                    757:                (void)printf("\n");
                    758:        }
                    759:
                    760:        currfn = crfn;
                    761:
                    762:        (void)fflush(stdout);
                    763:
1.15      jwise     764:        switch (vfork()) {
1.1       cgd       765:        case -1:
                    766:                warn("cannot fork");
                    767:                terminate(-1);
                    768:                /* NOTREACHED */
                    769:        default:
                    770:                /* parent */
                    771:                break;
                    772:        case 0:
                    773:                /* child */
1.10      mrg       774:
                    775:                /* setup the standard output if necessary */
                    776:                if (fdout != -1) {
                    777:                        dup2(fdout, STDOUT_FILENO);
                    778:                        close(fdout);
                    779:                }
1.19      wrstuden  780:                (void)execvp(path, args);
1.1       cgd       781:                warn("cannot exec %s", path);
1.15      jwise     782:                _exit(1);
1.1       cgd       783:                /* NOTREACHED */
                    784:        }
                    785:
                    786:        while ((rv = wait(&status)) == -1 && errno == EINTR) ;
                    787:        if (rv == -1) {
                    788:                warn("wait");
                    789:                terminate(-1);
                    790:        }
                    791:        if (WIFSIGNALED(status)) {
                    792:                signo = WTERMSIG(status);
1.25      tv        793: #if HAVE_DECL_SYS_SIGNAME
1.1       cgd       794:                warnx("%s got SIG%s", path, sys_signame[signo]);
1.25      tv        795: #else
                    796:                warnx("%s got signal %d", path, signo);
                    797: #endif
1.1       cgd       798:                terminate(-1);
                    799:        }
                    800:        if (WEXITSTATUS(status) != 0)
                    801:                terminate(-1);
                    802:        currfn = NULL;
                    803: }
                    804:
                    805: static void
1.23      lukem     806: findlibs(char *const *liblst)
1.1       cgd       807: {
                    808:        int     i, k;
                    809:        const   char *lib, *path;
                    810:        char    *lfn;
                    811:        size_t  len;
                    812:
                    813:        lfn = NULL;
                    814:
                    815:        for (i = 0; (lib = liblst[i]) != NULL; i++) {
                    816:                for (k = 0; (path = libsrchpath[k]) != NULL; k++) {
                    817:                        len = strlen(path) + strlen(lib);
1.58      rillig    818:                        lfn = xrealloc(lfn, len + sizeof("/llib-l.ln"));
1.1       cgd       819:                        (void)sprintf(lfn, "%s/llib-l%s.ln", path, lib);
                    820:                        if (rdok(lfn))
                    821:                                break;
1.58      rillig    822:                        lfn = xrealloc(lfn, len + sizeof("/lint/llib-l.ln"));
1.1       cgd       823:                        (void)sprintf(lfn, "%s/lint/llib-l%s.ln", path, lib);
                    824:                        if (rdok(lfn))
                    825:                                break;
                    826:                }
                    827:                if (path != NULL) {
1.3       jpo       828:                        appstrg(&l2libs, concat2("-l", lfn));
1.1       cgd       829:                } else {
                    830:                        warnx("cannot find llib-l%s.ln", lib);
                    831:                }
                    832:        }
                    833:
                    834:        free(lfn);
                    835: }
                    836:
1.56      rillig    837: static bool
1.23      lukem     838: rdok(const char *path)
1.1       cgd       839: {
                    840:        struct  stat sbuf;
                    841:
                    842:        if (stat(path, &sbuf) == -1)
1.56      rillig    843:                return false;
1.5       mycroft   844:        if (!S_ISREG(sbuf.st_mode))
1.56      rillig    845:                return false;
1.1       cgd       846:        if (access(path, R_OK) == -1)
1.56      rillig    847:                return false;
                    848:        return true;
1.1       cgd       849: }
                    850:
                    851: static void
1.23      lukem     852: lint2(void)
1.1       cgd       853: {
                    854:        char    *path, **args;
                    855:
1.58      rillig    856:        args = xcalloc(1, sizeof(*args));
1.1       cgd       857:
1.17      garbled   858:        if (!Bflag) {
1.58      rillig    859:                path = xmalloc(strlen(PATH_LIBEXEC) + sizeof("/lint2") +
1.24      thorpej   860:                    strlen(target_prefix));
                    861:                (void)sprintf(path, "%s/%slint2", PATH_LIBEXEC,
                    862:                    target_prefix);
1.17      garbled   863:        } else {
1.24      thorpej   864:                /*
                    865:                 * XXX Unclear whether we should be using target_prefix
                    866:                 * XXX here.  --thorpej@wasabisystems.com
                    867:                 */
1.58      rillig    868:                path = xmalloc(strlen(libexec_path) + sizeof("/lint2"));
1.17      garbled   869:                (void)sprintf(path, "%s/lint2", libexec_path);
1.23      lukem     870:        }
                    871:
1.3       jpo       872:        appcstrg(&args, path);
1.1       cgd       873:        applst(&args, l2flags);
                    874:        applst(&args, l2libs);
                    875:        applst(&args, p2in);
                    876:
1.10      mrg       877:        runchild(path, args, p2out, -1);
1.1       cgd       878:        free(path);
                    879:        freelst(&args);
                    880:        free(args);
                    881: }
                    882:
                    883: static void
1.23      lukem     884: cat(char *const *srcs, const char *dest)
1.1       cgd       885: {
                    886:        int     ifd, ofd, i;
                    887:        char    *src, *buf;
                    888:        ssize_t rlen;
                    889:
                    890:        if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
                    891:                warn("cannot open %s", dest);
                    892:                terminate(-1);
                    893:        }
                    894:
                    895:        buf = xmalloc(MBLKSIZ);
                    896:
                    897:        for (i = 0; (src = srcs[i]) != NULL; i++) {
                    898:                if ((ifd = open(src, O_RDONLY)) == -1) {
                    899:                        free(buf);
                    900:                        warn("cannot open %s", src);
                    901:                        terminate(-1);
                    902:                }
                    903:                do {
                    904:                        if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) {
                    905:                                free(buf);
                    906:                                warn("read error on %s", src);
                    907:                                terminate(-1);
                    908:                        }
                    909:                        if (write(ofd, buf, (size_t)rlen) == -1) {
                    910:                                free(buf);
                    911:                                warn("write error on %s", dest);
                    912:                                terminate(-1);
                    913:                        }
                    914:                } while (rlen == MBLKSIZ);
                    915:                (void)close(ifd);
                    916:        }
                    917:        (void)close(ofd);
                    918:        free(buf);
                    919: }

CVSweb <webmaster@jp.NetBSD.org>