Annotation of src/usr.bin/make/main.c, Revision 1.7
1.7 ! deraadt 1: /* $OpenBSD: main.c,v 1.6 1996/03/27 19:32:36 niklas Exp $ */
! 2: /* $NetBSD: main.c,v 1.28 1996/03/31 21:30:05 christos Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
6: * Copyright (c) 1988, 1989 by Adam de Boor
7: * Copyright (c) 1989 by Berkeley Softworks
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Adam de Boor.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the University of
24: * California, Berkeley and its contributors.
25: * 4. Neither the name of the University nor the names of its contributors
26: * may be used to endorse or promote products derived from this software
27: * without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: */
41:
42: #ifndef lint
43: char copyright[] =
44: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
45: All rights reserved.\n";
46: #endif /* not lint */
47:
48: #ifndef lint
49: #if 0
50: static char sccsid[] = "@(#)main.c 5.25 (Berkeley) 4/1/91";
1.6 niklas 51: static char rcsid[] = "$NetBSD: main.c,v 1.26 1996/03/11 13:45:33 christos Exp $";
1.1 deraadt 52: #else
1.7 ! deraadt 53: static char rcsid[] = "$OpenBSD: main.c,v 1.6 1996/03/27 19:32:36 niklas Exp $";
1.1 deraadt 54: #endif
55: #endif /* not lint */
56:
57: /*-
58: * main.c --
59: * The main file for this entire program. Exit routines etc
60: * reside here.
61: *
62: * Utility functions defined in this file:
63: * Main_ParseArgLine Takes a line of arguments, breaks them and
64: * treats them as if they were given when first
65: * invoked. Used by the parse module to implement
66: * the .MFLAGS target.
67: *
68: * Error Print a tagged error message. The global
69: * MAKE variable must have been defined. This
70: * takes a format string and two optional
71: * arguments for it.
72: *
73: * Fatal Print an error message and exit. Also takes
74: * a format string and two arguments.
75: *
76: * Punt Aborts all jobs and exits with a message. Also
77: * takes a format string and two arguments.
78: *
79: * Finish Finish things up by printing the number of
80: * errors which occured, as passed to it, and
81: * exiting.
82: */
83:
84: #include <sys/types.h>
85: #include <sys/time.h>
86: #include <sys/param.h>
87: #include <sys/resource.h>
1.2 deraadt 88: #include <sys/signal.h>
1.1 deraadt 89: #include <sys/stat.h>
90: #include <sys/utsname.h>
91: #include <errno.h>
92: #include <fcntl.h>
93: #include <stdio.h>
94: #if __STDC__
95: #include <stdarg.h>
96: #else
97: #include <varargs.h>
98: #endif
99: #include "make.h"
100: #include "hash.h"
101: #include "dir.h"
102: #include "job.h"
103: #include "pathnames.h"
104:
105: #ifndef DEFMAXLOCAL
106: #define DEFMAXLOCAL DEFMAXJOBS
1.4 niklas 107: #endif /* DEFMAXLOCAL */
1.1 deraadt 108:
109: #define MAKEFLAGS ".MAKEFLAGS"
110:
111: Lst create; /* Targets to be made */
112: time_t now; /* Time at start of make */
113: GNode *DEFAULT; /* .DEFAULT node */
114: Boolean allPrecious; /* .PRECIOUS given on line by itself */
115:
116: static Boolean noBuiltins; /* -r flag */
117: static Lst makefiles; /* ordered list of makefiles to read */
1.2 deraadt 118: int maxJobs; /* -j argument */
1.1 deraadt 119: static int maxLocal; /* -L argument */
120: Boolean compatMake; /* -B argument */
121: Boolean debug; /* -d flag */
122: Boolean noExecute; /* -n flag */
123: Boolean keepgoing; /* -k flag */
124: Boolean queryFlag; /* -q flag */
125: Boolean touchFlag; /* -t flag */
126: Boolean usePipes; /* !-P flag */
127: Boolean ignoreErrors; /* -i flag */
128: Boolean beSilent; /* -s flag */
129: Boolean oldVars; /* variable substitution style */
130: Boolean checkEnvFirst; /* -e flag */
131: static Boolean jobsRunning; /* TRUE if the jobs might be running */
132:
133: static Boolean ReadMakefile();
134: static void usage();
135:
136: static char *curdir; /* startup directory */
137: static char *objdir; /* where we chdir'ed to */
138:
139: /*-
140: * MainParseArgs --
141: * Parse a given argument vector. Called from main() and from
142: * Main_ParseArgLine() when the .MAKEFLAGS target is used.
143: *
144: * XXX: Deal with command line overriding .MAKEFLAGS in makefile
145: *
146: * Results:
147: * None
148: *
149: * Side Effects:
150: * Various global and local flags will be set depending on the flags
151: * given
152: */
153: static void
154: MainParseArgs(argc, argv)
155: int argc;
156: char **argv;
157: {
158: extern int optind;
159: extern char *optarg;
160: int c;
1.2 deraadt 161: int forceJobs = 0;
1.1 deraadt 162:
163: optind = 1; /* since we're called more than once */
1.2 deraadt 164: #ifdef REMOTE
1.5 niklas 165: # define OPTFLAGS "BD:I:L:PSd:ef:ij:km:nqrst"
1.1 deraadt 166: #else
1.5 niklas 167: # define OPTFLAGS "BD:I:PSd:ef:ij:km:nqrst"
1.1 deraadt 168: #endif
169: rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
170: switch(c) {
171: case 'D':
172: Var_Set(optarg, "1", VAR_GLOBAL);
173: Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
174: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
175: break;
176: case 'I':
177: Parse_AddIncludeDir(optarg);
178: Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
179: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
180: break;
181: case 'B':
182: compatMake = TRUE;
183: break;
1.2 deraadt 184: #ifdef REMOTE
1.1 deraadt 185: case 'L':
186: maxLocal = atoi(optarg);
187: Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
188: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
189: break;
1.2 deraadt 190: #endif
1.1 deraadt 191: case 'P':
192: usePipes = FALSE;
193: Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
194: break;
195: case 'S':
196: keepgoing = FALSE;
197: Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
198: break;
199: case 'd': {
200: char *modules = optarg;
201:
202: for (; *modules; ++modules)
203: switch (*modules) {
204: case 'A':
205: debug = ~0;
206: break;
207: case 'a':
208: debug |= DEBUG_ARCH;
209: break;
210: case 'c':
211: debug |= DEBUG_COND;
212: break;
213: case 'd':
214: debug |= DEBUG_DIR;
215: break;
216: case 'f':
217: debug |= DEBUG_FOR;
218: break;
219: case 'g':
220: if (modules[1] == '1') {
221: debug |= DEBUG_GRAPH1;
222: ++modules;
223: }
224: else if (modules[1] == '2') {
225: debug |= DEBUG_GRAPH2;
226: ++modules;
227: }
228: break;
229: case 'j':
230: debug |= DEBUG_JOB;
231: break;
232: case 'm':
233: debug |= DEBUG_MAKE;
234: break;
235: case 's':
236: debug |= DEBUG_SUFF;
237: break;
238: case 't':
239: debug |= DEBUG_TARG;
240: break;
241: case 'v':
242: debug |= DEBUG_VAR;
243: break;
244: default:
245: (void)fprintf(stderr,
246: "make: illegal argument to d option -- %c\n",
247: *modules);
248: usage();
249: }
250: Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
251: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
252: break;
253: }
254: case 'e':
255: checkEnvFirst = TRUE;
256: Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
257: break;
258: case 'f':
259: (void)Lst_AtEnd(makefiles, (ClientData)optarg);
260: break;
261: case 'i':
262: ignoreErrors = TRUE;
263: Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
264: break;
265: case 'j':
1.2 deraadt 266: forceJobs = TRUE;
1.1 deraadt 267: maxJobs = atoi(optarg);
1.2 deraadt 268: #ifndef REMOTE
269: maxLocal = maxJobs;
270: #endif
1.1 deraadt 271: Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
272: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
273: break;
274: case 'k':
275: keepgoing = TRUE;
276: Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
277: break;
1.5 niklas 278: case 'm':
279: Dir_AddDir(sysIncPath, optarg);
280: Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
281: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
282: break;
1.1 deraadt 283: case 'n':
284: noExecute = TRUE;
285: Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
286: break;
287: case 'q':
288: queryFlag = TRUE;
289: /* Kind of nonsensical, wot? */
290: Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
291: break;
292: case 'r':
293: noBuiltins = TRUE;
294: Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
295: break;
296: case 's':
297: beSilent = TRUE;
298: Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
299: break;
300: case 't':
301: touchFlag = TRUE;
302: Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
303: break;
304: default:
305: case '?':
306: usage();
307: }
308: }
309:
1.2 deraadt 310: /*
311: * Be compatible if user did not specify -j and did not explicitly
312: * turned compatibility on
313: */
314: if (!compatMake && !forceJobs)
315: compatMake = TRUE;
316:
1.1 deraadt 317: oldVars = TRUE;
318:
319: /*
320: * See if the rest of the arguments are variable assignments and
321: * perform them if so. Else take them to be targets and stuff them
322: * on the end of the "create" list.
323: */
324: for (argv += optind, argc -= optind; *argv; ++argv, --argc)
1.3 deraadt 325: if (Parse_IsVar(*argv)) {
326: char *var = strdup(*argv);
327:
328: Parse_DoVar(var, VAR_CMD);
329: free(var);
330: } else {
1.1 deraadt 331: if (!**argv)
332: Punt("illegal (null) argument.");
333: if (**argv == '-') {
334: if ((*argv)[1])
335: optind = 0; /* -flag... */
336: else
337: optind = 1; /* - */
338: goto rearg;
339: }
340: (void)Lst_AtEnd(create, (ClientData)strdup(*argv));
341: }
342: }
343:
344: /*-
345: * Main_ParseArgLine --
346: * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
347: * is encountered and by main() when reading the .MAKEFLAGS envariable.
348: * Takes a line of arguments and breaks it into its
349: * component words and passes those words and the number of them to the
350: * MainParseArgs function.
351: * The line should have all its leading whitespace removed.
352: *
353: * Results:
354: * None
355: *
356: * Side Effects:
357: * Only those that come from the various arguments.
358: */
359: void
360: Main_ParseArgLine(line)
361: char *line; /* Line to fracture */
362: {
363: char **argv; /* Manufactured argument vector */
364: int argc; /* Number of arguments in argv */
365:
366: if (line == NULL)
367: return;
368: for (; *line == ' '; ++line)
369: continue;
370: if (!*line)
371: return;
372:
373: argv = brk_string(line, &argc, TRUE);
374: MainParseArgs(argc, argv);
375: }
376:
377: /*-
378: * main --
379: * The main function, for obvious reasons. Initializes variables
380: * and a few modules, then parses the arguments give it in the
381: * environment and on the command line. Reads the system makefile
382: * followed by either Makefile, makefile or the file given by the
383: * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
384: * flags it has received by then uses either the Make or the Compat
385: * module to create the initial list of targets.
386: *
387: * Results:
388: * If -q was given, exits -1 if anything was out-of-date. Else it exits
389: * 0.
390: *
391: * Side Effects:
392: * The program exits when done. Targets are created. etc. etc. etc.
393: */
394: int
395: main(argc, argv)
396: int argc;
397: char **argv;
398: {
399: Lst targs; /* target nodes to create -- passed to Make_Init */
400: Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
401: struct stat sb, sa;
402: char *p, *p1, *path, *pwd, *getenv(), *getwd();
403: char mdpath[MAXPATHLEN + 1];
404: char obpath[MAXPATHLEN + 1];
405: char cdpath[MAXPATHLEN + 1];
406: struct utsname utsname;
407: char *machine = getenv("MACHINE");
1.5 niklas 408: Lst sysMkPath; /* Path of sys.mk */
409: char *cp = NULL, *start;
410: /* avoid faults on read-only strings */
411: static char syspath[] = _PATH_DEFSYSPATH;
1.1 deraadt 412:
1.2 deraadt 413: #ifdef RLIMIT_NOFILE
414: /*
415: * get rid of resource limit on file descriptors
416: */
417: {
418: struct rlimit rl;
419: if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
420: rl.rlim_cur != rl.rlim_max) {
421: rl.rlim_cur = rl.rlim_max;
422: (void) setrlimit(RLIMIT_NOFILE, &rl);
423: }
424: }
425: #endif
1.1 deraadt 426: /*
427: * Find where we are and take care of PWD for the automounter...
428: * All this code is so that we know where we are when we start up
429: * on a different machine with pmake.
430: */
431: curdir = cdpath;
432: if (getcwd(curdir, MAXPATHLEN) == NULL) {
433: (void)fprintf(stderr, "make: %s.\n", strerror(errno));
434: exit(2);
435: }
436:
437: if (stat(curdir, &sa) == -1) {
438: (void)fprintf(stderr, "make: %s: %s.\n",
439: curdir, strerror(errno));
440: exit(2);
441: }
442:
443: if ((pwd = getenv("PWD")) != NULL) {
444: if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
445: sa.st_dev == sb.st_dev)
446: (void) strcpy(curdir, pwd);
447: }
448:
449: /*
450: * Get the name of this type of MACHINE from utsname
451: * so we can share an executable for similar machines.
452: * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
453: *
454: * Note that while MACHINE is decided at run-time,
455: * MACHINE_ARCH is always known at compile time.
456: */
457: if (!machine) {
1.6 niklas 458: #ifndef MACHINE
1.2 deraadt 459: if (uname(&utsname) == -1) {
1.1 deraadt 460: perror("make: uname");
461: exit(2);
462: }
463: machine = utsname.machine;
1.6 niklas 464: #else
465: machine = MACHINE;
466: #endif
1.1 deraadt 467: }
468:
469: /*
470: * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
471: * exists, change into it and build there. Once things are
472: * initted, have to add the original directory to the search path,
473: * and modify the paths for the Makefiles apropriately. The
474: * current directory is also placed as a variable for make scripts.
475: */
476: if (!(path = getenv("MAKEOBJDIR"))) {
477: path = _PATH_OBJDIR;
478: (void) sprintf(mdpath, "%s.%s", path, machine);
479: }
480: else
481: (void) strncpy(mdpath, path, MAXPATHLEN + 1);
482:
483: if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
484:
485: if (chdir(mdpath)) {
486: (void)fprintf(stderr, "make warning: %s: %s.\n",
487: mdpath, strerror(errno));
488: objdir = curdir;
489: }
490: else {
491: if (mdpath[0] != '/') {
492: (void) sprintf(obpath, "%s/%s", curdir, mdpath);
493: objdir = obpath;
494: }
495: else
496: objdir = mdpath;
497: }
498: }
499: else {
500: if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
501:
502: if (chdir(path)) {
503: (void)fprintf(stderr, "make warning: %s: %s.\n",
504: path, strerror(errno));
505: objdir = curdir;
506: }
507: else {
508: if (path[0] != '/') {
509: (void) sprintf(obpath, "%s/%s", curdir,
510: path);
511: objdir = obpath;
512: }
513: else
514: objdir = obpath;
515: }
516: }
517: else
518: objdir = curdir;
519: }
520:
521: setenv("PWD", objdir, 1);
522:
523: create = Lst_Init(FALSE);
524: makefiles = Lst_Init(FALSE);
525: beSilent = FALSE; /* Print commands as executed */
526: ignoreErrors = FALSE; /* Pay attention to non-zero returns */
527: noExecute = FALSE; /* Execute all commands */
528: keepgoing = FALSE; /* Stop on error */
529: allPrecious = FALSE; /* Remove targets when interrupted */
530: queryFlag = FALSE; /* This is not just a check-run */
531: noBuiltins = FALSE; /* Read the built-in rules */
532: touchFlag = FALSE; /* Actually update targets */
533: usePipes = TRUE; /* Catch child output in pipes */
534: debug = 0; /* No debug verbosity, please. */
535: jobsRunning = FALSE;
536:
1.2 deraadt 537: maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
538: #ifdef REMOTE
1.1 deraadt 539: maxJobs = DEFMAXJOBS; /* Set default max concurrency */
540: #else
1.2 deraadt 541: maxJobs = maxLocal;
1.1 deraadt 542: #endif
1.2 deraadt 543: compatMake = FALSE; /* No compat mode */
1.1 deraadt 544:
545:
546: /*
547: * Initialize the parsing, directory and variable modules to prepare
548: * for the reading of inclusion paths and variable settings on the
549: * command line
550: */
551: Dir_Init(); /* Initialize directory structures so -I flags
552: * can be processed correctly */
553: Parse_Init(); /* Need to initialize the paths of #include
554: * directories */
555: Var_Init(); /* As well as the lists of variables for
556: * parsing arguments */
557: str_init();
558: if (objdir != curdir)
559: Dir_AddDir(dirSearchPath, curdir);
560: Var_Set(".CURDIR", curdir, VAR_GLOBAL);
561: Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
562:
563: /*
564: * Initialize various variables.
565: * MAKE also gets this name, for compatibility
566: * .MAKEFLAGS gets set to the empty string just in case.
567: * MFLAGS also gets initialized empty, for compatibility.
568: */
569: Var_Set("MAKE", argv[0], VAR_GLOBAL);
570: Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
571: Var_Set("MFLAGS", "", VAR_GLOBAL);
572: Var_Set("MACHINE", machine, VAR_GLOBAL);
573: #ifdef MACHINE_ARCH
574: Var_Set("MACHINE_ARCH", MACHINE_ARCH, VAR_GLOBAL);
575: #endif
576:
577: /*
578: * First snag any flags out of the MAKE environment variable.
579: * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
580: * in a different format).
581: */
582: #ifdef POSIX
583: Main_ParseArgLine(getenv("MAKEFLAGS"));
584: #else
585: Main_ParseArgLine(getenv("MAKE"));
586: #endif
587:
588: MainParseArgs(argc, argv);
589:
590: /*
591: * Initialize archive, target and suffix modules in preparation for
592: * parsing the makefile(s)
593: */
594: Arch_Init();
595: Targ_Init();
596: Suff_Init();
597:
598: DEFAULT = NILGNODE;
599: (void)time(&now);
600:
601: /*
602: * Set up the .TARGETS variable to contain the list of targets to be
603: * created. If none specified, make the variable empty -- the parser
604: * will fill the thing in with the default or .MAIN target.
605: */
606: if (!Lst_IsEmpty(create)) {
607: LstNode ln;
608:
609: for (ln = Lst_First(create); ln != NILLNODE;
610: ln = Lst_Succ(ln)) {
611: char *name = (char *)Lst_Datum(ln);
612:
613: Var_Append(".TARGETS", name, VAR_GLOBAL);
614: }
615: } else
616: Var_Set(".TARGETS", "", VAR_GLOBAL);
617:
1.5 niklas 618:
619: /*
620: * If no user-supplied system path was given (through the -m option)
621: * add the directories from the DEFSYSPATH (more than one may be given
622: * as dir1:...:dirn) to the system include path.
623: */
624: if (Lst_IsEmpty(sysIncPath)) {
625: for (start = syspath; *start != '\0'; start = cp) {
626: for (cp = start; *cp != '\0' && *cp != ':'; cp++)
627: continue;
628: if (*cp == '\0') {
629: Dir_AddDir(sysIncPath, start);
630: } else {
631: *cp++ = '\0';
632: Dir_AddDir(sysIncPath, start);
633: }
634: }
635: }
636:
1.1 deraadt 637: /*
1.5 niklas 638: * Read in the built-in rules first, followed by the specified
639: * makefile, if it was (makefile != (char *) NULL), or the default
640: * Makefile and makefile, in that order, if it wasn't.
1.1 deraadt 641: */
1.5 niklas 642: if (!noBuiltins) {
643: LstNode ln;
644:
645: sysMkPath = Lst_Init (FALSE);
646: Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
647: if (Lst_IsEmpty(sysMkPath))
648: Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
649: ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
650: if (ln != NILLNODE)
651: Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
652: }
1.1 deraadt 653:
654: if (!Lst_IsEmpty(makefiles)) {
655: LstNode ln;
656:
657: ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
658: if (ln != NILLNODE)
659: Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
660: } else if (!ReadMakefile("makefile"))
661: (void)ReadMakefile("Makefile");
662:
663: (void)ReadMakefile(".depend");
664:
665: Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
666: if (p1)
667: free(p1);
668:
669: /* Install all the flags into the MAKE envariable. */
670: if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
671: #ifdef POSIX
672: setenv("MAKEFLAGS", p, 1);
673: #else
674: setenv("MAKE", p, 1);
675: #endif
676: if (p1)
677: free(p1);
678:
679: /*
680: * For compatibility, look at the directories in the VPATH variable
681: * and add them to the search path, if the variable is defined. The
682: * variable's value is in the same format as the PATH envariable, i.e.
683: * <directory>:<directory>:<directory>...
684: */
685: if (Var_Exists("VPATH", VAR_CMD)) {
686: char *vpath, *path, *cp, savec;
687: /*
688: * GCC stores string constants in read-only memory, but
689: * Var_Subst will want to write this thing, so store it
690: * in an array
691: */
692: static char VPATH[] = "${VPATH}";
693:
694: vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
695: path = vpath;
696: do {
697: /* skip to end of directory */
698: for (cp = path; *cp != ':' && *cp != '\0'; cp++)
699: continue;
700: /* Save terminator character so know when to stop */
701: savec = *cp;
702: *cp = '\0';
703: /* Add directory to search path */
704: Dir_AddDir(dirSearchPath, path);
705: *cp = savec;
706: path = cp + 1;
707: } while (savec == ':');
708: (void)free((Address)vpath);
709: }
710:
711: /*
712: * Now that all search paths have been read for suffixes et al, it's
713: * time to add the default search path to their lists...
714: */
715: Suff_DoPaths();
716:
717: /* print the initial graph, if the user requested it */
718: if (DEBUG(GRAPH1))
719: Targ_PrintGraph(1);
720:
721: /*
722: * Have now read the entire graph and need to make a list of targets
723: * to create. If none was given on the command line, we consult the
724: * parsing module to find the main target(s) to create.
725: */
726: if (Lst_IsEmpty(create))
727: targs = Parse_MainName();
728: else
729: targs = Targ_FindList(create, TARG_CREATE);
730:
731: if (!compatMake) {
732: /*
733: * Initialize job module before traversing the graph, now that
734: * any .BEGIN and .END targets have been read. This is done
735: * only if the -q flag wasn't given (to prevent the .BEGIN from
736: * being executed should it exist).
737: */
738: if (!queryFlag) {
739: if (maxLocal == -1)
740: maxLocal = maxJobs;
741: Job_Init(maxJobs, maxLocal);
742: jobsRunning = TRUE;
743: }
744:
745: /* Traverse the graph, checking on all the targets */
746: outOfDate = Make_Run(targs);
747: } else
748: /*
749: * Compat_Init will take care of creating all the targets as
750: * well as initializing the module.
751: */
752: Compat_Run(targs);
753:
754: Lst_Destroy(targs, NOFREE);
755: Lst_Destroy(makefiles, NOFREE);
756: Lst_Destroy(create, (void (*) __P((ClientData))) free);
757:
758: /* print the graph now it's been processed if the user requested it */
759: if (DEBUG(GRAPH2))
760: Targ_PrintGraph(2);
761:
762: Suff_End();
763: Targ_End();
764: Arch_End();
765: str_end();
766: Var_End();
767: Parse_End();
768: Dir_End();
769:
770: if (queryFlag && outOfDate)
771: return(1);
772: else
773: return(0);
774: }
775:
776: /*-
777: * ReadMakefile --
778: * Open and parse the given makefile.
779: *
780: * Results:
781: * TRUE if ok. FALSE if couldn't open file.
782: *
783: * Side Effects:
784: * lots
785: */
786: static Boolean
787: ReadMakefile(fname)
788: char *fname; /* makefile to read */
789: {
1.5 niklas 790: extern Lst parseIncPath;
1.1 deraadt 791: FILE *stream;
792: char *name, path[MAXPATHLEN + 1];
793:
794: if (!strcmp(fname, "-")) {
795: Parse_File("(stdin)", stdin);
796: Var_Set("MAKEFILE", "", VAR_GLOBAL);
797: } else {
798: if ((stream = fopen(fname, "r")) != NULL)
799: goto found;
800: /* if we've chdir'd, rebuild the path name */
801: if (curdir != objdir && *fname != '/') {
802: (void)sprintf(path, "%s/%s", curdir, fname);
803: if ((stream = fopen(path, "r")) != NULL) {
804: fname = path;
805: goto found;
806: }
807: }
808: /* look in -I and system include directories. */
809: name = Dir_FindFile(fname, parseIncPath);
810: if (!name)
811: name = Dir_FindFile(fname, sysIncPath);
812: if (!name || !(stream = fopen(name, "r")))
813: return(FALSE);
814: fname = name;
815: /*
816: * set the MAKEFILE variable desired by System V fans -- the
817: * placement of the setting here means it gets set to the last
818: * makefile specified, as it is set by SysV make.
819: */
820: found: Var_Set("MAKEFILE", fname, VAR_GLOBAL);
821: Parse_File(fname, stream);
822: (void)fclose(stream);
823: }
824: return(TRUE);
825: }
826:
827: /*-
828: * Error --
829: * Print an error message given its format.
830: *
831: * Results:
832: * None.
833: *
834: * Side Effects:
835: * The message is printed.
836: */
837: /* VARARGS */
838: void
839: #if __STDC__
840: Error(char *fmt, ...)
841: #else
842: Error(va_alist)
843: va_dcl
844: #endif
845: {
846: va_list ap;
847: #if __STDC__
848: va_start(ap, fmt);
849: #else
850: char *fmt;
851:
852: va_start(ap);
853: fmt = va_arg(ap, char *);
854: #endif
855: (void)vfprintf(stderr, fmt, ap);
856: va_end(ap);
857: (void)fprintf(stderr, "\n");
858: (void)fflush(stderr);
859: }
860:
861: /*-
862: * Fatal --
863: * Produce a Fatal error message. If jobs are running, waits for them
864: * to finish.
865: *
866: * Results:
867: * None
868: *
869: * Side Effects:
870: * The program exits
871: */
872: /* VARARGS */
873: void
874: #if __STDC__
875: Fatal(char *fmt, ...)
876: #else
877: Fatal(va_alist)
878: va_dcl
879: #endif
880: {
881: va_list ap;
882: #if __STDC__
883: va_start(ap, fmt);
884: #else
885: char *fmt;
886:
887: va_start(ap);
888: fmt = va_arg(ap, char *);
889: #endif
890: if (jobsRunning)
891: Job_Wait();
892:
893: (void)vfprintf(stderr, fmt, ap);
894: va_end(ap);
895: (void)fprintf(stderr, "\n");
896: (void)fflush(stderr);
897:
898: if (DEBUG(GRAPH2))
899: Targ_PrintGraph(2);
900: exit(2); /* Not 1 so -q can distinguish error */
901: }
902:
903: /*
904: * Punt --
905: * Major exception once jobs are being created. Kills all jobs, prints
906: * a message and exits.
907: *
908: * Results:
909: * None
910: *
911: * Side Effects:
912: * All children are killed indiscriminately and the program Lib_Exits
913: */
914: /* VARARGS */
915: void
916: #if __STDC__
917: Punt(char *fmt, ...)
918: #else
919: Punt(va_alist)
920: va_dcl
921: #endif
922: {
923: va_list ap;
924: #if __STDC__
925: va_start(ap, fmt);
926: #else
927: char *fmt;
928:
929: va_start(ap);
930: fmt = va_arg(ap, char *);
931: #endif
932:
933: (void)fprintf(stderr, "make: ");
934: (void)vfprintf(stderr, fmt, ap);
935: va_end(ap);
936: (void)fprintf(stderr, "\n");
937: (void)fflush(stderr);
938:
939: DieHorribly();
940: }
941:
942: /*-
943: * DieHorribly --
944: * Exit without giving a message.
945: *
946: * Results:
947: * None
948: *
949: * Side Effects:
950: * A big one...
951: */
952: void
953: DieHorribly()
954: {
955: if (jobsRunning)
956: Job_AbortAll();
957: if (DEBUG(GRAPH2))
958: Targ_PrintGraph(2);
959: exit(2); /* Not 1, so -q can distinguish error */
960: }
961:
962: /*
963: * Finish --
964: * Called when aborting due to errors in child shell to signal
965: * abnormal exit.
966: *
967: * Results:
968: * None
969: *
970: * Side Effects:
971: * The program exits
972: */
973: void
974: Finish(errors)
975: int errors; /* number of errors encountered in Make_Make */
976: {
977: Fatal("%d error%s", errors, errors == 1 ? "" : "s");
978: }
979:
980: /*
981: * emalloc --
982: * malloc, but die on error.
983: */
1.7 ! deraadt 984: void *
1.1 deraadt 985: emalloc(len)
986: size_t len;
987: {
1.7 ! deraadt 988: void *p;
1.1 deraadt 989:
1.7 ! deraadt 990: if ((p = malloc(len)) == NULL)
1.1 deraadt 991: enomem();
992: return(p);
1.7 ! deraadt 993: }
! 994:
! 995: /*
! 996: * erealloc --
! 997: * realloc, but die on error.
! 998: */
! 999: void *
! 1000: erealloc(ptr, size)
! 1001: void *ptr;
! 1002: size_t size;
! 1003: {
! 1004: if ((ptr = realloc(ptr, size)) == NULL)
! 1005: enomem();
! 1006: return(ptr);
1.1 deraadt 1007: }
1008:
1009: /*
1010: * enomem --
1011: * die when out of memory.
1012: */
1013: void
1014: enomem()
1015: {
1016: (void)fprintf(stderr, "make: %s.\n", strerror(errno));
1017: exit(2);
1.2 deraadt 1018: }
1019:
1020: /*
1021: * enunlink --
1022: * Remove a file carefully, avoiding directories.
1023: */
1024: int
1025: eunlink(file)
1026: const char *file;
1027: {
1028: struct stat st;
1029:
1030: if (lstat(file, &st) == -1)
1031: return -1;
1032:
1033: if (S_ISDIR(st.st_mode)) {
1034: errno = EISDIR;
1035: return -1;
1036: }
1037: return unlink(file);
1.1 deraadt 1038: }
1039:
1040: /*
1041: * usage --
1042: * exit with usage message
1043: */
1044: static void
1045: usage()
1046: {
1047: (void)fprintf(stderr,
1048: "usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
1.5 niklas 1049: [-I directory] [-j max_jobs] [-m directory] [variable=value]\n");
1.1 deraadt 1050: exit(2);
1051: }
1052:
1053:
1054: int
1055: PrintAddr(a, b)
1056: ClientData a;
1057: ClientData b;
1058: {
1059: printf("%lx ", (unsigned long) a);
1060: return b ? 0 : 0;
1061: }