[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.81

1.81    ! rillig      1: /* $NetBSD: xlint.c,v 1.80 2021/08/28 14:42:29 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.81    ! rillig     41: __RCSID("$NetBSD: xlint.c,v 1.80 2021/08/28 14:42:29 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:
1.71      rillig     64: /* Parameters for the C preprocessor. */
                     65: static struct {
                     66:        char    **flags;        /* flags always passed */
                     67:        char    **lcflags;      /* flags, controlled by sflag/tflag */
                     68:        char    *outfile;       /* path name for preprocessed C source */
                     69:        int     outfd;          /* file descriptor for outfile */
                     70: } cpp = { NULL, NULL, NULL, -1 };
                     71:
                     72: /* Parameters for lint1, which checks an isolated translation unit. */
                     73: static struct {
                     74:        char    **flags;
                     75:        char    **outfiles;
                     76: } lint1;
                     77:
                     78: /* Parameters for lint2, which performs cross-translation-unit checks. */
                     79: static struct {
                     80:        char    **flags;
                     81:        char    **infiles;      /* input files (without libraries) */
                     82:        char    **inlibs;       /* input libraries */
                     83:        char    *outlib;        /* output library that will be created */
                     84: } lint2;
                     85:
1.1       cgd        86: /* directory for temporary files */
1.71      rillig     87: static const char *tmpdir;
1.1       cgd        88:
                     89: /* default libraries */
                     90: static char    **deflibs;
                     91:
                     92: /* additional libraries */
                     93: static char    **libs;
                     94:
                     95: /* search path for libraries */
                     96: static char    **libsrchpath;
                     97:
1.77      rillig     98: static const char *libexec_dir;
1.17      garbled    99:
1.1       cgd       100: /* flags */
1.77      rillig    101: static bool    iflag, oflag, Cflag, sflag, tflag, Fflag, dflag;
1.1       cgd       102:
                    103: /* print the commands executed to run the stages of compilation */
1.56      rillig    104: static bool    Vflag;
1.1       cgd       105:
                    106: /* filename for oflag */
                    107: static char    *outputfn;
                    108:
                    109: /* reset after first .c source has been processed */
1.54      rillig    110: static bool    first = true;
1.1       cgd       111:
                    112: /*
                    113:  * name of a file which is currently written by a child and should
                    114:  * be removed after abnormal termination of the child
                    115:  */
                    116: static const   char *currfn;
                    117:
1.24      thorpej   118: #if !defined(TARGET_PREFIX)
                    119: #define        TARGET_PREFIX   ""
                    120: #endif
                    121: static const char target_prefix[] = TARGET_PREFIX;
1.1       cgd       122:
1.23      lukem     123: static char    *concat2(const char *, const char *);
                    124: static void    terminate(int) __attribute__((__noreturn__));
1.25      tv        125: static const   char *lbasename(const char *, int);
1.23      lukem     126: static void    usage(void);
1.27      tv        127: static void    fname(const char *);
1.23      lukem     128: static void    runchild(const char *, char *const *, const char *, int);
                    129: static void    findlibs(char *const *);
1.56      rillig    130: static bool    rdok(const char *);
1.71      rillig    131: static void    run_lint2(void);
1.23      lukem     132: static void    cat(char *const *, const char *);
1.1       cgd       133:
1.67      rillig    134: static char **
                    135: list_new(void)
                    136: {
                    137:        char **list;
                    138:
                    139:        list = xcalloc(1, sizeof(*list));
                    140:        return list;
                    141: }
                    142:
1.1       cgd       143: static void
1.67      rillig    144: list_add(char ***lstp, char *s)
1.1       cgd       145: {
                    146:        char    **lst, **olst;
                    147:        int     i;
                    148:
                    149:        olst = *lstp;
1.23      lukem     150:        for (i = 0; olst[i] != NULL; i++)
                    151:                continue;
1.58      rillig    152:        lst = xrealloc(olst, (i + 2) * sizeof(*lst));
1.3       jpo       153:        lst[i] = s;
1.1       cgd       154:        lst[i + 1] = NULL;
                    155:        *lstp = lst;
1.23      lukem     156: }
1.1       cgd       157:
                    158: static void
1.67      rillig    159: list_add_copy(char ***lstp, const char *s)
1.1       cgd       160: {
1.23      lukem     161:
1.67      rillig    162:        list_add(lstp, xstrdup(s));
1.1       cgd       163: }
                    164:
                    165: static void
1.67      rillig    166: list_add_all(char ***destp, char *const *src)
1.1       cgd       167: {
                    168:        int     i, k;
                    169:        char    **dest, **odest;
                    170:
                    171:        odest = *destp;
1.23      lukem     172:        for (i = 0; odest[i] != NULL; i++)
                    173:                continue;
                    174:        for (k = 0; src[k] != NULL; k++)
                    175:                continue;
1.58      rillig    176:        dest = xrealloc(odest, (i + k + 1) * sizeof(*dest));
1.1       cgd       177:        for (k = 0; src[k] != NULL; k++)
                    178:                dest[i + k] = xstrdup(src[k]);
                    179:        dest[i + k] = NULL;
                    180:        *destp = dest;
                    181: }
                    182:
                    183: static void
1.70      rillig    184: list_clear(char ***lstp)
1.1       cgd       185: {
                    186:        char    *s;
                    187:        int     i;
                    188:
1.23      lukem     189:        for (i = 0; (*lstp)[i] != NULL; i++)
                    190:                continue;
1.1       cgd       191:        while (i-- > 0) {
                    192:                s = (*lstp)[i];
                    193:                (*lstp)[i] = NULL;
                    194:                free(s);
                    195:        }
                    196: }
                    197:
1.61      rillig    198: static void
                    199: pass_to_lint1(const char *opt)
                    200: {
                    201:
1.71      rillig    202:        list_add_copy(&lint1.flags, opt);
1.61      rillig    203: }
                    204:
                    205: static void
1.73      rillig    206: pass_flag_to_lint1(int flag)
                    207: {
                    208:        char buf[3];
                    209:
                    210:        buf[0] = '-';
                    211:        buf[1] = (char)flag;
                    212:        buf[2] = '\0';
                    213:        pass_to_lint1(buf);
                    214: }
                    215:
                    216: static void
1.61      rillig    217: pass_to_lint2(const char *opt)
                    218: {
                    219:
1.71      rillig    220:        list_add_copy(&lint2.flags, opt);
1.61      rillig    221: }
                    222:
                    223: static void
1.73      rillig    224: pass_flag_to_lint2(int flag)
                    225: {
                    226:        char buf[3];
                    227:
                    228:        buf[0] = '-';
                    229:        buf[1] = (char)flag;
                    230:        buf[2] = '\0';
                    231:        pass_to_lint2(buf);
                    232: }
                    233:
                    234: static void
1.61      rillig    235: pass_to_cpp(const char *opt)
                    236: {
                    237:
1.71      rillig    238:        list_add_copy(&cpp.flags, opt);
1.61      rillig    239: }
                    240:
1.3       jpo       241: static char *
1.23      lukem     242: concat2(const char *s1, const char *s2)
1.3       jpo       243: {
                    244:        char    *s;
                    245:
                    246:        s = xmalloc(strlen(s1) + strlen(s2) + 1);
                    247:        (void)strcpy(s, s1);
                    248:        (void)strcat(s, s2);
                    249:
1.51      rillig    250:        return s;
1.3       jpo       251: }
                    252:
1.1       cgd       253: /*
                    254:  * Clean up after a signal.
                    255:  */
                    256: static void
1.23      lukem     257: terminate(int signo)
1.1       cgd       258: {
                    259:        int     i;
                    260:
1.71      rillig    261:        if (cpp.outfd != -1)
                    262:                (void)close(cpp.outfd);
                    263:        if (cpp.outfile != NULL) {
1.63      rillig    264:                if (signo != 0 && getenv("LINT_KEEP_CPPOUT_ON_ERROR") != NULL)
                    265:                        printf("lint: preprocessor output kept in %s\n",
1.71      rillig    266:                            cpp.outfile);
1.63      rillig    267:                else
1.71      rillig    268:                        (void)remove(cpp.outfile);
1.63      rillig    269:        }
1.1       cgd       270:
1.71      rillig    271:        if (lint1.outfiles != NULL) {
                    272:                for (i = 0; lint1.outfiles[i] != NULL; i++)
                    273:                        (void)remove(lint1.outfiles[i]);
1.1       cgd       274:        }
                    275:
1.71      rillig    276:        if (lint2.outlib != NULL)
                    277:                (void)remove(lint2.outlib);
1.1       cgd       278:
                    279:        if (currfn != NULL)
                    280:                (void)remove(currfn);
                    281:
1.38      lukem     282:        if (signo != 0)
                    283:                (void)raise_default_signal(signo);
1.1       cgd       284:        exit(signo != 0 ? 1 : 0);
                    285: }
                    286:
                    287: /*
                    288:  * Returns a pointer to the last component of strg after delim.
                    289:  * Returns strg if the string does not contain delim.
                    290:  */
                    291: static const char *
1.25      tv        292: lbasename(const char *strg, int delim)
1.1       cgd       293: {
                    294:        const   char *cp, *cp1, *cp2;
                    295:
                    296:        cp = cp1 = cp2 = strg;
                    297:        while (*cp != '\0') {
                    298:                if (*cp++ == delim) {
                    299:                        cp2 = cp1;
                    300:                        cp1 = cp;
                    301:                }
                    302:        }
1.51      rillig    303:        return *cp1 == '\0' ? cp2 : cp1;
1.1       cgd       304: }
                    305:
1.62      rillig    306: static void __attribute__((noreturn))
1.23      lukem     307: usage(void)
1.1       cgd       308: {
1.59      rillig    309:        const char *name;
                    310:        int indent;
1.22      cgd       311:
1.59      rillig    312:        name = getprogname();
                    313:        indent = (int)(strlen("usage: ") + strlen(name));
1.12      christos  314:        (void)fprintf(stderr,
1.59      rillig    315:            "usage: %s [-abceghprvwxzHFST] [-s|-t] [-i|-nu]\n"
                    316:            "%*s [-Dname[=def]] [-Uname] [-Idirectory] [-Z <cpparg>]\n"
                    317:            "%*s [-Ldirectory] [-llibrary] [-ooutputfile]\n"
1.60      rillig    318:            "%*s [-X <id>[,<id>]...] [-Ac11] file...\n",
1.59      rillig    319:            name, indent, "", indent, "", indent, "");
1.23      lukem     320:        (void)fprintf(stderr,
1.59      rillig    321:            "       %s [-abceghprvwzHFST] [-s|-t] -Clibrary\n"
                    322:            "%*s [-Dname[=def]] [-Uname] [-Idirectory] [-Z <cpparg>]\n"
                    323:            "%*s [-Bpath] [-X <id>[,<id>]...] [-R old=new] file ...\n",
                    324:            name, indent, "", indent, "");
1.1       cgd       325:        terminate(-1);
                    326: }
1.6       christos  327:
1.1       cgd       328:
                    329: int
1.23      lukem     330: main(int argc, char *argv[])
1.1       cgd       331: {
                    332:        int     c;
1.73      rillig    333:        char    *tmp;
1.1       cgd       334:        size_t  len;
1.41      lukem     335:        const char *ks;
1.1       cgd       336:
1.27      tv        337:        setprogname(argv[0]);
                    338:
1.1       cgd       339:        if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) {
                    340:                tmpdir = xstrdup(_PATH_TMP);
                    341:        } else {
1.65      rillig    342:                tmpdir = concat2(tmp, tmp[len - 1] == '/' ? "" : "/");
1.1       cgd       343:        }
                    344:
1.71      rillig    345:        cpp.outfile = concat2(tmpdir, "lint0.XXXXXX");
                    346:        cpp.outfd = mkstemp(cpp.outfile);
                    347:        if (cpp.outfd == -1) {
1.1       cgd       348:                warn("can't make temp");
                    349:                terminate(-1);
                    350:        }
                    351:
1.71      rillig    352:        lint1.outfiles = list_new();
                    353:        lint2.infiles = list_new();
                    354:        cpp.flags = list_new();
                    355:        cpp.lcflags = list_new();
                    356:        lint1.flags = list_new();
                    357:        lint2.flags = list_new();
                    358:        lint2.inlibs = list_new();
1.67      rillig    359:        deflibs = list_new();
                    360:        libs = list_new();
                    361:        libsrchpath = list_new();
1.1       cgd       362:
1.61      rillig    363:        pass_to_cpp("-E");
                    364:        pass_to_cpp("-x");
                    365:        pass_to_cpp("c");
                    366:        pass_to_cpp("-U__GNUC__");
                    367:        pass_to_cpp("-U__PCC__");
                    368:        pass_to_cpp("-U__SSE__");
                    369:        pass_to_cpp("-U__SSE4_1__");
                    370:        pass_to_cpp("-Wp,-CC");
                    371:        pass_to_cpp("-Wcomment");
                    372:        pass_to_cpp("-D__LINT__");
                    373:        pass_to_cpp("-Dlint");          /* XXX don't def. with -s */
1.68      rillig    374:        pass_to_cpp("-D__lint");
                    375:        pass_to_cpp("-D__lint__");
1.10      mrg       376:
1.67      rillig    377:        list_add_copy(&deflibs, "c");
1.1       cgd       378:
                    379:        if (signal(SIGHUP, terminate) == SIG_IGN)
                    380:                (void)signal(SIGHUP, SIG_IGN);
                    381:        (void)signal(SIGINT, terminate);
                    382:        (void)signal(SIGQUIT, terminate);
                    383:        (void)signal(SIGTERM, terminate);
1.53      rillig    384:        while ((c = getopt(argc, argv,
1.60      rillig    385:            "abcd:eghil:no:prstuvwxzA:B:C:D:FHI:L:M:PR:STU:VX:Z:")) != -1) {
1.1       cgd       386:                switch (c) {
                    387:
                    388:                case 'a':
                    389:                case 'b':
                    390:                case 'c':
                    391:                case 'e':
                    392:                case 'g':
                    393:                case 'r':
                    394:                case 'v':
1.20      christos  395:                case 'w':
1.1       cgd       396:                case 'z':
1.74      rillig    397:                case 'P':
1.73      rillig    398:                        pass_flag_to_lint1(c);
1.1       cgd       399:                        break;
                    400:
1.60      rillig    401:                case 'A':
1.74      rillig    402:                case 'R':
                    403:                case 'X':
1.73      rillig    404:                        pass_flag_to_lint1(c);
1.61      rillig    405:                        pass_to_lint1(optarg);
1.60      rillig    406:                        break;
                    407:
1.1       cgd       408:                case 'F':
1.54      rillig    409:                        Fflag = true;
1.1       cgd       410:                        /* FALLTHROUGH */
                    411:                case 'u':
                    412:                case 'h':
1.73      rillig    413:                        pass_flag_to_lint1(c);
                    414:                        pass_flag_to_lint2(c);
1.20      christos  415:                        break;
                    416:
1.1       cgd       417:                case 'i':
                    418:                        if (Cflag)
                    419:                                usage();
1.54      rillig    420:                        iflag = true;
1.1       cgd       421:                        break;
                    422:
                    423:                case 'n':
1.70      rillig    424:                        list_clear(&deflibs);
1.1       cgd       425:                        break;
                    426:
                    427:                case 'p':
                    428:                        if (*deflibs != NULL) {
1.70      rillig    429:                                list_clear(&deflibs);
1.67      rillig    430:                                list_add_copy(&deflibs, "c");
1.1       cgd       431:                        }
1.73      rillig    432:                        pass_flag_to_lint1(c);
1.74      rillig    433:                        pass_flag_to_lint2(c);
1.46      christos  434:                        break;
                    435:
1.1       cgd       436:                case 's':
                    437:                        if (tflag)
                    438:                                usage();
1.71      rillig    439:                        list_clear(&cpp.lcflags);
                    440:                        list_add_copy(&cpp.lcflags, "-trigraphs");
                    441:                        list_add_copy(&cpp.lcflags, "-Wtrigraphs");
                    442:                        list_add_copy(&cpp.lcflags, "-pedantic");
                    443:                        list_add_copy(&cpp.lcflags, "-D__STRICT_ANSI__");
1.74      rillig    444:                        sflag = true;
1.73      rillig    445:                        pass_flag_to_lint1(c);
                    446:                        pass_flag_to_lint2(c);
1.30      christos  447:                        break;
                    448:
                    449:                case 'S':
                    450:                        if (tflag)
                    451:                                usage();
1.73      rillig    452:                        pass_flag_to_lint1(c);
1.1       cgd       453:                        break;
                    454:
1.55      rillig    455:                case 'T':
1.61      rillig    456:                        pass_to_cpp("-I" PATH_STRICT_BOOL_INCLUDE);
1.73      rillig    457:                        pass_flag_to_lint1(c);
                    458:                        pass_flag_to_lint2(c);
1.55      rillig    459:                        break;
                    460:
1.71      rillig    461: #if !HAVE_NBTOOL_CONFIG_H
1.1       cgd       462:                case 't':
                    463:                        if (sflag)
                    464:                                usage();
1.74      rillig    465:                        tflag = true;
1.71      rillig    466:                        list_clear(&cpp.lcflags);
                    467:                        list_add_copy(&cpp.lcflags, "-traditional");
                    468:                        list_add_copy(&cpp.lcflags, "-Wtraditional");
                    469:                        list_add_copy(&cpp.lcflags, "-D" MACHINE);
                    470:                        list_add_copy(&cpp.lcflags, "-D" MACHINE_ARCH);
1.73      rillig    471:                        pass_flag_to_lint1(c);
                    472:                        pass_flag_to_lint2(c);
1.1       cgd       473:                        break;
1.25      tv        474: #endif
1.1       cgd       475:
                    476:                case 'x':
1.74      rillig    477:                case 'H':
1.73      rillig    478:                        pass_flag_to_lint2(c);
1.1       cgd       479:                        break;
                    480:
                    481:                case 'C':
                    482:                        if (Cflag || oflag || iflag)
                    483:                                usage();
1.54      rillig    484:                        Cflag = true;
1.73      rillig    485:                        pass_flag_to_lint2(c);
                    486:                        pass_to_lint2(optarg);
1.71      rillig    487:                        lint2.outlib = xasprintf("llib-l%s.ln", optarg);
1.70      rillig    488:                        list_clear(&deflibs);
1.1       cgd       489:                        break;
                    490:
1.7       sommerfe  491:                case 'd':
                    492:                        if (dflag)
                    493:                                usage();
1.54      rillig    494:                        dflag = true;
1.61      rillig    495:                        pass_to_cpp("-nostdinc");
                    496:                        pass_to_cpp("-isystem");
                    497:                        pass_to_cpp(optarg);
1.7       sommerfe  498:                        break;
1.23      lukem     499:
1.1       cgd       500:                case 'D':
                    501:                case 'I':
1.34      dsl       502:                case 'M':
1.1       cgd       503:                case 'U':
1.71      rillig    504:                        list_add(&cpp.flags, xasprintf("-%c%s", c, optarg));
1.1       cgd       505:                        break;
                    506:
                    507:                case 'l':
1.67      rillig    508:                        list_add_copy(&libs, optarg);
1.1       cgd       509:                        break;
                    510:
                    511:                case 'o':
                    512:                        if (Cflag || oflag)
                    513:                                usage();
1.54      rillig    514:                        oflag = true;
1.1       cgd       515:                        outputfn = xstrdup(optarg);
                    516:                        break;
                    517:
                    518:                case 'L':
1.67      rillig    519:                        list_add_copy(&libsrchpath, optarg);
1.1       cgd       520:                        break;
                    521:
1.17      garbled   522:                case 'B':
1.77      rillig    523:                        libexec_dir = xstrdup(optarg);
1.17      garbled   524:                        break;
                    525:
1.1       cgd       526:                case 'V':
1.54      rillig    527:                        Vflag = true;
1.1       cgd       528:                        break;
                    529:
1.50      christos  530:                case 'Z':
1.61      rillig    531:                        pass_to_cpp(optarg);
1.50      christos  532:                        break;
                    533:
1.25      tv        534:                default:
                    535:                        usage();
                    536:                        /* NOTREACHED */
1.1       cgd       537:                }
                    538:        }
1.21      wiz       539:        argc -= optind;
                    540:        argv += optind;
1.1       cgd       541:
1.27      tv        542:        /*
                    543:         * To avoid modifying getopt(3)'s state engine midstream, we
                    544:         * explicitly accept just a few options after the first source file.
                    545:         *
                    546:         * In particular, only -l<lib> and -L<libdir> (and these with a space
                    547:         * after -l or -L) are allowed.
                    548:         */
                    549:        while (argc > 0) {
                    550:                const char *arg = argv[0];
                    551:
                    552:                if (arg[0] == '-') {
                    553:                        char ***list;
                    554:
                    555:                        /* option */
1.75      rillig    556:                        if (arg[1] == 'l')
1.27      tv        557:                                list = &libs;
1.75      rillig    558:                        else if (arg[1] == 'L')
1.27      tv        559:                                list = &libsrchpath;
1.75      rillig    560:                        else {
1.27      tv        561:                                usage();
                    562:                                /* NOTREACHED */
                    563:                        }
1.75      rillig    564:
1.56      rillig    565:                        if (arg[2] != '\0')
1.67      rillig    566:                                list_add_copy(list, arg + 2);
1.27      tv        567:                        else if (argc > 1) {
                    568:                                argc--;
1.67      rillig    569:                                list_add_copy(list, *++argv);
1.27      tv        570:                        } else
                    571:                                usage();
                    572:                } else {
                    573:                        /* filename */
                    574:                        fname(arg);
1.54      rillig    575:                        first = false;
1.27      tv        576:                }
                    577:                argc--;
                    578:                argv++;
                    579:        }
                    580:
1.1       cgd       581:        if (first)
                    582:                usage();
                    583:
                    584:        if (iflag)
                    585:                terminate(0);
                    586:
                    587:        if (!oflag) {
1.41      lukem     588:                if ((ks = getenv("LIBDIR")) == NULL || strlen(ks) == 0)
                    589:                        ks = PATH_LINTLIB;
1.67      rillig    590:                list_add_copy(&libsrchpath, ks);
1.1       cgd       591:                findlibs(libs);
                    592:                findlibs(deflibs);
                    593:        }
                    594:
                    595:        (void)printf("Lint pass2:\n");
1.71      rillig    596:        run_lint2();
1.1       cgd       597:
                    598:        if (oflag)
1.71      rillig    599:                cat(lint2.infiles, outputfn);
1.1       cgd       600:
                    601:        if (Cflag)
1.71      rillig    602:                lint2.outlib = NULL;
1.1       cgd       603:
                    604:        terminate(0);
                    605:        /* NOTREACHED */
                    606: }
                    607:
                    608: /*
                    609:  * Read a file name from the command line
                    610:  * and pass it through lint1 if it is a C source.
                    611:  */
                    612: static void
1.27      tv        613: fname(const char *name)
1.1       cgd       614: {
                    615:        const   char *bn, *suff;
1.41      lukem     616:        char    **args, *ofn, *pathname;
1.79      rillig    617:        const char *CC;
1.49      christos  618:        size_t  len;
1.10      mrg       619:        int     fd;
1.1       cgd       620:
1.25      tv        621:        bn = lbasename(name, '/');
                    622:        suff = lbasename(bn, '.');
1.1       cgd       623:
                    624:        if (strcmp(suff, "ln") == 0) {
                    625:                /* only for lint2 */
                    626:                if (!iflag)
1.71      rillig    627:                        list_add_copy(&lint2.infiles, name);
1.1       cgd       628:                return;
                    629:        }
                    630:
1.69      rillig    631:        if (strcmp(suff, "c") != 0 &&
1.1       cgd       632:            (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) {
1.29      grant     633:                warnx("unknown file type: %s", name);
1.1       cgd       634:                return;
                    635:        }
                    636:
1.27      tv        637:        if (!iflag || !first)
1.69      rillig    638:                (void)printf("%s:\n", Fflag ? name : bn);
1.1       cgd       639:
                    640:        /* build the name of the output file of lint1 */
                    641:        if (oflag) {
                    642:                ofn = outputfn;
                    643:                outputfn = NULL;
1.54      rillig    644:                oflag = false;
1.1       cgd       645:        } else if (iflag) {
1.42      christos  646:                len = bn == suff ? strlen(bn) : (size_t)((suff - 1) - bn);
1.64      rillig    647:                ofn = xasprintf("%.*s.ln", (int)len, bn);
1.1       cgd       648:        } else {
1.64      rillig    649:                ofn = xasprintf("%slint1.XXXXXX", tmpdir);
1.10      mrg       650:                fd = mkstemp(ofn);
                    651:                if (fd == -1) {
1.1       cgd       652:                        warn("can't make temp");
                    653:                        terminate(-1);
                    654:                }
1.80      rillig    655:                (void)close(fd);
1.1       cgd       656:        }
                    657:        if (!iflag)
1.71      rillig    658:                list_add_copy(&lint1.outfiles, ofn);
1.1       cgd       659:
1.67      rillig    660:        args = list_new();
1.1       cgd       661:
1.10      mrg       662:        /* run cc */
1.28      simonb    663:        if ((CC = getenv("CC")) == NULL)
1.79      rillig    664:                CC = DEFAULT_CC;
1.28      simonb    665:        if ((pathname = findcc(CC)) == NULL)
1.56      rillig    666:                if (setenv("PATH", DEFAULT_PATH, 1) == 0)
1.28      simonb    667:                        pathname = findcc(CC);
                    668:        if (pathname == NULL) {
                    669:                (void)fprintf(stderr, "%s: %s: not found\n", getprogname(), CC);
                    670:                exit(EXIT_FAILURE);
1.17      garbled   671:        }
1.1       cgd       672:
1.67      rillig    673:        list_add_copy(&args, pathname);
1.71      rillig    674:        list_add_all(&args, cpp.flags);
                    675:        list_add_all(&args, cpp.lcflags);
1.67      rillig    676:        list_add_copy(&args, name);
1.1       cgd       677:
1.15      jwise     678:        /* we reuse the same tmp file for cpp output, so rewind and truncate */
1.71      rillig    679:        if (lseek(cpp.outfd, (off_t)0, SEEK_SET) != 0) {
1.15      jwise     680:                warn("lseek");
                    681:                terminate(-1);
                    682:        }
1.71      rillig    683:        if (ftruncate(cpp.outfd, (off_t)0) != 0) {
1.15      jwise     684:                warn("ftruncate");
                    685:                terminate(-1);
                    686:        }
1.23      lukem     687:
1.71      rillig    688:        runchild(pathname, args, cpp.outfile, cpp.outfd);
1.28      simonb    689:        free(pathname);
1.70      rillig    690:        list_clear(&args);
1.1       cgd       691:
                    692:        /* run lint1 */
                    693:
1.77      rillig    694:        if (libexec_dir == NULL) {
1.65      rillig    695:                pathname = xasprintf("%s/%slint1",
                    696:                    PATH_LIBEXEC, target_prefix);
1.17      garbled   697:        } else {
1.24      thorpej   698:                /*
                    699:                 * XXX Unclear whether we should be using target_prefix
                    700:                 * XXX here.  --thorpej@wasabisystems.com
                    701:                 */
1.77      rillig    702:                pathname = concat2(libexec_dir, "/lint1");
1.17      garbled   703:        }
1.1       cgd       704:
1.67      rillig    705:        list_add_copy(&args, pathname);
1.71      rillig    706:        list_add_all(&args, lint1.flags);
                    707:        list_add_copy(&args, cpp.outfile);
1.67      rillig    708:        list_add_copy(&args, ofn);
1.1       cgd       709:
1.28      simonb    710:        runchild(pathname, args, ofn, -1);
                    711:        free(pathname);
1.70      rillig    712:        list_clear(&args);
1.1       cgd       713:
1.71      rillig    714:        list_add_copy(&lint2.infiles, ofn);
1.1       cgd       715:        free(ofn);
                    716:
                    717:        free(args);
                    718: }
                    719:
                    720: static void
1.23      lukem     721: runchild(const char *path, char *const *args, const char *crfn, int fdout)
1.1       cgd       722: {
                    723:        int     status, rv, signo, i;
                    724:
                    725:        if (Vflag) {
                    726:                for (i = 0; args[i] != NULL; i++)
                    727:                        (void)printf("%s ", args[i]);
                    728:                (void)printf("\n");
                    729:        }
                    730:
                    731:        currfn = crfn;
                    732:
                    733:        (void)fflush(stdout);
                    734:
1.15      jwise     735:        switch (vfork()) {
1.1       cgd       736:        case -1:
                    737:                warn("cannot fork");
                    738:                terminate(-1);
                    739:                /* NOTREACHED */
                    740:        default:
                    741:                /* parent */
                    742:                break;
                    743:        case 0:
                    744:                /* child */
1.10      mrg       745:
                    746:                /* setup the standard output if necessary */
                    747:                if (fdout != -1) {
1.81    ! rillig    748:                        (void)dup2(fdout, STDOUT_FILENO);
1.80      rillig    749:                        (void)close(fdout);
1.10      mrg       750:                }
1.19      wrstuden  751:                (void)execvp(path, args);
1.1       cgd       752:                warn("cannot exec %s", path);
1.15      jwise     753:                _exit(1);
1.1       cgd       754:                /* NOTREACHED */
                    755:        }
                    756:
                    757:        while ((rv = wait(&status)) == -1 && errno == EINTR) ;
                    758:        if (rv == -1) {
                    759:                warn("wait");
                    760:                terminate(-1);
                    761:        }
                    762:        if (WIFSIGNALED(status)) {
                    763:                signo = WTERMSIG(status);
1.25      tv        764: #if HAVE_DECL_SYS_SIGNAME
1.1       cgd       765:                warnx("%s got SIG%s", path, sys_signame[signo]);
1.25      tv        766: #else
                    767:                warnx("%s got signal %d", path, signo);
                    768: #endif
1.1       cgd       769:                terminate(-1);
                    770:        }
                    771:        if (WEXITSTATUS(status) != 0)
                    772:                terminate(-1);
                    773:        currfn = NULL;
                    774: }
                    775:
                    776: static void
1.66      rillig    777: findlib(const char *lib)
1.1       cgd       778: {
1.66      rillig    779:        char *const *dir;
                    780:        char *lfn;
1.1       cgd       781:
1.66      rillig    782:        for (dir = libsrchpath; *dir != NULL; dir++) {
                    783:                lfn = xasprintf("%s/llib-l%s.ln", *dir, lib);
                    784:                if (rdok(lfn))
                    785:                        goto found;
                    786:                free(lfn);
1.1       cgd       787:
1.66      rillig    788:                lfn = xasprintf("%s/lint/llib-l%s.ln", *dir, lib);
                    789:                if (rdok(lfn))
                    790:                        goto found;
                    791:                free(lfn);
1.1       cgd       792:        }
                    793:
1.66      rillig    794:        warnx("cannot find llib-l%s.ln", lib);
                    795:        return;
                    796:
                    797: found:
1.71      rillig    798:        list_add(&lint2.inlibs, concat2("-l", lfn));
1.1       cgd       799:        free(lfn);
                    800: }
                    801:
1.66      rillig    802: static void
                    803: findlibs(char *const *liblst)
                    804: {
                    805:        char *const *p;
                    806:
                    807:        for (p = liblst; *p != NULL; p++)
                    808:                findlib(*p);
                    809: }
                    810:
1.56      rillig    811: static bool
1.23      lukem     812: rdok(const char *path)
1.1       cgd       813: {
                    814:        struct  stat sbuf;
                    815:
                    816:        if (stat(path, &sbuf) == -1)
1.56      rillig    817:                return false;
1.5       mycroft   818:        if (!S_ISREG(sbuf.st_mode))
1.56      rillig    819:                return false;
1.1       cgd       820:        if (access(path, R_OK) == -1)
1.56      rillig    821:                return false;
                    822:        return true;
1.1       cgd       823: }
                    824:
                    825: static void
1.71      rillig    826: run_lint2(void)
1.1       cgd       827: {
                    828:        char    *path, **args;
                    829:
1.67      rillig    830:        args = list_new();
1.1       cgd       831:
1.77      rillig    832:        if (libexec_dir == NULL) {
1.65      rillig    833:                path = xasprintf("%s/%slint2", PATH_LIBEXEC, target_prefix);
1.17      garbled   834:        } else {
1.24      thorpej   835:                /*
                    836:                 * XXX Unclear whether we should be using target_prefix
                    837:                 * XXX here.  --thorpej@wasabisystems.com
                    838:                 */
1.77      rillig    839:                path = concat2(libexec_dir, "/lint2");
1.23      lukem     840:        }
                    841:
1.67      rillig    842:        list_add_copy(&args, path);
1.71      rillig    843:        list_add_all(&args, lint2.flags);
                    844:        list_add_all(&args, lint2.inlibs);
                    845:        list_add_all(&args, lint2.infiles);
1.1       cgd       846:
1.71      rillig    847:        runchild(path, args, lint2.outlib, -1);
1.1       cgd       848:        free(path);
1.70      rillig    849:        list_clear(&args);
1.1       cgd       850:        free(args);
                    851: }
                    852:
                    853: static void
1.23      lukem     854: cat(char *const *srcs, const char *dest)
1.1       cgd       855: {
                    856:        int     ifd, ofd, i;
                    857:        char    *src, *buf;
                    858:        ssize_t rlen;
                    859:
                    860:        if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
                    861:                warn("cannot open %s", dest);
                    862:                terminate(-1);
                    863:        }
                    864:
                    865:        buf = xmalloc(MBLKSIZ);
                    866:
                    867:        for (i = 0; (src = srcs[i]) != NULL; i++) {
                    868:                if ((ifd = open(src, O_RDONLY)) == -1) {
                    869:                        free(buf);
                    870:                        warn("cannot open %s", src);
                    871:                        terminate(-1);
                    872:                }
                    873:                do {
                    874:                        if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) {
                    875:                                free(buf);
                    876:                                warn("read error on %s", src);
                    877:                                terminate(-1);
                    878:                        }
                    879:                        if (write(ofd, buf, (size_t)rlen) == -1) {
                    880:                                free(buf);
                    881:                                warn("write error on %s", dest);
                    882:                                terminate(-1);
                    883:                        }
                    884:                } while (rlen == MBLKSIZ);
                    885:                (void)close(ifd);
                    886:        }
                    887:        (void)close(ofd);
                    888:        free(buf);
                    889: }

CVSweb <webmaster@jp.NetBSD.org>