VirtualBox

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

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

KMK.

  • 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
516#ifdef KMK
517main_kMk(argc, argv)
518#else
519main(argc, argv)
520#endif
521 int argc;
522 char **argv;
523{
524 Lst targs; /* target nodes to create -- passed to Make_Init */
525 Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
526 struct stat sa;
527 char *p, *p1, *path, *pathp;
528#ifdef WANT_ENV_PWD
529 struct stat sb;
530 char *pwd;
531#endif
532 char mdpath[MAXPATHLEN + 1];
533 char obpath[MAXPATHLEN + 1];
534 char cdpath[MAXPATHLEN + 1];
535 char *machine = getenv("MACHINE");
536 char *machine_arch = getenv("MACHINE_ARCH");
537 char *machine_cpu = getenv("MACHINE_CPU");
538 Lst sysMkPath; /* Path of sys.mk */
539 char *cp = NULL, *start;
540 /* avoid faults on read-only strings */
541 #ifndef KMK
542 static char syspath[] = _PATH_DEFSYSPATH;
543 #endif
544
545#ifdef RLIMIT_NOFILE
546 /*
547 * get rid of resource limit on file descriptors
548 */
549 {
550 struct rlimit rl;
551 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
552 rl.rlim_cur != rl.rlim_max) {
553 rl.rlim_cur = rl.rlim_max;
554 (void) setrlimit(RLIMIT_NOFILE, &rl);
555 }
556 }
557#endif
558 /*
559 * Find where we are and take care of PWD for the automounter...
560 * All this code is so that we know where we are when we start up
561 * on a different machine with pmake.
562 */
563 curdir = cdpath;
564 if (getcwd(curdir, MAXPATHLEN) == NULL)
565 err(2, NULL);
566
567 if (stat(curdir, &sa) == -1)
568 err(2, "%s", curdir);
569
570#ifdef WANT_ENV_PWD
571 if ((pwd = getenv("PWD")) != NULL) {
572 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
573 sa.st_dev == sb.st_dev)
574 (void) strcpy(curdir, pwd);
575 }
576#endif
577
578#if defined(__i386__) && defined(__FreeBSD_version) && \
579 __FreeBSD_version > 300003
580 /*
581 * PC-98 kernel sets the `i386' string to the utsname.machine and
582 * it cannot be distinguished from IBM-PC by uname(3). Therefore,
583 * we check machine.ispc98 and adjust the machine variable before
584 * using usname(3) below.
585 * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
586 * __FreeBSD_version was defined as 300003. So, this check can
587 * safely be done with any kernel with version > 300003.
588 */
589 if (!machine) {
590 int ispc98;
591 size_t len;
592
593 len = sizeof(ispc98);
594 if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
595 if (ispc98)
596 machine = "pc98";
597 }
598 }
599#endif
600
601 /*
602 * Get the name of this type of MACHINE from utsname
603 * so we can share an executable for similar machines.
604 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
605 *
606 * Note that while MACHINE is decided at run-time,
607 * MACHINE_ARCH is always known at compile time.
608 */
609 if (!machine) {
610#ifndef MACHINE
611 struct utsname utsname;
612
613 if (uname(&utsname) == -1) {
614 perror(MAKE_NAME ": uname");
615 exit(2);
616 }
617 machine = utsname.machine;
618#else
619 machine = MACHINE;
620#endif
621 }
622
623 if (!machine_arch) {
624#ifndef MACHINE_ARCH
625 machine_arch = "unknown";
626#else
627 machine_arch = MACHINE_ARCH;
628#endif
629 }
630
631 /*
632 * Set machine_cpu to the minumum supported CPU revision based
633 * on the target architecture, if not already set.
634 */
635 if (!machine_cpu) {
636 if (!strcmp(machine_arch, "i386"))
637 machine_cpu = "i386";
638 else if (!strcmp(machine_arch, "alpha"))
639 machine_cpu = "ev4";
640 else
641 machine_cpu = "unknown";
642 }
643
644 #ifdef KMK
645 /* @todo figure out how to set object directory! */
646 #else
647 /*
648 * The object directory location is determined using the
649 * following order of preference:
650 *
651 * 1. MAKEOBJDIRPREFIX`cwd`
652 * 2. MAKEOBJDIR
653 * 3. _PATH_OBJDIR.${MACHINE}
654 * 4. _PATH_OBJDIR
655 * 5. _PATH_OBJDIRPREFIX`cwd`
656 *
657 * If one of the first two fails, use the current directory.
658 * If the remaining three all fail, use the current directory.
659 *
660 * Once things are initted,
661 * have to add the original directory to the search path,
662 * and modify the paths for the Makefiles apropriately. The
663 * current directory is also placed as a variable for make scripts.
664 */
665 if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
666 if (!(path = getenv("MAKEOBJDIR"))) {
667 path = _PATH_OBJDIR;
668 pathp = _PATH_OBJDIRPREFIX;
669 (void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
670 path, machine);
671 if (!(objdir = chdir_verify_path(mdpath, obpath)))
672 if (!(objdir=chdir_verify_path(path, obpath))) {
673 (void) snprintf(mdpath, MAXPATHLEN,
674 "%s%s", pathp, curdir);
675 if (!(objdir=chdir_verify_path(mdpath,
676 obpath)))
677 objdir = curdir;
678 }
679 }
680 else if (!(objdir = chdir_verify_path(path, obpath)))
681 objdir = curdir;
682 }
683 else {
684 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
685 if (!(objdir = chdir_verify_path(mdpath, obpath)))
686 objdir = curdir;
687 }
688 #endif
689
690#ifdef WANT_ENV_PWD
691 #ifdef USE_KLIB
692 kEnvSet("PWD", objdir);
693 #else
694 setenv("PWD", objdir, 1);
695 #endif
696#endif
697
698 create = Lst_Init(FALSE);
699 makefiles = Lst_Init(FALSE);
700 envFirstVars = Lst_Init(FALSE);
701 printVars = FALSE;
702 expandVars = TRUE;
703 variables = Lst_Init(FALSE);
704 beSilent = FALSE; /* Print commands as executed */
705 ignoreErrors = FALSE; /* Pay attention to non-zero returns */
706 noExecute = FALSE; /* Execute all commands */
707 keepgoing = FALSE; /* Stop on error */
708 allPrecious = FALSE; /* Remove targets when interrupted */
709 queryFlag = FALSE; /* This is not just a check-run */
710 noBuiltins = FALSE; /* Read the built-in rules */
711 touchFlag = FALSE; /* Actually update targets */
712 usePipes = TRUE; /* Catch child output in pipes */
713 debug = 0; /* No debug verbosity, please. */
714 jobsRunning = FALSE;
715#ifdef NMAKE
716 go_to_objdir = FALSE;
717#endif
718
719 maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
720#ifdef REMOTE
721 maxJobs = DEFMAXJOBS; /* Set default max concurrency */
722#else
723 maxJobs = maxLocal;
724#endif
725 forceJobs = FALSE; /* No -j flag */
726 compatMake = FALSE; /* No compat mode */
727
728
729 /*
730 * Initialize the parsing, directory and variable modules to prepare
731 * for the reading of inclusion paths and variable settings on the
732 * command line
733 */
734 Dir_Init(); /* Initialize directory structures so -I flags
735 * can be processed correctly */
736 Parse_Init(); /* Need to initialize the paths of #include
737 * directories */
738 Var_Init(); /* As well as the lists of variables for
739 * parsing arguments */
740 str_init();
741 if (objdir != curdir)
742 Dir_AddDir(dirSearchPath, curdir);
743 Var_Set(".CURDIR", curdir, VAR_GLOBAL);
744 Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
745
746 /*
747 * Initialize various variables.
748 * MAKE also gets this name, for compatibility
749 * .MAKEFLAGS gets set to the empty string just in case.
750 * MFLAGS also gets initialized empty, for compatibility.
751 */
752 Var_Set("MAKE", argv[0], VAR_GLOBAL);
753 Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
754 Var_Set("MFLAGS", "", VAR_GLOBAL);
755 Var_Set("MACHINE", machine, VAR_GLOBAL);
756 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
757 Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
758
759 /*
760 * First snag any flags out of the MAKE environment variable.
761 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
762 * in a different format).
763 */
764#ifdef POSIX
765 Main_ParseArgLine(getenv("MAKEFLAGS"));
766#else
767 Main_ParseArgLine(getenv("MAKE"));
768#endif
769
770 MainParseArgs(argc, argv);
771
772 /*
773 * Be compatible if user did not specify -j and did not explicitly
774 * turned compatibility on
775 */
776 if (!compatMake && !forceJobs)
777 compatMake = TRUE;
778
779 /*
780 * Initialize archive, target and suffix modules in preparation for
781 * parsing the makefile(s)
782 */
783#ifdef USE_ARCHIVES
784 Arch_Init();
785#endif
786 Targ_Init();
787 Suff_Init();
788
789 DEFAULT = NILGNODE;
790 (void)time(&now);
791
792 /*
793 * Set up the .TARGETS variable to contain the list of targets to be
794 * created. If none specified, make the variable empty -- the parser
795 * will fill the thing in with the default or .MAIN target.
796 */
797 if (!Lst_IsEmpty(create)) {
798 LstNode ln;
799
800 for (ln = Lst_First(create); ln != NILLNODE;
801 ln = Lst_Succ(ln)) {
802 char *name = (char *)Lst_Datum(ln);
803
804 Var_Append(".TARGETS", name, VAR_GLOBAL);
805 }
806 } else
807 Var_Set(".TARGETS", "", VAR_GLOBAL);
808
809
810 #ifdef KMK
811 /*
812 * Add current directory tree to system include path all levels up to the root.
813 * ASSUMES that curdir is absolute.
814 */
815 {
816 char * psz = estrdup(curdir);
817 char * pszEnd = psz + strlen(psz);
818 while (psz < pszEnd)
819 {
820 Dir_AddDir(sysIncPath, psz);
821
822 /* Trim of the last directory component. */
823 while (pszEnd-- > psz)
824 if (*pszEnd == '/' || *pszEnd == ':')
825 {
826 if (*pszEnd == ':') /*Drive letter means end of story */
827 pszEnd = psz;
828 *pszEnd = '\0';
829 break;
830 }
831 }
832 efree(psz);
833 }
834
835 #else
836 /*
837 * If no user-supplied system path was given (through the -m option)
838 * add the directories from the DEFSYSPATH (more than one may be given
839 * as dir1:...:dirn) to the system include path.
840 */
841 if (Lst_IsEmpty(sysIncPath)) {
842 for (start = syspath; *start != '\0'; start = cp) {
843 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
844 continue;
845 if (*cp == '\0') {
846 Dir_AddDir(sysIncPath, start);
847 } else {
848 *cp++ = '\0';
849 Dir_AddDir(sysIncPath, start);
850 }
851 }
852 }
853 #endif
854
855 /*
856 * Read in the built-in rules first, followed by the specified
857 * makefile, if it was (makefile != (char *) NULL), or the default
858 * Makefile and makefile, in that order, if it wasn't.
859 */
860 if (!noBuiltins) {
861 LstNode ln;
862
863 sysMkPath = Lst_Init (FALSE);
864 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
865#ifdef NMAKE
866 if (!Lst_IsEmpty(sysMkPath))
867 {
868 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
869 if (ln != NILLNODE)
870 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
871 }
872
873#elif defined(KMK)
874 if (!Lst_IsEmpty(sysMkPath))
875 {
876 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
877 if (ln != NILLNODE)
878 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
879
880 }
881 Error(MAKE_NAME ": no config rules (%s).", _PATH_DEFSYSMK);
882#else
883 if (Lst_IsEmpty(sysMkPath))
884 Fatal(MAKE_NAME ": no system rules (%s).", _PATH_DEFSYSMK);
885 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
886 if (ln != NILLNODE)
887 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
888#endif
889 }
890
891 if (!Lst_IsEmpty(makefiles)) {
892 LstNode ln;
893
894 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
895 if (ln != NILLNODE)
896 Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
897 } else
898 #ifdef KMK
899 if ( !ReadMakefile("Makefile.kMk", NULL)
900 #if KFILE_CASE
901 || !ReadMakefile("makefile.kMk", NULL)
902 || !ReadMakefile("Makefile.kmk", NULL)
903 || !ReadMakefile("makefile.kmk", NULL)
904 || !ReadMakefile("makefile", NULL)
905 #endif
906 )
907 (void)ReadMakefile("Makefile", NULL);
908 #else
909 if (!ReadMakefile("makefile", NULL))
910 (void)ReadMakefile("Makefile", NULL);
911 #endif
912
913 (void)ReadMakefile(".depend", NULL);
914
915 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
916 efree(p1);
917
918 /* Install all the flags into the MAKE envariable. */
919 if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
920#ifdef POSIX
921 #ifdef USE_KLIB
922 kEnvSet("MAKEFLAGS", p, TRUE);
923 #else
924 setenv("MAKEFLAGS", p, 1);
925 #endif
926#else
927 #ifdef USE_KLIB
928 kEnvSet("MAKE", p, TRUE);
929 #else
930 setenv("MAKE", p, 1);
931 #endif
932#endif
933 efree(p1);
934
935 /*
936 * For compatibility, look at the directories in the VPATH variable
937 * and add them to the search path, if the variable is defined. The
938 * variable's value is in the same format as the PATH envariable, i.e.
939 * <directory>:<directory>:<directory>...
940 */
941 if (Var_Exists("VPATH", VAR_CMD)) {
942 char *vpath, *path, *cp, savec;
943 /*
944 * GCC stores string constants in read-only memory, but
945 * Var_Subst will want to write this thing, so store it
946 * in an array
947 */
948 static char VPATH[] = "${VPATH}";
949
950 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
951 path = vpath;
952 do {
953 /* skip to end of directory */
954 for (cp = path; *cp != ':' && *cp != '\0'; cp++)
955 continue;
956 /* Save terminator character so know when to stop */
957 savec = *cp;
958 *cp = '\0';
959 /* Add directory to search path */
960 Dir_AddDir(dirSearchPath, path);
961 *cp = savec;
962 path = cp + 1;
963 } while (savec == ':');
964 (void)efree((Address)vpath);
965 }
966
967 /*
968 * Now that all search paths have been read for suffixes et al, it's
969 * time to add the default search path to their lists...
970 */
971 Suff_DoPaths();
972
973 /* print the initial graph, if the user requested it */
974 if (DEBUG(GRAPH1))
975 Targ_PrintGraph(1);
976
977 /* print the values of any variables requested by the user */
978 if (printVars) {
979 LstNode ln;
980
981 for (ln = Lst_First(variables); ln != NILLNODE;
982 ln = Lst_Succ(ln)) {
983 char *value;
984 if (expandVars) {
985 p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
986 /* This sprintf is safe, because of the malloc above */
987 (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
988 value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
989 } else {
990 value = Var_Value((char *)Lst_Datum(ln),
991 VAR_GLOBAL, &p1);
992 }
993 printf("%s\n", value ? value : "");
994 if (p1)
995 efree(p1);
996 }
997 }
998
999 /*
1000 * Have now read the entire graph and need to make a list of targets
1001 * to create. If none was given on the command line, we consult the
1002 * parsing module to find the main target(s) to create.
1003 */
1004 if (Lst_IsEmpty(create))
1005 targs = Parse_MainName();
1006 else
1007 targs = Targ_FindList(create, TARG_CREATE);
1008
1009 if (!compatMake && !printVars) {
1010 /*
1011 * Initialize job module before traversing the graph, now that
1012 * any .BEGIN and .END targets have been read. This is done
1013 * only if the -q flag wasn't given (to prevent the .BEGIN from
1014 * being executed should it exist).
1015 */
1016 if (!queryFlag) {
1017 if (maxLocal == -1)
1018 maxLocal = maxJobs;
1019 Job_Init(maxJobs, maxLocal);
1020 jobsRunning = TRUE;
1021 }
1022
1023 /* Traverse the graph, checking on all the targets */
1024 outOfDate = Make_Run(targs);
1025 } else if (!printVars) {
1026 /*
1027 * Compat_Init will take care of creating all the targets as
1028 * well as initializing the module.
1029 */
1030 Compat_Run(targs);
1031 }
1032
1033 Lst_Destroy(targs, NOFREE);
1034 Lst_Destroy(variables, NOFREE);
1035 Lst_Destroy(makefiles, NOFREE);
1036 Lst_Destroy(create, (void (*) __P((ClientData))) efree);
1037
1038 /* print the graph now it's been processed if the user requested it */
1039 if (DEBUG(GRAPH2))
1040 Targ_PrintGraph(2);
1041
1042 Suff_End();
1043 Targ_End();
1044#ifdef USE_ARCHIVES
1045 Arch_End();
1046#endif
1047 str_end();
1048 Var_End();
1049 Parse_End();
1050 Dir_End();
1051
1052 if (queryFlag && outOfDate)
1053 return(1);
1054 else
1055 return(0);
1056}
1057
1058/*-
1059 * ReadMakefile --
1060 * Open and parse the given makefile.
1061 *
1062 * Results:
1063 * TRUE if ok. FALSE if couldn't open file.
1064 *
1065 * Side Effects:
1066 * lots
1067 */
1068static Boolean
1069ReadMakefile(p, q)
1070 ClientData p, q;
1071{
1072 char *fname = p; /* makefile to read */
1073 extern Lst parseIncPath;
1074 FILE *stream;
1075 char *name, path[MAXPATHLEN + 1];
1076 char *MAKEFILE;
1077 int setMAKEFILE;
1078
1079 if (!strcmp(fname, "-")) {
1080 Parse_File("(stdin)", stdin);
1081 Var_Set("MAKEFILE", "", VAR_GLOBAL);
1082 } else {
1083 setMAKEFILE = strcmp(fname, ".depend");
1084
1085 /* if we've chdir'd, rebuild the path name */
1086 if (curdir != objdir && *fname != '/') {
1087 (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
1088 if (realpath(path, path) != NULL &&
1089 (stream = fopen(path, "r")) != NULL) {
1090 MAKEFILE = fname;
1091 fname = path;
1092 goto found;
1093 }
1094 } else if (realpath(fname, path) != NULL) {
1095 MAKEFILE = fname;
1096 fname = path;
1097 if ((stream = fopen(fname, "r")) != NULL)
1098 goto found;
1099 }
1100 /* look in -I and system include directories. */
1101 name = Dir_FindFile(fname, parseIncPath);
1102 if (!name)
1103 name = Dir_FindFile(fname, sysIncPath);
1104 if (!name || !(stream = fopen(name, "r")))
1105 return(FALSE);
1106 MAKEFILE = fname = name;
1107 /*
1108 * set the MAKEFILE variable desired by System V fans -- the
1109 * placement of the setting here means it gets set to the last
1110 * makefile specified, as it is set by SysV make.
1111 */
1112found:
1113 if (setMAKEFILE)
1114 Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL);
1115 Parse_File(fname, stream);
1116 (void)fclose(stream);
1117 }
1118 return(TRUE);
1119}
1120
1121/*-
1122 * Cmd_Exec --
1123 * Execute the command in cmd, and return the output of that command
1124 * in a string.
1125 *
1126 * Results:
1127 * A string containing the output of the command, or the empty string
1128 * If err is not NULL, it contains the reason for the command failure
1129 *
1130 * Side Effects:
1131 * The string must be freed by the caller.
1132 */
1133char *
1134Cmd_Exec(cmd, err)
1135 char *cmd;
1136 char **err;
1137{
1138 char *args[4]; /* Args for invoking the shell */
1139 int fds[2]; /* Pipe streams */
1140 int cpid; /* Child PID */
1141 int pid; /* PID from wait() */
1142 char *res; /* result */
1143 int status; /* command exit status */
1144 Buffer buf; /* buffer to store the result */
1145 char *cp;
1146 int cc;
1147
1148
1149 *err = NULL;
1150
1151 /*
1152 * Set up arguments for shell
1153 */
1154 args[0] = "sh";
1155 args[1] = "-c";
1156 args[2] = cmd;
1157 args[3] = NULL;
1158
1159 /*
1160 * Open a pipe for fetching its output
1161 */
1162 if (pipe(fds) == -1) {
1163 *err = "Couldn't create pipe for \"%s\"";
1164 goto bad;
1165 }
1166
1167 /*
1168 * Fork
1169 */
1170#ifdef __EMX__
1171 switch (cpid = fork()) {
1172#else
1173 switch (cpid = vfork()) {
1174#endif
1175 case 0:
1176 /*
1177 * Close input side of pipe
1178 */
1179 (void) close(fds[0]);
1180
1181 /*
1182 * Duplicate the output stream to the shell's output, then
1183 * shut the extra thing down. Note we don't fetch the error
1184 * stream...why not? Why?
1185 */
1186 (void) dup2(fds[1], 1);
1187 (void) close(fds[1]);
1188
1189 #ifdef OS2
1190 {
1191 const char *psz = getenv("COMSPEC");
1192 if (!psz)
1193 psz = getenv("OS2_SHELL");
1194 if (!psz)
1195 psz = "c:\\os2\\cmd.exe";
1196 (void) execv(psz, args);
1197 }
1198 #else
1199 (void) execv("/bin/sh", args);
1200 #endif
1201 _exit(1);
1202 /*NOTREACHED*/
1203
1204 case -1:
1205 *err = "Couldn't exec \"%s\"";
1206 goto bad;
1207
1208 default:
1209 /*
1210 * No need for the writing half
1211 */
1212 (void) close(fds[1]);
1213
1214 buf = Buf_Init (MAKE_BSIZE);
1215
1216 do {
1217 char result[BUFSIZ];
1218 cc = read(fds[0], result, sizeof(result));
1219 if (cc > 0)
1220 Buf_AddBytes(buf, cc, (Byte *) result);
1221 }
1222 while (cc > 0 || (cc == -1 && errno == EINTR));
1223
1224 /*
1225 * Close the input side of the pipe.
1226 */
1227 (void) close(fds[0]);
1228
1229 /*
1230 * Wait for the process to exit.
1231 */
1232 while(((pid = wait(&status)) != cpid) && (pid >= 0))
1233 continue;
1234
1235 if (cc == -1)
1236 *err = "Error reading shell's output for \"%s\"";
1237
1238 res = (char *)Buf_GetAll (buf, &cc);
1239 Buf_Destroy (buf, FALSE);
1240
1241 if (status)
1242 *err = "\"%s\" returned non-zero status";
1243
1244 /*
1245 * Null-terminate the result, convert newlines to spaces and
1246 * install it in the variable.
1247 */
1248 res[cc] = '\0';
1249 cp = &res[cc] - 1;
1250
1251 if (*cp == '\n') {
1252 /*
1253 * A final newline is just stripped
1254 */
1255 *cp-- = '\0';
1256 }
1257 while (cp >= res) {
1258 if (*cp == '\n') {
1259 *cp = ' ';
1260 }
1261 cp--;
1262 }
1263 break;
1264 }
1265 return res;
1266bad:
1267 res = emalloc(1);
1268 *res = '\0';
1269 return res;
1270}
1271
1272/*-
1273 * Error --
1274 * Print an error message given its format.
1275 *
1276 * Results:
1277 * None.
1278 *
1279 * Side Effects:
1280 * The message is printed.
1281 */
1282/* VARARGS */
1283void
1284#if defined(__STDC__) || defined(__IBMC__)
1285Error(char *fmt, ...)
1286#else
1287Error(va_alist)
1288 va_dcl
1289#endif
1290{
1291 va_list ap;
1292#if defined(__STDC__) || defined(__IBMC__)
1293 va_start(ap, fmt);
1294#else
1295 char *fmt;
1296
1297 va_start(ap);
1298 fmt = va_arg(ap, char *);
1299#endif
1300 (void)vfprintf(stderr, fmt, ap);
1301 va_end(ap);
1302 (void)fprintf(stderr, "\n");
1303 (void)fflush(stderr);
1304}
1305
1306/*-
1307 * Fatal --
1308 * Produce a Fatal error message. If jobs are running, waits for them
1309 * to finish.
1310 *
1311 * Results:
1312 * None
1313 *
1314 * Side Effects:
1315 * The program exits
1316 */
1317/* VARARGS */
1318void
1319#if defined(__STDC__) || defined(__IBMC__)
1320Fatal(char *fmt, ...)
1321#else
1322Fatal(va_alist)
1323 va_dcl
1324#endif
1325{
1326 va_list ap;
1327#if defined(__STDC__) || defined(__IBMC__)
1328 va_start(ap, fmt);
1329#else
1330 char *fmt;
1331
1332 va_start(ap);
1333 fmt = va_arg(ap, char *);
1334#endif
1335 if (jobsRunning)
1336 Job_Wait();
1337
1338 (void)vfprintf(stderr, fmt, ap);
1339 va_end(ap);
1340 (void)fprintf(stderr, "\n");
1341 (void)fflush(stderr);
1342
1343 if (DEBUG(GRAPH2))
1344 Targ_PrintGraph(2);
1345 exit(2); /* Not 1 so -q can distinguish error */
1346}
1347
1348/*
1349 * Punt --
1350 * Major exception once jobs are being created. Kills all jobs, prints
1351 * a message and exits.
1352 *
1353 * Results:
1354 * None
1355 *
1356 * Side Effects:
1357 * All children are killed indiscriminately and the program Lib_Exits
1358 */
1359/* VARARGS */
1360void
1361#if defined(__STDC__) || defined(__IBMC__)
1362Punt(char *fmt, ...)
1363#else
1364Punt(va_alist)
1365 va_dcl
1366#endif
1367{
1368 va_list ap;
1369#if defined(__STDC__) || defined(__IBMC__)
1370 va_start(ap, fmt);
1371#else
1372 char *fmt;
1373
1374 va_start(ap);
1375 fmt = va_arg(ap, char *);
1376#endif
1377
1378 (void)fprintf(stderr, MAKE_NAME ": ");
1379 (void)vfprintf(stderr, fmt, ap);
1380 va_end(ap);
1381 (void)fprintf(stderr, "\n");
1382 (void)fflush(stderr);
1383
1384 DieHorribly();
1385}
1386
1387/*-
1388 * DieHorribly --
1389 * Exit without giving a message.
1390 *
1391 * Results:
1392 * None
1393 *
1394 * Side Effects:
1395 * A big one...
1396 */
1397void
1398DieHorribly()
1399{
1400 if (jobsRunning)
1401 Job_AbortAll();
1402 if (DEBUG(GRAPH2))
1403 Targ_PrintGraph(2);
1404 exit(2); /* Not 1, so -q can distinguish error */
1405}
1406
1407/*
1408 * Finish --
1409 * Called when aborting due to errors in child shell to signal
1410 * abnormal exit.
1411 *
1412 * Results:
1413 * None
1414 *
1415 * Side Effects:
1416 * The program exits
1417 */
1418void
1419Finish(errors)
1420 int errors; /* number of errors encountered in Make_Make */
1421{
1422 Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1423}
1424
1425/*
1426 * emalloc --
1427 * malloc, but die on error.
1428 */
1429void *
1430emalloc(len)
1431 size_t len;
1432{
1433 void *p;
1434
1435 if ((p = malloc(len)) == NULL)
1436 enomem();
1437 return(p);
1438}
1439
1440/*
1441 * estrdup --
1442 * strdup, but die on error.
1443 */
1444char *
1445estrdup(str)
1446 const char *str;
1447{
1448 char *p;
1449
1450 if ((p = strdup(str)) == NULL)
1451 enomem();
1452 return(p);
1453}
1454
1455/*
1456 * erealloc --
1457 * realloc, but die on error.
1458 */
1459void *
1460erealloc(ptr, size)
1461 void *ptr;
1462 size_t size;
1463{
1464 if ((ptr = realloc(ptr, size)) == NULL)
1465 enomem();
1466 return(ptr);
1467}
1468
1469/*
1470 * efree --
1471 * efree, no change.
1472 */
1473void
1474efree(ptr)
1475 void *ptr;
1476{
1477 if (ptr)
1478 free(ptr);
1479}
1480
1481/*
1482 * enomem --
1483 * die when out of memory.
1484 */
1485void
1486enomem()
1487{
1488 err(2, NULL);
1489}
1490
1491/*
1492 * enunlink --
1493 * Remove a file carefully, avoiding directories.
1494 */
1495int
1496eunlink(file)
1497 const char *file;
1498{
1499 struct stat st;
1500
1501#ifdef __EMX__
1502 if (stat(file, &st) == -1)
1503#else
1504 if (lstat(file, &st) == -1)
1505#endif
1506 return -1;
1507
1508 if (S_ISDIR(st.st_mode)) {
1509 errno = EISDIR;
1510 return -1;
1511 }
1512 return unlink(file);
1513}
1514
1515/*
1516 * usage --
1517 * exit with usage message
1518 */
1519static void
1520usage()
1521{
1522 (void)fprintf(stderr, "%s\n%s\n%s\n"
1523#ifdef NMAKE
1524"%s\n"
1525#endif
1526#ifdef KMK
1527"%s\n"
1528#endif
1529 ,
1530"usage: kmk [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]",
1531" [-I directory] [-j max_jobs] [-m directory] [-V variable]",
1532" [variable=value] [target ...]"
1533#ifdef NMAKE
1534,"NMAKE compatible mode enabled."
1535#endif
1536#ifdef KMK
1537,"kMk extensions enabled."
1538#endif
1539);
1540 exit(2);
1541}
1542
1543
1544int
1545PrintAddr(a, b)
1546 ClientData a;
1547 ClientData b;
1548{
1549 printf("%lx ", (unsigned long) a);
1550 return b ? 0 : 0;
1551}
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