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>