mirror of
https://github.com/mirror/make.git
synced 2026-08-21 17:33:28 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b134da5505 | ||
|
|
d0b03e9355 | ||
|
|
5dc4b92b60 | ||
|
|
b3fa4b3c7e | ||
|
|
6fa76a7d15 | ||
|
|
4ff6c62456 | ||
|
|
cbb9e38d10 | ||
|
|
9e79637ec3 |
@@ -22,3 +22,5 @@ sun4 i386 i386-netbsd hp300-netbsd hp300 rs6000 sun3 news800 amiga
|
||||
hp700 hp834 mips sol2 i486-linux
|
||||
|
||||
customs
|
||||
|
||||
install-sh mkinstalldirs
|
||||
|
||||
150
ChangeLog
150
ChangeLog
@@ -1,3 +1,153 @@
|
||||
1999-08-25 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* Version 3.77.94 released.
|
||||
|
||||
* main.c (main) [__MSDOS__]: If the user uses -j, warn that it's
|
||||
not supported and reset it.
|
||||
|
||||
* make.h (ISDIGIT): Obtained this from the textutils distribution.
|
||||
* main.c (decode_switches): Use it.
|
||||
* function.c (is_numeric): Use it.
|
||||
|
||||
* main.c (struct command_switch): Store the switch char in an
|
||||
unsigned char to shut up GCC about using it with ctype.h macros.
|
||||
Besides, it _is_ always unsigned.
|
||||
|
||||
1999-08-24 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* make.texinfo: Change "dependency" to "prerequisite" and
|
||||
"dependencies" to "prerequisites". Various other cleanups related
|
||||
to the terminology change.
|
||||
* file.c: Change debugging and error messages to use
|
||||
"prerequisite" instead of "dependency".
|
||||
* implicit.c: Ditto.
|
||||
* remake.c: Ditto.
|
||||
* NEWS: Document it.
|
||||
|
||||
1999-08-23 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* remake.c (update_file): Move the considered check into the
|
||||
double-colon rule loop, so we consider double-colon rules
|
||||
individually (otherwise after the first is pruned, the rest won't
|
||||
get run).
|
||||
|
||||
* README.template: Minor changes.
|
||||
|
||||
Remove the debugging features of the jobserver, so it no longer
|
||||
writes distinct tokens to the pipe. Thus, we don't need to store
|
||||
the token we get. A side effect of this is to remove a potential
|
||||
"unavailable token" situation: make-1 invokes make-2 with its
|
||||
special token and make-3 with a normal token; make-2 completes.
|
||||
Now we're waiting for make-3 but using 2 tokens; our special token
|
||||
is idle. In the new version we don't have special tokens per se,
|
||||
we merely decide if we already have a child or not. If we don't,
|
||||
we don't need a token. If we do, we have to get one to run the
|
||||
next child. Similar for putting tokens back: if we're cleaning up
|
||||
the last child, we don't put a token back. Otherwise, we do.
|
||||
|
||||
* main.c: Add a new, internal flag --jobserver-fds instead of
|
||||
overloading the meaning of -j. Remove job_slots_str and add the
|
||||
stringlist jobserver_fds.
|
||||
(struct command_switch): We don't need the int_string type.
|
||||
(switches[]): Add a new option for --jobserver-fds and remove
|
||||
conditions around -j. Make the description for the former 0 so it
|
||||
doesn't print during "make --help".
|
||||
(main): Rework jobserver parsing. If we got --jobserver-fds
|
||||
make sure it's valid. We only get one and job_slots must be 0.
|
||||
If we're the toplevel make (-jN without --jobserver-fds) create
|
||||
the pipe and write generic tokens.
|
||||
Create the stringlist struct for the submakes.
|
||||
Clean up the stringlist where necessary.
|
||||
(init_switches): Remove int_string handling.
|
||||
(print_usage): Don't print internal flags (description ptr is 0).
|
||||
(decode_switches): Remove int_string handling.
|
||||
(define_makeflags): Remove int_string handling.
|
||||
|
||||
* job.c: Remove my_job_token flag and all references to the
|
||||
child->job_token field.
|
||||
(free_job_token): Remove this and merge it into free_child().
|
||||
(reap_children): Rework the "reaped a child" logic slightly.
|
||||
Don't call defunct free_job_token anymore. Always call
|
||||
free_child, even if we're dying.
|
||||
(free_child): If we're not freeing the only child, put a token
|
||||
back in the pipe. Then, if we're dying, don't bother to free.
|
||||
(new_job): If we are using the jobserver, loop checking to see if
|
||||
a) there are no children or b) we get a token from the pipe.
|
||||
|
||||
* job.h (struct child): Remove the job_token field.
|
||||
|
||||
1999-08-20 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* variable.c (try_variable_definition): Allocate for variable
|
||||
expansion in f_append with a simple variable: if we're looking at
|
||||
target-specific variables we don't want to trash the buffer.
|
||||
Noticed by Reiner Beninga <Reiner.Beninga@mchp.siemens.de>.
|
||||
|
||||
1999-08-16 Eli Zaretskii <eliz@is.elta.co.il>
|
||||
|
||||
* main.c (main) [__MSDOS__]: Mirror any backslashes in argv[0], to
|
||||
avoid problems in shell commands that use backslashes as escape
|
||||
characters.
|
||||
|
||||
1999-08-16 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* Version 3.77.93 released.
|
||||
|
||||
1999-08-13 Paul D. Smith <psmith@gnu.org
|
||||
|
||||
* function.c (func_if): New function $(if ...) based on the
|
||||
original by Han-Wen but reworked quite a bit.
|
||||
(function_table): Add it.
|
||||
* NEWS: Introduce it.
|
||||
* make.texinfo (If Function): Document it.
|
||||
|
||||
* job.c (free_job_token): Check for EINTR when writing tokens to
|
||||
the jobserver pipe.
|
||||
|
||||
1999-08-12 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
Another jobserver algorithm change. We conveniently forgot that
|
||||
the blocking bit is shared by all users of the pipe, it's not a
|
||||
per-process setting. Since we have many make processes all
|
||||
sharing the pipe we can't use the blocking bit as a signal handler
|
||||
flag. Instead, we'll dup the pipe's read FD and have the SIGCHLD
|
||||
handler close the dup'd FD. This will cause the read() to fail
|
||||
with EBADF the next time we invoke it, so we know we need to reap
|
||||
children. We then re-dup and reap.
|
||||
|
||||
* main.c (main): Define the job_rfd variable to hold the dup'd FD.
|
||||
Actually dup the read side of the pipe. Don't bother setting the
|
||||
blocking bit on the file descriptor.
|
||||
* make.h: Declare the job_rfd variable.
|
||||
* job.c (child_handler): If the dup'd jobserver pipe is open,
|
||||
close it and assign -1 to job_rfd to notify the main program that
|
||||
we got a SIGCHLD.
|
||||
(start_job_command): Close the dup'd FD before exec'ing children.
|
||||
Since we open and close this thing so often it doesn't seem
|
||||
worth it to use the close-on-exec bit.
|
||||
(new_job): Remove code for testing/setting the blocking bit.
|
||||
Instead of EAGAIN, test for EBADF. If the dup'd FD has been
|
||||
closed, re-dup it before we reap children.
|
||||
|
||||
* function.c (func_shell): Be a little more accurate about the
|
||||
length of the error string to allocate.
|
||||
|
||||
* expand.c (variable_expand_for_file): If there's no filenm info
|
||||
(say, from a builtin command) then reset reading_file to 0.
|
||||
|
||||
1999-08-09 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* maintMakefile: Use g in sed (s///g) to replace >1 variable per
|
||||
line.
|
||||
|
||||
* Makefile.DOS.template [__MSDOS__]: Fix mostlyclean-aminfo to
|
||||
remove the right files.
|
||||
|
||||
1999-08-01 Eli Zaretskii <eliz@is.elta.co.il>
|
||||
|
||||
* function.c (msdos_openpipe) [__MSDOS__]: *Really* return a FILE
|
||||
ptr.
|
||||
|
||||
1999-08-01 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
New jobserver algorithm to avoid a possible hole where we could
|
||||
|
||||
@@ -224,7 +224,9 @@ dist-info: $(INFO_DEPS)
|
||||
for base in $(INFO_DEPS); do d=$(srcdir); for file in `cd $$d && eval echo $$base*`; do test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; done
|
||||
|
||||
mostlyclean-aminfo:
|
||||
cd $(srcdir) && for i in $(INFO_DEPS) make.i; do rm -f `eval echo $$i*`; done
|
||||
-rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky \
|
||||
make.kys make.ps make.log make.pg make.toc make.tp make.tps \
|
||||
make.vr make.vrs make.op make.tr make.cv make.cn
|
||||
|
||||
clean-aminfo:
|
||||
|
||||
|
||||
14
NEWS
14
NEWS
@@ -12,17 +12,21 @@ Please send GNU make bug reports to bug-make@gnu.org.
|
||||
|
||||
Version 3.78
|
||||
|
||||
* Two new functions, $(error ...) and $(warning ...) are provided. The
|
||||
* Two new functions, $(error ...) and $(warning ...) are available. The
|
||||
former will cause make to fail and exit immediately upon expansion of
|
||||
the function, with the text provided as the error message. The latter
|
||||
causes the text provided to be printed as a warning message, but make
|
||||
proceeds normally.
|
||||
|
||||
* A new function, $(call ...) is provided. This allows users to create
|
||||
* A new function $(call ...) is available. This allows users to create
|
||||
their own parameterized macros and invoke them later. Original
|
||||
implementation of this feature was provided by Han-Wen Nienhuys
|
||||
implementation of this function was provided by Han-Wen Nienhuys
|
||||
<hanwen@cs.uu.nl>.
|
||||
|
||||
* A new function $(if ...) is available. It provides if-then-else
|
||||
capabilities in a builtin function. Original implementation of this
|
||||
function was provided by Han-Wen Nienhuys <hanwen@cs.uu.nl>.
|
||||
|
||||
* Make defines a new variable, .LIBPATTERNS. This variable controls how
|
||||
library dependency expansion (dependencies like ``-lfoo'') is performed.
|
||||
|
||||
@@ -42,6 +46,10 @@ Version 3.78
|
||||
each other to ensure that no more than N jobs are started across all
|
||||
makes. To get the old behavior of -j back, you can configure make
|
||||
with the --disable-job-server option.
|
||||
|
||||
* The confusing term "dependency" has been replaced by the more accurate
|
||||
and standard term "prerequisite", both in the manual and in all GNU make
|
||||
output.
|
||||
|
||||
Version 3.77
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
This directory contains the %VERSION% release of GNU Make.
|
||||
All bugs reported for previous releases have been fixed.
|
||||
Some bugs surely remain.
|
||||
|
||||
See the file NEWS for the user-visible changes from previous releases.
|
||||
In addition, there have been bugs fixed.
|
||||
|
||||
For general building and installation instructions, see the file INSTALL.
|
||||
|
||||
@@ -24,6 +25,8 @@ site. There is information there about ordering hardcopy documentation.
|
||||
http://www.gnu.org/doc/doc.html
|
||||
http://www.gnu.org/manual/manual.html
|
||||
|
||||
You can also find the latest versions of GNU Make from there.
|
||||
|
||||
Please send GNU make bug reports to bug-make@gnu.org. Please see the
|
||||
section of the manual entitles `Problems and Bugs' for information on
|
||||
submitting bug reports.
|
||||
@@ -61,9 +64,5 @@ debug this code, you can do `make check-loadavg' to see if it works
|
||||
properly on your system. (You must run `configure' beforehand, but you
|
||||
need not build Make itself to run this test.)
|
||||
|
||||
See the file NEWS for what has changed since previous releases.
|
||||
|
||||
GNU Make is fully documented in make.texinfo. See the section entitled
|
||||
`Problems and Bugs' for information on submitting bug reports.
|
||||
|
||||
GNU Make is free software. See the file COPYING for copying conditions.
|
||||
|
||||
@@ -3,7 +3,7 @@ AC_REVISION([$Id$])
|
||||
AC_PREREQ(2.13)dnl dnl Minimum Autoconf version required.
|
||||
AC_INIT(vpath.c)dnl dnl A distinctive file to look for in srcdir.
|
||||
|
||||
AM_INIT_AUTOMAKE(make, 3.77.92)
|
||||
AM_INIT_AUTOMAKE(make, 3.77.94)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl Regular configure stuff
|
||||
|
||||
5
expand.c
5
expand.c
@@ -442,7 +442,10 @@ variable_expand_for_file (line, file)
|
||||
|
||||
save = current_variable_set_list;
|
||||
current_variable_set_list = file->variables;
|
||||
reading_file = &file->cmds->fileinfo;
|
||||
if (file->cmds && file->cmds->fileinfo.filenm)
|
||||
reading_file = &file->cmds->fileinfo;
|
||||
else
|
||||
reading_file = 0;
|
||||
fnext = file->variables->next;
|
||||
/* See if there's a pattern-specific variable struct for this target. */
|
||||
if (!file->pat_searched)
|
||||
|
||||
6
file.c
6
file.c
@@ -620,9 +620,9 @@ print_file (f)
|
||||
putchar ('\n');
|
||||
|
||||
if (f->precious)
|
||||
puts (_("# Precious file (dependency of .PRECIOUS)."));
|
||||
puts (_("# Precious file (prerequisite of .PRECIOUS)."));
|
||||
if (f->phony)
|
||||
puts (_("# Phony target (dependency of .PHONY)."));
|
||||
puts (_("# Phony target (prerequisite of .PHONY)."));
|
||||
if (f->cmd_target)
|
||||
puts (_("# Command-line target."));
|
||||
if (f->dontcare)
|
||||
@@ -632,7 +632,7 @@ print_file (f)
|
||||
if (f->stem != 0)
|
||||
printf (_("# Implicit/static pattern stem: `%s'\n"), f->stem);
|
||||
if (f->intermediate)
|
||||
puts (_("# File is an intermediate dependency."));
|
||||
puts (_("# File is an intermediate prerequisite."));
|
||||
if (f->also_make != 0)
|
||||
{
|
||||
fputs (_("# Also makes:"), stdout);
|
||||
|
||||
131
function.c
131
function.c
@@ -699,16 +699,13 @@ int
|
||||
is_numeric (p)
|
||||
char *p;
|
||||
{
|
||||
char *end = p + strlen (p) -1;
|
||||
char *end = p + strlen (p) - 1;
|
||||
char *beg = p;
|
||||
strip_whitespace (&p, &end);
|
||||
while (p <= end)
|
||||
{
|
||||
if (!isdigit (*p))
|
||||
return 0;
|
||||
|
||||
p++;
|
||||
}
|
||||
while (p <= end)
|
||||
if (!ISDIGIT (*(p++))) /* ISDIGIT only evals its arg once: see make.h. */
|
||||
return 0;
|
||||
|
||||
return (end - beg >= 0);
|
||||
}
|
||||
@@ -817,9 +814,9 @@ func_foreach (o, argv, funcname)
|
||||
const char *funcname;
|
||||
{
|
||||
/* expand only the first two. */
|
||||
char *varname = expand_argument (argv[0], argv[1] -1);
|
||||
char *varname = expand_argument (argv[0], argv[1] - 1);
|
||||
char *list = expand_argument (argv[1], argv[2] -1);
|
||||
char *body = savestring (argv[2], argv[3] - argv[2] -1 );
|
||||
char *body = savestring (argv[2], argv[3] - argv[2] - 1);
|
||||
|
||||
int len =0;
|
||||
char *list_iterator = list;
|
||||
@@ -1075,6 +1072,68 @@ func_sort (o, argv, funcname)
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
$(if condition,true-part[,false-part])
|
||||
|
||||
CONDITION is false iff it evaluates to an empty string. White
|
||||
space before and after condition are stripped before evaluation.
|
||||
|
||||
If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is
|
||||
evaluated (if it exists). Because only one of the two PARTs is evaluated,
|
||||
you can use $(if ...) to create side-effects (with $(shell ...), for
|
||||
example).
|
||||
*/
|
||||
|
||||
static char *
|
||||
func_if (o, argv, funcname)
|
||||
char *o;
|
||||
char **argv;
|
||||
const char *funcname;
|
||||
{
|
||||
char *begp = argv[0];
|
||||
char *endp = argv[1]-1;
|
||||
int result = 0;
|
||||
|
||||
/* Find the result of the condition: if we have a value, and it's not
|
||||
empty, the condition is true. If we don't have a value, or it's the
|
||||
empty string, then it's false. */
|
||||
|
||||
strip_whitespace (&begp, &endp);
|
||||
|
||||
if (begp < endp)
|
||||
{
|
||||
char *expansion = expand_argument (begp, endp);
|
||||
|
||||
result = strlen (expansion);
|
||||
free (expansion);
|
||||
}
|
||||
|
||||
/* If the result is true (1) we want to eval the first argument, and if
|
||||
it's false (0) we want to eval the second. If the argument doesn't
|
||||
exist we do nothing, otherwise expand it and add to the buffer. */
|
||||
|
||||
argv += 1 + !result;
|
||||
|
||||
if (argv[0] != NULL && argv[1] != NULL)
|
||||
{
|
||||
char *expansion;
|
||||
char **endp = argv+1;
|
||||
|
||||
/* If we're doing the else-clause, make sure we concatenate any
|
||||
potential extra arguments into the last argument. */
|
||||
if (!result)
|
||||
while (*endp && **endp != '\0')
|
||||
++endp;
|
||||
|
||||
expansion = expand_argument (*argv, *endp-1);
|
||||
|
||||
o = variable_buffer_output (o, expansion, strlen (expansion));
|
||||
free (expansion);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
static char *
|
||||
func_wildcard(o, argv, funcname)
|
||||
char *o;
|
||||
@@ -1203,7 +1262,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp)
|
||||
|
||||
|
||||
#ifdef __MSDOS__
|
||||
int
|
||||
FILE *
|
||||
msdos_openpipe (int* pipedes, int *pidp, char *text)
|
||||
{
|
||||
FILE *fpipe=0;
|
||||
@@ -1307,7 +1366,7 @@ func_shell (o, argv, funcname)
|
||||
/* For error messages. */
|
||||
if (reading_file != 0)
|
||||
{
|
||||
error_prefix = (char *) alloca (strlen(reading_file->filenm)+100);
|
||||
error_prefix = (char *) alloca (strlen(reading_file->filenm)+11+4);
|
||||
sprintf (error_prefix,
|
||||
"%s:%lu: ", reading_file->filenm, reading_file->lineno);
|
||||
}
|
||||
@@ -1546,54 +1605,6 @@ func_not (char* o, char **argv, char *funcname)
|
||||
o = variable_buffer_output (o, result ? "1" : "", result);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
This is an experimental conditional function.
|
||||
|
||||
Syntax:
|
||||
|
||||
$(if condition, true-part, false-part)
|
||||
|
||||
This is fully not consistent with make's syntax, but more in line
|
||||
with `normal' programming languages.
|
||||
|
||||
Semantics:
|
||||
|
||||
- CONDITION is false iff it evaluates to an empty string. White
|
||||
space before and after condition are stripped before evaluation.
|
||||
|
||||
- If CONDITION is true, then TRUE-PART is evaluated, otherwise
|
||||
FALSE-PART is evaluated. Because only one of the two PARTs is
|
||||
evaluated, you can use $(if ) to create side-effects with the
|
||||
$(shell ) function
|
||||
|
||||
*/
|
||||
static char *
|
||||
func_if (char* o, char **argv, char *funcname)
|
||||
{
|
||||
char *begp = argv[0];
|
||||
char *endp = argv[1]-2;
|
||||
char *expansion =0;
|
||||
int result = 0;
|
||||
|
||||
strip_whitespace (&begp, &endp);
|
||||
if(begp <= endp)
|
||||
expansion = expand_argument (begp, endp + 1);
|
||||
|
||||
result = expansion
|
||||
? strlen (expansion)
|
||||
: 0;
|
||||
|
||||
result = !result;
|
||||
free (expansion);
|
||||
|
||||
expansion = expand_argument (argv[1 + result], argv[2+result] -1);
|
||||
o = variable_buffer_output (o, expansion, strlen (expansion));
|
||||
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1645,9 +1656,9 @@ static struct function_table_entry function_table[] =
|
||||
{ STRING_SIZE_TUPLE("call"), -1, 1, func_call},
|
||||
{ STRING_SIZE_TUPLE("error"), 1, 1, func_error},
|
||||
{ STRING_SIZE_TUPLE("warning"), 1, 1, func_error},
|
||||
{ STRING_SIZE_TUPLE("if"), -2, 0, func_if},
|
||||
#ifdef EXPERIMENTAL
|
||||
{ STRING_SIZE_TUPLE("eq"), 2, 1, func_eq},
|
||||
{ STRING_SIZE_TUPLE("if"), 3, 0, func_if},
|
||||
{ STRING_SIZE_TUPLE("not"), 1, 1, func_not},
|
||||
#endif
|
||||
{ 0 }
|
||||
|
||||
@@ -376,7 +376,7 @@ pattern_search (file, archive, depth, recursions)
|
||||
"impossible", then the rule fails and don't
|
||||
bother trying it on the second pass either
|
||||
since we know that will fail too. */
|
||||
DEBUGP2 (_("Rejecting impossible %s dependency `%s'.\n"),
|
||||
DEBUGP2 (_("Rejecting impossible %s prerequisite `%s'.\n"),
|
||||
p == depname ? _("implicit") : _("rule"), p);
|
||||
tryrules[i] = 0;
|
||||
break;
|
||||
@@ -384,7 +384,7 @@ pattern_search (file, archive, depth, recursions)
|
||||
|
||||
intermediate_files[deps_found] = 0;
|
||||
|
||||
DEBUGP2 (_("Trying %s dependency `%s'.\n"),
|
||||
DEBUGP2 (_("Trying %s prerequisite `%s'.\n"),
|
||||
p == depname ? _("implicit") : _("rule"), p);
|
||||
|
||||
/* The DEP->changed flag says that this dependency resides in a
|
||||
@@ -408,8 +408,9 @@ pattern_search (file, archive, depth, recursions)
|
||||
vp = p;
|
||||
if (vpath_search (&vp, (FILE_TIMESTAMP *) 0))
|
||||
{
|
||||
DEBUGP2 (_("Found dependency `%s' as VPATH `%s'\n"), p, vp);
|
||||
strcpy(vp, p);
|
||||
DEBUGP2 (_("Found prerequisite `%s' as VPATH `%s'\n"),
|
||||
p, vp);
|
||||
strcpy (vp, p);
|
||||
found_files[deps_found++] = vp;
|
||||
continue;
|
||||
}
|
||||
|
||||
247
job.c
247
job.c
@@ -202,11 +202,6 @@ unsigned int job_slots_used = 0;
|
||||
|
||||
static int good_stdin_used = 0;
|
||||
|
||||
/* Specifies whether the current process's reserved job token is in use.
|
||||
'+' means it's available, '-' means it isn't. */
|
||||
|
||||
static char my_job_token = '+';
|
||||
|
||||
/* Chain of children waiting to run until the load average goes down. */
|
||||
|
||||
static struct child *waiting_jobs = 0;
|
||||
@@ -224,40 +219,11 @@ int unixy_shell = 1;
|
||||
*/
|
||||
int w32_kill(int pid, int sig)
|
||||
{
|
||||
return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
|
||||
return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
|
||||
}
|
||||
#endif /* WINDOWS32 */
|
||||
|
||||
|
||||
static void
|
||||
free_job_token (child)
|
||||
struct child *child;
|
||||
{
|
||||
switch (child->job_token)
|
||||
{
|
||||
case '-':
|
||||
/* If this child doesn't have a token, punt. */
|
||||
return;
|
||||
|
||||
case '+':
|
||||
/* If this child has the reserved token, take it back. */
|
||||
my_job_token = '+';
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Write any other job tokens back to the pipe. */
|
||||
write (job_fds[1], &child->job_token, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug_flag)
|
||||
printf (_("Released token `%c' for child 0x%08lx (%s).\n"),
|
||||
child->job_token, (unsigned long int) child, child->file->name);
|
||||
|
||||
child->job_token = '-';
|
||||
}
|
||||
|
||||
|
||||
/* Write an error message describing the exit status given in
|
||||
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
|
||||
Append "(ignored)" if IGNORED is nonzero. */
|
||||
@@ -308,11 +274,10 @@ vmsWaitForChildren(int *status)
|
||||
|
||||
/* Handle a dead child. This handler may or may not ever be installed.
|
||||
|
||||
If we're using the jobserver blocking read, we need it. First, installing
|
||||
it ensures the read will interrupt on SIGCHLD. Second, we reset the
|
||||
blocking bit on the read side of the pipe to ensure we don't enter another
|
||||
blocking read without reaping all the dead children. In this case we
|
||||
don't need the dead_children count.
|
||||
If we're using the jobserver feature, we need it. First, installing it
|
||||
ensures the read will interrupt on SIGCHLD. Second, we close the dup'd
|
||||
read FD to ensure we don't enter another blocking read without reaping all
|
||||
the dead children. In this case we don't need the dead_children count.
|
||||
|
||||
If we don't have either waitpid or wait3, then make is unreliable, but we
|
||||
use the dead_children count to reap children as best we can. */
|
||||
@@ -325,15 +290,11 @@ child_handler (sig)
|
||||
{
|
||||
++dead_children;
|
||||
|
||||
#ifdef HAVE_JOBSERVER
|
||||
if (job_fds[0] >= 0)
|
||||
if (job_rfd >= 0)
|
||||
{
|
||||
int fl = fcntl(job_fds[0], F_GETFL, 0);
|
||||
|
||||
if (fl >= 0)
|
||||
fcntl(job_fds[0], F_SETFL, fl | O_NONBLOCK);
|
||||
close (job_rfd);
|
||||
job_rfd = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (debug_flag)
|
||||
printf (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children);
|
||||
@@ -354,14 +315,23 @@ reap_children (block, err)
|
||||
int block, err;
|
||||
{
|
||||
WAIT_T status;
|
||||
#ifdef WAIT_NOHANG
|
||||
/* Initially, assume we have some. */
|
||||
int reap_more = 1;
|
||||
|
||||
#ifdef WAIT_NOHANG
|
||||
# define REAP_MORE reap_more
|
||||
#else
|
||||
# define REAP_MORE dead_children
|
||||
#endif
|
||||
|
||||
/* As long as:
|
||||
|
||||
We have at least one child outstanding OR a shell function in progress,
|
||||
AND
|
||||
We're blocking for a complete child OR there are more children to reap
|
||||
|
||||
we'll keep reaping children. */
|
||||
|
||||
while ((children != 0 || shell_function_pid != 0) &&
|
||||
(block || REAP_MORE))
|
||||
{
|
||||
@@ -406,10 +376,9 @@ reap_children (block, err)
|
||||
any_remote |= c->remote;
|
||||
any_local |= ! c->remote;
|
||||
if (debug_flag)
|
||||
printf (_("Live child 0x%08lx (%s) PID %ld token %c%s\n"),
|
||||
printf (_("Live child 0x%08lx (%s) PID %ld %s\n"),
|
||||
(unsigned long int) c, c->file->name,
|
||||
(long) c->pid, c->job_token,
|
||||
c->remote ? _(" (remote)") : "");
|
||||
(long) c->pid, c->remote ? _(" (remote)") : "");
|
||||
#ifdef VMS
|
||||
break;
|
||||
#endif
|
||||
@@ -457,10 +426,11 @@ reap_children (block, err)
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
/* The wait*() failed miserably. Punt. */
|
||||
/* EINTR? Try again. */
|
||||
if (EINTR_SET)
|
||||
goto local_wait;
|
||||
|
||||
/* The wait*() failed miserably. Punt. */
|
||||
pfatal_with_name ("wait");
|
||||
}
|
||||
else if (pid > 0)
|
||||
@@ -473,26 +443,24 @@ reap_children (block, err)
|
||||
else
|
||||
{
|
||||
/* No local children are dead. */
|
||||
#ifdef WAIT_NOHANG
|
||||
reap_more = 0;
|
||||
#endif
|
||||
if (block && any_remote)
|
||||
{
|
||||
/* Now try a blocking wait for a remote child. */
|
||||
pid = remote_status (&exit_code, &exit_sig, &coredump, 1);
|
||||
if (pid < 0)
|
||||
goto remote_status_lose;
|
||||
else if (pid == 0)
|
||||
/* No remote children either. Finally give up. */
|
||||
break;
|
||||
else
|
||||
/* We got a remote child. */
|
||||
remote = 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
if (!block || !any_remote)
|
||||
break;
|
||||
|
||||
/* Now try a blocking wait for a remote child. */
|
||||
pid = remote_status (&exit_code, &exit_sig, &coredump, 1);
|
||||
if (pid < 0)
|
||||
goto remote_status_lose;
|
||||
else if (pid == 0)
|
||||
/* No remote children either. Finally give up. */
|
||||
break;
|
||||
|
||||
/* We got a remote child. */
|
||||
remote = 1;
|
||||
}
|
||||
#endif /* !__MSDOS__, !Amiga, !WINDOWS32. */
|
||||
|
||||
#ifdef __MSDOS__
|
||||
/* Life is very different on MSDOS. */
|
||||
pid = dos_pid - 1;
|
||||
@@ -567,9 +535,9 @@ reap_children (block, err)
|
||||
continue;
|
||||
|
||||
if (debug_flag)
|
||||
printf (_("Reaping %s child 0x%08lx PID %ld token %c%s\n"),
|
||||
printf (_("Reaping %s child 0x%08lx PID %ld %s\n"),
|
||||
child_failed ? _("losing") : _("winning"),
|
||||
(unsigned long int) c, (long) c->pid, c->job_token,
|
||||
(unsigned long int) c, (long) c->pid,
|
||||
c->remote ? _(" (remote)") : "");
|
||||
|
||||
if (c->sh_batch_file) {
|
||||
@@ -667,8 +635,8 @@ reap_children (block, err)
|
||||
notice_finished_file (c->file);
|
||||
|
||||
if (debug_flag)
|
||||
printf (_("Removing child 0x%08lx PID %ld token %c%s from chain.\n"),
|
||||
(unsigned long int) c, (long) c->pid, c->job_token,
|
||||
printf (_("Removing child 0x%08lx PID %ld %s from chain.\n"),
|
||||
(unsigned long int) c, (long) c->pid,
|
||||
c->remote ? _(" (remote)") : "");
|
||||
|
||||
/* Block fatal signals while frobnicating the list, so that
|
||||
@@ -678,9 +646,6 @@ reap_children (block, err)
|
||||
live and call reap_children again. */
|
||||
block_sigs ();
|
||||
|
||||
/* If this job has a token out, return it. */
|
||||
free_job_token(c);
|
||||
|
||||
/* There is now another slot open. */
|
||||
if (job_slots_used > 0)
|
||||
--job_slots_used;
|
||||
@@ -690,8 +655,8 @@ reap_children (block, err)
|
||||
children = c->next;
|
||||
else
|
||||
lastc->next = c->next;
|
||||
if (! handling_fatal_signal) /* Don't bother if about to die. */
|
||||
free_child (c);
|
||||
|
||||
free_child (c);
|
||||
|
||||
unblock_sigs ();
|
||||
|
||||
@@ -715,6 +680,28 @@ static void
|
||||
free_child (child)
|
||||
register struct child *child;
|
||||
{
|
||||
/* If this child is the only one it was our "free" job, so don't put a
|
||||
token back for it. This child has already been removed from the list,
|
||||
so if there any left this wasn't the last one. */
|
||||
|
||||
if (job_fds[1] >= 0 && children)
|
||||
{
|
||||
char token = '+';
|
||||
|
||||
/* Write a job token back to the pipe. */
|
||||
|
||||
while (write (job_fds[1], &token, 1) != 1)
|
||||
if (!EINTR_SET)
|
||||
pfatal_with_name (_("write jobserver"));
|
||||
|
||||
if (debug_flag)
|
||||
printf (_("Released token for child 0x%08lx (%s).\n"),
|
||||
(unsigned long int) child, child->file->name);
|
||||
}
|
||||
|
||||
if (handling_fatal_signal) /* Don't bother free'ing if about to die. */
|
||||
return;
|
||||
|
||||
if (child->command_lines != 0)
|
||||
{
|
||||
register unsigned int i;
|
||||
@@ -731,11 +718,6 @@ free_child (child)
|
||||
free ((char *) child->environment);
|
||||
}
|
||||
|
||||
/* If this child has a token it hasn't relinquished, give it up now.
|
||||
This can happen if the job completes immediately, mainly because
|
||||
all the command lines evaluated to empty strings. */
|
||||
free_job_token(child);
|
||||
|
||||
free ((char *) child);
|
||||
}
|
||||
|
||||
@@ -883,17 +865,18 @@ start_job_command (child)
|
||||
? "%s" : (char *) 0, p);
|
||||
|
||||
/* Optimize an empty command. People use this for timestamp rules,
|
||||
and forking a useless shell all the time leads to inefficiency. */
|
||||
so avoid forking a useless shell. */
|
||||
|
||||
#if !defined(VMS) && !defined(_AMIGA)
|
||||
if (
|
||||
#ifdef __MSDOS__
|
||||
unixy_shell /* the test is complicated and we already did it */
|
||||
#else
|
||||
(argv[0] && !strcmp(argv[0], "/bin/sh"))
|
||||
(argv[0] && !strcmp (argv[0], "/bin/sh"))
|
||||
#endif
|
||||
&& (argv[1] && !strcmp(argv[1], "-c"))
|
||||
&& (argv[2] && !strcmp(argv[2], ":"))
|
||||
&& (argv[1]
|
||||
&& argv[1][0] == '-' && argv[1][1] == 'c' && argv[1][2] == '\0')
|
||||
&& (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0')
|
||||
&& argv[3] == NULL)
|
||||
{
|
||||
free (argv[0]);
|
||||
@@ -1032,6 +1015,8 @@ start_job_command (child)
|
||||
close (job_fds[0]);
|
||||
close (job_fds[1]);
|
||||
}
|
||||
if (job_rfd >= 0)
|
||||
close (job_rfd);
|
||||
|
||||
child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
|
||||
argv, child->environment);
|
||||
@@ -1202,10 +1187,9 @@ start_waiting_job (c)
|
||||
case cs_running:
|
||||
c->next = children;
|
||||
if (debug_flag)
|
||||
printf (_("Putting child 0x%08lx (%s) PID %ld token %c%s on the chain.\n"),
|
||||
printf (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"),
|
||||
(unsigned long int) c, c->file->name,
|
||||
(long) c->pid, c->job_token,
|
||||
c->remote ? _(" (remote)") : "");
|
||||
(long) c->pid, c->remote ? _(" (remote)") : "");
|
||||
children = c;
|
||||
/* One more job slot is in use. */
|
||||
++job_slots_used;
|
||||
@@ -1362,62 +1346,69 @@ new_job (file)
|
||||
c->command_ptr = 0;
|
||||
c->environment = 0;
|
||||
c->sh_batch_file = NULL;
|
||||
c->job_token = '-';
|
||||
|
||||
/* Fetch the first command line to be run. */
|
||||
job_next_command (c);
|
||||
|
||||
/* Wait for a job slot to be freed up. If we allow an infinite number
|
||||
don't bother; also job_slots will == 0 if we're using the jobserver. */
|
||||
|
||||
if (job_slots != 0)
|
||||
while (job_slots_used == job_slots)
|
||||
reap_children (1, 0);
|
||||
|
||||
#ifdef MAKE_JOBSERVER
|
||||
/* If we are controlling multiple jobs, and we don't yet have one,
|
||||
obtain a token before starting the child. */
|
||||
/* If we are controlling multiple jobs make sure we have a token before
|
||||
starting the child. */
|
||||
|
||||
/* This can be inefficient. There's a decent chance that this job won't
|
||||
actually have to run any subprocesses: the command script may be empty
|
||||
or otherwise optimized away. It would be nice if we could defer
|
||||
obtaining a token until just before we need it, in start_job_command.
|
||||
To do that we'd need to keep track of whether we'd already obtained a
|
||||
token (since start_job_command is called for each line of the job, not
|
||||
just once). Also more thought needs to go into the entire algorithm;
|
||||
this is where the old parallel job code waits, so... */
|
||||
|
||||
else if (job_fds[0] >= 0)
|
||||
{
|
||||
while (c->job_token == '-')
|
||||
/* If the reserved token is available, just use that. */
|
||||
if (my_job_token == '+')
|
||||
{
|
||||
c->job_token = my_job_token;
|
||||
my_job_token = '-';
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
char token;
|
||||
|
||||
/* If we don't already have a job started, use our "free" token. */
|
||||
if (!children)
|
||||
break;
|
||||
|
||||
/* Read a token. As long as there's no token available we'll block.
|
||||
If we get a SIGCHLD we'll return with EINTR. If one happened
|
||||
before we got here we'll return immediately with EAGAIN because
|
||||
the signal handler unsets the blocking bit. */
|
||||
else if (read (job_fds[0], &c->job_token, 1) < 1)
|
||||
before we got here we'll return immediately with EBADF because
|
||||
the signal handler closes the dup'd file descriptor. */
|
||||
|
||||
if (read (job_rfd, &token, 1) == 1)
|
||||
{
|
||||
int fl;
|
||||
|
||||
#if !defined(EAGAIN)
|
||||
# define EAGAIN EWOULDBLOCK
|
||||
#endif
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
pfatal_with_name (_("read jobs pipe"));
|
||||
|
||||
/* Set the blocking bit on the read FD again, just in case. */
|
||||
fl = fcntl(job_fds[0], F_GETFL, 0);
|
||||
if (fl >= 0)
|
||||
fcntl(job_fds[0], F_SETFL, fl & ~O_NONBLOCK);
|
||||
|
||||
/* Something's done. We don't want to block for a whole child,
|
||||
just reap whatever's there. */
|
||||
reap_children (0, 0);
|
||||
if (debug_flag)
|
||||
printf (_("Obtained token for child 0x%08lx (%s).\n"),
|
||||
(unsigned long int) c, c->file->name);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(c->job_token != '-');
|
||||
if (debug_flag)
|
||||
printf (_("Obtained token `%c' for child 0x%08lx (%s).\n"),
|
||||
c->job_token, (unsigned long int) c, c->file->name);
|
||||
}
|
||||
if (errno != EINTR && errno != EBADF)
|
||||
pfatal_with_name (_("read jobs pipe"));
|
||||
|
||||
/* Re-dup the read side of the pipe, so the signal handler can
|
||||
notify us if we miss a child. */
|
||||
if (job_rfd < 0)
|
||||
job_rfd = dup (job_fds[0]);
|
||||
|
||||
/* Something's done. We don't want to block for a whole child,
|
||||
just reap whatever's there. */
|
||||
reap_children (0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The job is now primed. Start it running.
|
||||
(This will notice if there are in fact no commands.) */
|
||||
(void)start_waiting_job (c);
|
||||
(void) start_waiting_job (c);
|
||||
|
||||
if (job_slots == 1)
|
||||
/* Since there is only one job slot, make things run linearly.
|
||||
@@ -2150,7 +2141,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
|
||||
/* Note these overlap and strcpy() is undefined for
|
||||
overlapping objects in ANSI C. The strlen() _IS_ right,
|
||||
since we need to copy the nul byte too. */
|
||||
bcopy (p + 1, p, strlen(p));
|
||||
bcopy (p + 1, p, strlen (p));
|
||||
|
||||
if (instring)
|
||||
goto string_char;
|
||||
@@ -2318,7 +2309,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
|
||||
}
|
||||
*dptr = 0;
|
||||
|
||||
new_argv = (char **) xmalloc(2 * sizeof(char *));
|
||||
new_argv = (char **) xmalloc (2 * sizeof (char *));
|
||||
new_argv[0] = buffer;
|
||||
new_argv[1] = 0;
|
||||
}
|
||||
|
||||
1
job.h
1
job.h
@@ -46,7 +46,6 @@ struct child
|
||||
|
||||
unsigned int good_stdin:1; /* Nonzero if this child has a good stdin. */
|
||||
unsigned int deleted:1; /* Nonzero if targets have been deleted. */
|
||||
char job_token; /* The token read from the job pipe. */
|
||||
};
|
||||
|
||||
extern struct child *children;
|
||||
|
||||
240
main.c
240
main.c
@@ -79,14 +79,13 @@ static char *quote_as_word PARAMS ((char *out, char *in, int double_dollars));
|
||||
|
||||
struct command_switch
|
||||
{
|
||||
char c; /* The switch character. */
|
||||
unsigned char c; /* The switch character. */
|
||||
|
||||
enum /* Type of the value. */
|
||||
{
|
||||
flag, /* Turn int flag on. */
|
||||
flag_off, /* Turn int flag off. */
|
||||
string, /* One string per switch. */
|
||||
int_string, /* One string. */
|
||||
positive_int, /* A positive integer. */
|
||||
floating, /* A floating-point number (double). */
|
||||
ignore /* Ignored. */
|
||||
@@ -104,6 +103,7 @@ struct command_switch
|
||||
char *long_name; /* Long option name. */
|
||||
char *argdesc; /* Descriptive word for argument. */
|
||||
char *description; /* Description for usage message. */
|
||||
/* 0 means internal; don't display help. */
|
||||
};
|
||||
|
||||
|
||||
@@ -195,16 +195,16 @@ static struct stringlist *makefiles = 0;
|
||||
unsigned int job_slots = 1;
|
||||
unsigned int default_job_slots = 1;
|
||||
|
||||
static char *job_slots_str = "1";
|
||||
|
||||
#ifndef MAKE_JOBSERVER
|
||||
/* Value of job_slots that means no limit. */
|
||||
|
||||
static unsigned int inf_jobs = 0;
|
||||
#endif
|
||||
|
||||
/* File descriptors for the jobs pipe. */
|
||||
|
||||
static struct stringlist *jobserver_fds = 0;
|
||||
|
||||
int job_fds[2] = { -1, -1 };
|
||||
int job_rfd = -1;
|
||||
|
||||
/* Maximum load average at which multiple jobs will be run.
|
||||
Negative values mean unlimited, while zero means limit to
|
||||
@@ -277,14 +277,13 @@ static const struct command_switch switches[] =
|
||||
"include-dir", _("DIRECTORY"),
|
||||
_("Search DIRECTORY for included makefiles") },
|
||||
{ 'j',
|
||||
#ifndef MAKE_JOBSERVER
|
||||
positive_int, (char *) &job_slots, 1, 1, 0,
|
||||
(char *) &inf_jobs, (char *) &default_job_slots,
|
||||
#else
|
||||
int_string, (char *)&job_slots_str, 1, 1, 0, "0", "1",
|
||||
#endif
|
||||
"jobs", "N",
|
||||
_("Allow N jobs at once; infinite jobs with no arg") },
|
||||
{ 2, string, (char *) &jobserver_fds, 1, 1, 0, 0, 0,
|
||||
"jobserver-fds", 0,
|
||||
0 },
|
||||
{ 'k', flag, (char *) &keep_going_flag, 1, 1, 0,
|
||||
0, (char *) &default_keep_going_flag,
|
||||
"keep-going", 0,
|
||||
@@ -337,13 +336,13 @@ static const struct command_switch switches[] =
|
||||
{ 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0,
|
||||
"print-directory", 0,
|
||||
_("Print the current directory") },
|
||||
{ 2, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
|
||||
{ 3, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
|
||||
"no-print-directory", 0,
|
||||
_("Turn off -w, even if it was turned on implicitly") },
|
||||
{ 'W', string, (char *) &new_files, 0, 0, 0, 0, 0,
|
||||
"what-if", _("FILE"),
|
||||
_("Consider FILE to be infinitely new") },
|
||||
{ 3, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
|
||||
{ 4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
|
||||
"warn-undefined-variables", 0,
|
||||
_("Warn when an undefined variable is referenced") },
|
||||
{ '\0', }
|
||||
@@ -944,7 +943,7 @@ int main (int argc, char ** argv)
|
||||
if (print_version_flag)
|
||||
die (0);
|
||||
|
||||
#if !defined(__MSDOS__) && !defined(VMS)
|
||||
#ifndef VMS
|
||||
/* Set the "MAKE_COMMAND" variable to the name we were invoked with.
|
||||
(If it is a relative pathname with a slash, prepend our directory name
|
||||
so the result will run the same program regardless of the current dir.
|
||||
@@ -962,9 +961,21 @@ int main (int argc, char ** argv)
|
||||
strneq(argv[0], "//", 2))
|
||||
argv[0] = xstrdup(w32ify(argv[0],1));
|
||||
#else /* WINDOWS32 */
|
||||
#ifdef __MSDOS__
|
||||
if (strchr (argv[0], '\\'))
|
||||
{
|
||||
char *p;
|
||||
|
||||
argv[0] = xstrdup (argv[0]);
|
||||
for (p = argv[0]; *p; p++)
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
}
|
||||
#else /* !__MSDOS__ */
|
||||
if (current_directory[0] != '\0'
|
||||
&& argv[0] != 0 && argv[0][0] != '/' && index (argv[0], '/') != 0)
|
||||
argv[0] = concat (current_directory, "/", argv[0]);
|
||||
#endif /* !__MSDOS__ */
|
||||
#endif /* WINDOWS32 */
|
||||
#endif
|
||||
|
||||
@@ -1138,7 +1149,7 @@ int main (int argc, char ** argv)
|
||||
while (!feof (stdin))
|
||||
{
|
||||
char buf[2048];
|
||||
unsigned int n = fread (buf, 1, sizeof(buf), stdin);
|
||||
unsigned int n = fread (buf, 1, sizeof (buf), stdin);
|
||||
if (n > 0 && fwrite (buf, 1, n, outfile) != n)
|
||||
pfatal_with_name (_("fwrite (temporary file)"));
|
||||
}
|
||||
@@ -1155,7 +1166,7 @@ int main (int argc, char ** argv)
|
||||
}
|
||||
|
||||
/* Make sure the temporary file will not be remade. */
|
||||
stdin_nm = savestring (name, sizeof(name) -1);
|
||||
stdin_nm = savestring (name, sizeof (name) -1);
|
||||
f = enter_file (stdin_nm);
|
||||
f->updated = 1;
|
||||
f->update_status = 0;
|
||||
@@ -1192,9 +1203,9 @@ int main (int argc, char ** argv)
|
||||
/* This is supposed to be the default, but what the heck... */
|
||||
sa.sa_flags = SA_INTERRUPT;
|
||||
# endif
|
||||
# define HANDLESIG(s) sigaction(s, &sa, NULL)
|
||||
# define HANDLESIG(s) sigaction (s, &sa, NULL)
|
||||
# else
|
||||
# define HANDLESIG(s) signal(s, child_handler)
|
||||
# define HANDLESIG(s) signal (s, child_handler)
|
||||
# endif
|
||||
|
||||
/* OK, now actually install the handlers. */
|
||||
@@ -1259,7 +1270,7 @@ int main (int argc, char ** argv)
|
||||
/* We need to know what kind of shell we will be using. */
|
||||
{
|
||||
extern int _is_unixy_shell (const char *_path);
|
||||
struct variable *shv = lookup_variable("SHELL", 5);
|
||||
struct variable *shv = lookup_variable ("SHELL", 5);
|
||||
extern int unixy_shell;
|
||||
extern char *default_shell;
|
||||
|
||||
@@ -1283,81 +1294,90 @@ int main (int argc, char ** argv)
|
||||
decode_env_switches ("MFLAGS", 6);
|
||||
#endif
|
||||
|
||||
#ifdef __MSDOS__
|
||||
if (job_slots != 1)
|
||||
{
|
||||
error (NILF, _("Parallel jobs (-j) are not supported on MS-DOS."));
|
||||
error (NILF, _("Resetting to single job mode."));
|
||||
job_slots = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAKE_JOBSERVER
|
||||
/* If extended jobs are available then the -j option can have one of 4
|
||||
formats: (1) not specified: default is "1"; (2) specified with no value:
|
||||
default is "0" (infinite); (3) specified with a single value: this means
|
||||
the user wants N job slots; or (4) specified with 2 values separated by
|
||||
a comma. The latter means we're a submake; the two values are the read
|
||||
and write FDs, respectively, for the pipe. Note this last form is
|
||||
undocumented for the user! */
|
||||
/* If the jobserver-fds option is seen, make sure that -j is reasonable. */
|
||||
|
||||
sscanf (job_slots_str, "%d", &job_slots);
|
||||
if (jobserver_fds)
|
||||
{
|
||||
char *cp = index (job_slots_str, ',');
|
||||
char *cp;
|
||||
|
||||
/* In case #4, get the FDs. */
|
||||
if (cp && sscanf (cp+1, "%d", &job_fds[1]) == 1)
|
||||
if (jobserver_fds->idx > 1)
|
||||
fatal (NILF, _("internal error: multiple --jobserver-fds options"));
|
||||
|
||||
/* The combination of a pipe + !job_slots means we're using the
|
||||
jobserver. If !job_slots and we don't have a pipe, we can start
|
||||
infinite jobs. */
|
||||
|
||||
if (job_slots != 0)
|
||||
fatal (NILF, _("internal error: --jobserver-fds unexpected"));
|
||||
|
||||
/* Now parse the fds string and make sure it has the proper format. */
|
||||
|
||||
cp = jobserver_fds->list[0];
|
||||
|
||||
if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
|
||||
fatal (NILF,
|
||||
_("internal error: invalid --jobserver-fds string `%s'"), cp);
|
||||
|
||||
/* Create a duplicate pipe, that will be closed in the SIGCHLD
|
||||
handler. If this fails with EBADF, the parent has closed the pipe
|
||||
on us because it didn't think we were a submake. If so, print a
|
||||
warning then default to -j1. */
|
||||
|
||||
if ((job_rfd = dup (job_fds[0])) < 0)
|
||||
{
|
||||
/* Set up the first FD and set job_slots to 0. The combination of a
|
||||
pipe + !job_slots means we're using the jobserver. If !job_slots
|
||||
and we don't have a pipe, we can start infinite jobs. */
|
||||
job_fds[0] = job_slots;
|
||||
job_slots = 0;
|
||||
if (errno != EBADF)
|
||||
pfatal_with_name (_("dup jobserver"));
|
||||
|
||||
/* Make sure the pipe is open! The parent might have closed it
|
||||
because it didn't think we were a submake. If so, print a warning
|
||||
then default to -j1. */
|
||||
if (fcntl (job_fds[0], F_GETFL, 0) < 0
|
||||
|| fcntl (job_fds[1], F_GETFL, 0) < 0)
|
||||
{
|
||||
error (NILF,
|
||||
_("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
|
||||
job_slots = 1;
|
||||
job_fds[0] = job_fds[1] = -1;
|
||||
job_slots_str = "1";
|
||||
}
|
||||
error (NILF,
|
||||
_("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
|
||||
job_slots = 1;
|
||||
job_fds[0] = job_fds[1] = -1;
|
||||
free (jobserver_fds->list);
|
||||
free (jobserver_fds);
|
||||
jobserver_fds = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* In case #3 above, set up the pipe and set up the submake options
|
||||
properly. */
|
||||
/* If we have >1 slot but no jobserver-fds, then we're a top-level make.
|
||||
Set up the pipe and install the fds option for our children. */
|
||||
|
||||
if (job_slots > 1)
|
||||
else if (job_slots > 1)
|
||||
{
|
||||
char buf[(sizeof("1024")*2)+1];
|
||||
char c = '0';
|
||||
char c = '+';
|
||||
|
||||
if (pipe (job_fds) < 0)
|
||||
if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
|
||||
pfatal_with_name (_("creating jobs pipe"));
|
||||
|
||||
/* Every make assumes that it always has one job it can run. For the
|
||||
submakes it's the token they were given by their parent. For the
|
||||
top make, we just subtract one from the number the user wants. */
|
||||
top make, we just subtract one from the number the user wants. We
|
||||
want job_slots to be 0 to indicate we're using the jobserver. */
|
||||
|
||||
while (--job_slots)
|
||||
{
|
||||
write(job_fds[1], &c, 1);
|
||||
if (c == '9')
|
||||
c = 'a';
|
||||
else if (c == 'z')
|
||||
c = 'A';
|
||||
else if (c == 'Z')
|
||||
c = '0'; /* Start over again!! */
|
||||
else
|
||||
++c;
|
||||
}
|
||||
while (write (job_fds[1], &c, 1) != 1)
|
||||
if (!EINTR_SET)
|
||||
pfatal_with_name (_("init jobserver pipe"));
|
||||
|
||||
sprintf(buf, "%d,%d", job_fds[0], job_fds[1]);
|
||||
job_slots_str = xstrdup(buf);
|
||||
}
|
||||
/* Fill in the jobserver_fds struct for our children. */
|
||||
|
||||
/* Be sure the blocking bit on the read FD is set to start with. */
|
||||
if (job_fds[0] >= 0)
|
||||
{
|
||||
int fl = fcntl(job_fds[0], F_GETFL, 0);
|
||||
if (fl >= 0)
|
||||
fcntl(job_fds[0], F_SETFL, fl & ~O_NONBLOCK);
|
||||
jobserver_fds = (struct stringlist *)
|
||||
xmalloc (sizeof (struct stringlist));
|
||||
jobserver_fds->list = (char **) xmalloc (sizeof (char *));
|
||||
jobserver_fds->list[0] = xmalloc ((sizeof ("1024")*2)+1);
|
||||
|
||||
sprintf (jobserver_fds->list[0], "%d,%d", job_fds[0], job_fds[1]);
|
||||
jobserver_fds->idx = 1;
|
||||
jobserver_fds->max = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1594,9 +1614,9 @@ int main (int argc, char ** argv)
|
||||
/* Add -o option for the stdin temporary file, if necessary. */
|
||||
if (stdin_nm)
|
||||
{
|
||||
nargv = (char **)xmalloc((nargc + 2) * sizeof(char *));
|
||||
bcopy((char *)argv, (char *)nargv, argc * sizeof(char *));
|
||||
nargv[nargc++] = concat("-o", stdin_nm, "");
|
||||
nargv = (char **) xmalloc ((nargc + 2) * sizeof (char *));
|
||||
bcopy ((char *) argv, (char *) nargv, argc * sizeof (char *));
|
||||
nargv[nargc++] = concat ("-o", stdin_nm, "");
|
||||
nargv[nargc] = 0;
|
||||
}
|
||||
|
||||
@@ -1674,8 +1694,8 @@ int main (int argc, char ** argv)
|
||||
|
||||
/* If there is a temp file from reading a makefile from stdin, get rid of
|
||||
it now. */
|
||||
if (stdin_nm && unlink(stdin_nm) < 0 && errno != ENOENT)
|
||||
perror_with_name(_("unlink (temporary file): "), stdin_nm);
|
||||
if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT)
|
||||
perror_with_name (_("unlink (temporary file): "), stdin_nm);
|
||||
|
||||
{
|
||||
int status;
|
||||
@@ -1780,7 +1800,6 @@ init_switches ()
|
||||
long_options[i].has_arg = no_argument;
|
||||
break;
|
||||
|
||||
case int_string:
|
||||
case string:
|
||||
case positive_int:
|
||||
case floating:
|
||||
@@ -1841,8 +1860,7 @@ handle_non_switch_argument (arg, env)
|
||||
}
|
||||
else
|
||||
{
|
||||
lastgoal->next
|
||||
= (struct dep *) xmalloc (sizeof (struct dep));
|
||||
lastgoal->next = (struct dep *) xmalloc (sizeof (struct dep));
|
||||
lastgoal = lastgoal->next;
|
||||
}
|
||||
lastgoal->name = 0;
|
||||
@@ -1853,7 +1871,7 @@ handle_non_switch_argument (arg, env)
|
||||
struct variable *v;
|
||||
char *value;
|
||||
|
||||
v = lookup_variable("MAKECMDGOALS", 12);
|
||||
v = lookup_variable ("MAKECMDGOALS", 12);
|
||||
if (v == 0)
|
||||
value = f->name;
|
||||
else
|
||||
@@ -1861,14 +1879,14 @@ handle_non_switch_argument (arg, env)
|
||||
/* Paste the old and new values together */
|
||||
unsigned int oldlen, newlen;
|
||||
|
||||
oldlen = strlen(v->value);
|
||||
newlen = strlen(f->name);
|
||||
value = (char *)alloca(oldlen + 1 + newlen + 1);
|
||||
bcopy(v->value, value, oldlen);
|
||||
oldlen = strlen (v->value);
|
||||
newlen = strlen (f->name);
|
||||
value = (char *) alloca (oldlen + 1 + newlen + 1);
|
||||
bcopy (v->value, value, oldlen);
|
||||
value[oldlen] = ' ';
|
||||
bcopy(f->name, &value[oldlen + 1], newlen + 1);
|
||||
bcopy (f->name, &value[oldlen + 1], newlen + 1);
|
||||
}
|
||||
define_variable("MAKECMDGOALS", 12, value, o_default, 0);
|
||||
define_variable ("MAKECMDGOALS", 12, value, o_default, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1894,7 +1912,7 @@ print_usage (bad)
|
||||
{
|
||||
char buf[1024], shortarg[50], longarg[50], *p;
|
||||
|
||||
if (cs->description[0] == '-')
|
||||
if (!cs->description || cs->description[0] == '-')
|
||||
continue;
|
||||
|
||||
switch (long_options[cs - switches].has_arg)
|
||||
@@ -1939,8 +1957,9 @@ print_usage (bad)
|
||||
{
|
||||
const struct command_switch *ncs = cs;
|
||||
while ((++ncs)->c != '\0')
|
||||
if (ncs->description[0] == '-' &&
|
||||
ncs->description[1] == cs->c)
|
||||
if (ncs->description
|
||||
&& ncs->description[0] == '-'
|
||||
&& ncs->description[1] == cs->c)
|
||||
{
|
||||
/* This is another switch that does the same
|
||||
one as the one we are processing. We want
|
||||
@@ -2034,20 +2053,6 @@ decode_switches (argc, argv, env)
|
||||
*(int *) cs->value_ptr = cs->type == flag;
|
||||
break;
|
||||
|
||||
case int_string:
|
||||
if (optarg == 0 && argc > optind
|
||||
&& isdigit (argv[optind][0]))
|
||||
optarg = argv[optind++];
|
||||
|
||||
if (!doit)
|
||||
break;
|
||||
|
||||
if (optarg == 0)
|
||||
optarg = cs->noarg_value;
|
||||
|
||||
*(char **)cs->value_ptr = optarg;
|
||||
break;
|
||||
|
||||
case string:
|
||||
if (!doit)
|
||||
break;
|
||||
@@ -2078,7 +2083,7 @@ decode_switches (argc, argv, env)
|
||||
|
||||
case positive_int:
|
||||
if (optarg == 0 && argc > optind
|
||||
&& isdigit (argv[optind][0]))
|
||||
&& ISDIGIT (argv[optind][0]))
|
||||
optarg = argv[optind++];
|
||||
|
||||
if (!doit)
|
||||
@@ -2090,8 +2095,7 @@ decode_switches (argc, argv, env)
|
||||
if (i < 1)
|
||||
{
|
||||
if (doit)
|
||||
error (NILF, _("the `-%c' option requires a \
|
||||
positive integral argument"),
|
||||
error (NILF, _("the `-%c' option requires a positive integral argument"),
|
||||
cs->c);
|
||||
bad = 1;
|
||||
}
|
||||
@@ -2106,7 +2110,7 @@ positive integral argument"),
|
||||
#ifndef NO_FLOAT
|
||||
case floating:
|
||||
if (optarg == 0 && optind < argc
|
||||
&& (isdigit (argv[optind][0]) || argv[optind][0] == '.'))
|
||||
&& (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.'))
|
||||
optarg = argv[optind++];
|
||||
|
||||
if (doit)
|
||||
@@ -2133,7 +2137,7 @@ positive integral argument"),
|
||||
|
||||
if (!env && (bad || print_usage_flag))
|
||||
{
|
||||
print_usage(bad);
|
||||
print_usage (bad);
|
||||
die (bad ? 2 : 0);
|
||||
}
|
||||
}
|
||||
@@ -2346,22 +2350,6 @@ define_makeflags (all, makefile)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case int_string:
|
||||
if (all)
|
||||
{
|
||||
char *vp = *(char **)cs->value_ptr;
|
||||
|
||||
if (cs->default_value != 0
|
||||
&& streq(vp, cs->default_value))
|
||||
break;
|
||||
if (cs->noarg_value != 0
|
||||
&& streq(vp, cs->noarg_value))
|
||||
ADD_FLAG("", 0); /* Optional value omitted; see below. */
|
||||
else
|
||||
ADD_FLAG(vp, strlen(vp));
|
||||
}
|
||||
break;
|
||||
|
||||
case string:
|
||||
if (all)
|
||||
{
|
||||
|
||||
@@ -18,29 +18,29 @@ MTEMPLATES = Makefile.DOS SMakefile
|
||||
|
||||
# General rule for turning a .template into a regular file.
|
||||
#
|
||||
$(TEMPLATES) : % : %.template configure.in
|
||||
$(TEMPLATES) : % : %.template Makefile
|
||||
rm -f $@
|
||||
sed -e 's@%VERSION%@$(VERSION)@' \
|
||||
-e 's@%PACKAGE%@$(PACKAGE)@' \
|
||||
sed -e 's@%VERSION%@$(VERSION)@g' \
|
||||
-e 's@%PACKAGE%@$(PACKAGE)@g' \
|
||||
$< > $@
|
||||
chmod a-w $@
|
||||
|
||||
# Construct Makefiles by adding on dependencies, etc.
|
||||
#
|
||||
$(MTEMPLATES) : % : %.template .dep_segment Makefile.am maintMakefile
|
||||
$(MTEMPLATES) : % : %.template .dep_segment Makefile
|
||||
rm -f $@
|
||||
sed -e 's@%VERSION%@$(VERSION)@' \
|
||||
-e 's@%PROGRAMS%@$(bin_PROGRAMS)@' \
|
||||
-e 's@%SOURCES%@$(filter-out remote-%,$(make_SOURCES)) remote-$$(REMOTE).c@' \
|
||||
-e 's@%OBJECTS%@$(filter-out remote-%,$(make_OBJECTS)) remote-$$(REMOTE).o@' \
|
||||
-e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@' \
|
||||
-e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@' \
|
||||
sed -e 's@%VERSION%@$(VERSION)@g' \
|
||||
-e 's@%PROGRAMS%@$(bin_PROGRAMS)@g' \
|
||||
-e 's@%SOURCES%@$(filter-out remote-%,$(make_SOURCES)) remote-$$(REMOTE).c@g' \
|
||||
-e 's@%OBJECTS%@$(filter-out remote-%,$(make_OBJECTS)) remote-$$(REMOTE).o@g' \
|
||||
-e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@g' \
|
||||
-e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@g' \
|
||||
$< > $@
|
||||
echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
|
||||
cat $(word 2,$^) >>$@
|
||||
chmod a-w $@
|
||||
|
||||
NMakefile: NMakefile.template .dep_segment Makefile.am maintMakefile
|
||||
NMakefile: NMakefile.template .dep_segment Makefile
|
||||
rm -f $@
|
||||
cp $< $@
|
||||
echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
|
||||
@@ -49,10 +49,10 @@ NMakefile: NMakefile.template .dep_segment Makefile.am maintMakefile
|
||||
|
||||
# Construct build.sh.in
|
||||
#
|
||||
build.sh.in: build.template Makefile.am maintMakefile
|
||||
build.sh.in: build.template Makefile
|
||||
rm -f $@
|
||||
sed -e 's@%objs%@$(filter-out remote-%, $(make_OBJECTS)@' \
|
||||
-e 's@%globobjs%@$(patsubst %.c,%.o,$(globsrc)))@' \
|
||||
sed -e 's@%objs%@$(filter-out remote-%, $(make_OBJECTS)@g' \
|
||||
-e 's@%globobjs%@$(patsubst %.c,%.o,$(globsrc)))@g' \
|
||||
$< > $@
|
||||
chmod a-w+x $@
|
||||
|
||||
|
||||
12
make.h
12
make.h
@@ -299,6 +299,17 @@ extern char *alloca ();
|
||||
# endif /* HAVE_ALLOCA_H. */
|
||||
#endif /* GCC. */
|
||||
|
||||
/* ISDIGIT offers the following features:
|
||||
- Its arg may be any int or unsigned int; it need not be an unsigned char.
|
||||
- It's guaranteed to evaluate its argument exactly once.
|
||||
NOTE! Make relies on this behavior, don't change it!
|
||||
- It's typically faster.
|
||||
Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
|
||||
only '0' through '9' are digits. Prefer ISDIGIT to isdigit() unless
|
||||
it's important to use the locale's definition of `digit' even when the
|
||||
host does not conform to Posix. */
|
||||
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
|
||||
|
||||
#ifndef iAPX286
|
||||
# define streq(a, b) \
|
||||
((a) == (b) || \
|
||||
@@ -479,6 +490,7 @@ extern int batch_mode_shell;
|
||||
|
||||
extern unsigned int job_slots;
|
||||
extern int job_fds[2];
|
||||
extern int job_rfd;
|
||||
#ifndef NO_FLOAT
|
||||
extern double max_load_average;
|
||||
#else
|
||||
|
||||
760
make.texinfo
760
make.texinfo
File diff suppressed because it is too large
Load Diff
38
remake.c
38
remake.c
@@ -316,19 +316,19 @@ update_file (file, depth)
|
||||
register int status = 0;
|
||||
register struct file *f;
|
||||
|
||||
/* Prune the dependency graph: if we've already been here on _this_ pass
|
||||
through the dependency graph, we don't have to go any further. We won't
|
||||
reap_children until we start the next pass, so no state change is
|
||||
possible below here until then. */
|
||||
if (file->considered == considered)
|
||||
{
|
||||
DEBUGPR (_("Pruning file `%s'.\n"));
|
||||
return 0;
|
||||
}
|
||||
file->considered = considered;
|
||||
|
||||
for (f = file->double_colon ? file->double_colon : file; f != 0; f = f->prev)
|
||||
{
|
||||
/* Prune the dependency graph: if we've already been here on _this_
|
||||
pass through the dependency graph, we don't have to go any further.
|
||||
We won't reap_children until we start the next pass, so no state
|
||||
change is possible below here until then. */
|
||||
if (f->considered == considered)
|
||||
{
|
||||
DEBUGPR (_("Pruning file `%s'.\n"));
|
||||
continue;
|
||||
}
|
||||
f->considered = considered;
|
||||
|
||||
status |= update_file_1 (f, depth);
|
||||
check_renamed (f);
|
||||
|
||||
@@ -452,7 +452,7 @@ update_file_1 (file, depth)
|
||||
|
||||
if (d->file->updating)
|
||||
{
|
||||
error (NILF, _("Circular %s <- %s dependency dropped."),
|
||||
error (NILF, _("Circular %s <- %s prerequisite dropped."),
|
||||
file->name, d->file->name);
|
||||
/* We cannot free D here because our the caller will still have
|
||||
a reference to it when we were called recursively via
|
||||
@@ -530,13 +530,13 @@ update_file_1 (file, depth)
|
||||
|
||||
file->updating = 0;
|
||||
|
||||
DEBUGPR (_("Finished dependencies of target file `%s'.\n"));
|
||||
DEBUGPR (_("Finished prerequisites of target file `%s'.\n"));
|
||||
|
||||
if (running)
|
||||
{
|
||||
set_command_state (file, cs_deps_running);
|
||||
--depth;
|
||||
DEBUGPR (_("The dependencies of `%s' are being made.\n"));
|
||||
DEBUGPR (_("The prerequisites of `%s' are being made.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -598,9 +598,9 @@ update_file_1 (file, depth)
|
||||
{
|
||||
print_spaces (depth);
|
||||
if (d_mtime == (FILE_TIMESTAMP) -1)
|
||||
printf (_("Dependency `%s' does not exist.\n"), dep_name (d));
|
||||
printf (_("Prerequisite `%s' does not exist.\n"), dep_name (d));
|
||||
else
|
||||
printf (_("Dependency `%s' is %s than dependent `%s'.\n"),
|
||||
printf (_("Prerequisite `%s' is %s than target `%s'.\n"),
|
||||
dep_name (d), d->changed ? _("newer") : _("older"), file->name);
|
||||
fflush (stdout);
|
||||
}
|
||||
@@ -612,12 +612,12 @@ update_file_1 (file, depth)
|
||||
if (file->double_colon && file->deps == 0)
|
||||
{
|
||||
must_make = 1;
|
||||
DEBUGPR (_("Target `%s' is double-colon and has no dependencies.\n"));
|
||||
DEBUGPR (_("Target `%s' is double-colon and has no prerequisites.\n"));
|
||||
}
|
||||
else if (!noexist && file->is_target && !deps_changed && file->cmds == 0)
|
||||
{
|
||||
must_make = 0;
|
||||
DEBUGPR (_("No commands for `%s' and no dependencies actually changed.\n"));
|
||||
DEBUGPR (_("No commands for `%s' and no prerequisites actually changed.\n"));
|
||||
}
|
||||
|
||||
if (!must_make)
|
||||
@@ -851,7 +851,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
{
|
||||
if (d->file->updating)
|
||||
{
|
||||
error (NILF, _("Circular %s <- %s dependency dropped."),
|
||||
error (NILF, _("Circular %s <- %s prerequisite dropped."),
|
||||
file->name, d->file->name);
|
||||
if (lastd == 0)
|
||||
{
|
||||
|
||||
15
variable.c
15
variable.c
@@ -780,9 +780,9 @@ try_variable_definition (flocp, line, origin)
|
||||
case f_simple:
|
||||
/* A simple variable definition "var := value". Expand the value.
|
||||
We have to allocate memory since otherwise it'll clobber the
|
||||
variable buffer, and we still need that. */
|
||||
alloc_value = allocated_variable_expand (p);
|
||||
value = alloc_value;
|
||||
variable buffer, and we may still need that if we're looking at a
|
||||
target-specific variable. */
|
||||
value = alloc_value = allocated_variable_expand (p);
|
||||
break;
|
||||
case f_conditional:
|
||||
/* A conditional variable definition "var ?= value".
|
||||
@@ -824,8 +824,10 @@ try_variable_definition (flocp, line, origin)
|
||||
else
|
||||
/* The previous definition of the variable was simple.
|
||||
The new value comes from the old value, which was expanded
|
||||
when it was set; and from the expanded new value. */
|
||||
p = variable_expand (p);
|
||||
when it was set; and from the expanded new value. Allocate
|
||||
memory for the expansion as we may still need the rest of the
|
||||
buffer if we're looking at a target-specific variable. */
|
||||
p = alloc_value = allocated_variable_expand (p);
|
||||
|
||||
oldlen = strlen (v->value);
|
||||
newlen = strlen (p);
|
||||
@@ -952,7 +954,7 @@ print_variable (v, prefix)
|
||||
register struct variable *v;
|
||||
char *prefix;
|
||||
{
|
||||
char *origin;
|
||||
const char *origin;
|
||||
|
||||
switch (v->origin)
|
||||
{
|
||||
@@ -980,7 +982,6 @@ print_variable (v, prefix)
|
||||
case o_invalid:
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
printf ("# %s\n", origin);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user