mirror of
https://github.com/mirror/make.git
synced 2026-08-20 00:43:29 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52191d9d61 | ||
|
|
dc9ae5e017 | ||
|
|
723e047428 | ||
|
|
b69b04dc8c | ||
|
|
b539908f73 | ||
|
|
2fb91e19a0 | ||
|
|
f96c114e22 | ||
|
|
98197303b1 | ||
|
|
f8786092ad | ||
|
|
1d4c15b4e1 | ||
|
|
b1c7f0df4e | ||
|
|
8e12202870 | ||
|
|
1f4ca0539b | ||
|
|
d0944ee2e8 | ||
|
|
38066b6f19 | ||
|
|
3bf3fde984 | ||
|
|
543521cd47 | ||
|
|
e8122ecb5d | ||
|
|
55a0c0e414 |
106
ChangeLog
106
ChangeLog
@@ -1,3 +1,109 @@
|
||||
2013-10-09 Paul Smith <psmith@gnu.org>
|
||||
|
||||
Version 4.0 released.
|
||||
|
||||
* configure.ac: Updated for the release.
|
||||
* NEWS: Updated for the release.
|
||||
|
||||
* maintMakefile (tag-release): New target to add a Git tag.
|
||||
* read.c (eval): Typo fix.
|
||||
* ChangeLog.1: Typo fixes.
|
||||
* w32/subproc/sub_proc.c (process_cleanup): Typo fix.
|
||||
|
||||
2013-10-07 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* w32/compat/posixfcn.c (tmpfile): Move declaration of h before
|
||||
the first executable statement. Reported by Gisle Vanem
|
||||
<gvanem@yahoo.no>.
|
||||
|
||||
2013-10-05 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* makeint.h (MAP_USERFUNC): A new map type for function names.
|
||||
* main.c (initialize_stopchar_map): Set up the function name map.
|
||||
|
||||
* gnumake.h (gmk_func_ptr): Define a type for function pointers.
|
||||
(gmk_add_function): Convert the last argument to FLAGS.
|
||||
(GMK_FUNC_*): Define flags for the function. Change the default
|
||||
behavior to "expand" since that's the most common one.
|
||||
|
||||
* function.c (function_table_entry): Use new function pointer type.
|
||||
(lookup_function): Accept any valid function name character based
|
||||
on the MAP_USERFUNC values.
|
||||
(define_new_function): Use the new calling signature. Verify that
|
||||
registered functions have valid names.
|
||||
|
||||
* guile.c (guile_gmake_setup): Use new calling signatures.
|
||||
* loadapi.c (gmk_add_function): Ditto.
|
||||
* variable.h (define_new_function): Ditto.
|
||||
|
||||
* doc/make.texi (Loaded Object API): Make the registered function
|
||||
API documentation more clear.
|
||||
|
||||
2013-10-03 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* function.c (abspath): Reset root_len to one for Cygwin only when
|
||||
HAVE_DOS_PATHS is defined. Suggested by Christopher Faylor.
|
||||
|
||||
2013-10-02 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* w32/compat/posixfcn.c (tmpfile): New function, a replacement for
|
||||
the Windows libc version.
|
||||
|
||||
Fix $abspath on Cygwin when HAVE_DOS_PATHS is in effect.
|
||||
* function.c (IS_ABSOLUTE) [__CYGWIN__]: Special definition for
|
||||
Cygwin.
|
||||
(abspath) [__CYGWIN__]: Reset root_len to 1 if the absolute file
|
||||
name has the Posix /foo/bar form.
|
||||
[HAVE_DOS_PATHS]: Use root_len instead of hard-coded 2.
|
||||
|
||||
2013-10-01 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* configure.ac: Update version to 3.99.93.
|
||||
* NEWS: Ditto.
|
||||
|
||||
2013-09-30 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* guile.c: Portability fixes for Guile 1.8.
|
||||
|
||||
2013-09-29 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* output.c (output_dump): Always write Enter/Leave messages to stdio.
|
||||
(log_working_directory): This now always writes to stdio, so we
|
||||
don't need the struct output parameter anymore.
|
||||
(output_start): Show the working directory when output_sync is not
|
||||
set or is recursive.
|
||||
* main.c (main): Ensure the special "already shown Enter message"
|
||||
token is removed from MAKE_RESTARTS before the user can see it.
|
||||
* function.c (func_shell_base): If the output_context stderr
|
||||
exists but is invalid, write to the real stderr.
|
||||
Fixes suggested by Frank Heckenbach <f.heckenbach@fh-soft.de>.
|
||||
|
||||
* output.c: Guard unistd.h inclusion, add io.h.
|
||||
* gnumake.h: Move GMK_EXPORT before the declarations.
|
||||
* make_msvc_net2003.vcproj: Add missing files.
|
||||
Changes for MSVC suggested by Gerte Hoogewerf <g.hoogewerf@gmail.com>
|
||||
|
||||
* function.c (func_shell_base) [EMX]: Fix EMX support for output-sync.
|
||||
* job.c (child_execute_job) [EMX]: Ditto.
|
||||
* job.h (child_execute_job) [EMX]: Ditto.
|
||||
* w32/compat/posixfcn.c: Invert the test for NO_OUTPUT_SYNC.
|
||||
|
||||
* guile.c (GSUBR_TYPE): Pre-2.0 Guile doesn't provide a typedef
|
||||
for gsubr pointers. Create one.
|
||||
(guile_define_module): Use it.
|
||||
(internal_guile_eval): Force UTF-8 encoding for Guile strings.
|
||||
|
||||
* main.c (main): Clear GNUMAKEFLAGS after parsing, to avoid
|
||||
proliferation of options.
|
||||
* NEWS: Document it.
|
||||
* doc/make.texi (Options/Recursion): Ditto.
|
||||
|
||||
2013-09-23 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* w32/compat/posixfcn.c: Fix the forgotten OUTPUT_SYNC conditional.
|
||||
|
||||
* job.h: Ditto, but in a comment.
|
||||
|
||||
2013-09-22 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* configure.ac: Update version to 3.99.92.
|
||||
|
||||
@@ -1703,7 +1703,7 @@ Thu Sep 14 18:29:38 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU)
|
||||
existing variable's origin, is `o_env', make it `o_env_override'.
|
||||
|
||||
* load.c: Use the symbol KERNEL_FILE_NAME instead of KERNEL_FILE.
|
||||
* compatMakefile: Changed the comment for `LOAD_AVG' accordinly.
|
||||
* compatMakefile: Changed the comment for `LOAD_AVG' accordingly.
|
||||
|
||||
Thu Sep 7 16:46:26 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU)
|
||||
|
||||
@@ -3218,7 +3218,7 @@ Sun Feb 5 19:52:38 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU)
|
||||
* variable.c (expand_function: `shell'): Use
|
||||
`shell_function_completed'. Block children before forking and
|
||||
unblock after `shell_function_pid' is set properly and
|
||||
`shell_functon_completed' is reset to 0.
|
||||
`shell_function_completed' is reset to 0.
|
||||
|
||||
* commands.c (child_handler): When the child of the `shell' function
|
||||
completes, set `shell_function_completed' to 1 if it actually ran,
|
||||
@@ -4465,7 +4465,7 @@ Fri Sep 16 13:59:59 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU)
|
||||
`maxsuffix', and must be called before count_implicit_rule_limits.
|
||||
|
||||
* rule.c (pattern_search): If an existent (non-intermediate)
|
||||
dependendency was found via a terminal rule, set its
|
||||
dependency was found via a terminal rule, set its
|
||||
`tried_implicit' flag, so it will never have implicit rule search done.
|
||||
|
||||
* glob.c: Bug fix to avoid alloca(0).
|
||||
@@ -4826,7 +4826,7 @@ Sat Jul 30 15:47:23 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU)
|
||||
new entry as the old entry's prev pointer.
|
||||
|
||||
* dir.c: Re-indented the `struct dir' definition to be right.
|
||||
(dir_load): Cleaned up slighty.
|
||||
(dir_load): Cleaned up slightly.
|
||||
(file_exists_p): Removed comment saying we could use `access', since
|
||||
that is a bad idea (except for setuid programs). Cleaned up slightly.
|
||||
|
||||
|
||||
28
NEWS
28
NEWS
@@ -1,6 +1,6 @@
|
||||
GNU make NEWS -*-indented-text-*-
|
||||
History of user-visible changes.
|
||||
23 Sep 2013
|
||||
09 Oct 2013
|
||||
|
||||
See the end of this file for copyrights and conditions.
|
||||
|
||||
@@ -9,7 +9,7 @@ manual, which is contained in this distribution as the file doc/make.texi.
|
||||
See the README file and the GNU make manual for instructions for
|
||||
reporting bugs.
|
||||
|
||||
Version 3.99.92
|
||||
Version 4.0 (09 Oct 2013)
|
||||
|
||||
A complete list of bugs fixed in this version is available here:
|
||||
|
||||
@@ -23,6 +23,14 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
* Each backslash/newline (plus subsequent whitespace) is converted to a
|
||||
single space
|
||||
|
||||
* New feature: GNU Guile integration
|
||||
This version of GNU make can be compiled with GNU Guile integration.
|
||||
GNU Guile serves as an embedded extension language for make.
|
||||
See the "Guile Function" section in the GNU Make manual for details.
|
||||
Currently GNU Guile 1.8 and 2.0+ are supported. In Guile 1.8 there is no
|
||||
support for internationalized character sets. In Guile 2.0+, scripts can be
|
||||
encoded in UTF-8.
|
||||
|
||||
* New command line option: --output-sync (-O) enables grouping of output by
|
||||
target or by recursive make. This is useful during parallel builds to avoid
|
||||
mixing output from different jobs together giving hard-to-understand
|
||||
@@ -47,6 +55,8 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
|
||||
* New feature: "!=" shell assignment operator as an alternative to the
|
||||
$(shell ...) function. Implemented for compatibility with BSD makefiles.
|
||||
Note there are subtle differences between "!=" and $(shell ...). See the
|
||||
description in the GNU make manual.
|
||||
WARNING: Backward-incompatibility!
|
||||
Variables ending in "!" previously defined as "variable!= value" will now be
|
||||
interpreted as shell assignment. Change your assignment to add whitespace
|
||||
@@ -58,11 +68,6 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
version of POSIX (see http://austingroupbugs.net/view.php?id=330). It is
|
||||
not necessary to define the .POSIX target to access this operator.
|
||||
|
||||
* New feature: GNU Guile integration
|
||||
This version of GNU make can be compiled with GNU Guile integration.
|
||||
GNU Guile serves as an embedded extension language for make.
|
||||
See the "Guile Function" section in the GNU Make manual for details.
|
||||
|
||||
* New feature: Loadable objects
|
||||
This version of GNU make contains a "technology preview": the ability to
|
||||
load dynamic objects into the make runtime. These objects can be created by
|
||||
@@ -73,7 +78,8 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
* New variable: $(GNUMAKEFLAGS) will be parsed for make flags, just like
|
||||
MAKEFLAGS is. It can be set in the environment or the makefile, containing
|
||||
GNU make-specific flags to allow your makefile to be portable to other
|
||||
versions of make. GNU make never sets or modifies GNUMAKEFLAGS.
|
||||
versions of make. Once this variable is parsed, GNU make will set it to the
|
||||
empty string so that flags will not be duplicated on recursion.
|
||||
|
||||
* New variable: `MAKE_HOST' gives the name of the host architecture
|
||||
make was compiled for. This is the same value you see after 'Built for'
|
||||
@@ -81,8 +87,10 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
|
||||
* Behavior of MAKEFLAGS and MFLAGS is more rigorously defined. All simple
|
||||
flags are grouped together in the first word of MAKEFLAGS. No options that
|
||||
accept arguments appear there. If no simple flags are present MAKEFLAGS
|
||||
begins with a space. MFLAGS never begins with "- ".
|
||||
accept arguments appear in the first word. If no simple flags are present
|
||||
MAKEFLAGS begins with a space. Flags with both short and long versions
|
||||
always use the short versions in MAKEFLAGS. Flags are listed in
|
||||
alphabetical order using ASCII ordering. MFLAGS never begins with "- ".
|
||||
|
||||
* Setting the -r and -R options in MAKEFLAGS inside a makefile now works as
|
||||
expected, removing all built-in rules and variables, respectively.
|
||||
|
||||
@@ -7,7 +7,7 @@ It builds with the MinGW port of GCC (tested with GCC 3.4.2).
|
||||
It also builds with MSVC 2.x, 4.x, 5.x, 6.x, and 2003 as well as
|
||||
with .NET 7.x and .NET 2003.
|
||||
|
||||
As of version 3.83, a build with Guile is supported (tested with Guile
|
||||
As of version 4.0, a build with Guile is supported (tested with Guile
|
||||
2.0.3). To build with Guile, you will need, in addition to Guile
|
||||
itself, its dependency libraries and the pkg-config program. The
|
||||
latter is used to figure out which compilation and link switches and
|
||||
|
||||
24
TODO.private
24
TODO.private
@@ -99,30 +99,6 @@ The Rest of the List
|
||||
you just can't figure it out. The way variables are expanded now
|
||||
means this isn't 100% trivial, but it probably won't be hard.
|
||||
|
||||
8) Integration of Guile as an embedded scripting language. This means:
|
||||
allowing Guile functions to be declared in makefiles somehow, then
|
||||
providing a syntax for invoking them. At least one formulation of
|
||||
that would have the function resolve to a string which would be
|
||||
substituted in the makefile, kind of like $(shell ...) does now, but
|
||||
using the embedded interpreter so there's no process forked of
|
||||
course. Obviously this is an optional add-on feature.
|
||||
|
||||
It could be more advanced than that, even, who knows? Maybe make
|
||||
could provide Guile functions that allow Guile scripts more direct
|
||||
access to internal make structures, somehow. This kind of thing
|
||||
needs a lot of thought.
|
||||
|
||||
Also there's always the flip side: in some very fundamental ways
|
||||
make isn't the best choice right now for a complex build tool. It's
|
||||
great for simple-to-medium tasks, but there are already other tools
|
||||
available for the really tough situations. Ask yourself,
|
||||
realistically, how much work is worthwhile to add to make, given the
|
||||
fundamentals you can't really overcome without significantly
|
||||
affecting backward compatibility--and then why not use another tool
|
||||
in the first place?
|
||||
|
||||
Something to think about.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1997-2013 Free Software Foundation, Inc.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AC_INIT([GNU make],[3.99.92],[bug-make@gnu.org])
|
||||
AC_INIT([GNU make],[4.0],[bug-make@gnu.org])
|
||||
|
||||
AC_PREREQ([2.62])
|
||||
|
||||
|
||||
@@ -4808,10 +4808,17 @@ to GNU @code{make}, and hence do not want to add GNU
|
||||
@code{make}-specific flags to the @code{MAKEFLAGS} variable, you can
|
||||
add them to the @code{GNUMAKEFLAGS} variable instead. This variable
|
||||
is parsed just before @code{MAKEFLAGS}, in the same way as
|
||||
@code{MAKEFLAGS}. Note, however, that when @code{make} constructs
|
||||
@code{MAKEFLAGS} to pass to a recursive @code{make} it will include
|
||||
all flags. GNU @code{make} never sets the @code{GNUMAKEFLAGS}
|
||||
variable itself.
|
||||
@code{MAKEFLAGS}. When @code{make} constructs @code{MAKEFLAGS} to
|
||||
pass to a recursive @code{make} it will include all flags, even those
|
||||
taken from @code{GNUMAKEFLAGS}. As a result, after parsing
|
||||
@code{GNUMAKEFLAGS} GNU @code{make} sets this variable to the empty
|
||||
string to avoid duplicating flags during recursion.
|
||||
|
||||
It's best to use @code{GNUMAKEFLAGS} only with flags which won't
|
||||
materially change the behavior of your makefiles. If your makefiles
|
||||
require GNU make anyway then simply use @code{MAKEFLAGS}. Flags such
|
||||
as @samp{--no-print-directory} or @samp{--output-sync} may be
|
||||
appropriate for @code{GNUMAKEFLAGS}.
|
||||
|
||||
@node -w Option, , Options/Recursion, Recursion
|
||||
@subsection The @samp{--print-directory} Option
|
||||
@@ -11108,16 +11115,14 @@ arguments are as follows:
|
||||
@table @code
|
||||
@item name
|
||||
The function name. This is what the makefile should use to invoke the
|
||||
function. The name must be between 1 and 255 characters long.
|
||||
function. The name must be between 1 and 255 characters long and it
|
||||
may only contain alphanumeric, period (@samp{.}), dash (@samp{-}), and
|
||||
underscore (@samp{_}) characters. It may not begin with a period.
|
||||
|
||||
@item func_ptr
|
||||
A pointer to a function that @code{make} will invoke when it expands
|
||||
the function in a makefile. This function must be defined by the
|
||||
loaded object. GNU @code{make} will call it with three arguments:
|
||||
@code{name} (the same name as above), @code{argc} (the number of
|
||||
arguments to the function), and @code{argv} (the list of arguments to
|
||||
the function). The last argument (that is, @code{argv[argc]} will be
|
||||
null (@code{0}).
|
||||
loaded object.
|
||||
|
||||
@item min_args
|
||||
The minimum number of arguments the function will accept. Must be
|
||||
@@ -11133,12 +11138,30 @@ arguments. If the value is 0, then any number of arguments is
|
||||
accepted. If the value is greater than 0, then it must be greater
|
||||
than or equal to @code{min_args}.
|
||||
|
||||
@item expand_args
|
||||
If this value is 0, then @code{make} will not expand the arguments to
|
||||
the function before passing them to @code{func_ptr}. If the value is
|
||||
non-0, then the arguments will be expanded first.
|
||||
@item flags
|
||||
Flags that specify how this function will operate; the desired flags
|
||||
should be OR'd together. If the @code{GMK_FUNC_NOEXPAND} flag is
|
||||
given then the function arguments will not be expanded before the
|
||||
function is called; otherwise they will be expanded first.
|
||||
@end table
|
||||
|
||||
@subsubheading Registered Function Interface
|
||||
@findex gmk_func_ptr
|
||||
|
||||
A function registered with @code{make} must match the
|
||||
@code{gmk_func_ptr} type. It will be invoked with three parameters:
|
||||
@code{name} (the name of the function), @code{argc} (the number of
|
||||
arguments to the function), and @code{argv} (an array of pointers to
|
||||
arguments to the function). The last pointer (that is,
|
||||
@code{argv[argc]}) will be null (@code{0}).
|
||||
|
||||
The return value of the function is the result of expanding the
|
||||
function. If the function expands to nothing the return value may be
|
||||
null. Otherwise, it must be a pointer to a string created with
|
||||
@code{gmk_alloc}. Once the function returns, @code{make} owns this
|
||||
string and will free it when appropriate; it cannot be accessed by the
|
||||
loaded object.
|
||||
|
||||
@subsubheading GNU @code{make} Facilities
|
||||
|
||||
There are some facilities exported by GNU @code{make} for use by
|
||||
@@ -11177,6 +11200,12 @@ should never pass memory that you've allocated directly to any
|
||||
memory returned to you by any @code{make} function. Instead, use the
|
||||
@code{gmk_alloc} and @code{gmk_free} functions.
|
||||
|
||||
In particular, the string returned to @code{make} by a function
|
||||
registered using @code{gmk_add_function} @emph{must} be allocated
|
||||
using @code{gmk_alloc}, and the string returned from the @code{make}
|
||||
@code{gmk_expand} function @emph{must} be freed (when no longer
|
||||
needed) using @code{gmk_free}.
|
||||
|
||||
@table @code
|
||||
@item gmk_alloc
|
||||
@findex gmk_alloc
|
||||
|
||||
86
function.c
86
function.c
@@ -31,7 +31,7 @@ struct function_table_entry
|
||||
{
|
||||
union {
|
||||
char *(*func_ptr) (char *output, char **argv, const char *fname);
|
||||
char *(*alloc_func_ptr) (const char *fname, int argc, char **argv);
|
||||
gmk_func_ptr alloc_func_ptr;
|
||||
} fptr;
|
||||
const char *name;
|
||||
unsigned char len;
|
||||
@@ -269,19 +269,19 @@ patsubst_expand (char *o, const char *text, char *pattern, char *replace)
|
||||
static const struct function_table_entry *
|
||||
lookup_function (const char *s)
|
||||
{
|
||||
struct function_table_entry function_table_entry_key;
|
||||
const char *e = s;
|
||||
|
||||
while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
|
||||
while (STOP_SET (*e, MAP_USERFUNC))
|
||||
e++;
|
||||
if (*e == '\0' || isblank ((unsigned char) *e))
|
||||
{
|
||||
struct function_table_entry function_table_entry_key;
|
||||
function_table_entry_key.name = s;
|
||||
function_table_entry_key.len = e - s;
|
||||
|
||||
return hash_find_item (&function_table, &function_table_entry_key);
|
||||
}
|
||||
return 0;
|
||||
if (e == s || !STOP_SET(*e, MAP_NUL|MAP_SPACE))
|
||||
return NULL;
|
||||
|
||||
function_table_entry_key.name = s;
|
||||
function_table_entry_key.len = e - s;
|
||||
|
||||
return hash_find_item (&function_table, &function_table_entry_key);
|
||||
}
|
||||
|
||||
|
||||
@@ -1620,7 +1620,7 @@ char *
|
||||
func_shell_base (char *o, char **argv, int trim_newlines)
|
||||
{
|
||||
char *batch_filename = NULL;
|
||||
|
||||
int errfd;
|
||||
#ifdef __MSDOS__
|
||||
FILE *fpipe;
|
||||
#endif
|
||||
@@ -1636,9 +1636,9 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||
are used to run the commands, because we normally refrain from
|
||||
creating batch files under -n. */
|
||||
int j_p_f = just_print_flag;
|
||||
|
||||
just_print_flag = 0;
|
||||
#endif
|
||||
|
||||
/* Construct the argument list. */
|
||||
command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
|
||||
&batch_filename);
|
||||
@@ -1652,15 +1652,15 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||
#endif
|
||||
|
||||
/* Using a target environment for 'shell' loses in cases like:
|
||||
export var = $(shell echo foobie)
|
||||
because target_environment hits a loop trying to expand $(var)
|
||||
to put it in the environment. This is even more confusing when
|
||||
var was not explicitly exported, but just appeared in the
|
||||
calling environment.
|
||||
export var = $(shell echo foobie)
|
||||
bad := $(var)
|
||||
because target_environment hits a loop trying to expand $(var) to put it
|
||||
in the environment. This is even more confusing when 'var' was not
|
||||
explicitly exported, but just appeared in the calling environment.
|
||||
|
||||
See Savannah bug #10593.
|
||||
|
||||
envp = target_environment (NILF);
|
||||
envp = target_environment (NULL);
|
||||
*/
|
||||
|
||||
envp = environ;
|
||||
@@ -1678,6 +1678,9 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||
/* Set up the output in case the shell writes something. */
|
||||
output_start ();
|
||||
|
||||
errfd = (output_context && output_context->err >= 0
|
||||
? output_context->err : FD_STDERR);
|
||||
|
||||
#if defined(__MSDOS__)
|
||||
fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
|
||||
if (pipedes[0] < 0)
|
||||
@@ -1710,7 +1713,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||
CLOSE_ON_EXEC(pipedes[1]);
|
||||
CLOSE_ON_EXEC(pipedes[0]);
|
||||
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
|
||||
pid = child_execute_job (FD_STDIN, pipedes[1], FD_STDOUT, command_argv, envp);
|
||||
pid = child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp);
|
||||
if (pid < 0)
|
||||
perror_with_name (error_prefix, "spawn");
|
||||
# else /* ! __EMX__ */
|
||||
@@ -1724,9 +1727,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||
if (stack_limit.rlim_cur)
|
||||
setrlimit (RLIMIT_STACK, &stack_limit);
|
||||
# endif
|
||||
child_execute_job (FD_STDIN, pipedes[1],
|
||||
output_context ? output_context->err : FD_STDERR,
|
||||
command_argv, envp);
|
||||
child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
@@ -1948,8 +1949,12 @@ func_not (char *o, char **argv, char *funcname UNUSED)
|
||||
|
||||
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
#define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
|
||||
#define ROOT_LEN 3
|
||||
# ifdef __CYGWIN__
|
||||
# define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || STOP_SET (n[0], MAP_PATHSEP))
|
||||
# else
|
||||
# define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
|
||||
# endif
|
||||
# define ROOT_LEN 3
|
||||
#else
|
||||
#define IS_ABSOLUTE(n) (n[0] == '/')
|
||||
#define ROOT_LEN 1
|
||||
@@ -2000,13 +2005,17 @@ abspath (const char *name, char *apath)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS)
|
||||
if (STOP_SET (name[0], MAP_PATHSEP))
|
||||
root_len = 1;
|
||||
#endif
|
||||
strncpy (apath, name, root_len);
|
||||
apath[root_len] = '\0';
|
||||
dest = apath + root_len;
|
||||
/* Get past the root, since we already copied it. */
|
||||
name += root_len;
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
if (! STOP_SET (apath[2], MAP_PATHSEP))
|
||||
if (! STOP_SET (apath[root_len - 1], MAP_PATHSEP))
|
||||
{
|
||||
/* Convert d:foo into d:./foo and increase root_len. */
|
||||
apath[2] = '.';
|
||||
@@ -2017,7 +2026,7 @@ abspath (const char *name, char *apath)
|
||||
name--;
|
||||
}
|
||||
else
|
||||
apath[2] = '/'; /* make sure it's a forward slash */
|
||||
apath[root_len - 1] = '/'; /* make sure it's a forward slash */
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2436,7 +2445,7 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
|
||||
/* There is no way to define a variable with a space in the name, so strip
|
||||
leading and trailing whitespace as a favor to the user. */
|
||||
fname = argv[0];
|
||||
while (*fname != '\0' && isspace ((unsigned char)*fname))
|
||||
while (isspace ((unsigned char)*fname))
|
||||
++fname;
|
||||
|
||||
cp = fname + strlen (fname) - 1;
|
||||
@@ -2521,19 +2530,28 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
|
||||
}
|
||||
|
||||
void
|
||||
define_new_function (const gmk_floc *flocp,
|
||||
const char *name, int min, int max, int expand,
|
||||
char *(*func)(const char *, int, char **))
|
||||
define_new_function (const gmk_floc *flocp, const char *name,
|
||||
unsigned int min, unsigned int max, unsigned int flags,
|
||||
gmk_func_ptr func)
|
||||
{
|
||||
const char *e = name;
|
||||
struct function_table_entry *ent;
|
||||
size_t len = strlen (name);
|
||||
size_t len;
|
||||
|
||||
while (STOP_SET (*e, MAP_USERFUNC))
|
||||
e++;
|
||||
len = e - name;
|
||||
|
||||
if (len == 0)
|
||||
fatal (flocp, _("Empty function name\n"));
|
||||
if (*name == '.' || *e != '\0')
|
||||
fatal (flocp, _("Invalid function name: %s\n"), name);
|
||||
if (len > 255)
|
||||
fatal (flocp, _("Function name too long: %s\n"), name);
|
||||
if (min < 0 || min > 255)
|
||||
if (min > 255)
|
||||
fatal (flocp, _("Invalid minimum argument count (%d) for function %s\n"),
|
||||
min, name);
|
||||
if (max < 0 || max > 255 || (max && max < min))
|
||||
if (max > 255 || (max && max < min))
|
||||
fatal (flocp, _("Invalid maximum argument count (%d) for function %s\n"),
|
||||
max, name);
|
||||
|
||||
@@ -2542,7 +2560,7 @@ define_new_function (const gmk_floc *flocp,
|
||||
ent->len = len;
|
||||
ent->minimum_args = min;
|
||||
ent->maximum_args = max;
|
||||
ent->expand_args = expand ? 1 : 0;
|
||||
ent->expand_args = ANY_SET(flags, GMK_FUNC_NOEXPAND) ? 0 : 1;
|
||||
ent->alloc_fn = 1;
|
||||
ent->fptr.alloc_func_ptr = func;
|
||||
|
||||
|
||||
28
gnumake.h
28
gnumake.h
@@ -26,6 +26,7 @@ typedef struct
|
||||
unsigned long lineno;
|
||||
} gmk_floc;
|
||||
|
||||
typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef GMK_BUILDING_MAKE
|
||||
@@ -38,17 +39,17 @@ typedef struct
|
||||
#endif
|
||||
|
||||
/* Free memory returned by the gmk_expand() function. */
|
||||
void GMK_EXPORT gmk_free (char *str);
|
||||
GMK_EXPORT void gmk_free (char *str);
|
||||
|
||||
/* Allocate memory in GNU make's context. */
|
||||
char * GMK_EXPORT gmk_alloc (unsigned int len);
|
||||
GMK_EXPORT char *gmk_alloc (unsigned int len);
|
||||
|
||||
/* Run $(eval ...) on the provided string BUFFER. */
|
||||
void GMK_EXPORT gmk_eval (const char *buffer, const gmk_floc *floc);
|
||||
GMK_EXPORT void gmk_eval (const char *buffer, const gmk_floc *floc);
|
||||
|
||||
/* Run GNU make expansion on the provided string STR.
|
||||
Returns an allocated buffer that the caller must free with gmk_free(). */
|
||||
char * GMK_EXPORT gmk_expand (const char *str);
|
||||
GMK_EXPORT char *gmk_expand (const char *str);
|
||||
|
||||
/* Register a new GNU make function NAME (maximum of 255 chars long).
|
||||
When the function is expanded in the makefile, FUNC will be invoked with
|
||||
@@ -60,14 +61,19 @@ char * GMK_EXPORT gmk_expand (const char *str);
|
||||
|
||||
MIN_ARGS is the minimum number of arguments the function requires.
|
||||
MAX_ARGS is the maximum number of arguments (or 0 if there's no maximum).
|
||||
MIN_ARGS and MAX_ARGS must be >= 0 and <= 255.
|
||||
MIN_ARGS and MAX_ARGS may not exceed 255.
|
||||
|
||||
If EXPAND_ARGS is 0, the arguments to the function will not be expanded
|
||||
before FUNC is called. If EXPAND_ARGS is non-0, they will be expanded.
|
||||
The FLAGS value may be GMK_FUNC_DEFAULT, or one or more of the following
|
||||
flags OR'd together:
|
||||
|
||||
GMK_FUNC_NOEXPAND: the arguments to the function will be not be expanded
|
||||
before FUNC is called.
|
||||
*/
|
||||
void GMK_EXPORT gmk_add_function (const char *name,
|
||||
char *(*func)(const char *nm,
|
||||
int argc, char **argv),
|
||||
int min_args, int max_args, int expand_args);
|
||||
GMK_EXPORT void gmk_add_function (const char *name, gmk_func_ptr func,
|
||||
unsigned int min_args, unsigned int max_args,
|
||||
unsigned int flags);
|
||||
|
||||
#define GMK_FUNC_DEFAULT 0x00
|
||||
#define GMK_FUNC_NOEXPAND 0x01
|
||||
|
||||
#endif /* _GNUMAKE_H_ */
|
||||
|
||||
20
guile.c
20
guile.c
@@ -24,6 +24,16 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <libguile.h>
|
||||
|
||||
/* Pre-2.0 versions of Guile don't have a typedef for gsubr function types. */
|
||||
#if SCM_MAJOR_VERSION < 2
|
||||
# define GSUBR_TYPE SCM (*) ()
|
||||
/* Guile 1.x doesn't really support i18n. */
|
||||
# define EVAL_STRING(_s) scm_c_eval_string (_s)
|
||||
#else
|
||||
# define GSUBR_TYPE scm_t_subr
|
||||
# define EVAL_STRING(_s) scm_eval_string (scm_from_utf8_string (_s))
|
||||
#endif
|
||||
|
||||
static SCM make_mod = SCM_EOL;
|
||||
static SCM obj_to_str = SCM_EOL;
|
||||
|
||||
@@ -72,10 +82,10 @@ guile_define_module (void *data UNUSED)
|
||||
#include "gmk-default.h"
|
||||
|
||||
/* Register a subr for GNU make's eval capability. */
|
||||
scm_c_define_gsubr ("gmk-expand", 1, 0, 0, (scm_t_subr) guile_expand_wrapper);
|
||||
scm_c_define_gsubr ("gmk-expand", 1, 0, 0, (GSUBR_TYPE) guile_expand_wrapper);
|
||||
|
||||
/* Register a subr for GNU make's eval capability. */
|
||||
scm_c_define_gsubr ("gmk-eval", 1, 0, 0, (scm_t_subr) guile_eval_wrapper);
|
||||
scm_c_define_gsubr ("gmk-eval", 1, 0, 0, (GSUBR_TYPE) guile_eval_wrapper);
|
||||
|
||||
/* Define the rest of the module. */
|
||||
scm_c_eval_string (GUILE_module_defn);
|
||||
@@ -100,12 +110,12 @@ guile_init (void *arg UNUSED)
|
||||
static void *
|
||||
internal_guile_eval (void *arg)
|
||||
{
|
||||
return cvt_scm_to_str (scm_c_eval_string (arg));
|
||||
return cvt_scm_to_str (EVAL_STRING (arg));
|
||||
}
|
||||
|
||||
/* This is the function registered with make */
|
||||
static char *
|
||||
func_guile (const char *funcname UNUSED, int argc UNUSED, char **argv)
|
||||
func_guile (const char *funcname UNUSED, unsigned int argc UNUSED, char **argv)
|
||||
{
|
||||
static int init = 0;
|
||||
|
||||
@@ -130,7 +140,7 @@ int
|
||||
guile_gmake_setup (const gmk_floc *flocp UNUSED)
|
||||
{
|
||||
/* Create a make function "guile". */
|
||||
gmk_add_function ("guile", func_guile, 0, 1, 1);
|
||||
gmk_add_function ("guile", func_guile, 0, 1, GMK_FUNC_DEFAULT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
6
job.c
6
job.c
@@ -2234,7 +2234,7 @@ child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd,
|
||||
/* Restore stdout/stdin/stderr of the parent and close temporary FDs. */
|
||||
if (save_stdin >= 0)
|
||||
{
|
||||
if (dup2 (save_stdin, FD_STDIN) != 0)
|
||||
if (dup2 (save_stdin, FD_STDIN) != FD_STDIN)
|
||||
fatal (NILF, _("Could not restore stdin\n"));
|
||||
else
|
||||
close (save_stdin);
|
||||
@@ -2242,7 +2242,7 @@ child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd,
|
||||
|
||||
if (save_stdout >= 0)
|
||||
{
|
||||
if (dup2 (save_stdout, FD_STDOUT) != 0)
|
||||
if (dup2 (save_stdout, FD_STDOUT) != FD_STDOUT)
|
||||
fatal (NILF, _("Could not restore stdout\n"));
|
||||
else
|
||||
close (save_stdout);
|
||||
@@ -2250,7 +2250,7 @@ child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd,
|
||||
|
||||
if (save_stderr >= 0)
|
||||
{
|
||||
if (dup2 (save_stderr, FD_STDERR) != 0)
|
||||
if (dup2 (save_stderr, FD_STDERR) != FD_STDERR)
|
||||
fatal (NILF, _("Could not restore stderr\n"));
|
||||
else
|
||||
close (save_stderr);
|
||||
|
||||
4
job.h
4
job.h
@@ -80,7 +80,7 @@ typedef int sync_handle_t; /* file descriptor */
|
||||
# define RECORD_SYNC_MUTEX(m) (void)(m)
|
||||
|
||||
# endif
|
||||
#endif /* !OUTPUT_SYNC */
|
||||
#endif /* !NO_OUTPUT_SYNC */
|
||||
|
||||
/* Structure describing a running or dead child process. */
|
||||
|
||||
@@ -128,7 +128,7 @@ int child_execute_job (char *argv, struct child *child);
|
||||
# define FD_STDERR (fileno (stderr))
|
||||
# if defined(__EMX__)
|
||||
int child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd,
|
||||
char **argv, char **envp)
|
||||
char **argv, char **envp);
|
||||
# else
|
||||
void child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd,
|
||||
char **argv, char **envp) __attribute__ ((noreturn));
|
||||
|
||||
@@ -54,9 +54,8 @@ gmk_expand (const char *ref)
|
||||
|
||||
/* Register a function to be called from makefiles. */
|
||||
void
|
||||
gmk_add_function (const char *name,
|
||||
char *(*func)(const char *nm, int argc, char **argv),
|
||||
int min, int max, int expand)
|
||||
gmk_add_function (const char *name, gmk_func_ptr func,
|
||||
unsigned int min, unsigned int max, unsigned int flags)
|
||||
{
|
||||
define_new_function (reading_file, name, min, max, expand, func);
|
||||
define_new_function (reading_file, name, min, max, flags, func);
|
||||
}
|
||||
|
||||
97
main.c
97
main.c
@@ -612,10 +612,13 @@ initialize_stopchar_map ()
|
||||
stopchar_map[(int)':'] = MAP_COLON;
|
||||
stopchar_map[(int)'%'] = MAP_PERCENT;
|
||||
stopchar_map[(int)'|'] = MAP_PIPE;
|
||||
stopchar_map[(int)'.'] = MAP_DOT;
|
||||
stopchar_map[(int)'.'] = MAP_DOT | MAP_USERFUNC;
|
||||
stopchar_map[(int)','] = MAP_COMMA;
|
||||
stopchar_map[(int)'$'] = MAP_VARIABLE;
|
||||
|
||||
stopchar_map[(int)'-'] = MAP_USERFUNC;
|
||||
stopchar_map[(int)'_'] = MAP_USERFUNC;
|
||||
|
||||
stopchar_map[(int)'/'] = MAP_PATHSEP;
|
||||
#if defined(VMS)
|
||||
stopchar_map[(int)']'] = MAP_PATHSEP;
|
||||
@@ -629,6 +632,8 @@ initialize_stopchar_map ()
|
||||
stopchar_map[i] = MAP_BLANK;
|
||||
if (isspace(i))
|
||||
stopchar_map[i] |= MAP_SPACE;
|
||||
if (isalnum(i))
|
||||
stopchar_map[i] = MAP_USERFUNC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1295,64 +1300,62 @@ main (int argc, char **argv, char **envp)
|
||||
|
||||
for (i = 0; envp[i] != 0; ++i)
|
||||
{
|
||||
int do_not_define = 0;
|
||||
struct variable *v;
|
||||
char *ep = envp[i];
|
||||
/* By default, export all variables culled from the environment. */
|
||||
enum variable_export export = v_export;
|
||||
unsigned int len;
|
||||
|
||||
while (! STOP_SET (*ep, MAP_EQUALS))
|
||||
++ep;
|
||||
|
||||
/* If there's no equals sign it's a malformed environment. Ignore. */
|
||||
if (*ep == '\0')
|
||||
continue;
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if (!unix_path && strneq (envp[i], "PATH=", 5))
|
||||
unix_path = ep+1;
|
||||
else if (!strnicmp (envp[i], "Path=", 5))
|
||||
{
|
||||
do_not_define = 1; /* it gets defined after loop exits */
|
||||
if (!windows32_path)
|
||||
windows32_path = ep+1;
|
||||
/* PATH gets defined after the loop exits. */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* The result of pointer arithmetic is cast to unsigned int for
|
||||
machines where ptrdiff_t is a different size that doesn't widen
|
||||
the same. */
|
||||
if (!do_not_define)
|
||||
|
||||
/* Length of the variable name, and skip the '='. */
|
||||
len = ep++ - envp[i];
|
||||
|
||||
/* If this is MAKE_RESTARTS, check to see if the "already printed
|
||||
the enter statement" flag is set. */
|
||||
if (len == 13 && strneq (envp[i], "MAKE_RESTARTS", 13))
|
||||
{
|
||||
struct variable *v;
|
||||
|
||||
v = define_variable (envp[i], (unsigned int) (ep - envp[i]),
|
||||
ep + 1, o_env, 1);
|
||||
/* Force exportation of every variable culled from the
|
||||
environment. We used to rely on target_environment's
|
||||
v_default code to do this. But that does not work for the
|
||||
case where an environment variable is redefined in a makefile
|
||||
with 'override'; it should then still be exported, because it
|
||||
was originally in the environment. */
|
||||
v->export = v_export;
|
||||
|
||||
/* Another wrinkle is that POSIX says the value of SHELL set in
|
||||
the makefile won't change the value of SHELL given to
|
||||
subprocesses. */
|
||||
if (streq (v->name, "SHELL"))
|
||||
if (*ep == '-')
|
||||
{
|
||||
#ifndef __MSDOS__
|
||||
v->export = v_noexport;
|
||||
#endif
|
||||
shell_var.name = "SHELL";
|
||||
shell_var.length = 5;
|
||||
shell_var.value = xstrdup (ep + 1);
|
||||
}
|
||||
|
||||
/* If MAKE_RESTARTS is set, remember it but don't export it.
|
||||
If it's negative, it means the "enter" message was printed. */
|
||||
else if (streq (v->name, "MAKE_RESTARTS"))
|
||||
{
|
||||
v->export = v_noexport;
|
||||
if (*(++ep) == '-')
|
||||
{
|
||||
OUTPUT_TRACED ();
|
||||
++ep;
|
||||
}
|
||||
restarts = (unsigned int) atoi (ep);
|
||||
OUTPUT_TRACED ();
|
||||
++ep;
|
||||
}
|
||||
restarts = (unsigned int) atoi (ep);
|
||||
export = v_noexport;
|
||||
}
|
||||
|
||||
v = define_variable (envp[i], len, ep, o_env, 1);
|
||||
|
||||
/* POSIX says the value of SHELL set in the makefile won't change the
|
||||
value of SHELL given to subprocesses. */
|
||||
if (streq (v->name, "SHELL"))
|
||||
{
|
||||
#ifndef __MSDOS__
|
||||
export = v_noexport;
|
||||
#endif
|
||||
shell_var.name = "SHELL";
|
||||
shell_var.length = 5;
|
||||
shell_var.value = xstrdup (ep);
|
||||
}
|
||||
|
||||
v->export = export;
|
||||
}
|
||||
}
|
||||
#ifdef WINDOWS32
|
||||
@@ -1396,6 +1399,10 @@ main (int argc, char **argv, char **envp)
|
||||
/* Decode the switches. */
|
||||
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS"));
|
||||
|
||||
/* Clear GNUMAKEFLAGS to avoid duplication. */
|
||||
define_variable_cname ("GNUMAKEFLAGS", "", o_env, 0);
|
||||
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
|
||||
|
||||
/* In output sync mode we need to sync any output generated by reading the
|
||||
@@ -1931,12 +1938,16 @@ main (int argc, char **argv, char **envp)
|
||||
|
||||
/* Decode switches again, for variables set by the makefile. */
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS"));
|
||||
|
||||
/* Clear GNUMAKEFLAGS to avoid duplication. */
|
||||
define_variable_cname ("GNUMAKEFLAGS", "", o_override, 0);
|
||||
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
|
||||
#if 0
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
|
||||
#endif
|
||||
|
||||
/* Reset in case the switches changed our minds. */
|
||||
/* Reset in case the switches changed our mind. */
|
||||
syncing = (output_sync == OUTPUT_SYNC_LINE
|
||||
|| output_sync == OUTPUT_SYNC_TARGET);
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# only if you have the full copy of the GNU make sources from the Git
|
||||
# tree, not a dist copy.
|
||||
|
||||
GPG_FINGERPRINT := 6338B6D4
|
||||
|
||||
# We like mondo-warnings!
|
||||
AM_CFLAGS += -Wall -Wextra -Wdeclaration-after-statement -Wshadow -Wpointer-arith -Wbad-function-cast
|
||||
|
||||
@@ -243,6 +245,17 @@ po-check:
|
||||
rm -f $@-1 $@-2; \
|
||||
fi
|
||||
|
||||
## ------------------------- ##
|
||||
## Make release targets. ##
|
||||
## ------------------------- ##
|
||||
|
||||
tag-release:
|
||||
case '$(VERSION)' in \
|
||||
(*.*.9*) message=" candidate" ;; \
|
||||
(*) message= ;; \
|
||||
esac; \
|
||||
$(GIT) tag -m "GNU Make release$$message $(VERSION)" -u '$(GPG_FINGERPRINT)' '$(VERSION)'
|
||||
|
||||
## ------------------------- ##
|
||||
## GNU FTP upload artifacts. ##
|
||||
## ------------------------- ##
|
||||
@@ -252,7 +265,7 @@ po-check:
|
||||
# you're SOL! :)
|
||||
|
||||
GPG = gpg
|
||||
GPGFLAGS = -u 6338B6D4
|
||||
GPGFLAGS = -u $(GPG_FINGERPRINT)
|
||||
|
||||
DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES))
|
||||
DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES))
|
||||
|
||||
@@ -171,6 +171,9 @@
|
||||
<File
|
||||
RelativePath=".\job.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\load.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\output.c">
|
||||
</File>
|
||||
@@ -210,6 +213,9 @@
|
||||
<File
|
||||
RelativePath=".\w32\compat\dirent.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\w32\compat\posixfcn.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\w32\subproc\misc.c">
|
||||
<FileConfiguration
|
||||
|
||||
@@ -396,6 +396,8 @@ extern int unixy_shell;
|
||||
#define MAP_DOT 0x0200
|
||||
#define MAP_COMMA 0x0400
|
||||
|
||||
/* These are the valid characters for a user-defined function. */
|
||||
#define MAP_USERFUNC 0x2000
|
||||
/* This means not only a '$', but skip the variable reference. */
|
||||
#define MAP_VARIABLE 0x4000
|
||||
/* The set of characters which are path separators is OS-specific. */
|
||||
|
||||
36
output.c
36
output.c
@@ -22,7 +22,10 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
@@ -32,6 +35,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef WINDOWS32
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include "sub_proc.h"
|
||||
#endif /* WINDOWS32 */
|
||||
|
||||
@@ -92,10 +96,8 @@ _outputs (struct output *out, int is_err, const char *msg)
|
||||
while (1)
|
||||
{
|
||||
EINTRLOOP (r, write (fd, msg, len));
|
||||
if (r == len)
|
||||
if (r == len || r <= 0)
|
||||
break;
|
||||
if (r <= 0)
|
||||
return;
|
||||
len -= r;
|
||||
msg += r;
|
||||
}
|
||||
@@ -106,7 +108,7 @@ _outputs (struct output *out, int is_err, const char *msg)
|
||||
left (according to ENTERING) the current directory. */
|
||||
|
||||
static int
|
||||
log_working_directory (struct output *out, int entering)
|
||||
log_working_directory (int entering)
|
||||
{
|
||||
static char *buf = NULL;
|
||||
static unsigned int len = 0;
|
||||
@@ -168,7 +170,7 @@ log_working_directory (struct output *out, int entering)
|
||||
else
|
||||
sprintf (p, fmt, program, makelevel, starting_directory);
|
||||
|
||||
_outputs (out, 0, buf);
|
||||
_outputs (NULL, 0, buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -387,7 +389,7 @@ output_dump (struct output *out)
|
||||
|
||||
/* Log the working directory for this dump. */
|
||||
if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
|
||||
traced = log_working_directory (output_context, 1);
|
||||
traced = log_working_directory (1);
|
||||
|
||||
if (outfd_not_empty)
|
||||
pump_from_tmp (out->out, stdout);
|
||||
@@ -395,7 +397,7 @@ output_dump (struct output *out)
|
||||
pump_from_tmp (out->err, stderr);
|
||||
|
||||
if (traced)
|
||||
log_working_directory (output_context, 0);
|
||||
log_working_directory (0);
|
||||
|
||||
/* Exit the critical section. */
|
||||
if (sem)
|
||||
@@ -558,7 +560,7 @@ output_close (struct output *out)
|
||||
if (! out)
|
||||
{
|
||||
if (stdio_traced)
|
||||
log_working_directory (NULL, 0);
|
||||
log_working_directory (0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -579,15 +581,17 @@ void
|
||||
output_start ()
|
||||
{
|
||||
#ifndef NO_OUTPUT_SYNC
|
||||
if (output_context && output_context->syncout && ! OUTPUT_ISSET(output_context))
|
||||
setup_tmpfile (output_context);
|
||||
/* If we're syncing output make sure the temporary file is set up. */
|
||||
if (output_context && output_context->syncout)
|
||||
if (! OUTPUT_ISSET(output_context))
|
||||
setup_tmpfile (output_context);
|
||||
#endif
|
||||
|
||||
if (! output_context || output_sync == OUTPUT_SYNC_RECURSE)
|
||||
{
|
||||
if (! stdio_traced && print_directory_flag)
|
||||
stdio_traced = log_working_directory (NULL, 1);
|
||||
}
|
||||
/* If we're not syncing this output per-line or per-target, make sure we emit
|
||||
the "Entering..." message where appropriate. */
|
||||
if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
|
||||
if (! stdio_traced && print_directory_flag)
|
||||
stdio_traced = log_working_directory (1);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
2
read.c
2
read.c
@@ -1073,7 +1073,7 @@ eval (struct ebuffer *ebuf, int set_default)
|
||||
here, but merely copy, since now you're beyond a ";"
|
||||
and into a command script. However, the old parser
|
||||
expanded the whole line, so we continue that for
|
||||
backwards-compatiblity. Also, it wouldn't be
|
||||
backwards-compatibility. Also, it wouldn't be
|
||||
entirely consistent, since we do an unconditional
|
||||
expand below once we know we don't have a
|
||||
target-specific variable. */
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
2013-10-09 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/features/patspecific_vars: Typo fixes.
|
||||
|
||||
2013-10-05 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* test_driver.pl (run_all_tests): Rewrite to be more clear.
|
||||
* scripts/features/jobserver: Avoid using $ENV{HOME} as it doesn't
|
||||
exist everywhere.
|
||||
* scripts/features/default_names: End with 1;
|
||||
|
||||
* scripts/features/loadapi: Use new calling signatures. Verify
|
||||
the NOEXPAND flag works. Test with all valid function name
|
||||
characters.
|
||||
|
||||
2013-09-29 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/variables/SHELL: Solaris /bin/sh can't handle options in
|
||||
multiple words; skip that test.
|
||||
* scripts/targets/ONESHELL: Ditto.
|
||||
|
||||
* scripts/variables/GNUMAKEFLAGS: Verify that GNUMAKEFLAGS is
|
||||
cleared and options are not duplicated.
|
||||
|
||||
2013-09-23 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/options/print-directory: Rename dash-w to
|
||||
print-directory to avoid conflicts with dash-W on case-insensitive
|
||||
filesystems.
|
||||
|
||||
2013-09-22 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/features/se_implicit: Verify that order-only tokens
|
||||
|
||||
@@ -40,3 +40,5 @@ if ($case_sensitive) {
|
||||
compare_output("It chose Makefile\n",&get_logfile(1));
|
||||
unlink("Makefile");
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -43,10 +43,10 @@ unlink('inc.mk');
|
||||
# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474
|
||||
|
||||
open(MAKEFILE,"> Makefile2");
|
||||
print MAKEFILE <<EOF;
|
||||
vpath %.c $ENV{HOME}/
|
||||
print MAKEFILE '
|
||||
vpath %.c ../
|
||||
foo:
|
||||
EOF
|
||||
';
|
||||
close(MAKEFILE);
|
||||
|
||||
run_make_test(q!
|
||||
|
||||
@@ -36,7 +36,15 @@ test_expand (const char *val)
|
||||
}
|
||||
|
||||
static char *
|
||||
func_test (const char *funcname, int argc, char **argv)
|
||||
test_noexpand (const char *val)
|
||||
{
|
||||
char *str = gmk_alloc (strlen (val));
|
||||
strcpy (str, val);
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *
|
||||
func_test (const char *funcname, unsigned int argc, char **argv)
|
||||
{
|
||||
char *mem;
|
||||
|
||||
@@ -46,7 +54,10 @@ func_test (const char *funcname, int argc, char **argv)
|
||||
if (strcmp (funcname, "test-eval") == 0)
|
||||
return test_eval (argv[0]);
|
||||
|
||||
mem = gmk_alloc (strlen ("unknown") + 1);
|
||||
if (strcmp (funcname, "test-noexpand") == 0)
|
||||
return test_noexpand (argv[0]);
|
||||
|
||||
mem = gmk_alloc (sizeof ("unknown"));
|
||||
strcpy (mem, "unknown");
|
||||
return mem;
|
||||
}
|
||||
@@ -54,8 +65,10 @@ func_test (const char *funcname, int argc, char **argv)
|
||||
int
|
||||
testapi_gmk_setup ()
|
||||
{
|
||||
gmk_add_function ("test-expand", func_test, 1, 1, 1);
|
||||
gmk_add_function ("test-eval", func_test, 1, 1, 1);
|
||||
gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT);
|
||||
gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND);
|
||||
gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT);
|
||||
gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
EOF
|
||||
@@ -84,6 +97,15 @@ all:;@echo '$(VAR)'
|
||||
!,
|
||||
'', "hi there\n");
|
||||
|
||||
# TEST 2
|
||||
# Check the no-expand capability
|
||||
run_make_test(q!
|
||||
load testapi.so
|
||||
TEST = hi
|
||||
all:;@echo '$(test-noexpand $(TEST))'
|
||||
!,
|
||||
'', "\$(TEST)\n");
|
||||
|
||||
unlink(qw(testapi.c testapi.so)) unless $keep;
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
|
||||
@@ -81,7 +81,7 @@ all: bar baz
|
||||
|
||||
b%: pattern := good $$t
|
||||
|
||||
global := orginal $$t
|
||||
global := original $$t
|
||||
|
||||
|
||||
# normal target
|
||||
@@ -103,14 +103,14 @@ else
|
||||
%z: a := global: $(global) pattern: $(pattern) inherit: $(inherit)
|
||||
endif
|
||||
|
||||
%z: ; @echo \'pattrn: $a;\'
|
||||
%z: ; @echo \'pattern: $a;\'
|
||||
|
||||
|
||||
global := new $$t
|
||||
',
|
||||
'',
|
||||
'normal: global: orginal $t pattern: inherit: ;
|
||||
pattrn: global: orginal $t pattern: inherit: ;');
|
||||
'normal: global: original $t pattern: inherit: ;
|
||||
pattern: global: original $t pattern: inherit: ;');
|
||||
|
||||
|
||||
# TEST #7 -- test expansion of pattern-specific recursive variables
|
||||
@@ -118,7 +118,7 @@ pattrn: global: orginal $t pattern: inherit: ;');
|
||||
run_make_test(undef, # reuse previous makefile
|
||||
'rec=1',
|
||||
'normal: global: new $t pattern: good $t inherit: good $t;
|
||||
pattrn: global: new $t pattern: good $t inherit: good $t;');
|
||||
pattern: global: new $t pattern: good $t inherit: good $t;');
|
||||
|
||||
# TEST #8: override in pattern-specific variables
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ $description = "Test the behaviour of the .ONESHELL target.";
|
||||
|
||||
$details = "";
|
||||
|
||||
# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
|
||||
# separate arguments.
|
||||
my $t = `/bin/sh -e -c true 2>/dev/null`;
|
||||
my $multi_ok = $? == 0;
|
||||
|
||||
# Simple
|
||||
|
||||
@@ -19,7 +23,8 @@ all:
|
||||
|
||||
# Simple but use multi-word SHELLFLAGS
|
||||
|
||||
run_make_test(q!
|
||||
if ($multi_ok) {
|
||||
run_make_test(q!
|
||||
.ONESHELL:
|
||||
.SHELLFLAGS = -e -c
|
||||
all:
|
||||
@@ -29,6 +34,7 @@ all:
|
||||
'', 'a=$$
|
||||
[ 0"$a" -eq "$$" ] || echo fail
|
||||
');
|
||||
}
|
||||
|
||||
# Again, but this time with inner prefix chars
|
||||
|
||||
|
||||
@@ -23,4 +23,20 @@ all: ; @echo $(MAKEFLAGS)
|
||||
echo erR --trace --no-print-directory
|
||||
erR --trace --no-print-directory");
|
||||
|
||||
# Verify that re-exec / recursion doesn't duplicate flags from GNUMAKEFLAGS
|
||||
|
||||
unlink('x.mk');
|
||||
|
||||
$extraENV{GNUMAKEFLAGS} = '-Itst/bad -Oline';
|
||||
|
||||
run_make_test(q!
|
||||
recurse: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; #MAKEPATH# -f #MAKEFILE# all
|
||||
all: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS
|
||||
-include x.mk
|
||||
x.mk: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; echo > $@
|
||||
!,
|
||||
"", "x.mk\nMAKEFLAGS = -Itst/bad -Oline\nGNUMAKEFLAGS =\nrecurse\nMAKEFLAGS = -Itst/bad -Oline\nGNUMAKEFLAGS =\n#MAKE#[1]: Entering directory '#PWD#'\nall\nMAKEFLAGS = w -Itst/bad -Oline\nGNUMAKEFLAGS =\n#MAKE#[1]: Leaving directory '#PWD#'\n");
|
||||
|
||||
unlink('x.mk');
|
||||
|
||||
1;
|
||||
|
||||
@@ -71,12 +71,20 @@ all: ; \@$script
|
||||
'', $out);
|
||||
|
||||
# Do it again but add spaces to SHELLFLAGS
|
||||
$flags = '-x -c';
|
||||
run_make_test(qq!
|
||||
|
||||
# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
|
||||
# separate arguments.
|
||||
my $t = `/bin/sh -e -c true 2>/dev/null`;
|
||||
my $multi_ok = $? == 0;
|
||||
|
||||
if ($multi_ok) {
|
||||
$flags = '-x -c';
|
||||
run_make_test(qq!
|
||||
.SHELLFLAGS = $flags
|
||||
all: ; \@$script
|
||||
!,
|
||||
'', $out);
|
||||
}
|
||||
|
||||
# We can't just use "false" because on different systems it provides a
|
||||
# different exit code--once again Solaris: false exits with 255 not 1
|
||||
|
||||
@@ -202,7 +202,7 @@ sub toplevel
|
||||
|
||||
print "\n";
|
||||
|
||||
&run_each_test;
|
||||
run_all_tests();
|
||||
|
||||
foreach $dir (@rmdirs)
|
||||
{
|
||||
@@ -415,128 +415,133 @@ sub print_banner
|
||||
print "\n";
|
||||
}
|
||||
|
||||
sub run_each_test
|
||||
sub run_all_tests
|
||||
{
|
||||
$categories_run = 0;
|
||||
$categories_run = 0;
|
||||
|
||||
foreach $testname (sort @TESTS)
|
||||
{
|
||||
++$categories_run;
|
||||
$suite_passed = 1; # reset by test on failure
|
||||
$num_of_logfiles = 0;
|
||||
$num_of_tmpfiles = 0;
|
||||
$description = "";
|
||||
$details = "";
|
||||
$old_makefile = undef;
|
||||
$testname =~ s/^$scriptpath$pathsep//;
|
||||
$perl_testname = "$scriptpath$pathsep$testname";
|
||||
$testname =~ s/(\.pl|\.perl)$//;
|
||||
$testpath = "$workpath$pathsep$testname";
|
||||
# Leave enough space in the extensions to append a number, even
|
||||
# though it needs to fit into 8+3 limits.
|
||||
if ($short_filenames) {
|
||||
$logext = 'l';
|
||||
$diffext = 'd';
|
||||
$baseext = 'b';
|
||||
$runext = 'r';
|
||||
$extext = '';
|
||||
} else {
|
||||
$logext = 'log';
|
||||
$diffext = 'diff';
|
||||
$baseext = 'base';
|
||||
$runext = 'run';
|
||||
$extext = '.';
|
||||
foreach $testname (sort @TESTS) {
|
||||
$suite_passed = 1; # reset by test on failure
|
||||
$num_of_logfiles = 0;
|
||||
$num_of_tmpfiles = 0;
|
||||
$description = "";
|
||||
$details = "";
|
||||
$old_makefile = undef;
|
||||
$testname =~ s/^$scriptpath$pathsep//;
|
||||
$perl_testname = "$scriptpath$pathsep$testname";
|
||||
$testname =~ s/(\.pl|\.perl)$//;
|
||||
$testpath = "$workpath$pathsep$testname";
|
||||
# Leave enough space in the extensions to append a number, even
|
||||
# though it needs to fit into 8+3 limits.
|
||||
if ($short_filenames) {
|
||||
$logext = 'l';
|
||||
$diffext = 'd';
|
||||
$baseext = 'b';
|
||||
$runext = 'r';
|
||||
$extext = '';
|
||||
} else {
|
||||
$logext = 'log';
|
||||
$diffext = 'diff';
|
||||
$baseext = 'base';
|
||||
$runext = 'run';
|
||||
$extext = '.';
|
||||
}
|
||||
$log_filename = "$testpath.$logext";
|
||||
$diff_filename = "$testpath.$diffext";
|
||||
$base_filename = "$testpath.$baseext";
|
||||
$run_filename = "$testpath.$runext";
|
||||
$tmp_filename = "$testpath.$tmpfilesuffix";
|
||||
|
||||
setup_for_test();
|
||||
|
||||
$output = "........................................................ ";
|
||||
|
||||
substr($output,0,length($testname)) = "$testname ";
|
||||
|
||||
print $output;
|
||||
|
||||
$tests_run = 0;
|
||||
$tests_passed = 0;
|
||||
|
||||
# Run the test!
|
||||
$code = do $perl_testname;
|
||||
|
||||
++$categories_run;
|
||||
$total_tests_run += $tests_run;
|
||||
$total_tests_passed += $tests_passed;
|
||||
|
||||
# How did it go?
|
||||
if (!defined($code)) {
|
||||
# Failed to parse or called die
|
||||
if (length ($@)) {
|
||||
warn "\n*** Test died ($testname): $@\n";
|
||||
} else {
|
||||
warn "\n*** Couldn't parse $perl_testname\n";
|
||||
}
|
||||
$status = "FAILED ($tests_passed/$tests_run passed)";
|
||||
}
|
||||
|
||||
elsif ($code == -1) {
|
||||
# Skipped... not supported
|
||||
$status = "N/A";
|
||||
--$categories_run;
|
||||
}
|
||||
|
||||
elsif ($code != 1) {
|
||||
# Bad result... this shouldn't really happen. Usually means that
|
||||
# the suite forgot to end with "1;".
|
||||
warn "\n*** Test returned $code\n";
|
||||
$status = "FAILED ($tests_passed/$tests_run passed)";
|
||||
}
|
||||
|
||||
elsif ($tests_run == 0) {
|
||||
# Nothing was done!!
|
||||
$status = "FAILED (no tests found!)";
|
||||
}
|
||||
|
||||
elsif ($tests_run > $tests_passed) {
|
||||
# Lose!
|
||||
$status = "FAILED ($tests_passed/$tests_run passed)";
|
||||
}
|
||||
|
||||
else {
|
||||
# Win!
|
||||
++$categories_passed;
|
||||
$status = "ok ($tests_passed passed)";
|
||||
|
||||
# Clean up
|
||||
for ($i = $num_of_tmpfiles; $i; $i--) {
|
||||
rmfiles($tmp_filename . num_suffix($i));
|
||||
}
|
||||
for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--) {
|
||||
rmfiles($log_filename . num_suffix($i));
|
||||
rmfiles($base_filename . num_suffix($i));
|
||||
}
|
||||
}
|
||||
|
||||
# If the verbose option has been specified, then a short description
|
||||
# of each test is printed before displaying the results of each test
|
||||
# describing WHAT is being tested.
|
||||
|
||||
if ($verbose) {
|
||||
if ($detail) {
|
||||
print "\nWHAT IS BEING TESTED\n";
|
||||
print "--------------------";
|
||||
}
|
||||
print "\n\n$description\n\n";
|
||||
}
|
||||
|
||||
# If the detail option has been specified, then the details of HOW
|
||||
# the test is testing what it says it is testing in the verbose output
|
||||
# will be displayed here before the results of the test are displayed.
|
||||
|
||||
if ($detail) {
|
||||
print "\nHOW IT IS TESTED\n";
|
||||
print "----------------";
|
||||
print "\n\n$details\n\n";
|
||||
}
|
||||
|
||||
print "$status\n";
|
||||
}
|
||||
$log_filename = "$testpath.$logext";
|
||||
$diff_filename = "$testpath.$diffext";
|
||||
$base_filename = "$testpath.$baseext";
|
||||
$run_filename = "$testpath.$runext";
|
||||
$tmp_filename = "$testpath.$tmpfilesuffix";
|
||||
|
||||
&setup_for_test; # suite-defined
|
||||
|
||||
$output = "........................................................ ";
|
||||
|
||||
substr($output,0,length($testname)) = "$testname ";
|
||||
|
||||
print $output;
|
||||
|
||||
# Run the actual test!
|
||||
$tests_run = 0;
|
||||
$tests_passed = 0;
|
||||
|
||||
$code = do $perl_testname;
|
||||
|
||||
$total_tests_run += $tests_run;
|
||||
$total_tests_passed += $tests_passed;
|
||||
|
||||
# How did it go?
|
||||
if (!defined($code))
|
||||
{
|
||||
$suite_passed = 0;
|
||||
if (length ($@)) {
|
||||
warn "\n*** Test died ($testname): $@\n";
|
||||
} else {
|
||||
warn "\n*** Couldn't run $perl_testname\n";
|
||||
}
|
||||
}
|
||||
elsif ($code == -1) {
|
||||
$suite_passed = 0;
|
||||
}
|
||||
elsif ($code != 1 && $code != -1) {
|
||||
$suite_passed = 0;
|
||||
warn "\n*** Test returned $code\n";
|
||||
}
|
||||
|
||||
if ($suite_passed) {
|
||||
++$categories_passed;
|
||||
$status = "ok ($tests_passed passed)";
|
||||
for ($i = $num_of_tmpfiles; $i; $i--)
|
||||
{
|
||||
&rmfiles ($tmp_filename . &num_suffix ($i) );
|
||||
}
|
||||
|
||||
for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--)
|
||||
{
|
||||
&rmfiles ($log_filename . &num_suffix ($i) );
|
||||
&rmfiles ($base_filename . &num_suffix ($i) );
|
||||
}
|
||||
}
|
||||
elsif (!defined $code || $code > 0) {
|
||||
$status = "FAILED ($tests_passed/$tests_run passed)";
|
||||
}
|
||||
elsif ($code < 0) {
|
||||
$status = "N/A";
|
||||
--$categories_run;
|
||||
}
|
||||
|
||||
# If the verbose option has been specified, then a short description
|
||||
# of each test is printed before displaying the results of each test
|
||||
# describing WHAT is being tested.
|
||||
|
||||
if ($verbose)
|
||||
{
|
||||
if ($detail)
|
||||
{
|
||||
print "\nWHAT IS BEING TESTED\n";
|
||||
print "--------------------";
|
||||
}
|
||||
print "\n\n$description\n\n";
|
||||
}
|
||||
|
||||
# If the detail option has been specified, then the details of HOW
|
||||
# the test is testing what it says it is testing in the verbose output
|
||||
# will be displayed here before the results of the test are displayed.
|
||||
|
||||
if ($detail)
|
||||
{
|
||||
print "\nHOW IT IS TESTED\n";
|
||||
print "----------------";
|
||||
print "\n\n$details\n\n";
|
||||
}
|
||||
|
||||
print "$status\n";
|
||||
}
|
||||
}
|
||||
|
||||
# If the keep flag is not set, this subroutine deletes all filenames that
|
||||
@@ -713,7 +718,6 @@ sub compare_output
|
||||
&run_command_with_output(&get_difffile,$command);
|
||||
}
|
||||
|
||||
$suite_passed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -165,9 +165,9 @@ struct variable *try_variable_definition (const gmk_floc *flocp, char *line,
|
||||
int target_var);
|
||||
void init_hash_global_variable_set (void);
|
||||
void hash_init_function_table (void);
|
||||
void define_new_function(const gmk_floc *flocp,
|
||||
const char *name, int min, int max, int expand,
|
||||
char *(*func)(const char *, int, char **));
|
||||
void define_new_function(const gmk_floc *flocp, const char *name,
|
||||
unsigned int min, unsigned int max, unsigned int flags,
|
||||
gmk_func_ptr func);
|
||||
struct variable *lookup_variable (const char *name, unsigned int length);
|
||||
struct variable *lookup_variable_in_set (const char *name, unsigned int length,
|
||||
const struct variable_set *set);
|
||||
|
||||
@@ -26,7 +26,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "makeint.h"
|
||||
#include "job.h"
|
||||
|
||||
#ifdef OUTPUT_SYNC
|
||||
#ifndef NO_OUTPUT_SYNC
|
||||
/* Support for OUTPUT_SYNC and related functionality. */
|
||||
|
||||
/* Emulation of fcntl that supports only F_GETFD and F_SETLKW. */
|
||||
@@ -40,106 +40,106 @@ fcntl (intptr_t fd, int cmd, ...)
|
||||
switch (cmd)
|
||||
{
|
||||
case F_GETFD:
|
||||
va_end (ap);
|
||||
/* Could have used GetHandleInformation, but that isn't
|
||||
supported on Windows 9X. */
|
||||
if (_get_osfhandle (fd) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
va_end (ap);
|
||||
/* Could have used GetHandleInformation, but that isn't
|
||||
supported on Windows 9X. */
|
||||
if (_get_osfhandle (fd) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
case F_SETLKW:
|
||||
{
|
||||
void *buf = va_arg (ap, void *);
|
||||
struct flock *fl = (struct flock *)buf;
|
||||
HANDLE hmutex = (HANDLE)fd;
|
||||
static struct flock last_fl;
|
||||
short last_type = last_fl.l_type;
|
||||
{
|
||||
void *buf = va_arg (ap, void *);
|
||||
struct flock *fl = (struct flock *)buf;
|
||||
HANDLE hmutex = (HANDLE)fd;
|
||||
static struct flock last_fl;
|
||||
short last_type = last_fl.l_type;
|
||||
|
||||
va_end (ap);
|
||||
va_end (ap);
|
||||
|
||||
if (hmutex == INVALID_HANDLE_VALUE || !hmutex)
|
||||
return -1;
|
||||
if (hmutex == INVALID_HANDLE_VALUE || !hmutex)
|
||||
return -1;
|
||||
|
||||
last_fl = *fl;
|
||||
last_fl = *fl;
|
||||
|
||||
switch (fl->l_type)
|
||||
{
|
||||
switch (fl->l_type)
|
||||
{
|
||||
|
||||
case F_WRLCK:
|
||||
{
|
||||
DWORD result;
|
||||
case F_WRLCK:
|
||||
{
|
||||
DWORD result;
|
||||
|
||||
if (last_type == F_WRLCK)
|
||||
{
|
||||
/* Don't call WaitForSingleObject if we already
|
||||
own the mutex, because doing so will require
|
||||
us to call ReleaseMutex an equal number of
|
||||
times, before the mutex is actually
|
||||
released. */
|
||||
return 0;
|
||||
}
|
||||
if (last_type == F_WRLCK)
|
||||
{
|
||||
/* Don't call WaitForSingleObject if we already
|
||||
own the mutex, because doing so will require
|
||||
us to call ReleaseMutex an equal number of
|
||||
times, before the mutex is actually
|
||||
released. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = WaitForSingleObject (hmutex, INFINITE);
|
||||
switch (result)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
/* We don't care if the mutex owner crashed or
|
||||
exited. */
|
||||
case WAIT_ABANDONED:
|
||||
return 0;
|
||||
case WAIT_FAILED:
|
||||
case WAIT_TIMEOUT: /* cannot happen, really */
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
result = WaitForSingleObject (hmutex, INFINITE);
|
||||
switch (result)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
/* We don't care if the mutex owner crashed or
|
||||
exited. */
|
||||
case WAIT_ABANDONED:
|
||||
return 0;
|
||||
case WAIT_FAILED:
|
||||
case WAIT_TIMEOUT: /* cannot happen, really */
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
|
||||
/* Invalidate the last command. */
|
||||
memset (&last_fl, 0, sizeof (last_fl));
|
||||
/* Invalidate the last command. */
|
||||
memset (&last_fl, 0, sizeof (last_fl));
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
default:
|
||||
errno = EDEADLOCK;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case F_UNLCK:
|
||||
{
|
||||
/* FIXME: Perhaps we should call ReleaseMutex
|
||||
repatedly until it errors out, to make sure the
|
||||
mutext is released even if we somehow managed to
|
||||
to take ownership multiple times? */
|
||||
BOOL status = ReleaseMutex (hmutex);
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
default:
|
||||
errno = EDEADLOCK;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case F_UNLCK:
|
||||
{
|
||||
/* FIXME: Perhaps we should call ReleaseMutex
|
||||
repatedly until it errors out, to make sure the
|
||||
mutext is released even if we somehow managed to
|
||||
to take ownership multiple times? */
|
||||
BOOL status = ReleaseMutex (hmutex);
|
||||
|
||||
if (status)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
if (status)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
|
||||
if (err == ERROR_NOT_OWNER)
|
||||
errno = EPERM;
|
||||
else
|
||||
{
|
||||
memset (&last_fl, 0, sizeof (last_fl));
|
||||
errno = EINVAL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (err == ERROR_NOT_OWNER)
|
||||
errno = EPERM;
|
||||
else
|
||||
{
|
||||
memset (&last_fl, 0, sizeof (last_fl));
|
||||
errno = EINVAL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
va_end (ap);
|
||||
return -1;
|
||||
errno = ENOSYS;
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,54 +210,156 @@ same_stream (FILE *f1, FILE *f2)
|
||||
&& fh2 && fh2 != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (fh1 == fh2)
|
||||
return 1;
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
DWORD ftyp1 = GetFileType (fh1), ftyp2 = GetFileType (fh2);
|
||||
{
|
||||
DWORD ftyp1 = GetFileType (fh1), ftyp2 = GetFileType (fh2);
|
||||
|
||||
if (ftyp1 != ftyp2
|
||||
|| ftyp1 == FILE_TYPE_UNKNOWN || ftyp2 == FILE_TYPE_UNKNOWN)
|
||||
return 0;
|
||||
else if (ftyp1 == FILE_TYPE_CHAR)
|
||||
{
|
||||
/* For character devices, check if they both refer to a
|
||||
console. This loses if both handles refer to the
|
||||
null device (FIXME!), but in that case we don't care
|
||||
in the context of Make. */
|
||||
DWORD conmode1, conmode2;
|
||||
if (ftyp1 != ftyp2
|
||||
|| ftyp1 == FILE_TYPE_UNKNOWN || ftyp2 == FILE_TYPE_UNKNOWN)
|
||||
return 0;
|
||||
else if (ftyp1 == FILE_TYPE_CHAR)
|
||||
{
|
||||
/* For character devices, check if they both refer to a
|
||||
console. This loses if both handles refer to the
|
||||
null device (FIXME!), but in that case we don't care
|
||||
in the context of Make. */
|
||||
DWORD conmode1, conmode2;
|
||||
|
||||
/* Each process on Windows can have at most 1 console,
|
||||
so if both handles are for the console device, they
|
||||
are the same. We also compare the console mode to
|
||||
distinguish between stdin and stdout/stderr. */
|
||||
if (GetConsoleMode (fh1, &conmode1)
|
||||
&& GetConsoleMode (fh2, &conmode2)
|
||||
&& conmode1 == conmode2)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For disk files and pipes, compare their unique
|
||||
attributes. */
|
||||
BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
|
||||
/* Each process on Windows can have at most 1 console,
|
||||
so if both handles are for the console device, they
|
||||
are the same. We also compare the console mode to
|
||||
distinguish between stdin and stdout/stderr. */
|
||||
if (GetConsoleMode (fh1, &conmode1)
|
||||
&& GetConsoleMode (fh2, &conmode2)
|
||||
&& conmode1 == conmode2)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For disk files and pipes, compare their unique
|
||||
attributes. */
|
||||
BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
|
||||
|
||||
/* Pipes get zero in the volume serial number, but do
|
||||
appear to have meaningful information in file index
|
||||
attributes. We test file attributes as well, for a
|
||||
good measure. */
|
||||
if (GetFileInformationByHandle (fh1, &bhfi1)
|
||||
&& GetFileInformationByHandle (fh2, &bhfi2))
|
||||
return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
|
||||
&& bhfi1.nFileIndexLow == bhfi2.nFileIndexLow
|
||||
&& bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
|
||||
&& bhfi1.dwFileAttributes == bhfi2.dwFileAttributes);
|
||||
}
|
||||
}
|
||||
/* Pipes get zero in the volume serial number, but do
|
||||
appear to have meaningful information in file index
|
||||
attributes. We test file attributes as well, for a
|
||||
good measure. */
|
||||
if (GetFileInformationByHandle (fh1, &bhfi1)
|
||||
&& GetFileInformationByHandle (fh2, &bhfi2))
|
||||
return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
|
||||
&& bhfi1.nFileIndexLow == bhfi2.nFileIndexLow
|
||||
&& bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
|
||||
&& bhfi1.dwFileAttributes == bhfi2.dwFileAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* OUTPUT_SYNC */
|
||||
/* A replacement for tmpfile, since the MSVCRT implementation creates
|
||||
the file in the root directory of the current drive, which might
|
||||
not be writable by our user. Most of the code borrowed from
|
||||
create_batch_file, see job.c. */
|
||||
FILE *
|
||||
tmpfile (void)
|
||||
{
|
||||
char temp_path[MAXPATHLEN];
|
||||
unsigned path_size = GetTempPath (sizeof temp_path, temp_path);
|
||||
int path_is_dot = 0;
|
||||
/* The following variable is static so we won't try to reuse a name
|
||||
that was generated a little while ago, because that file might
|
||||
not be on disk yet, since we use FILE_ATTRIBUTE_TEMPORARY below,
|
||||
which tells the OS it doesn't need to flush the cache to disk.
|
||||
If the file is not yet on disk, we might think the name is
|
||||
available, while it really isn't. This happens in parallel
|
||||
builds, where Make doesn't wait for one job to finish before it
|
||||
launches the next one. */
|
||||
static unsigned uniq = 0;
|
||||
static int second_loop = 0;
|
||||
const char base[] = "gmake_tmpf";
|
||||
const unsigned sizemax = sizeof base - 1 + 4 + 10 + 10;
|
||||
unsigned pid = GetCurrentProcessId ();
|
||||
|
||||
if (path_size == 0)
|
||||
{
|
||||
path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
|
||||
path_is_dot = 1;
|
||||
}
|
||||
|
||||
++uniq;
|
||||
if (uniq >= 0x10000 && !second_loop)
|
||||
{
|
||||
/* If we already had 64K batch files in this
|
||||
process, make a second loop through the numbers,
|
||||
looking for free slots, i.e. files that were
|
||||
deleted in the meantime. */
|
||||
second_loop = 1;
|
||||
uniq = 1;
|
||||
}
|
||||
while (path_size > 0 &&
|
||||
path_size + sizemax < sizeof temp_path &&
|
||||
!(uniq >= 0x10000 && second_loop))
|
||||
{
|
||||
HANDLE h;
|
||||
|
||||
sprintf (temp_path + path_size,
|
||||
"%s%s%u-%x.tmp",
|
||||
temp_path[path_size - 1] == '\\' ? "" : "\\",
|
||||
base, pid, uniq);
|
||||
h = CreateFile (temp_path, /* file name */
|
||||
GENERIC_READ | GENERIC_WRITE | DELETE, /* desired access */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
|
||||
NULL, /* default security attributes */
|
||||
CREATE_NEW, /* creation disposition */
|
||||
FILE_ATTRIBUTE_NORMAL | /* flags and attributes */
|
||||
FILE_ATTRIBUTE_TEMPORARY |
|
||||
FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL); /* no template file */
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
const DWORD er = GetLastError ();
|
||||
|
||||
if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
++uniq;
|
||||
if (uniq == 0x10000 && !second_loop)
|
||||
{
|
||||
second_loop = 1;
|
||||
uniq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The temporary path is not guaranteed to exist, or might
|
||||
not be writable by user. Use the current directory as
|
||||
fallback. */
|
||||
else if (path_is_dot == 0)
|
||||
{
|
||||
path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
|
||||
path_is_dot = 1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
errno = EACCES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int fd = _open_osfhandle ((intptr_t)h, 0);
|
||||
|
||||
return _fdopen (fd, "w+b");
|
||||
}
|
||||
}
|
||||
|
||||
if (uniq >= 0x10000)
|
||||
errno = EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* !NO_OUTPUT_SYNC */
|
||||
|
||||
#if MAKE_LOAD
|
||||
|
||||
@@ -286,8 +388,8 @@ dlopen (const char *file, int mode)
|
||||
/* MSDN says to be sure to use backslashes in the DLL file name. */
|
||||
strcpy (dllfn, file);
|
||||
for (p = dllfn; *p; p++)
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
|
||||
dllhandle = LoadLibrary (dllfn);
|
||||
}
|
||||
@@ -307,8 +409,8 @@ dlerror (void)
|
||||
return NULL;
|
||||
|
||||
ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);
|
||||
while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r'))
|
||||
--ret;
|
||||
|
||||
@@ -350,5 +452,5 @@ dlclose (void *handle)
|
||||
}
|
||||
|
||||
|
||||
#endif /* MAKE_LOAD */
|
||||
#endif /* MAKE_LOAD */
|
||||
|
||||
|
||||
@@ -1111,7 +1111,7 @@ done2:
|
||||
|
||||
/*
|
||||
* Description: Clean up any leftover handles, etc. It is up to the
|
||||
* caller to manage and free the input, ouput, and stderr buffers.
|
||||
* caller to manage and free the input, output, and stderr buffers.
|
||||
*/
|
||||
void
|
||||
process_cleanup(
|
||||
|
||||
Reference in New Issue
Block a user