VirtualBox

source: kBuild/trunk/src/kmk/main.c@ 93

Last change on this file since 93 was 51, checked in by bird, 22 years ago

kMk and porting to kLib.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.7 KB
Line 
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#ifndef lint
40static const char copyright[] =
41"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
42 The Regents of the University of California. All rights reserved.\n";
43#endif /* not lint */
44
45#ifndef lint
46#if 0
47static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
48#else
49static const char rcsid[] =
50 "$FreeBSD: src/usr.bin/make/main.c,v 1.35.2.6 2002/07/24 16:50:18 ru Exp $";
51#endif
52#define KLIBFILEDEF rcsid
53#endif /* not lint */
54
55/*-
56 * main.c --
57 * The main file for this entire program. Exit routines etc
58 * reside here.
59 *
60 * Utility functions defined in this file:
61 * Main_ParseArgLine Takes a line of arguments, breaks them and
62 * treats them as if they were given when first
63 * invoked. Used by the parse module to implement
64 * the .MFLAGS target.
65 *
66 * Error Print a tagged error message. The global
67 * MAKE variable must have been defined. This
68 * takes a format string and two optional
69 * arguments for it.
70 *
71 * Fatal Print an error message and exit. Also takes
72 * a format string and two arguments.
73 *
74 * Punt Aborts all jobs and exits with a message. Also
75 * takes a format string and two arguments.
76 *
77 * Finish Finish things up by printing the number of
78 * errors which occured, as passed to it, and
79 * exiting.
80 */
81
82#if defined(USE_KLIB)
83 #define KLIB_INSTRICT
84 #include <kLib/kLib.h>
85#endif
86
87#include <sys/types.h>
88#include <sys/time.h>
89#include <sys/param.h>
90#if !defined(__IBMC__)
91#include <sys/resource.h>
92#include <sys/signal.h>
93#endif
94#include <sys/stat.h>
95#if defined(__i386__) && !defined(__EMX__)
96#include <sys/sysctl.h>
97#endif
98#ifndef MACHINE
99# include <sys/utsname.h>
100#endif
101#ifndef USE_KLIB
102#include <sys/wait.h>
103#endif
104#include <err.h>
105#include <stdlib.h>
106#include <errno.h>
107#include <fcntl.h>
108#include <stdio.h>
109#if defined(__EMX__)
110#include <sysexits.h>
111#endif
112#if defined(__STDC__)
113#include <stdarg.h>
114#else
115#include <varargs.h>
116#endif
117#if defined(__IBMC__)
118 #include <io.h>
119 #include <direct.h>
120 #ifndef MAXPATHLEN
121 #define MAXPATHLEN _MAX_PATH
122 #endif
123 #ifndef EISDIR
124 #define EISDIR 21 /* unused in errno.h, defined like this in DDK header. */
125 #endif
126 #ifndef S_ISDIR
127 #define S_IFMT (S_IFDIR | S_IFCHR | S_IFREG)
128 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
129 #endif
130 char *realpath(const char *pszFileName, char *pszResolvedName);
131 #define snprintf kStrNFormat
132#endif
133#include <getopt.h>
134#include "make.h"
135#include "hash.h"
136#include "dir.h"
137#include "job.h"
138#include "pathnames.h"
139
140#ifndef DEFMAXLOCAL
141#define DEFMAXLOCAL DEFMAXJOBS
142#endif /* DEFMAXLOCAL */
143
144#define MAKEFLAGS ".MAKEFLAGS"
145
146Lst create; /* Targets to be made */
147time_t now; /* Time at start of make */
148GNode *DEFAULT; /* .DEFAULT node */
149Boolean allPrecious; /* .PRECIOUS given on line by itself */
150
151static Boolean noBuiltins; /* -r flag */
152static Lst makefiles; /* ordered list of makefiles to read */
153static Boolean printVars; /* print value of one or more vars */
154static Boolean expandVars; /* fully expand printed variables */
155static Lst variables; /* list of variables to print */
156int maxJobs; /* -j argument */
157static Boolean forceJobs; /* -j argument given */
158static int maxLocal; /* -L argument */
159Boolean compatMake; /* -B argument */
160Boolean debug; /* -d flag */
161Boolean noExecute; /* -n flag */
162Boolean keepgoing; /* -k flag */
163Boolean queryFlag; /* -q flag */
164Boolean touchFlag; /* -t flag */
165Boolean usePipes; /* !-P flag */
166Boolean ignoreErrors; /* -i flag */
167Boolean beSilent; /* -s flag */
168Boolean beVerbose; /* -v flag */
169Boolean oldVars; /* variable substitution style */
170Boolean checkEnvFirst; /* -e flag */
171Lst envFirstVars; /* (-E) vars to override from env */
172static Boolean jobsRunning; /* TRUE if the jobs might be running */
173#ifdef NMAKE
174static Boolean go_to_objdir; /* ! -o flag */
175#endif
176static void MainParseArgs __P((int, char **));
177char * chdir_verify_path __P((char *, char *));
178static int ReadMakefile __P((ClientData, ClientData));
179static void usage __P((void));
180
181static char *curdir; /* startup directory */
182static char *objdir; /* where we chdir'ed to */
183#ifdef KMK
184char * argv0 = NULL;
185#endif
186
187/*-
188 * MainParseArgs --
189 * Parse a given argument vector. Called from main() and from
190 * Main_ParseArgLine() when the .MAKEFLAGS target is used.
191 *
192 * XXX: Deal with command line overriding .MAKEFLAGS in makefile
193 *
194 * Results:
195 * None
196 *
197 * Side Effects:
198 * Various global and local flags will be set depending on the flags
199 * given
200 */
201static void
202MainParseArgs(argc, argv)
203 int argc;
204 char **argv;
205{
206 extern int optind;
207 extern char *optarg;
208 char *p;
209 int c;
210
211 optind = 1; /* since we're called more than once */
212#ifdef REMOTE
213# ifdef NMAKE
214# define OPTFLAGS "BD:E:I:L:PSV:Xd:ef:ij:km:nqrstvo"
215# else
216# define OPTFLAGS "BD:E:I:L:PSV:Xd:ef:ij:km:nqrstv"
217# endif
218#else
219# ifdef NMAKE
220# define OPTFLAGS "BD:E:I:PSV:Xd:ef:ij:km:nqrstvo"
221# else
222# define OPTFLAGS "BD:E:I:PSV:Xd:ef:ij:km:nqrstv"
223# endif
224#endif
225rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
226 switch(c) {
227 case 'D':
228 Var_Set(optarg, "1", VAR_GLOBAL);
229 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
230 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
231 break;
232 case 'I':
233 Parse_AddIncludeDir(optarg);
234 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
235 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
236 break;
237 case 'V':
238 printVars = TRUE;
239 (void)Lst_AtEnd(variables, (ClientData)optarg);
240 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
241 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
242 break;
243 case 'X':
244 expandVars = FALSE;
245 break;
246 case 'B':
247 compatMake = TRUE;
248 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
249 break;
250#ifdef REMOTE
251 case 'L': {
252 char *endptr;
253
254 maxLocal = strtol(optarg, &endptr, 10);
255 if (maxLocal < 0 || *endptr != '\0') {
256 warnx("illegal number, -L argument -- %s",
257 optarg);
258 usage();
259 }
260 Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
261 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
262 break;
263 }
264#endif
265 case 'P':
266 usePipes = FALSE;
267 Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
268 break;
269 case 'S':
270 keepgoing = FALSE;
271 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
272 break;
273 case 'd': {
274 char *modules = optarg;
275
276 for (; *modules; ++modules)
277 switch (*modules) {
278 case 'A':
279 debug = ~0;
280 break;
281 case 'a':
282#ifdef USE_ARCHIVES
283 debug |= DEBUG_ARCH;
284#endif /* else ignore */
285 break;
286 case 'c':
287 debug |= DEBUG_COND;
288 break;
289 case 'd':
290 debug |= DEBUG_DIR;
291 break;
292 case 'f':
293 debug |= DEBUG_FOR;
294 break;
295 case 'g':
296 if (modules[1] == '1') {
297 debug |= DEBUG_GRAPH1;
298 ++modules;
299 }
300 else if (modules[1] == '2') {
301 debug |= DEBUG_GRAPH2;
302 ++modules;
303 }
304 break;
305 case 'j':
306 debug |= DEBUG_JOB;
307 break;
308 case 'l':
309 debug |= DEBUG_LOUD;
310 break;
311 case 'm':
312 debug |= DEBUG_MAKE;
313 break;
314 case 'p': /*kso*/
315 debug |= DEBUG_PARSE;
316 break;
317 case 's':
318 debug |= DEBUG_SUFF;
319 break;
320 case 't':
321 debug |= DEBUG_TARG;
322 break;
323 case 'v':
324 debug |= DEBUG_VAR;
325 break;
326 default:
327 warnx("illegal argument to d option -- %c", *modules);
328 usage();
329 }
330 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
331 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
332 break;
333 }
334 case 'E':
335 p = emalloc(strlen(optarg) + 1);
336 (void)strcpy(p, optarg);
337 (void)Lst_AtEnd(envFirstVars, (ClientData)p);
338 Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL);
339 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
340 break;
341 case 'e':
342 checkEnvFirst = TRUE;
343 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
344 break;
345 case 'f':
346 (void)Lst_AtEnd(makefiles, (ClientData)optarg);
347 break;
348 case 'i':
349 ignoreErrors = TRUE;
350 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
351 break;
352 case 'j': {
353 char *endptr;
354
355 forceJobs = TRUE;
356 maxJobs = strtol(optarg, &endptr, 10);
357 if (maxJobs <= 0 || *endptr != '\0') {
358 warnx("illegal number, -j argument -- %s",
359 optarg);
360 usage();
361 }
362#ifndef REMOTE
363 maxLocal = maxJobs;
364#endif
365 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
366 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
367 break;
368 }
369 case 'k':
370 keepgoing = TRUE;
371 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
372 break;
373 case 'm':
374 Dir_AddDir(sysIncPath, optarg);
375 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
376 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
377 break;
378 case 'n':
379 noExecute = TRUE;
380 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
381 break;
382#ifdef NMAKE
383 case 'o':
384 go_to_objdir = TRUE;
385 Var_Append(MAKEFLAGS, "-o", VAR_GLOBAL);
386 break;
387#endif
388 case 'q':
389 queryFlag = TRUE;
390 /* Kind of nonsensical, wot? */
391 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
392 break;
393 case 'r':
394 noBuiltins = TRUE;
395 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
396 break;
397 case 's':
398 beSilent = TRUE;
399 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
400 break;
401 case 't':
402 touchFlag = TRUE;
403 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
404 break;
405 case 'v':
406 beVerbose = TRUE;
407 Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL);
408 break;
409 default:
410 case '?':
411 usage();
412 }
413 }
414
415 oldVars = TRUE;
416
417 /*
418 * See if the rest of the arguments are variable assignments and
419 * perform them if so. Else take them to be targets and stuff them
420 * on the end of the "create" list.
421 */
422 for (argv += optind, argc -= optind; *argv; ++argv, --argc)
423 if (Parse_IsVar(*argv))
424 Parse_DoVar(*argv, VAR_CMD);
425 else {
426 if (!**argv)
427 Punt("illegal (null) argument.");
428 if (**argv == '-') {
429 if ((*argv)[1])
430 optind = 0; /* -flag... */
431 else
432 optind = 1; /* - */
433 goto rearg;
434 }
435 (void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
436 }
437}
438
439/*-
440 * Main_ParseArgLine --
441 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
442 * is encountered and by main() when reading the .MAKEFLAGS envariable.
443 * Takes a line of arguments and breaks it into its
444 * component words and passes those words and the number of them to the
445 * MainParseArgs function.
446 * The line should have all its leading whitespace removed.
447 *
448 * Results:
449 * None
450 *
451 * Side Effects:
452 * Only those that come from the various arguments.
453 */
454void
455Main_ParseArgLine(line)
456 char *line; /* Line to fracture */
457{
458 char **argv; /* Manufactured argument vector */
459 int argc; /* Number of arguments in argv */
460
461 if (line == NULL)
462 return;
463 for (; *line == ' '; ++line)
464 continue;
465 if (!*line)
466 return;
467
468 argv = brk_string(line, &argc, TRUE);
469 MainParseArgs(argc, argv);
470}
471
472char *
473chdir_verify_path(path, obpath)
474 char *path;
475 char *obpath;
476{
477 struct stat sb;
478#ifdef NMAKE
479 if (!go_to_objdir)
480 return NULL;
481#endif
482
483 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
484 if (chdir(path)) {
485 warn("warning: %s", path);
486 return 0;
487 }
488 else {
489 if (path[0] != '/') {
490 (void) snprintf(obpath, MAXPATHLEN, "%s/%s",
491 curdir, path);
492 return obpath;
493 }
494 else
495 return path;
496 }
497 }
498
499 return 0;
500}
501
502
503/*-
504 * main --
505 * The main function, for obvious reasons. Initializes variables
506 * and a few modules, then parses the arguments give it in the
507 * environment and on the command line. Reads the system makefile
508 * followed by either Makefile, makefile or the file given by the
509 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
510 * flags it has received by then uses either the Make or the Compat
511 * module to create the initial list of targets.
512 *
513 * Results:
514 * If -q was given, exits -1 if anything was out-of-date. Else it exits
515 * 0.
516 *
517 * Side Effects:
518 * The program exits when done. Targets are created. etc. etc. etc.
519 */
520int
521#ifdef KMK
522main_kMk(argc, argv)
523#else
524main(argc, argv)
525#endif
526 int argc;
527 char **argv;
528{
529 Lst targs; /* target nodes to create -- passed to Make_Init */
530 Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
531 struct stat sa;
532 char *p, *p1, *path, *pathp;
533#ifdef WANT_ENV_PWD
534 struct stat sb;
535 char *pwd;
536#endif
537 char mdpath[MAXPATHLEN + 1];
538 char obpath[MAXPATHLEN + 1];
539 char cdpath[MAXPATHLEN + 1];
540 char *machine = getenv("MACHINE");
541 char *machine_arch = getenv("MACHINE_ARCH");
542 char *machine_cpu = getenv("MACHINE_CPU");
543 Lst sysMkPath; /* Path of sys.mk */
544 char *cp = NULL, *start;
545 /* avoid faults on read-only strings */
546 #ifndef KMK
547 static char syspath[] = _PATH_DEFSYSPATH;
548 #endif
549
550 #ifdef KMK
551 /*
552 * Save ourselfs.
553 */
554 argv0 = argv[0];
555 #endif
556
557#ifdef RLIMIT_NOFILE
558 /*
559 * get rid of resource limit on file descriptors
560 */
561 {
562 struct rlimit rl;
563 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
564 rl.rlim_cur != rl.rlim_max) {
565 rl.rlim_cur = rl.rlim_max;
566 (void) setrlimit(RLIMIT_NOFILE, &rl);
567 }
568 }
569#endif
570 /*
571 * Find where we are and take care of PWD for the automounter...
572 * All this code is so that we know where we are when we start up
573 * on a different machine with pmake.
574 */
575 curdir = cdpath;
576 if (getcwd(curdir, MAXPATHLEN) == NULL)
577 err(2, NULL);
578
579 if (stat(curdir, &sa) == -1)
580 err(2, "%s", curdir);
581
582#ifdef WANT_ENV_PWD
583 if ((pwd = getenv("PWD")) != NULL) {
584 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
585 sa.st_dev == sb.st_dev)
586 (void) strcpy(curdir, pwd);
587 }
588#endif
589
590#if defined(__i386__) && defined(__FreeBSD_version) && \
591 __FreeBSD_version > 300003
592 /*
593 * PC-98 kernel sets the `i386' string to the utsname.machine and
594 * it cannot be distinguished from IBM-PC by uname(3). Therefore,
595 * we check machine.ispc98 and adjust the machine variable before
596 * using usname(3) below.
597 * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
598 * __FreeBSD_version was defined as 300003. So, this check can
599 * safely be done with any kernel with version > 300003.
600 */
601 if (!machine) {
602 int ispc98;
603 size_t len;
604
605 len = sizeof(ispc98);
606 if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
607 if (ispc98)
608 machine = "pc98";
609 }
610 }
611#endif
612
613 /*
614 * Get the name of this type of MACHINE from utsname
615 * so we can share an executable for similar machines.
616 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
617 *
618 * Note that while MACHINE is decided at run-time,
619 * MACHINE_ARCH is always known at compile time.
620 */
621 if (!machine) {
622#ifndef MACHINE
623 struct utsname utsname;
624
625 if (uname(&utsname) == -1) {
626 perror(MAKE_NAME ": uname");
627 exit(2);
628 }
629 machine = utsname.machine;
630#else
631 machine = MACHINE;
632#endif
633 }
634
635 if (!machine_arch) {
636#ifndef MACHINE_ARCH
637 machine_arch = "unknown";
638#else
639 machine_arch = MACHINE_ARCH;
640#endif
641 }
642
643 /*
644 * Set machine_cpu to the minumum supported CPU revision based
645 * on the target architecture, if not already set.
646 */
647 if (!machine_cpu) {
648 if (!strcmp(machine_arch, "i386"))
649 machine_cpu = "i386";
650 else if (!strcmp(machine_arch, "alpha"))
651 machine_cpu = "ev4";
652 else
653 machine_cpu = "unknown";
654 }
655
656 #ifdef KMK
657 /* @todo figure out how to set object directory! */
658 #else
659 /*
660 * The object directory location is determined using the
661 * following order of preference:
662 *
663 * 1. MAKEOBJDIRPREFIX`cwd`
664 * 2. MAKEOBJDIR
665 * 3. _PATH_OBJDIR.${MACHINE}
666 * 4. _PATH_OBJDIR
667 * 5. _PATH_OBJDIRPREFIX`cwd`
668 *
669 * If one of the first two fails, use the current directory.
670 * If the remaining three all fail, use the current directory.
671 *
672 * Once things are initted,
673 * have to add the original directory to the search path,
674 * and modify the paths for the Makefiles apropriately. The
675 * current directory is also placed as a variable for make scripts.
676 */
677 if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
678 if (!(path = getenv("MAKEOBJDIR"))) {
679 path = _PATH_OBJDIR;
680 pathp = _PATH_OBJDIRPREFIX;
681 (void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
682 path, machine);
683 if (!(objdir = chdir_verify_path(mdpath, obpath)))
684 if (!(objdir=chdir_verify_path(path, obpath))) {
685 (void) snprintf(mdpath, MAXPATHLEN,
686 "%s%s", pathp, curdir);
687 if (!(objdir=chdir_verify_path(mdpath,
688 obpath)))
689 objdir = curdir;
690 }
691 }
692 else if (!(objdir = chdir_verify_path(path, obpath)))
693 objdir = curdir;
694 }
695 else {
696 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
697 if (!(objdir = chdir_verify_path(mdpath, obpath)))
698 objdir = curdir;
699 }
700 #endif
701
702#ifdef WANT_ENV_PWD
703 #ifdef USE_KLIB
704 kEnvSet("PWD", objdir);
705 #else
706 setenv("PWD", objdir, 1);
707 #endif
708#endif
709
710 create = Lst_Init(FALSE);
711 makefiles = Lst_Init(FALSE);
712 envFirstVars = Lst_Init(FALSE);
713 printVars = FALSE;
714 expandVars = TRUE;
715 variables = Lst_Init(FALSE);
716 beSilent = FALSE; /* Print commands as executed */
717 ignoreErrors = FALSE; /* Pay attention to non-zero returns */
718 noExecute = FALSE; /* Execute all commands */
719 keepgoing = FALSE; /* Stop on error */
720 allPrecious = FALSE; /* Remove targets when interrupted */
721 queryFlag = FALSE; /* This is not just a check-run */
722 noBuiltins = FALSE; /* Read the built-in rules */
723 touchFlag = FALSE; /* Actually update targets */
724#ifdef USE_PIPES
725 usePipes = TRUE; /* Catch child output in pipes */
726#else
727 usePipes = FALSE; /* Don't catch child output in pipes if multiple wait isn't supported */
728#endif
729 debug = 0; /* No debug verbosity, please. */
730 jobsRunning = FALSE;
731#ifdef NMAKE
732 go_to_objdir = FALSE;
733#endif
734
735 maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
736#ifdef REMOTE
737 maxJobs = DEFMAXJOBS; /* Set default max concurrency */
738#else
739 maxJobs = maxLocal;
740#endif
741 forceJobs = FALSE; /* No -j flag */
742 compatMake = FALSE; /* No compat mode */
743
744
745 /*
746 * Initialize the parsing, directory and variable modules to prepare
747 * for the reading of inclusion paths and variable settings on the
748 * command line
749 */
750 Dir_Init(); /* Initialize directory structures so -I flags
751 * can be processed correctly */
752 Parse_Init(); /* Need to initialize the paths of #include
753 * directories */
754 Var_Init(); /* As well as the lists of variables for
755 * parsing arguments */
756 str_init();
757 if (objdir != curdir)
758 Dir_AddDir(dirSearchPath, curdir);
759 Var_Set(".CURDIR", curdir, VAR_GLOBAL);
760 Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
761
762 /*
763 * Initialize various variables.
764 * MAKE also gets this name, for compatibility
765 * .MAKEFLAGS gets set to the empty string just in case.
766 * MFLAGS also gets initialized empty, for compatibility.
767 */
768 Var_Set("MAKE", argv[0], VAR_GLOBAL);
769 Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
770 Var_Set("MFLAGS", "", VAR_GLOBAL);
771 Var_Set("MACHINE", machine, VAR_GLOBAL);
772 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
773 Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
774
775 /*
776 * First snag any flags out of the MAKE environment variable.
777 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
778 * in a different format).
779 */
780#ifdef POSIX
781 Main_ParseArgLine(getenv("MAKEFLAGS"));
782#else
783 Main_ParseArgLine(getenv("MAKE"));
784#endif
785
786#ifdef KMK
787 /*
788 * Completely ignore the tool argument.
789 */
790 if (argc > 1 && !kStrCmp(argv[1], "--kMk"))
791 {
792 argc--;
793 argv++;
794 }
795#endif
796 MainParseArgs(argc, argv);
797
798 /*
799 * Be compatible if user did not specify -j and did not explicitly
800 * turned compatibility on
801 */
802 if (!compatMake && !forceJobs)
803 compatMake = TRUE;
804
805 /*
806 * Initialize archive, target and suffix modules in preparation for
807 * parsing the makefile(s)
808 */
809#ifdef USE_ARCHIVES
810 Arch_Init();
811#endif
812 Targ_Init();
813 Suff_Init();
814
815 DEFAULT = NILGNODE;
816 (void)time(&now);
817
818 /*
819 * Set up the .TARGETS variable to contain the list of targets to be
820 * created. If none specified, make the variable empty -- the parser
821 * will fill the thing in with the default or .MAIN target.
822 */
823 if (!Lst_IsEmpty(create)) {
824 LstNode ln;
825
826 for (ln = Lst_First(create); ln != NILLNODE;
827 ln = Lst_Succ(ln)) {
828 char *name = (char *)Lst_Datum(ln);
829
830 Var_Append(".TARGETS", name, VAR_GLOBAL);
831 }
832 } else
833 Var_Set(".TARGETS", "", VAR_GLOBAL);
834
835
836 #ifdef KMK
837 /*
838 * Add current directory tree to system include path all levels up to the root.
839 * ASSUMES that curdir is absolute.
840 */
841 {
842 char * psz = estrdup(curdir);
843 char * pszEnd = psz + strlen(psz);
844 while (psz < pszEnd)
845 {
846 Dir_AddDir(sysIncPath, psz);
847
848 /* Trim of the last directory component. */
849 while (pszEnd-- > psz)
850 if (*pszEnd == '/' || *pszEnd == ':')
851 {
852 if (*pszEnd == ':') /*Drive letter means end of story */
853 pszEnd = psz;
854 *pszEnd = '\0';
855 break;
856 }
857 }
858 efree(psz);
859 }
860
861 #else
862 /*
863 * If no user-supplied system path was given (through the -m option)
864 * add the directories from the DEFSYSPATH (more than one may be given
865 * as dir1:...:dirn) to the system include path.
866 */
867 if (Lst_IsEmpty(sysIncPath)) {
868 for (start = syspath; *start != '\0'; start = cp) {
869 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
870 continue;
871 if (*cp == '\0') {
872 Dir_AddDir(sysIncPath, start);
873 } else {
874 *cp++ = '\0';
875 Dir_AddDir(sysIncPath, start);
876 }
877 }
878 }
879 #endif
880
881 /*
882 * Read in the built-in rules first, followed by the specified
883 * makefile, if it was (makefile != (char *) NULL), or the default
884 * Makefile and makefile, in that order, if it wasn't.
885 */
886 if (!noBuiltins) {
887 LstNode ln;
888
889 sysMkPath = Lst_Init (FALSE);
890 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
891#ifdef NMAKE
892 if (!Lst_IsEmpty(sysMkPath))
893 {
894 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
895 if (ln != NILLNODE)
896 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
897 }
898
899#elif defined(KMK)
900 if (!Lst_IsEmpty(sysMkPath))
901 {
902 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
903 if (ln != NILLNODE)
904 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
905
906 }
907 Error(MAKE_NAME ": no config rules (%s).", _PATH_DEFSYSMK);
908#else
909 if (Lst_IsEmpty(sysMkPath))
910 Fatal(MAKE_NAME ": no system rules (%s).", _PATH_DEFSYSMK);
911 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
912 if (ln != NILLNODE)
913 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
914#endif
915 }
916
917 if (!Lst_IsEmpty(makefiles)) {
918 LstNode ln;
919
920 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
921 if (ln != NILLNODE)
922 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
923 } else
924 #ifdef KMK
925 if ( !ReadMakefile("Makefile.kMk", NULL)
926 #if KFILE_CASE
927 || !ReadMakefile("makefile.kMk", NULL)
928 || !ReadMakefile("Makefile.kmk", NULL)
929 || !ReadMakefile("makefile.kmk", NULL)
930 || !ReadMakefile("makefile", NULL)
931 #endif
932 )
933 (void)ReadMakefile("Makefile", NULL);
934 #else
935 if (!ReadMakefile("makefile", NULL))
936 (void)ReadMakefile("Makefile", NULL);
937 #endif
938
939 (void)ReadMakefile(".depend", NULL);
940
941 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
942 efree(p1);
943
944 /* Install all the flags into the MAKE envariable. */
945 if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
946#ifdef POSIX
947 #ifdef USE_KLIB
948 kEnvSet("MAKEFLAGS", p, TRUE);
949 #else
950 setenv("MAKEFLAGS", p, 1);
951 #endif
952#else
953 #ifdef USE_KLIB
954 kEnvSet("MAKE", p, TRUE);
955 #else
956 setenv("MAKE", p, 1);
957 #endif
958#endif
959 efree(p1);
960
961 /*
962 * For compatibility, look at the directories in the VPATH variable
963 * and add them to the search path, if the variable is defined. The
964 * variable's value is in the same format as the PATH envariable, i.e.
965 * <directory>:<directory>:<directory>...
966 */
967 if (Var_Exists("VPATH", VAR_CMD)) {
968 char *vpath, *path, *cp, savec;
969 /*
970 * GCC stores string constants in read-only memory, but
971 * Var_Subst will want to write this thing, so store it
972 * in an array
973 */
974 static char VPATH[] = "${VPATH}";
975
976 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
977 path = vpath;
978 do {
979 /* skip to end of directory */
980 for (cp = path; *cp != ':' && *cp != '\0'; cp++)
981 continue;
982 /* Save terminator character so know when to stop */
983 savec = *cp;
984 *cp = '\0';
985 /* Add directory to search path */
986 Dir_AddDir(dirSearchPath, path);
987 *cp = savec;
988 path = cp + 1;
989 } while (savec == ':');
990 (void)efree((Address)vpath);
991 }
992
993 /*
994 * Now that all search paths have been read for suffixes et al, it's
995 * time to add the default search path to their lists...
996 */
997 Suff_DoPaths();
998
999 /* print the initial graph, if the user requested it */
1000 if (DEBUG(GRAPH1))
1001 Targ_PrintGraph(1);
1002
1003 /* print the values of any variables requested by the user */
1004 if (printVars) {
1005 LstNode ln;
1006
1007 for (ln = Lst_First(variables); ln != NILLNODE;
1008 ln = Lst_Succ(ln)) {
1009 char *value;
1010 if (expandVars) {
1011 p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
1012 /* This sprintf is safe, because of the malloc above */
1013 (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
1014 value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
1015 } else {
1016 value = Var_Value((char *)Lst_Datum(ln),
1017 VAR_GLOBAL, &p1);
1018 }
1019 printf("%s\n", value ? value : "");
1020 if (p1)
1021 efree(p1);
1022 }
1023 }
1024
1025 /*
1026 * Have now read the entire graph and need to make a list of targets
1027 * to create. If none was given on the command line, we consult the
1028 * parsing module to find the main target(s) to create.
1029 */
1030 if (Lst_IsEmpty(create))
1031 targs = Parse_MainName();
1032 else
1033 targs = Targ_FindList(create, TARG_CREATE);
1034
1035 if (!compatMake && !printVars) {
1036 /*
1037 * Initialize job module before traversing the graph, now that
1038 * any .BEGIN and .END targets have been read. This is done
1039 * only if the -q flag wasn't given (to prevent the .BEGIN from
1040 * being executed should it exist).
1041 */
1042 if (!queryFlag) {
1043 if (maxLocal == -1)
1044 maxLocal = maxJobs;
1045 Job_Init(maxJobs, maxLocal);
1046 jobsRunning = TRUE;
1047 }
1048
1049 /* Traverse the graph, checking on all the targets */
1050 outOfDate = Make_Run(targs);
1051 } else if (!printVars) {
1052 /*
1053 * Compat_Init will take care of creating all the targets as
1054 * well as initializing the module.
1055 */
1056 Compat_Run(targs);
1057 }
1058
1059 Lst_Destroy(targs, NOFREE);
1060 Lst_Destroy(variables, NOFREE);
1061 Lst_Destroy(makefiles, NOFREE);
1062 Lst_Destroy(create, (void (*) __P((ClientData))) efree);
1063
1064 /* print the graph now it's been processed if the user requested it */
1065 if (DEBUG(GRAPH2))
1066 Targ_PrintGraph(2);
1067
1068 Suff_End();
1069 Targ_End();
1070#ifdef USE_ARCHIVES
1071 Arch_End();
1072#endif
1073 str_end();
1074 Var_End();
1075 Parse_End();
1076 Dir_End();
1077
1078 if (queryFlag && outOfDate)
1079 return(1);
1080 else
1081 return(0);
1082}
1083
1084/*-
1085 * ReadMakefile --
1086 * Open and parse the given makefile.
1087 *
1088 * Results:
1089 * TRUE if ok. FALSE if couldn't open file.
1090 *
1091 * Side Effects:
1092 * lots
1093 */
1094static Boolean
1095ReadMakefile(p, q)
1096 ClientData p, q;
1097{
1098 char *fname = p; /* makefile to read */
1099 extern Lst parseIncPath;
1100 FILE *stream;
1101 char *name, path[MAXPATHLEN + 1];
1102 char *MAKEFILE;
1103 int setMAKEFILE;
1104
1105 if (!strcmp(fname, "-")) {
1106 Parse_File("(stdin)", stdin);
1107 Var_Set("MAKEFILE", "", VAR_GLOBAL);
1108 } else {
1109 setMAKEFILE = strcmp(fname, ".depend");
1110
1111 /* if we've chdir'd, rebuild the path name */
1112 if (curdir != objdir && *fname != '/') {
1113 (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
1114 if (realpath(path, path) != NULL &&
1115 (stream = fopen(path, "r")) != NULL) {
1116 MAKEFILE = fname;
1117 fname = path;
1118 goto found;
1119 }
1120 } else if (realpath(fname, path) != NULL) {
1121 MAKEFILE = fname;
1122 fname = path;
1123 if ((stream = fopen(fname, "r")) != NULL)
1124 goto found;
1125 }
1126 /* look in -I and system include directories. */
1127 name = Dir_FindFile(fname, parseIncPath);
1128 if (!name)
1129 name = Dir_FindFile(fname, sysIncPath);
1130 if (!name || !(stream = fopen(name, "r")))
1131 return(FALSE);
1132 MAKEFILE = fname = name;
1133 /*
1134 * set the MAKEFILE variable desired by System V fans -- the
1135 * placement of the setting here means it gets set to the last
1136 * makefile specified, as it is set by SysV make.
1137 */
1138found:
1139 if (setMAKEFILE)
1140 Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL);
1141 Parse_File(fname, stream);
1142 (void)fclose(stream);
1143 }
1144 return(TRUE);
1145}
1146
1147/*-
1148 * Cmd_Exec --
1149 * Execute the command in cmd, and return the output of that command
1150 * in a string.
1151 *
1152 * Results:
1153 * A string containing the output of the command, or the empty string
1154 * If err is not NULL, it contains the reason for the command failure
1155 *
1156 * Side Effects:
1157 * The string must be freed by the caller.
1158 */
1159char *
1160Cmd_Exec(cmd, err)
1161 char *cmd;
1162 char **err;
1163{
1164#ifdef KMK
1165 /** @todo this can be executed directly in the shell!!!
1166 */
1167 int rc;
1168 char * args[4]; /* Args for invoking the shell */
1169 KFILE fhPipe; /* Pipe handle. */
1170 KPID cpid; /* Child PID */
1171 KPROCRES status; /* Child exit status. */
1172 char * res; /* result */
1173 Buffer buf; /* buffer to store the result */
1174 char * cp;
1175 int cc;
1176
1177
1178 *err = NULL;
1179
1180 /*
1181 * Set up arguments for shell
1182 */
1183 args[0] = argv0;
1184 args[1] = "--kShell";
1185 args[2] = cmd;
1186 args[3] = NULL;
1187
1188
1189 /*
1190 * Execute command in pipe.
1191 */
1192 rc = kProcPiped(&args[0],
1193 KPROCPIPED_FLAGS_STDOUT,
1194 &cpid,
1195 &fhPipe);
1196 if (!rc)
1197 {
1198 FILE *phPipe;
1199 buf = Buf_Init (MAKE_BSIZE);
1200
1201 /*
1202 * Read the output using a file stream for automatic '\n' newline conv.
1203 */
1204 phPipe = fdopen(fhPipe, "r");
1205 cc = -1;
1206 if (phPipe)
1207 {
1208 do {
1209 char result[BUFSIZ];
1210 cc = fread(result, 1, sizeof(result), phPipe);
1211 if (cc > 0)
1212 Buf_AddBytes(buf, cc, (Byte *) result);
1213 }
1214 while (cc > 0 || (cc == -1 && errno == EINTR));
1215 fclose(phPipe);
1216 }
1217
1218 /*
1219 * Close the input side of the pipe and wait for the child to exit.
1220 */
1221 kFileClose(fhPipe);
1222 rc = kProcWait(cpid, KPROCWAIT_FLAGS_WAIT, &status, NULL);
1223
1224 /*
1225 * Check for errors, get buffered bits.
1226 */
1227 if (cc == -1)
1228 *err = "Error reading shell's output for \"%s\"";
1229
1230 res = (char *)Buf_GetAll (buf, &cc);
1231 Buf_Destroy (buf, FALSE);
1232
1233 if (status.uExitCode || status.fFlags != KPROCRES_FLAGS_NORMAL)
1234 *err = "\"%s\" returned non-zero status";
1235
1236 /*
1237 * Null-terminate the result, convert newlines to spaces and
1238 * install it in the variable. Final newline is removed.
1239 */
1240 res[cc] = '\0';
1241 cp = &res[cc] - 1;
1242 if (*cp == '\n')
1243 *cp-- = '\0';
1244
1245 while (cp >= res)
1246 {
1247 if (*cp == '\n')
1248 *cp = ' ';
1249 cp--;
1250 }
1251
1252 return res;
1253 }
1254 else
1255 *err = "Couldn't exec \"%s\"";
1256
1257 res = emalloc(1);
1258 *res = '\0';
1259 return res;
1260
1261#else /* not KMK */
1262
1263 char *args[4]; /* Args for invoking the shell */
1264 int fds[2]; /* Pipe streams */
1265 int cpid; /* Child PID */
1266 int pid; /* PID from wait() */
1267 char *res; /* result */
1268 int status; /* command exit status */
1269 Buffer buf; /* buffer to store the result */
1270 char *cp;
1271 int cc;
1272
1273
1274 *err = NULL;
1275
1276 /*
1277 * Set up arguments for shell
1278 */
1279 args[0] = "sh";
1280 args[1] = "-c";
1281 args[2] = cmd;
1282 args[3] = NULL;
1283
1284 /*
1285 * Open a pipe for fetching its output
1286 */
1287 if (pipe(fds) == -1) {
1288 *err = "Couldn't create pipe for \"%s\"";
1289 goto bad;
1290 }
1291
1292 /*
1293 * Fork
1294 */
1295#ifdef __EMX__
1296 switch (cpid = fork())
1297#else
1298 switch (cpid = vfork())
1299#endif
1300 {
1301 case 0:
1302 /*
1303 * Close input side of pipe
1304 */
1305 (void) close(fds[0]);
1306
1307 /*
1308 * Duplicate the output stream to the shell's output, then
1309 * shut the extra thing down. Note we don't fetch the error
1310 * stream...why not? Why?
1311 */
1312 (void) dup2(fds[1], 1);
1313 (void) close(fds[1]);
1314
1315 #ifdef OS2
1316 {
1317 const char *psz = getenv("COMSPEC");
1318 if (!psz)
1319 psz = getenv("OS2_SHELL");
1320 if (!psz)
1321 psz = "c:\\os2\\cmd.exe";
1322 (void) execv(psz, args);
1323 }
1324 #else
1325 (void) execv("/bin/sh", args);
1326 #endif
1327 _exit(1);
1328 /*NOTREACHED*/
1329
1330 case -1:
1331 *err = "Couldn't exec \"%s\"";
1332 goto bad;
1333
1334 default:
1335 /*
1336 * No need for the writing half
1337 */
1338 (void) close(fds[1]);
1339
1340 buf = Buf_Init (MAKE_BSIZE);
1341
1342 do {
1343 char result[BUFSIZ];
1344 cc = read(fds[0], result, sizeof(result));
1345 if (cc > 0)
1346 Buf_AddBytes(buf, cc, (Byte *) result);
1347 }
1348 while (cc > 0 || (cc == -1 && errno == EINTR));
1349
1350 /*
1351 * Close the input side of the pipe.
1352 */
1353 (void) close(fds[0]);
1354
1355 /*
1356 * Wait for the process to exit.
1357 */
1358 while(((pid = wait(&status)) != cpid) && (pid >= 0))
1359 continue;
1360
1361 if (cc == -1)
1362 *err = "Error reading shell's output for \"%s\"";
1363
1364 res = (char *)Buf_GetAll (buf, &cc);
1365 Buf_Destroy (buf, FALSE);
1366
1367 if (status)
1368 *err = "\"%s\" returned non-zero status";
1369
1370 /*
1371 * Null-terminate the result, convert newlines to spaces and
1372 * install it in the variable.
1373 */
1374 res[cc] = '\0';
1375 cp = &res[cc] - 1;
1376
1377 if (*cp == '\n') {
1378 /*
1379 * A final newline is just stripped
1380 */
1381 *cp-- = '\0';
1382 }
1383 while (cp >= res) {
1384 if (*cp == '\n') {
1385 *cp = ' ';
1386 }
1387 cp--;
1388 }
1389 break;
1390 }
1391 return res;
1392bad:
1393 res = emalloc(1);
1394 *res = '\0';
1395 return res;
1396#endif /* KMK */
1397}
1398
1399/*-
1400 * Error --
1401 * Print an error message given its format.
1402 *
1403 * Results:
1404 * None.
1405 *
1406 * Side Effects:
1407 * The message is printed.
1408 */
1409/* VARARGS */
1410void
1411#if defined(__STDC__) || defined(__IBMC__)
1412Error(char *fmt, ...)
1413#else
1414Error(va_alist)
1415 va_dcl
1416#endif
1417{
1418 va_list ap;
1419#if defined(__STDC__) || defined(__IBMC__)
1420 va_start(ap, fmt);
1421#else
1422 char *fmt;
1423
1424 va_start(ap);
1425 fmt = va_arg(ap, char *);
1426#endif
1427 (void)vfprintf(stderr, fmt, ap);
1428 va_end(ap);
1429 (void)fprintf(stderr, "\n");
1430 (void)fflush(stderr);
1431}
1432
1433/*-
1434 * Fatal --
1435 * Produce a Fatal error message. If jobs are running, waits for them
1436 * to finish.
1437 *
1438 * Results:
1439 * None
1440 *
1441 * Side Effects:
1442 * The program exits
1443 */
1444/* VARARGS */
1445void
1446#if defined(__STDC__) || defined(__IBMC__)
1447Fatal(char *fmt, ...)
1448#else
1449Fatal(va_alist)
1450 va_dcl
1451#endif
1452{
1453 va_list ap;
1454#if defined(__STDC__) || defined(__IBMC__)
1455 va_start(ap, fmt);
1456#else
1457 char *fmt;
1458
1459 va_start(ap);
1460 fmt = va_arg(ap, char *);
1461#endif
1462 if (jobsRunning)
1463 Job_Wait();
1464
1465 (void)vfprintf(stderr, fmt, ap);
1466 va_end(ap);
1467 (void)fprintf(stderr, "\n");
1468 (void)fflush(stderr);
1469
1470 if (DEBUG(GRAPH2))
1471 Targ_PrintGraph(2);
1472 exit(2); /* Not 1 so -q can distinguish error */
1473}
1474
1475/*
1476 * Punt --
1477 * Major exception once jobs are being created. Kills all jobs, prints
1478 * a message and exits.
1479 *
1480 * Results:
1481 * None
1482 *
1483 * Side Effects:
1484 * All children are killed indiscriminately and the program Lib_Exits
1485 */
1486/* VARARGS */
1487void
1488#if defined(__STDC__) || defined(__IBMC__)
1489Punt(char *fmt, ...)
1490#else
1491Punt(va_alist)
1492 va_dcl
1493#endif
1494{
1495 va_list ap;
1496#if defined(__STDC__) || defined(__IBMC__)
1497 va_start(ap, fmt);
1498#else
1499 char *fmt;
1500
1501 va_start(ap);
1502 fmt = va_arg(ap, char *);
1503#endif
1504
1505 (void)fprintf(stderr, MAKE_NAME ": ");
1506 (void)vfprintf(stderr, fmt, ap);
1507 va_end(ap);
1508 (void)fprintf(stderr, "\n");
1509 (void)fflush(stderr);
1510
1511 DieHorribly();
1512}
1513
1514/*-
1515 * DieHorribly --
1516 * Exit without giving a message.
1517 *
1518 * Results:
1519 * None
1520 *
1521 * Side Effects:
1522 * A big one...
1523 */
1524void
1525DieHorribly()
1526{
1527 if (jobsRunning)
1528 Job_AbortAll();
1529 if (DEBUG(GRAPH2))
1530 Targ_PrintGraph(2);
1531 exit(2); /* Not 1, so -q can distinguish error */
1532}
1533
1534/*
1535 * Finish --
1536 * Called when aborting due to errors in child shell to signal
1537 * abnormal exit.
1538 *
1539 * Results:
1540 * None
1541 *
1542 * Side Effects:
1543 * The program exits
1544 */
1545void
1546Finish(errors)
1547 int errors; /* number of errors encountered in Make_Make */
1548{
1549 Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1550}
1551
1552/*
1553 * emalloc --
1554 * malloc, but die on error.
1555 */
1556void *
1557emalloc(len)
1558 size_t len;
1559{
1560 void *p;
1561
1562 if ((p = malloc(len)) == NULL)
1563 enomem();
1564 return(p);
1565}
1566
1567/*
1568 * estrdup --
1569 * strdup, but die on error.
1570 */
1571char *
1572estrdup(str)
1573 const char *str;
1574{
1575 char *p;
1576
1577 if ((p = strdup(str)) == NULL)
1578 enomem();
1579 return(p);
1580}
1581
1582/*
1583 * erealloc --
1584 * realloc, but die on error.
1585 */
1586void *
1587erealloc(ptr, size)
1588 void *ptr;
1589 size_t size;
1590{
1591 if ((ptr = realloc(ptr, size)) == NULL)
1592 enomem();
1593 return(ptr);
1594}
1595
1596/*
1597 * efree --
1598 * efree, no change.
1599 */
1600void
1601efree(ptr)
1602 void *ptr;
1603{
1604 if (ptr)
1605 free(ptr);
1606}
1607
1608/*
1609 * enomem --
1610 * die when out of memory.
1611 */
1612void
1613enomem()
1614{
1615 err(2, NULL);
1616}
1617
1618/*
1619 * enunlink --
1620 * Remove a file carefully, avoiding directories.
1621 */
1622int
1623eunlink(file)
1624 const char *file;
1625{
1626 struct stat st;
1627
1628#if defined(OS2)
1629 if (stat(file, &st) == -1)
1630#else
1631 if (lstat(file, &st) == -1)
1632#endif
1633 return -1;
1634
1635 if (S_ISDIR(st.st_mode)) {
1636 errno = EISDIR;
1637 return -1;
1638 }
1639 return unlink(file);
1640}
1641
1642/*
1643 * usage --
1644 * exit with usage message
1645 */
1646static void
1647usage()
1648{
1649 (void)fprintf(stderr, "%s\n%s\n%s\n"
1650#ifdef NMAKE
1651"%s\n"
1652#endif
1653#ifdef KMK
1654"%s\n"
1655#endif
1656 ,
1657"usage: kmk [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]",
1658" [-I directory] [-j max_jobs] [-m directory] [-V variable]",
1659" [variable=value] [target ...]"
1660#ifdef NMAKE
1661,"NMAKE compatible mode enabled."
1662#endif
1663#ifdef KMK
1664,"kMk extensions enabled."
1665#endif
1666);
1667 exit(2);
1668}
1669
1670
1671int
1672PrintAddr(a, b)
1673 ClientData a;
1674 ClientData b;
1675{
1676 printf("%lx ", (unsigned long) a);
1677 return b ? 0 : 0;
1678}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette