1/*	$OpenBSD: main.c,v 1.133 2024/06/18 02:11:03 millert Exp $ */
2/*	$NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $	*/
3
4/*
5 * Copyright (c) 1988, 1989, 1990, 1993
6 *	The Regents of the University of California.  All rights reserved.
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. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#include <sys/param.h>	/* MACHINE MACHINE_ARCH */
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <sys/utsname.h>
42#include <err.h>
43#include <errno.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48#include "defines.h"
49#include "var.h"
50#include "lowparse.h"
51#include "parse.h"
52#include "parsevar.h"
53#include "dir.h"
54#include "direxpand.h"
55#include "error.h"
56#include "pathnames.h"
57#include "init.h"
58#include "job.h"
59#include "targ.h"
60#include "suff.h"
61#include "str.h"
62#include "main.h"
63#include "lst.h"
64#include "memory.h"
65#include "dump.h"
66#include "enginechoice.h"
67
68#define MAKEFLAGS	".MAKEFLAGS"
69
70static LIST		to_create; 	/* Targets to be made */
71Lst create = &to_create;
72bool 		allPrecious;	/* .PRECIOUS given on line by itself */
73
74static bool	noBuiltins;	/* -r flag */
75static LIST	makefiles;	/* ordered list of makefiles to read */
76static LIST	varstoprint;	/* list of variables to print */
77static int	optj;		/* -j argument */
78static bool 	compatMake;	/* -B argument */
79static bool	forceJobs = false;
80int 		debug;		/* -d flag */
81bool 		noExecute;	/* -n flag */
82bool 		keepgoing;	/* -k flag */
83bool 		queryFlag;	/* -q flag */
84bool 		touchFlag;	/* -t flag */
85bool 		ignoreErrors;	/* -i flag */
86bool 		beSilent;	/* -s flag */
87bool		dumpData;	/* -p flag */
88
89static LIST 	unreadable;
90
91struct dirs {
92	char *current;
93	char *object;
94};
95
96static void MainParseArgs(int, char **);
97static void add_dirpath(Lst, const char *);
98static void usage(void);
99static void posixParseOptLetter(int);
100static void record_option(int, const char *);
101
102static char *figure_out_MACHINE(void);
103static char *figure_out_MACHINE_ARCH(void);
104static char *figure_out_MACHINE_CPU(void);
105
106static char *chdir_verify_path(const char *, struct dirs *);
107static char *figure_out_CURDIR(void);
108static void setup_CURDIR_OBJDIR(struct dirs *);
109
110static void setup_VPATH(void);
111
112static void read_all_make_rules(bool, bool, Lst, struct dirs *);
113static void read_makefile_list(Lst, struct dirs *);
114static bool ReadMakefile(void *, void *);
115
116static void
117record_option(int c, const char *arg)
118{
119    	char opt[3];
120
121	opt[0] = '-';
122	opt[1] = c;
123	opt[2] = '\0';
124	Var_Append(MAKEFLAGS, opt);
125	if (arg != NULL)
126		Var_Append(MAKEFLAGS, arg);
127}
128
129void
130set_notparallel(void)
131{
132	compatMake = true;
133}
134
135static void
136posixParseOptLetter(int c)
137{
138	switch(c) {
139	case 'B':
140		compatMake = true;
141		return;	/* XXX don't pass to submakes. */
142	case 'S':
143		keepgoing = false;
144		break;
145	case 'e':
146		Var_setCheckEnvFirst(true);
147		break;
148	case 'i':
149		ignoreErrors = true;
150		break;
151	case 'k':
152		keepgoing = true;
153		break;
154	case 'n':
155		noExecute = true;
156		break;
157	case 'p':
158		dumpData = true;
159		break;
160	case 'q':
161		queryFlag = true;
162		/* Kind of nonsensical, wot? */
163		break;
164	case 'r':
165		noBuiltins = true;
166		break;
167	case 's':
168		beSilent = true;
169		break;
170	case 't':
171		touchFlag = true;
172		break;
173	default:
174		usage();
175	}
176	record_option(c, NULL);
177}
178
179/*-
180 * MainParseArgs --
181 *	Parse a given argument vector. Called from main() and from
182 *	Main_ParseArgLine() when the .MAKEFLAGS target is used.
183 *
184 *	XXX: Deal with command line overriding .MAKEFLAGS in makefile
185 *
186 * Side Effects:
187 *	Various global and local flags will be set depending on the flags
188 *	given
189 */
190static void
191MainParseArgs(int argc, char **argv)
192{
193	int c, optend;
194
195#define OPTFLAGS "BC:D:I:SV:d:ef:ij:km:npqrst"
196#define OPTLETTERS "BSiknpqrst"
197
198	if (pledge("stdio rpath wpath cpath fattr proc exec", NULL) == -1)
199		err(2, "pledge");
200
201	optind = 1;	/* since we're called more than once */
202	optreset = 1;
203	optend = 0;
204	while (optind < argc) {
205		if (!optend && argv[optind][0] == '-') {
206			if (argv[optind][1] == '\0')
207				optind++;	/* ignore "-" */
208			else if (argv[optind][1] == '-' &&
209			    argv[optind][2] == '\0') {
210				optind++;	/* ignore "--" */
211				optend++;	/* "--" denotes end of flags */
212			}
213		}
214		c = optend ? -1 : getopt(argc, argv, OPTFLAGS);
215		switch (c) {
216		case 'C':
217			break;
218		case 'D':
219			Var_Set(optarg, "1");
220			record_option(c, optarg);
221			break;
222		case 'I':
223			Parse_AddIncludeDir(optarg);
224			record_option(c, optarg);
225			break;
226		case 'V':
227			Lst_AtEnd(&varstoprint, optarg);
228			record_option(c, optarg);
229			break;
230		case 'd': {
231			char *modules = optarg;
232
233			for (; *modules; ++modules)
234				switch (*modules) {
235				case 'A':
236					debug = ~0;
237					break;
238				case 'a':
239					debug |= DEBUG_ARCH;
240					break;
241				case 'c':
242					debug |= DEBUG_COND;
243					break;
244				case 'd':
245					debug |= DEBUG_DIR;
246					break;
247				case 'D':
248					debug |= DEBUG_DOUBLE;
249					break;
250				case 'e':
251					debug |= DEBUG_EXPENSIVE;
252					break;
253				case 'f':
254					debug |= DEBUG_FOR;
255					break;
256				case 'g':
257					if (modules[1] == '1') {
258						debug |= DEBUG_GRAPH1;
259						++modules;
260					}
261					else if (modules[1] == '2') {
262						debug |= DEBUG_GRAPH2;
263						++modules;
264					}
265					break;
266				case 'h':
267					debug |= DEBUG_HELDJOBS;
268					break;
269				case 'j':
270					debug |= DEBUG_JOB | DEBUG_KILL;
271					break;
272				case 'J':
273					/* ignore */
274					break;
275				case 'k':
276					debug |= DEBUG_KILL;
277					break;
278				case 'l':
279					debug |= DEBUG_LOUD;
280					break;
281				case 'm':
282					debug |= DEBUG_MAKE;
283					break;
284				case 'n':
285					debug |= DEBUG_NAME_MATCHING;
286					break;
287				case 'p':
288					debug |= DEBUG_PARALLEL;
289					break;
290				case 'q':
291					debug |= DEBUG_QUICKDEATH;
292					break;
293				case 's':
294					debug |= DEBUG_SUFF;
295					break;
296				case 't':
297					debug |= DEBUG_TARG;
298					break;
299				case 'T':
300					debug |= DEBUG_TARGGROUP;
301					break;
302				case 'v':
303					debug |= DEBUG_VAR;
304					break;
305				default:
306					(void)fprintf(stderr,
307				"make: illegal argument to -d option -- %c\n",
308					    *modules);
309					usage();
310				}
311			record_option(c, optarg);
312			break;
313		}
314		case 'f':
315			Lst_AtEnd(&makefiles, optarg);
316			break;
317		case 'j': {
318			const char *errstr;
319
320			forceJobs = true;
321			optj = strtonum(optarg, 1, INT_MAX, &errstr);
322			if (errstr != NULL) {
323				fprintf(stderr,
324				    "make: illegal argument to -j option"
325				    " -- %s -- %s\n", optarg, errstr);
326				usage();
327			}
328			record_option(c, optarg);
329			break;
330		}
331		case 'm':
332			Dir_AddDir(systemIncludePath, optarg);
333			record_option(c, optarg);
334			break;
335		case -1:
336			/* Check for variable assignments and targets. */
337			if (argv[optind] != NULL &&
338			    !Parse_CmdlineVar(argv[optind])) {
339				if (!*argv[optind])
340					Punt("illegal (null) argument.");
341				Lst_AtEnd(create, estrdup(argv[optind]));
342			}
343			optind++;	/* skip over non-option */
344			break;
345		default:
346			posixParseOptLetter(c);
347		}
348	}
349}
350
351static void
352MainParseChdir(int argc, char **argv)
353{
354	int c, optend, oldopterr;
355
356	optind = 1;	/* since we're called more than once */
357	optreset = 1;
358	optend = 0;
359	oldopterr = opterr;
360	opterr = 0;
361	while (optind < argc) {
362		if (!optend && argv[optind][0] == '-') {
363			if (argv[optind][1] == '\0')
364				optind++;	/* ignore "-" */
365			else if (argv[optind][1] == '-' &&
366			    argv[optind][2] == '\0') {
367				optind++;	/* ignore "--" */
368				optend++;	/* "--" denotes end of flags */
369			}
370		}
371		c = optend ? -1 : getopt(argc, argv, OPTFLAGS);
372		switch (c) {
373		case 'C':
374			if (chdir(optarg) == -1)
375				err(2, "chdir(%s)", optarg);
376			break;
377		case -1:
378			optind++;	/* skip over non-option */
379			break;
380		default:
381			break;
382		}
383	}
384	opterr = oldopterr;
385}
386
387/*-
388 * Main_ParseArgLine --
389 *	Used by the parse module when a .MFLAGS or .MAKEFLAGS target
390 *	is encountered and by main() when reading the .MAKEFLAGS envariable.
391 *	Takes a line of arguments and breaks it into its
392 *	component words and passes those words and the number of them to the
393 *	MainParseArgs function.
394 *	The line should have all its leading whitespace removed.
395 *
396 * Side Effects:
397 *	Only those that come from the various arguments.
398 */
399void
400Main_ParseArgLine(const char *line) 	/* Line to fracture */
401{
402	char **argv;			/* Manufactured argument vector */
403	int argc;			/* Number of arguments in argv */
404	char *args;			/* Space used by the args */
405	char *buf;
406	char *argv0;
407	const char *s;
408	size_t len;
409
410
411	if (line == NULL)
412		return;
413	for (; *line == ' '; ++line)
414		continue;
415	if (!*line)
416		return;
417
418	/* POSIX rule: MAKEFLAGS can hold a set of option letters without
419	 * any blanks or dashes. */
420	for (s = line;; s++) {
421		if (*s == '\0') {
422			while (line != s)
423				posixParseOptLetter(*line++);
424			return;
425		}
426		if (strchr(OPTLETTERS, *s) == NULL)
427			break;
428	}
429	argv0 = Var_Value(".MAKE");
430	len = strlen(line) + strlen(argv0) + 2;
431	buf = emalloc(len);
432	(void)snprintf(buf, len, "%s %s", argv0, line);
433
434	argv = brk_string(buf, &argc, &args);
435	free(buf);
436	MainParseArgs(argc, argv);
437
438	free(args);
439	free(argv);
440}
441
442/* Add a :-separated path to a Lst of directories.  */
443static void
444add_dirpath(Lst l, const char *n)
445{
446	const char *start;
447	const char *cp;
448
449	for (start = n;;) {
450		for (cp = start; *cp != '\0' && *cp != ':';)
451			cp++;
452		Dir_AddDiri(l, start, cp);
453		if (*cp == '\0')
454			break;
455		else
456			start= cp+1;
457	}
458}
459
460/*
461 * Get the name of this type of MACHINE from utsname so we can share an
462 * executable for similar machines. (i.e. m68k: amiga hp300, mac68k, sun3, ...)
463 *
464 * Note that MACHINE, MACHINE_ARCH and MACHINE_CPU are decided at
465 * run-time.
466 */
467static char *
468figure_out_MACHINE(void)
469{
470	char *r = getenv("MACHINE");
471	if (r == NULL) {
472		static struct utsname utsname;
473
474		if (uname(&utsname) == -1)
475			err(2, "uname");
476		r = utsname.machine;
477	}
478	return r;
479}
480
481static char *
482figure_out_MACHINE_ARCH(void)
483{
484	char *r = getenv("MACHINE_ARCH");
485	if (r == NULL) {
486#ifndef MACHINE_ARCH
487		r = "unknown";	/* XXX: no uname -p yet */
488#else
489		r = MACHINE_ARCH;
490#endif
491	}
492	return r;
493}
494static char *
495figure_out_MACHINE_CPU(void)
496{
497	char *r = getenv("MACHINE_CPU");
498	if (r == NULL) {
499#if !defined(MACHINE_CPU) && ! defined(MACHINE_ARCH)
500		r = "unknown";	/* XXX: no uname -p yet */
501#else
502#if defined(MACHINE_CPU)
503		r = MACHINE_CPU;
504#else
505		r = MACHINE_ARCH;
506#endif
507#endif
508	}
509	return r;
510}
511
512static char *
513figure_out_CURDIR(void)
514{
515	char *dir, *cwd;
516	struct stat sa, sb;
517
518	/* curdir is cwd... */
519	cwd = getcwd(NULL, 0);
520	if (cwd == NULL)
521		err(2, "getcwd");
522
523	if (stat(cwd, &sa) == -1)
524		err(2, "%s", cwd);
525
526	/* ...but we can use the alias $PWD if we can prove it is the same
527	 * directory */
528	if ((dir = getenv("PWD")) != NULL) {
529		if (stat(dir, &sb) == 0 && sa.st_ino == sb.st_ino &&
530		    sa.st_dev == sb.st_dev) {
531		    	free(cwd);
532			return estrdup(dir);
533		}
534	}
535
536	return cwd;
537}
538
539static char *
540chdir_verify_path(const char *path, struct dirs *d)
541{
542	if (chdir(path) == 0) {
543		if (path[0] != '/')
544			return Str_concat(d->current, path, '/');
545		else
546			return estrdup(path);
547	}
548	return NULL;
549}
550
551static void
552setup_CURDIR_OBJDIR(struct dirs *d)
553{
554	char *path;
555
556	d->current = figure_out_CURDIR();
557	/*
558	 * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
559	 * exists, change into it and build there.
560	 *
561	 * Once things are initted,
562	 * have to add the original directory to the search path,
563	 * and modify the paths for the Makefiles appropriately.  The
564	 * current directory is also placed as a variable for make scripts.
565	 */
566	if ((path = getenv("MAKEOBJDIR")) == NULL) {
567		path = _PATH_OBJDIR;
568	}
569	d->object = chdir_verify_path(path, d);
570	if (d->object == NULL)
571		d->object = d->current;
572}
573
574/*
575 * if the VPATH variable is defined, add its contents to the search path.
576 * Uses the same format as the PATH env variable, i.e.,
577 * <directory>:<directory>:<directory>...
578 */
579static void
580setup_VPATH(void)
581{
582	if (Var_Value("VPATH") != NULL) {
583		char *vpath;
584
585		vpath = Var_Subst("${VPATH}", NULL, false);
586		add_dirpath(defaultPath, vpath);
587		(void)free(vpath);
588	}
589}
590
591static void
592read_makefile_list(Lst mk, struct dirs *d)
593{
594	LstNode ln;
595	ln = Lst_Find(mk, ReadMakefile, d);
596	if (ln != NULL)
597		Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
598}
599
600static void
601read_all_make_rules(bool noBuiltins, bool read_depend,
602    Lst makefiles, struct dirs *d)
603{
604	/*
605	 * Read in the built-in rules first, followed by the specified
606	 * makefile(s), or the default Makefile or makefile, in that order.
607	 */
608	if (!noBuiltins) {
609		LIST sysMkPath; 		/* Path of sys.mk */
610
611		Lst_Init(&sysMkPath);
612		Dir_Expand(_PATH_DEFSYSMK, systemIncludePath, &sysMkPath);
613		if (Lst_IsEmpty(&sysMkPath))
614			Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
615
616		read_makefile_list(&sysMkPath, d);
617	}
618
619	if (!Lst_IsEmpty(makefiles)) {
620		read_makefile_list(makefiles, d);
621	} else if (!ReadMakefile("makefile", d))
622		(void)ReadMakefile("Makefile", d);
623
624	/* read a .depend file, if it exists, and we're not building depend */
625
626	if (read_depend)
627		(void)ReadMakefile(".depend", d);
628	Parse_End();
629}
630
631static void
632run_node(GNode *gn, bool *has_errors, bool *out_of_date)
633{
634	LIST l;
635
636	Lst_Init(&l);
637	Lst_AtEnd(&l, gn);
638	engine_run_list(&l, has_errors, out_of_date);
639	Lst_Destroy(&l, NOFREE);
640}
641
642int main(int, char **);
643
644int
645main(int argc, char **argv)
646{
647	static LIST targs;	/* target nodes to create */
648	bool outOfDate = false;	/* false if all targets up to date */
649	bool errored = false;	/* true if errors occurred */
650	char *machine = figure_out_MACHINE();
651	char *machine_arch = figure_out_MACHINE_ARCH();
652	char *machine_cpu = figure_out_MACHINE_CPU();
653	const char *syspath = _PATH_DEFSYSPATH;
654	char *p;
655	static struct dirs d;
656	bool read_depend = true;/* false if we don't want to read .depend */
657
658	MainParseChdir(argc, argv);
659	setup_CURDIR_OBJDIR(&d);
660
661	esetenv("PWD", d.object);
662	unsetenv("CDPATH");
663
664	Static_Lst_Init(create);
665	Static_Lst_Init(&makefiles);
666	Static_Lst_Init(&varstoprint);
667	Static_Lst_Init(&targs);
668	Static_Lst_Init(&special);
669
670	beSilent = false;		/* Print commands as executed */
671	ignoreErrors = false;		/* Pay attention to non-zero returns */
672	noExecute = false;		/* Execute all commands */
673	keepgoing = false;		/* Stop on error */
674	allPrecious = false;		/* Remove targets when interrupted */
675	queryFlag = false;		/* This is not just a check-run */
676	noBuiltins = false;		/* Read the built-in rules */
677	touchFlag = false;		/* Actually update targets */
678	debug = 0;			/* No debug verbosity, please. */
679
680	optj = DEFMAXJOBS;
681	compatMake = false;		/* No compat mode */
682
683
684	/*
685	 * Initialize all external modules.
686	 */
687	Init();
688
689	if (d.object != d.current)
690		Dir_AddDir(defaultPath, d.current);
691	Var_Set(".CURDIR", d.current);
692	Var_Set(".OBJDIR", d.object);
693	Parse_setcurdir(d.current);
694	Targ_setdirs(d.current, d.object);
695
696	/*
697	 * Initialize various variables.
698	 *	MAKE also gets this name, for compatibility
699	 *	.MAKEFLAGS gets set to the empty string just in case.
700	 *	MFLAGS also gets initialized empty, for compatibility.
701	 */
702	Var_Set("MAKE", argv[0]);
703	Var_Set(".MAKE", argv[0]);
704	Var_Set(MAKEFLAGS, "");
705	Var_Set("MFLAGS", "");
706	Var_Set("MACHINE", machine);
707	Var_Set("MACHINE_ARCH", machine_arch);
708	Var_Set("MACHINE_CPU", machine_cpu);
709
710	/*
711	 * First snag any flags out of the MAKEFLAGS environment variable.
712	 */
713	Main_ParseArgLine(getenv("MAKEFLAGS"));
714
715	basedirectory = getenv("MAKEBASEDIRECTORY");
716	if (basedirectory == NULL)
717		setenv("MAKEBASEDIRECTORY", d.current, 0);
718
719	MainParseArgs(argc, argv);
720
721	/*
722	 * Be compatible if user did not specify -j
723	 */
724	if (!forceJobs)
725		compatMake = true;
726
727	/* And set up everything for sub-makes */
728	Var_AddCmdline(MAKEFLAGS);
729
730
731	/*
732	 * Set up the .TARGETS variable to contain the list of targets to be
733	 * created. If none specified, make the variable empty -- the parser
734	 * will fill the thing in with the default or .MAIN target.
735	 */
736	if (!Lst_IsEmpty(create)) {
737		LstNode ln;
738
739		for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) {
740			char *name = Lst_Datum(ln);
741
742			if (strcmp(name, "depend") == 0)
743				read_depend = false;
744
745			Var_Append(".TARGETS", name);
746		}
747	} else
748		Var_Set(".TARGETS", "");
749
750
751	/*
752	 * If no user-supplied system path was given (through the -m option)
753	 * add the directories from the DEFSYSPATH (more than one may be given
754	 * as dir1:...:dirn) to the system include path.
755	 */
756	if (Lst_IsEmpty(systemIncludePath))
757	    add_dirpath(systemIncludePath, syspath);
758
759	read_all_make_rules(noBuiltins, read_depend, &makefiles, &d);
760
761	if (compatMake)
762		optj = 1;
763
764	Var_Append("MFLAGS", Var_Value(MAKEFLAGS));
765
766	/* Install all the flags into the MAKEFLAGS env variable. */
767	if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p)
768		esetenv("MAKEFLAGS", p);
769
770	setup_VPATH();
771
772	process_suffixes_after_makefile_is_read();
773
774	if (dumpData) {
775		dump_data();
776		exit(0);
777	}
778
779	/* Print the initial graph, if the user requested it.  */
780	if (DEBUG(GRAPH1))
781		dump_data();
782
783	/* Print the values of any variables requested by the user.  */
784	if (!Lst_IsEmpty(&varstoprint)) {
785		LstNode ln;
786
787		for (ln = Lst_First(&varstoprint); ln != NULL;
788		    ln = Lst_Adv(ln)) {
789			char *value = Var_Value(Lst_Datum(ln));
790
791			printf("%s\n", value ? value : "");
792		}
793	} else {
794		/* Have now read the entire graph and need to make a list
795		 * of targets to create. If none was given on the command
796		 * line, we consult the parsing module to find the main
797		 * target(s) to create.  */
798		if (Lst_IsEmpty(create))
799			Parse_MainName(&targs);
800		else
801			Targ_FindList(&targs, create);
802
803		choose_engine(compatMake);
804		Job_Init(optj);
805		if (!queryFlag && node_is_real(begin_node))
806			run_node(begin_node, &errored, &outOfDate);
807
808		if (!errored)
809			engine_run_list(&targs, &errored, &outOfDate);
810
811		if (!queryFlag && !errored && node_is_real(end_node))
812			run_node(end_node, &errored, &outOfDate);
813	}
814
815	/* print the graph now it's been processed if the user requested it */
816	if (DEBUG(GRAPH2))
817		post_mortem();
818
819	/* Note that we only hit this code if -k is used, otherwise we
820	 * exited early in case of errors. */
821	if (errored)
822		Fatal("Errors while building");
823
824	if (queryFlag && outOfDate)
825		return 1;
826	else
827		return 0;
828}
829
830struct unreadable {
831	char *fname;
832	int errcode;
833};
834
835void
836dump_unreadable(void)
837{
838	struct unreadable *u;
839
840	if (Lst_IsEmpty(&unreadable))
841		return;
842
843	fprintf(stderr, "Makefile(s) that couldn't be read:\n");
844
845	while ((u = Lst_Pop(&unreadable))) {
846		fprintf(stderr, "\t%s: %s\n", u->fname, strerror(u->errcode));
847		free(u->fname);
848		free(u);
849	}
850}
851
852static FILE *
853open_makefile(const char *fname)
854{
855	FILE *stream;
856	struct unreadable *u;
857
858	stream = fopen(fname, "r");
859	if (stream != NULL)
860		return stream;
861
862	if (errno != ENOENT) {
863		u = emalloc(sizeof *u);
864		u->fname = estrdup(fname);
865		u->errcode = errno;
866		Lst_AtEnd(&unreadable, u);
867	}
868
869	return NULL;
870}
871
872/*-
873 * ReadMakefile  --
874 *	Open and parse the given makefile.
875 *
876 * Results:
877 *	true if ok. false if couldn't open file.
878 *
879 * Side Effects:
880 *	lots
881 */
882static bool
883ReadMakefile(void *p, void *q)
884{
885	const char *fname = p;	/* makefile to read */
886	struct dirs *d = q;
887	FILE *stream;
888	char *name;
889
890	if (!strcmp(fname, "-")) {
891		Var_Set("MAKEFILE", "");
892		Parse_File(estrdup("(stdin)"), stdin);
893	} else {
894		if ((stream = open_makefile(fname)) != NULL)
895			goto found;
896		/* if we've chdir'd, rebuild the path name */
897		if (d->current != d->object && *fname != '/') {
898			char *path;
899
900			path = Str_concat(d->current, fname, '/');
901			if ((stream = open_makefile(path)) == NULL)
902				free(path);
903			else {
904				fname = path;
905				goto found;
906			}
907		}
908		/* look in -I and system include directories. */
909		name = Dir_FindFile(fname, userIncludePath);
910		if (!name)
911			name = Dir_FindFile(fname, systemIncludePath);
912		if (!name)
913			return false;
914		/* do not try to open a file we already have, so that
915		 * dump_unreadable() yields non-confusing results.
916		 */
917		if (strcmp(name, fname) == 0)
918			return false;
919		if ((stream = open_makefile(name)) == NULL)
920			return false;
921		fname = name;
922		/*
923		 * set the MAKEFILE variable desired by System V fans -- the
924		 * placement of the setting here means it gets set to the last
925		 * makefile specified, as it is set by SysV make.
926		 */
927found:		Var_Set("MAKEFILE", fname);
928		Parse_File(fname, stream);
929	}
930	return true;
931}
932
933
934/*
935 * usage --
936 *	exit with usage message
937 */
938static void
939usage(void)
940{
941	(void)fprintf(stderr,
942"usage: make [-BeiknpqrSst] [-C directory] [-D variable] [-d flags] [-f mk]\n\
943	    [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\
944	    [NAME=value ...] [target ...]\n");
945	exit(2);
946}
947
948
949