VirtualBox

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

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

kMk changes. Made extensions configurable from config.h. fixed parents.

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