Compare commits

...

240 Commits

Author SHA1 Message Date
Paul Smith
d523661ce2 [SV 66499] Detect jobserver values that are too large
Set the jobserver pipe to non-blocking before writing tokens; if a
token write fails the user's jobserver value is too large so fail.

Original implementation: Dmitry Goncharov <dgoncharov@users.sf.net>

* src/posixos.c (set_blocking): Split into force_blocking() which
always enables/disables blocking; set_blocking() may call it.
(jobserver_setup): Set the write side of the pipe to non-blocking
before writing tokens.  If it fails with EAGAIN we know the pipe
is full: create a fatal error.
* tests/scripts/features/jobserver: Test a too-large jobserver.
2024-12-08 23:30:37 -05:00
Paul Smith
f12a4fddce jobserver: Ensure the named pipe is deleted on error
Make sure the jobserver named pipe is deleted even if the
jobserver_setup() function calls fatal() and exits early.

* src/main.c (clean_jobserver): Always reset_jobserver().
* src/posixos.c (jobserver_setup): Set job_root up front.
* tests/test_driver.pl: Print out the logfile pathname on error.
For tests with regex matches this might be the only file available.
Don't print the base filename unless one is created.
2024-12-08 23:30:37 -05:00
Paul Smith
186522e480 * doc/make.texi: [SV 66324] Fix a typo 2024-12-08 23:30:00 -05:00
Dmitry Goncharov
aa8626ce09 [SV 66273] Double-colon targets must not be intermediate
An explicitly mentioned double-colon target cannot be intermediate.

* src/read.c (record_files): Set file->is_explicit in the case of an
explicitly mentioned file built by a double colon rule.
* src/file.c (print_file): Have print_file print whether a file is
explicitly mentioned.
* tests/scripts/features/patternrules: Add tests.
2024-10-01 22:27:25 -04:00
Dmitry Goncharov
93704dd565 [SV 66268] Include newlines in file removal error message
* src/file.c (remove_intermediates): Fix an error message about a
failure to remove an intermediate file.
* tests/scripts/features/patternrules: Add tests.
2024-10-01 22:14:31 -04:00
Paul Smith
101bf5636f * doc/make.texi: Clarify -j versus -jN behavior 2024-09-02 16:23:36 -04:00
Sergei Trofimovich
9251546bac Fix biased shuffle by avoiding already "struck" elements
Artem Klimov noticed that current shuffle implementation suffers from
probability bias due to a typical bug in the shuffling implementation.

When we consider already shuffled element we slightly bias their
propability.

https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
suggests shuffling each "struck" element only once.

Before the change probabilities of 4-element array to land from `i`
index to `j` index are:

          0     1     2     3
      _____ _____ _____ _____
  0 | 25.00 29.30 24.60 21.10
  1 | 25.00 22.25 28.13 24.63
  2 | 25.00 23.44 22.26 29.30
  3 | 25.00 25.01 25.01 24.98

Note that `0->1` probability is almost 29% while `0->3` os only 21%.

After the change probabilities are not as biased:

          0     1     2     3
      _____ _____ _____ _____
  0 | 24.99 24.99 25.01 25.01
  1 | 24.99 25.04 24.99 24.99
  2 | 25.01 25.00 25.00 24.99
  3 | 25.01 24.98 25.00 25.01

* src/shuffle.c (random_shuffle_array): Fix biased shuffle by avoiding
already "struck" elements.
2024-09-02 15:11:36 -04:00
Paul Smith
7dc23aff30 * doc/make.texi: GNUMAKEFLAGS is only read from the environment 2024-09-02 14:54:23 -04:00
Paul Eggert
0267eb64fa Check for snprintf truncation on W32
* src/main.c (find_and_set_default_shell) [MK_OS_W32]:
Do not use a buffer that snprintf truncated.
2024-09-02 14:43:24 -04:00
Paul Eggert
bba4427b5d Fix unlikely pointer overflow in abspath
* src/function.c (abspath): len is now ptrdiff_t,
to avoid GCC warning about comparing signed to unsigned.
It really is a pointer difference, after all.
Rejigger comparision to avoid undefined behavior
if dest + len is an invalid pointer.
2024-09-02 14:43:24 -04:00
Paul Eggert
c23a7e6232 Prefer memcpy to strncpy if either will do
strncpy is trickier and a bit slower.
* src/function.c (func_realpath, func_abspath):
* src/misc.c (xstrndup):
Prefer memcpy or mempcpy to strncpy when the source length is known.
2024-09-02 14:43:24 -04:00
Paul Eggert
4d3bf7838f Omit unused PATH_MAX code
* src/makeint.h (GET_PATH_MAX, PATH_VAR):
Simplify, since PATH_MAX is always defined here.
(NEED_GET_PATH_MAX): Remove.
* src/misc.c (get_path_max) [NEED_GET_PATH_MAX]: Remove.
2024-09-02 14:43:24 -04:00
Paul Eggert
8c8c7fc226 Avoid strlen calls after sprintf
* src/file.c (file_timestamp_sprintf):
* src/function.c (func_words, func_call):
* src/job.c (child_error):
* src/main.c (define_makeflags):
* src/output.c (message, error, fatal):
Use return value from sprintf instead of calling strlen
on the resulting buffer.
2024-09-02 14:43:24 -04:00
Paul Smith
9fee98f843 [SV 65759] Document special handling of "-" command line option
* doc/make.1: Add information on "-" option handling.
* doc/make.texi: Ditto.
2024-09-02 13:48:41 -04:00
Dan D
f800f8bae3 [SV 65777] Add more const
Add more const to static arrays.  On some systems this allows more
data to be placed in RO segments and shared between multiple
instances of the make executable.  Anyway more const is good hygiene.

* src/default.c: Add const to arrays.
* src/function.c: Ditto.
* src/hash.c: Ditto.
* src/hash.h: Ditto.
* src/job.c: Ditto.
* src/read.c: Ditto.
* src/remake.c: Ditto.
* src/rule.c: Ditto.
* src/rule.h: Ditto.
2024-09-02 13:48:30 -04:00
Paul Smith
39a4c81062 Remove obsolete email address for the FSF
* doc/make.texi: Use the newer email address in the manual.
* gl/lib/fnmatch.c: Use a URL instead of a street address.
* gl/lib/fnmatch.in.h: Ditto.
* gl/lib/glob.c: Ditto.
* gl/lib/glob.in.h: Ditto.
2024-09-01 21:12:37 -04:00
Paul Smith
d97e048b08 * bootstrap.conf: Update to newer prerequisites 2024-09-01 21:09:42 -04:00
Paul Smith
c63a5bc6a2 [SV 65917] Mark also_make targets as updated in make -n
Suggested patch by Hannes Domani <ssbssa@yahoo.de>

* src/remake.c (notice_finished_file): When run with -n, mark
also_make targets as updated.
* tests/scripts/options/dash-n: Test pattern and grouped targets.
2024-08-04 23:53:26 -04:00
Paul Smith
bc979e4949 * src/job.c (new_job): [SV-66030] Show all also-make targets 2024-08-04 17:16:23 -04:00
Paul Smith
6970561de0 Don't add a target to its own also_make list
* src/dep.h (copy_dep): Make a copy of one struct dep.
* src/misc.c (copy_dep): Implement the new function.
(copy_dep_chain): Call copy_dep() for each dep in the chain.
* src/read.c (record_files): Write our own copy loop and omit the
current file from its own also_make list.  Since we don't keep
the function's also_make, free it.
2024-08-04 17:13:07 -04:00
Paul Smith
f0db5e321f * doc/make.texi: [SV-65982] Clarify what --debug=makefile does 2024-08-04 16:04:19 -04:00
Paul Smith
8653c25fcf * src/remake.c (update_file_1): [SV 65999] Clarify debug output 2024-08-04 16:02:19 -04:00
Paul Smith
4d883c414d * doc/make.texi: [SV-66018] Mention .ONESHELL in [-+@] docs 2024-08-04 16:02:19 -04:00
Dmitry Goncharov
034f862361 [SV 66037] Avoid hang/crash from MAKEFLAGS=... on command line
Make enters an infinite loop when some option and MAKEFLAGS=<value>
are specified on the command line.  For example,
    $ make -r MAKEFLAGS=hello=world

If decode_switches() runs handle_non_switch_argument() from within
the getopt() loop, it would recursively call decode_switches() to
enter a new getopt() loop, corrupting the state of the outer loop.

* src/main.c (decode_switches): Save up non-option arguments and run
handle_non_switch_argument() only after we're done with getopt().
* tests/scripts/variables/MAKEFLAGS: Add tests.
2024-08-04 16:00:48 -04:00
Paul Smith
49b955a50d * doc/make.texi (Overview): Update reference to POSIX.1-2024 2024-08-04 15:21:59 -04:00
Paul Smith
69038e62e0 * src/warning.h: Put warnings into alphabetical order.
* src/warning.c: Ditto.
* tests/scripts/options/warn: Fix tests for the new order.
2024-08-04 15:21:59 -04:00
Dmitry Goncharov
a9e3eb1eec [SV 65739] Add warning circular-dep.
Add a warning to control circular dependency detection.  Use "warn" as
the default action to be backward-compatible.

* src/warning.h (enum warning_type): Add warning type wt_circular_dep.
* src/warning.c (warn_init): Set default wt_circular_dep to w_warn.
* src/remake.c (update_file_1): Consult the circular-dep warning to
handle circular dependencies.
* tests/scripts/options/warn: Test --warn circular-dep flag.
* tests/scripts/variables/WARNINGS: Test .WARNINGS circular-dep flag.
* doc/make.texi: Document circular-dep warning.
* doc/make.1: Ditto.
2024-08-04 15:21:59 -04:00
Dmitry Goncharov
e3f938caf8 * tests/scripts/functions/shell: [SV 65323] Run huge var test in bash
The long variable name causes ksh to crash.  Some systems use ksh as
/bin/sh, so force bash if it's available else skip the test.
2024-05-06 14:11:17 -04:00
Dmitry Goncharov
40664fef1f [SV 65324] disable_builtins: Don't dereference NULL suffix_file
Make crashes when -r and MAKEFLAGS= are specified on the command line.

On startup make begins to process command line arguments.
During processing of "MAKEFLAGS=" make calls reset_makeflags, which in
turn calls disable_builtins, which dereferences null suffix_file.
Here is the backtrace.

0 disable_builtins main.c:3482
1 reset_makeflags main.c:3104
2 set_special_var variable.c:1325
3 do_variable_definition variable.c:1693
4 try_variable_definition variable.c:1889
5 handle_non_switch_argument main.c:3021
6 decode_switches main.c:3150
7 main main.c:1621

* src/main.c (disable_builtins): Avoid dereferencing null suffix_file.
* tests/scripts/features/suffixrules: Add a test.
2024-05-06 14:11:17 -04:00
Paul Smith
f7985ab827 * make.texi (How to Use Variables): [SV 65536] Rewrite this chapter
Re-reading this chapter I decided it was time to introduce a complete
rewrite, of at least parts of this.  Much of the enhancements added
over the years were in the wrong place or not clear.
2024-05-06 14:11:17 -04:00
Paul Smith
8339232a2f * .dir-locals.el: Correct bug reference regex format 2024-04-14 15:51:23 -04:00
Paul Smith
949952258e [SV 65537] Update to newer gnulib
* bootstrap.conf: Switch to gnulib stable-202401 branch.
* maintMakefile: Support an EXTRA_CFLAGS variable in maintainer mode.
* README.git: Describe how to use it.
2024-04-14 15:27:37 -04:00
Paul Smith
479c54f6ed * NEWS: Clean up UTF-8 issues 2024-04-14 15:27:12 -04:00
Paul Smith
033330e34c * doc/make.texi (Pattern Rules): Clarify that rules must have recipes. 2024-03-28 19:14:25 -04:00
Paul Eggert
61ee4578f5 * src/arscan.c (parse_int): Fix integer overflow test
Use intprops.h macros rather than trying to detect integer overflow by
hand, and doing it incorrectly.  Example of incorrect behavior:
if val == 3689348814741910323, base == 10, UINTMAX_WIDTH == 64, and
 *ptr == '0' then (val*base)+(*ptr-'0') yields 18446744073709551614
which is greater than val even though overflow has occurred.
Fortunately this bug could not be triggered on GNU/Linux hosts,
although it may be possible on platforms (if any) where struct ar_hdr
has members so large that they can represent integers that do not fit
int uintmax_t.
2024-03-28 19:08:13 -04:00
KO Myung-Hun
f289ece6cf * src/makeint.h (JOBSERVER_USE_FIFO): Do not define on OS/2.
mkfifo() on OS/2 is a dummy, it even returns a wrong value on error.
2024-03-28 19:08:13 -04:00
Paul Smith
d791fb4139 * src/variable.c (do_variable_definition) [W32]: Fix bad variable. 2024-03-28 19:08:13 -04:00
Marco Sirabella
0b91f42f58 * src/arscan.c (ar_name_equal): Support GNU ar's -P option. 2024-03-28 19:08:13 -04:00
Marco Sirabella
882d59c672 * tests/README: Fix sample run_make_tests command line. 2024-03-24 16:36:35 -04:00
Paul Smith
5fc62f8295 * doc/make.texi: GNU Make does set GNUMAKEFLAGS, to empty. 2024-03-24 16:29:14 -04:00
Paul Smith
3d4f3e0627 * doc/make.texi: Document temporary file name prefix
* src/posixos.c (jobserver_setup): Set prefix for FIFO temp file.
Ensure it can't conflict with a "normal" temp file.
* src/w32/w32os.c (os_anontmp): Set prefix for anon temp files.
2024-03-24 16:23:28 -04:00
Paul Smith
242603fa46 [SV 65268] Un-set append mode for stdout/stderr on exit
It turns out that options set on stdout/stderr last after exit.
Leaving append-mode enabled can break other facilities, so reset the
flags on stdout/stderr before we exit.

* src/os.h: Add a new fd_reset_append() to reset flags on FDs.
Modify fd_set_append() to return the old flags.
* src/posixos.c (fd_reset_append): Set provided flags on the FD.
(fd_set_append): Return the previous flags set on the FD.
* src/output.c (output_init): Preserve old flags for stdout/stderr.
(output_close): Reset flags for stdout/stderr.
* src/w32/w32os.c: Implement dummy methods.
2024-03-24 15:25:53 -04:00
Paul Smith
b8a2a4424b [SV 65273] configure.ac: Remove check for sys/timeb.h
GNU Make doesn't use ftime(); we only checked for this to work around
an error in the completely obsolete SCO 3.2 system.  Since ftime() is
deprecated, including sys/timeb.h has started throwing warnings on
newer systems so just remove it completely.
Reported by: Collin Funk <collin.funk1@gmail.com>

* configure.ac: Remove the check for sys/timeb.h.
* src/makeint.h: Remove the include of sys/timeb.h.
* src/config.h-vms: Don't define HAVE_SYS_TIMEB_H.
* src/config.h.W32: Ditto.
2024-03-24 15:25:18 -04:00
Jouke Witteveen
bfbf169b63 [SV 65448] intcmp: Compare values instead of magnitudes
* src/function.c (func_intcmp): Reverse comparison direction when
both arguments are negative.
* tests/scripts/functions/intcmp: Add tests and remove useless ones.
2024-03-24 14:08:59 -04:00
Paul Smith
21a538ce8f [SV 65359] doc/make.texi: Describe invalid export variable names 2024-03-24 14:05:45 -04:00
Paul Smith
3176b60566 [SV 64085] Handle .POSIX plus .IGNORE correctly
POSIX requires that a conforming makefile should not use -e if
 1) make is invoked with -i
 2) A .IGNORE target exists with no prerequisites
 3) The current target is a prerequisite of .IGNORE

* src/job.c (start_job_command): Add the target's flags when
constructing argv so it can check (3) above.
(construct_command_argv_internal): Don't set shellflags if it's not
set: this only happens if we're parsing for the slow path and we
don't need them.
(construct_command_argv): Don't allocate buffers if not needed.
When detecting "-ec", check the global ignore_errors_flag and the
current command line flags.
* tests/scripts/targets/IGNORE: Add tests for .IGNORE.
* tests/scripts/targets/POSIX: Add tests for the three cases above.
2024-02-04 19:41:50 -05:00
Dmitry Goncharov
07187db947 [SV 64822, SV 36486] Fix appending to a pattern specific variable
Appending to a pattern specific variable produces an incorrect value
in the presence of a command line definition or an env override of
the variable.  Also, fix pattern/target-specific appending to a
variable with origin override.

* At parse time record_target_var sets the value of a pattern
  specific variable to the value defined on command line or to the
  value of the env override.
* Later, at build time, recursively_expand_for_file appends this
  value of the variable (set in record_target_var) to the command
  line value again, regardless of the origin of the variable.

This patch modifies recursively_expand_for_file to avoid appending,
unless the origin of the variable beats or equals the origin of one
of the parent definitions of this variable.

Reported by Rob <robw9739@gmail.com>,
Brian Vandenberg <phantall@gmail.com>,
Markus Oberhumer <markus@oberhumer.com>.

* NEWS: Note the change.
* src/variable.c (do_variable_definition): Avoid merging a
pattern-specific variable with the parent definition when a command
line or env override is present.
* src/expand.c (recursively_expand_for_file): Avoid appending to a
pattern-specific variable, unless the origin of this pattern-specific
variable beats or equals the origin of one of the parent definitions
of this variable.
* doc/make.texi (Override Directive): Add missing cross-reference.
* tests/scripts/variables/append: Add tests.
2024-02-04 18:26:21 -05:00
Paul Smith
a493d9ab6c * NEWS: Clean up 2024-02-04 11:34:49 -05:00
Dmitry Goncharov
a382ac6cd1 [SV 64803] Set origin for unmodified variables after -e
Ensure the origin of all variables inherited from the environment is
"environment override" if -e is given.  Previously only variables
that were set in the makefile had this origin.

PDS: Most of these changes are from Dmitry but I slightly modified
the algorithm: instead of rearranging the way in which MAKEFLAGS is
parsed we reset the env_override value to the default before we
re-parse MAKEFLAGS, then we set the origin of all env vars to the
correct value based on the new setting.

* NEWS: Mention the change for backward-compatibility.
* src/main.c (main): Ensure MAKEFLAGS is always marked special.
(reset_makeflags): Set env_overrides back to default before parsing
MAKEFLAGS.
(decode_switches): Call reset_env_override() to check for changes.
* src/variable.h (reset_env_override): Declare a new function.
* src/variable.c (reset_env_override): Go through all env variables
and ensure the origin is correct based on env_overrides.
(set_env_override): Helper function for the hash.
* tests/scripts/functions/foreach: Fix tests.
* tests/scripts/functions/let: Ditto.
* tests/scripts/functions/origin: Ditto.
* tests/scripts/options/dash-e: Add tests.
2024-02-04 11:34:49 -05:00
Paul Smith
63b602e74f * tests/test_driver.pl: Add cd to the .run output file 2024-02-04 11:34:49 -05:00
Dmitry Goncharov
ec348f51d0 Replace target_var boolean with enum variable_scope
Replace the target_var boolean with an enum to distinguish between
global, target-specific, and pattern-specific variables when defining.

* src/variable.h (enum variable_scope): Introduce enum variable_scope.
Replace parameter target_var of type int with enum variable_scope.
* src/load.c (load_file): Ditto.
* src/main.c (handle_non_switch_argument): Ditto.
* src/read.c (eval_makefile): Ditto.
(eval): Ditto.
(do_define): Ditto.
(record_target_var): Ditto.
(construct_include_path): Ditto.
* src/variable.c (initialize_file_variables): Ditto.
(shell_result): Ditto.
(try_variable_definition): Ditto.
(do_variable_definition): Ditto.
2024-02-04 11:32:50 -05:00
Paul Smith
51e56a028e * doc/make.texi: Grammar improvements.
Reported-by: David Apps <davidapps3+gnu@gmail.com>
2024-01-28 14:21:00 -05:00
Paul Smith
1eff20f6f6 Support conditional modifiers on all assignment operators
Rework the single "?=" operator to instead allow a "?" modifier to be
prepended to ANY assignment operator.  If "?" is given then the
variable is assigned (using whatever operator comes next) if and only
if the variable is not already defined.  If it is defined then no
action is taken (the right-hand side is not expanded, etc.)

* NEWS: Announce this new feature.
* doc/make.texi: Modify the documentation around assignment operators.
* src/variable.h: Remove the f_conditional variable flavor.
(do_variable_definition): Add an argument specifying conditional.
* src/variable.c (parse_variable_definition): Use the existing flag
"conditional" to remember if we saw "?" rather than the flavor.
When we see "?" skip it and continue trying to parse an assignment.
(try_variable_definition): Pass condition to do_variable_definition().
(initialize_file_variables): Ditto.
(do_variable_definition): Check for conditional up-front: quit if set.
Remove handling of obsolete f_conditional flavor.
* src/read.c (eval_makefile): MAKEFILE_LIST is not conditional.
(do_define): Unset conditional for define with no operator.  Pass the
conditional flag to do_variable_definition().
(construct_include_path): .INCLUDE_DIRS is not conditional.
* src/load.c (load_file): .LOADED is not conditional.
* tests/scripts/variables/conditional: Add new tests.
2024-01-28 14:20:47 -05:00
Paul Smith
82708b3a3a Remove unnecessary parsing during makefile read
* src/read.c (make_word_type): Remove w_varassign from the enum.
(get_next_mword): This function is never called on a string in a place
where we might find a variable assignment.  Any variable assignments
have already been handled via try_variable_definition(), so we don't
need to check for them here.
* tests/scripts/variables/flavors: Check triple-colon assignment in
target-specific variables.
2024-01-27 16:40:36 -05:00
Paul Smith
828906b6dc Create a common method for skipping variable references
* README.git: Add some notes about using ASAN.
* src/makeint.h: Declare skip_references().
* src/misc.c (skip_reference): A new function that will skip over a
variable reference, counting matching open paren/brace characters.
* src/implicit.c (get_next_word): Replace code with skip_reference().
* src/read.c (conditional_line): Ditto.
(find_map_unquote): Ditto.
(get_next_mword): Ditto.
(parse_variable_definition): Ditto.
* src/function.c (handle_function): Make clear that the passed in
pointers are not modified if the function returns false.
* src/expand.c (expand_string_buf): Don't create local variables to
call handle_function() since it doesn't modify its arguments.
* src/job.c (new_job): Small simplifications.
2024-01-27 16:40:36 -05:00
Paul Smith
b936970956 * src/misc.c (writebuf, readbuf): Return a constant -1 2024-01-27 16:40:36 -05:00
Dmitry Goncharov
1e43a5d104 [SV 65211] Fix load and loadapi tests.
* scripts/features/load: Suppress unused variable compiler warnings.
* scripts/features/loadapi: Ditto.
2024-01-27 16:40:36 -05:00
Paul Smith
25049fef16 [SV 65172] Avoid buffer overruns when expanding for $(shell ...)
Reported-by: MIAOW Miao <guoyr_2013@hotmail.com>
Patch from: Henrik Carlqvist <hc981@poolhem.se>
Test from: Dmitry Goncharov <dgoncharov@users.sf.net>

* src/expand.c (recursively_expand_for_file): Check the variable name
before checking for equality so we don't overrun the buffer.
* tests/scripts/functions/shell: Add a test with a very long variable.
2024-01-27 16:40:36 -05:00
Paul Smith
31036e648f [SV 64571] Add --print-targets option
Add an option to print a list of targets defined in the makefiles.
Don't print targets of implicit rules, or special targets.  To
support this remember which files are deemed suffix rule targets.

Add a missing warning for single-suffix targets with prerequisites.

Suggested by many.  Sample implementation by Tim <tdhutt@gmail.com>.

* NEWS: Announce the new option and single-suffix warning.
* doc/make.1: Add --print-targets to the man page.
* doc/make.texi: Add --print-targets to the documentation.  Clean up
the text around the definition of suffix rules.
* src/main.c (print_targets_flag): New variable for --print-targets.
(switches): Add a new long option --print-targets.
(main): If the option was provided call print_targets() and exit.
* src/filedef.h (struct file): Add a "suffix" boolean value.  Remove
print_prereqs() since it's static.  Add new print_targets().
* src/file.c (rehash_file): Merge the new suffix value.
(print_prereqs): Used only locally: change to static.
(print_target): Print targets which are not suffix rule targets and
are not special targets.
(print_targets): Call print_target() on each file.
* src/rule.c (convert_to_pattern): Make maxsuffix local; it doesn't
need to be static.  Emit ignoring prerequisites for single-suffix
rules as well as double-suffix rules.  Remember which files are
actually suffix rules.
* tests/scripts/features/suffixrules: Test single-suffix behavior.
* tests/scripts/options/print-targets: Add tests for --print-targets.
2024-01-08 23:31:58 -05:00
Paul Smith
1ff728bff4 * src/makeint.h: Add an ARRAYLEN macro to compute array sizes
* src/main.c: Replace inline array length computation with ARRAYLEN.
* src/function.c: Ditto.
* src/read.h: Ditto.
2024-01-07 11:28:23 -05:00
Paul Smith
1161779ef8 * doc/make.texi (Text Functions): [SV 64339] Clarify pattern use. 2024-01-07 10:22:20 -05:00
Paul Smith
a80670ad41 * (all): Update Copyright year to 2024 2024-01-06 18:06:09 -05:00
Paul Smith
d86448fe5f [SV 64402] Correct locating "," in ifeq/ifneq conditionals
Ensure that we correctly skip the entirety of a macro or function
reference when searching for the "," separator in an ifeq/ifneq
conditional, including using "$," and also "${foo,bar}".  Note that
this change means that parenthesis OTHER than those used for variable
expansion are not considered special, any longer.

* NEWS: Announce the change.
* src/read.c (conditional_line): Skip variable references when looking
  for "," and ensure that we match closing parens/braces properly.
* tests/scripts/features/conditionals: Add tests for this behavior.
2024-01-06 17:42:40 -05:00
Dmitry Goncharov
33932663b0 [SV 65006] Allow secondary expansion of .EXTRA_PREREQS
* src/rule.c (snap_implicit_rules): Set need_2nd_expansion of each
  prerequisite of global .EXTRA_PREREQS.
* src/file.c (snap_file):  Set need_2nd_expansion of each prerequisite
  of target-specific .EXTRA_PREREQS.
* tests/scripts/variables/EXTRA_PREREQS: Add tests.

Reported by Daniel Gerber <dg@atufi.org>.
2024-01-06 17:39:43 -05:00
Jouke Witteveen
89bea82af3 * src/function.c (func_let): Don't edit nonexistent values
* tests/scripts/functions/let: Test trailing whitespace in value list.
2024-01-01 19:31:37 -05:00
Paul Smith
dd1980426e * doc/make.texi (Text Functions): [SV 64818] Remove redundant text 2024-01-01 19:24:37 -05:00
Paul Smith
2ce7e40822 * .clangd: Add configuration for the clangd LSP server 2024-01-01 19:24:37 -05:00
Paul Smith
b1e240c554 * doc/make.texi: [SV 64924] Add missing parenthesis 2023-11-26 23:21:55 -05:00
Paul Smith
7fa40eb4fc * doc/make.texi: Add a quick reference appendix 2023-11-26 23:21:06 -05:00
Paul Smith
8817efe46a * src/function.c (function_table_entry): Sort 2023-11-26 23:20:22 -05:00
Paul Smith
66adfb7c6f make.texi: Cleanup 2023-09-01 16:57:58 -04:00
Paul Smith
9af3e60f4d make.texi: Add an appendix with troubleshooting tips 2023-08-29 15:39:16 -04:00
Paul Smith
8061929963 doc/make.texi: Clean up references to GNU Make 2023-08-29 15:20:31 -04:00
Paul Smith
cd33c9a1e9 doc/make.texi: Remove unnecessary @node arguments 2023-08-29 14:44:50 -04:00
Paul Smith
c4ecd9d9eb bootstrap.conf: Update to the latest gnulib stable branch 2023-08-25 11:10:14 -04:00
Paul Smith
6b7f35cb0b * AUTHORS: Updates 2023-07-04 14:26:58 -04:00
Torbjörn SVENSSON
1000374759 Fix GCC compile warning for "bad-function-cast" on Windows
Trick the compiler by hiding the cast in a function call.

* src/os.h: Declare the new function.
* src/w32/w32os.c (get_handle_for_fd): Convert and cast a file
descriptor into a Windows HANDLE.
(check_io_state): Call the new function rather than casting.
(osync_release): Ditto.
(fd_inherit): Ditto.
(fd_noinherit): Ditto.
* src/function.c (windows32_openpipe): Ditto.
* src/w32/compat/posixfcn.c (isatty): Ditto.
* src/w32/subproc/sub_proc.c (process_easy): Ditto.
2023-07-04 14:26:58 -04:00
Torbjörn SVENSSON
8d76fb8778 Fix GCC compile warning for "format-signedness" in Windows
* src/job.c (reap_children): Use unsigned int for DWORD.
* src/w32/subproc/sub_proc.c (process_easy): Ditto.
* src/w32/w32os.c (jobserver_setup): Ditto.
(jobserver_release): Ditto.
(jobserver_acquire): Ditto.
2023-07-01 12:49:24 -04:00
Torbjörn SVENSSON
ee366afbf1 * src/w32/compat/posixfcn.c (ttyname): Avoid const char* 2023-07-01 12:49:24 -04:00
Torbjörn SVENSSON
b686980c66 Fix GCC compile warning for "unused-parameter" on Windows
* src/w32/compat/posixfcn.c (isatty): Avoid unused-parameter warnings.
(jobserver_pre_child): Ditto.
(jobserver_post_child): Ditto.
(jobserver_acquire): Ditto.
(fd_set_append): Ditto.
2023-07-01 12:49:24 -04:00
Torbjörn SVENSSON
8e5c96c318 Fix GCC compile warning format-security on Windows
* src/job.c (create_batch_file): Avoid non-static format strings.
* src/main.c (handle_runtime_exceptions): Ditto.
* src/w32/subproc/w32err.c (map_windows32_error_to_string): Ditto.
2023-07-01 12:49:24 -04:00
Torbjörn SVENSSON
363bdaef8c Fix GCC compile warning declaration-after-statement on Windows
* src/w32/w32os.c (check_io_state): Move the HANDLE declarations.
2023-07-01 12:49:20 -04:00
Costas Argyris
b2bf660abc Add a UTF-8 resource when building for Windows
If a resource compiler is available, use it to add a UTF-8 resource
to the GNU Make executable on Windows.  As a result, GNU Make will
use UTF-8 as its ANSI code page, enabling it to work with UTF-8
encoded Makefiles, understand UTF-8 paths passed to it, etc.

These build process changes apply to all 3 ways that GNU Make can
be built for Windows:

1) configure
2) Basic.mk
3) build_w32.bat

When building with Visual Studio the resource compiler should always
be available.

When building with GCC or TCC, it depends on the availability of
'windres'.

If a resource compiler is not available, don't fail the build but
just proceed without the UTF-8 resource, effectively ignoring this
feature.

The UTF-8 resource only has an effect when GNU Make is running on a
minimum target version of Windows Version 1903 (May 2019 Update).
When the built GNU Make is running on an earlier version of Windows,
the embedded UTF-8 resource has no effect.

Code page information is added to --version output to tell users what
code pages are being used by any combination of GNU Make build (with
or without the UTF-8 resource) and Windows version that GNU Make is
running on (earlier than 1903 or not).

* README.git: Fix a typo.
* configure.ac: Search for windres and set WINDRES / HAVE_WINDRES.
* Makefile.am: Add manifest and resource files to EXTRA_DIST and
add a windres invocation to build them.
* build_w32.bat: Add support to build resource files.
* src/main.c (print_version): Add codepage info to Windows output.
* src/w32/utf8.manifest: Add a windres manifest file.
* src/w32/utf8.rc: Add a windres resource file.
* Basic.mk.template: Add support for building resource files.
* mk/Windows32.mk: Support windres resource files.
* .gitignore: Ignore TCC output directories.
2023-06-19 13:29:52 -04:00
Paul Smith
04f4c2b8d9 [SV 64124] Avoid stack overflows for large command lines
Modify areas dealing with large command lines to use the heap rather
than relying on alloca / stack space.

* src/main.c (main): Allocate potentially large buffers with xmalloc.
(decode_env_switches): Ditto.
* src/function.c (func_error): Replace alloca with xmalloc/free.
* tests/scripts/features/expand: Add a newline for readable diffs.
2023-06-19 13:27:50 -04:00
Paul Smith
347316fdf6 * po/LINGUAS: Add support for Georgian translation 2023-06-19 10:05:19 -04:00
Paul Smith
1a03888afa * NEWS: Set a prerelease version 2023-06-19 10:05:19 -04:00
Paul Smith
07fcee35f0 [SV 64815] Recipe lines cannot contain conditional statements
* NEWS: Mention this change.
* src/read.c (eval): Check for ignoring for any line even if not
in a rule context.
* tests/scripts/features/conditionals: Write new tests.
2023-05-22 23:36:13 -04:00
Paul Eggert
c85b71a396 make -p now uses consistent timestamp format
* NEWS: mention this.
* src/main.c (safer_ctime, time_now): Remove.
(print_data_base): Use file_timestamp_sprintf to format timestamps.
2023-05-14 18:26:35 -04:00
Paul Eggert
032f784601 make -p buffer overrun fix with outlandish current time
* src/main.c (safer_ctime): New function.
(print_data_base): Use it.
2023-05-14 18:26:35 -04:00
Paul Eggert
78e6a89b19 make -p uses same clock as rest of 'make'
Without this patch, the output of 'make -p' would generate output that
sometimes incorrectly implied that the clock jumped backwards.
* src/main.c (time_now): New function.
(print_data_base): Use it.
2023-05-14 18:26:35 -04:00
Paul Smith
1748e66414 [SV 63219] Support an "unload" function for loaded objects
If a loaded object defines a symbol <object>_gmk_unload, assume it's
a function and invoke it whenever the loaded object is unloaded.
Original implementation by Dmitry Goncharov <dgoncharov@users.sf.net>

* NEWS: Announce the change.
* doc/make.texi: Describe the behavior.
* src/gnumake.h: Add information to the comments.
* src/makeint.h (unload_all): Declare a new function.
* src/main.c (die): Invoke unload_all().
* src/load.c (unload_func_t): Declare a new type for unload.
(struct load_list): Remember the unload symbol if it exists.
(load_object): Move the parsing of the object name from load_file.
Check for the _gmk_unload symbol and if found, remember it.
(load_file): Allow load_object to do object filename parsing.
(unload_file): Remove the load_list entry when unloading the object.
(unload_all): Unload all the loaded objects.
* tests/scripts/features/loadapi: Test the unload function.
2023-05-14 18:26:35 -04:00
Paul Smith
8e0e6c678f Remove the "preview" status from the loaded object feature
Add an ABI version both to the header file and passed to the setup
function.  Unfortunately this itself is an ABI break and I couldn't
find a good way to avoid it.

* NEWS: Announce the ABI is not a preview and the incompatibility.
* doc/make.texi: Remove the preview warnings for object loading.
Document the new ABI version argument.
* src/gnumake.h (GMK_ABI_VERSION): Set the ABI version to 1.
Add comments documenting the format of the setup function.
* src/load.c (setup_func_t): Rename from load_func_t.
(load_file): Pass the ABI version to the setup function.
* tests/scripts/features/load: Rework the setup function.
* tests/scripts/features/loadapi: Ditto.
2023-05-07 16:51:06 -04:00
Paul Smith
3f28ec2f58 * src/read.c (eval): [SV 40942] Allow targets named "load"
Previously "load:" worked but "load :" failed.  Allow the latter as
well.  This doesn't fix all issues; "load foo :" is still treated
as a load operation for "foo" and ":".  Avoids SV 50413 as well.
* tests/scripts/features/load: Write tests.
2023-05-07 16:51:06 -04:00
Paul Smith
24a84f99bb * tests/test_driver.pl: Show info about failed tests
Remove working directories for skipped tests.
We use different directories per test so don't keep rmfiles.
2023-05-07 16:51:06 -04:00
Paul Smith
05c86bfcb2 * tests/scripts/features/comments: Add missing "1;" 2023-05-06 14:45:09 -04:00
Dmitry Goncharov
06c75a35b9 [SV 64124] Avoid use-after-free in expand_variable_buf()
When the expanded value of the variable in buf occupies more space
than available in variable_buffer, function variable_buffer_output
reallocates variable_buffer: return a pointer into the new memory,
not the old memory.

* src/expand.c (expand_variable_buf): Preserve the offset of buf and
return that offset into the (potentially reallocated) buffer.
* tests/scripts/features/expand: Add tests.
2023-04-30 09:41:02 -04:00
Dmitry Goncharov
ebe0a1c9f1 [SV 64115] Suppress warnings about undefined GNUMAKEFLAGS
* src/variable.c (defined_vars): Add GNUMAKEFLAGS to defined variables.
* tests/scripts/options/warn: Add a test.
2023-04-30 09:40:50 -04:00
Dmitry Goncharov
0880e5c86a [SV 64107] Disable builtins immediately on -R or -r
Disable builtin variables and rules immediately, when -R or -r is
added to MAKEFLAGS inside the makefile.

* src/main.c (disable_builtins): Add new function disable_builtins().
(main): Call disable_builtins().
(reset_makeflags): Call disable_builtins().
* tests/scripts/options/dash-r: Add tests.
* tests/scripts/variables/MAKEFLAGS: Update tests.
2023-04-30 09:40:50 -04:00
Paul Smith
0e06c75889 * tests/scripts/features/double_colon: Test parallel double-colon rules
Original test proposed by Dmitry Goncharov <dgoncharov@users.sf.net>
2023-04-30 09:40:50 -04:00
Dmitry Goncharov
5340a3d5d1 * src/remake.c (update_goal_chain): [SV 64016] Avoid double negation 2023-04-30 09:40:47 -04:00
Paul Smith
fec72ea308 * NEWS: Note the change to the tests suite 2023-04-23 11:35:02 -04:00
Paul Smith
6cf6311332 * src/warnings.c (decode_warn_actions): [SV 63990] Handle errors 2023-04-03 08:05:54 -04:00
Paul Smith
c4329fb953 Move local headers after system headers
Avoid compiler warnings on Windows by moving local headers after
system headers.

* src/job.c: Move all headers other than makeint.h.
* src/main.c: Ditto.
* src/read.c: Ditto.
2023-04-03 07:48:51 -04:00
Paul Smith
971b02d58e tests: Run each file in a separate directory
Avoid cross-contamination between test files by creating a new
working directory for each file, and setting it as the current
directory before starting the tests in that file.

Rename the test output as tNNN.{base,log,diff,mk} where NNN is
a test number starting with 001 for the first test.  It is
slightly more annoying to find diff files since you can't use
autocomplete directly but it is simpler to match things.

Detect the source directory as the location of the test_driver.pl
script, so remove the separate -srcdir option.

* Makefile.am: Remove hacks to create symlinks when building
out-of-tree, and remove -srcdir option from run_make_tests.
* tests/test_driver.pl: Locate $srcpath based on __FILE__, then
compute $toppath as its parent.  Set $scriptpath under $srcpath
and $workpath under the current directory.  Toss $*_filename
and modify get_logfile() etc. to use the suffix directly.  Add
a chdir() around the invocation of the test.
* tests/run_make_tests.pl: Throw out the -srcdir option and use
$srcpath set in test_driver.pl.  The #WORK# helper is no longer
useful so remove it.  Set #PWD# to the current working dir. Always
search the local directory and $srcpath for config-flags.pm.
Use $srcpath for finding the thelp.pl script.
* tests/scripts/features/vpath: Don't put things in work/ as it
is no longer a subdirectory.
* tests/scripts/features/vpathgpath: Ditto.
* tests/scripts/features/vpathplus: Ditto.
* tests/scripts/misc/general1: Ditto.
* tests/scripts/misc/general2: Ditto.
* tests/scripts/options/dash-k: Ditto.
* tests/scripts/options/symlinks: Use $testpath as the working
directory.
* tests/scripts/variables/GNUMAKEFLAGS: Use the test helper to
display env var values (grepping for GNUMAKEFLAGS finds extra things
now that it is our current working directory).
2023-04-02 17:32:09 -04:00
Paul Smith
fdd61fc068 * tests/scripts/targets/WAIT: Add whitespace to avoid W32 issues
On Windows systems, "X:" for any "X" is considered a drive letter
so add whitespace.
2023-04-02 17:30:27 -04:00
Dmitry Goncharov
80727d709c [SV 63856] Fix pruning of double-colon rules
Given this setup:

  $ cat Makefile
  A::; @echo A-1 && sleep 1 && echo A-1 done
  A::; @echo A-2 && sleep 1 && echo A-2 done
  A::; @echo A-3 && sleep 1 && echo A-3 done
  B::; @echo B-1 && sleep 1 && echo B-1 done
  B::; @echo B-2 && sleep 1 && echo B-2 done
  B::; @echo B-3 && sleep 1 && echo B-3 done

  $ make -j8 A .WAIT B

All recipes for A should be started sequentially and complete before
any recipe for B is started, then all recipes for B should be started
sequentially.  This wasn't happening because the double-colon target
was getting pruned too early.

* src/remake.c (update_file): Don't prune a target if it's a double
colon rule which is complete, but there are other recipes to run for
this target: we want those other recipes to be run first.
* tests/scripts/targets/WAIT: Test .WAIT with double colon rules.
2023-04-02 11:12:19 -04:00
Dmitry Goncharov
cd46baab90 [SV 63856] Implement .WAIT on the command line
* src/main.c (handle_non_switch_argument): Return 1 if arg is .WAIT.
(decode_switches): Set wait_here for a goal that follows .WAIT.
* src/remake.c (update_goal_chain): Honor wait_here for a command
line goal.  Don't allow double-colon targets to continue if .WAIT is
given for one of them.
* tests/scripts/targets/WAIT: Add .WAIT tests.
2023-04-02 11:12:11 -04:00
Paul Smith
54b3202f8d [SV 63981] Don't warn on explicit -j1
If -j1 is given explicitly on the command line don't warn about it.

* src/main.c (main): Skip the warning if -j1.
* tests/scripts/features/jobserver: Add a test for this behavior.
2023-04-02 10:29:37 -04:00
Paul Smith
5111087e12 * NEWS: Mention the new .WARNINGS variable 2023-04-02 10:29:19 -04:00
Paul Smith
0552b0abc8 * doc/make.texi: Clean up function and variable references
Avoid unnecessary extra remarks in the index and remove duplicates.
2023-04-02 10:02:18 -04:00
Paul Smith
c2792d6129 Adjust output strings to be aligned
Change error and fatal messages to start with lowercase and not
end with a period.  Note a few very common messages were left
as-is, just in case some other tools parse them.

Also modify the test known-good-output to satisfy the messages.
2023-04-02 10:02:18 -04:00
Paul Smith
a0d1e76d60 Add support for .WARNINGS special variable
Create a new special variable, .WARNINGS, to allow per-makefile
control over warnings.  The command line settings will override
this.

Move the handling of warning flags to a new file: src/warning.c.
Allow the decode to work with generic strings, and call it from
decode_switches().

* Makefile.am: Add new file src/warning.c.
* build_w32.bat: Ditto.
* builddos.bat: Ditto.
* po/POTFILES.in: Ditto.
* src/makeint.h: #define for the .WARNINGS variable name.
* src/warning.h: Add declarations for methods moved from main.c.
Rename the enum warning_state to warning_action.
* src/warning.c: New file.  Move all warning encode/decode here
from main.c.
* src/main.c: Move methods into warning.c and call those methods
instead.
(main): Set .WARNINGS as a special variable.
* src/job.c (construct_command_argv): Rename to warning_action.
* src/read.c (tilde_expand): Ditto.
* src/variable.c (set_special_var): Update warnings when the
.WARNINGS special variable is set.
* tests/scripts/options/warn: Check invalid warning options.
* tests/scripts/variables/WARNINGS: Add tests for the .WARNINGS
special variable.
2023-04-02 10:02:18 -04:00
Paul Smith
03ecd94488 Add new warnings invalid-var and invalid-ref
The "invalid-var" warning triggers if the makefile attempts to assign
a value to an invalid variable name (a name containing whitespace).
The "invalid-ref" warning triggers if the makefile attempts to
reference an invalid variable name.  Both new warnings have a default
action of "warn".

* NEWS: Add these new warnings.
* doc/make.1: Document them in the man page.
* doc/make.texi (Warnings): Document them in the user's manual.
* src/warning.h: Add enum values for the new warning types.
* src/main.c (initialize_warnings): Initialize the new warnings.
* src/variable.h (undefine_variable_in_set, undefine_variable_global):
Ask callers to provide a struct floc specifying where the variable
is undefined.
* src/read.c (do_undefine): Pass floc when undefining.
* src/variable.c (check_valid_name): If invalid-var is enabled, check
the variable name.
(define_variable_in_set): Call it.
(undefine_variable_in_set): Ditto.
(check_variable_reference): If invalid-ref is enabled, check the
variable reference.
(lookup_variable): Call it.
(lookup_variable_in_set): Ditto.
* tests/scripts/options/warn: Add tests for the new warning types.
2023-04-01 11:13:12 -04:00
Paul Smith
2611e1991f Introduce a --warn command line option
Replace the singleton --warn-undefined-variables with infrastructure
to manage multiple warnings: the --warn option can take an action
"ignore", "warn", or "error" (which will apply to all warnings), or
a specific warning type and an action for that type.  Multiple
options can be provided and are consolidated.

* NEWS: Announce the new option.
* doc/make.1: Document in the man page.
* doc/make.texi (Warnings): Document in the user's manual.
* Makefile.am: Add new header warning.h.
* src/warning.h: Define enum for actions and warning types, and
macros to test whether they are set.  Keep the default settings
separate so that we can correctly reconstruct MAKEFLAGS.
* src/makeint.h: Remove deprecated warn_undefined_variables_flag.
* src/main.c: Create global variables to hold warning settings.
(switches): Add a new switch for --warn.
(initialize_warnings): Set the default warning actions.
(main): Call initialize_warnings().
(encode_warning_state, decode_warning_state): Convert warning states
between strings and enums.
(encode_warning_name, decode_warning_name): Convert warning names
between strings and enums.
(decode_warn_flags): Convert a --warn option into enum values.  If
deprecated warn_undefined_variables_flag is set convert it to --warn.
(decode_switches): Don't remove duplicates of --warn since order
matters.  Call decode_warn_flags() to handle --warn.
(define_makeflags): Special-case handling of --warn options written
to MAKEFLAGS: write out the current settings.
* src/read.c (tilde_expand): Use new warning control macros.
* src/variable.c (warn_undefined): Ditto.
* src/job.c (construct_command_argv): Ditto.
* tests/scripts/options/warn: Rename from warn-undefined-variables
and add tests for --warn.
* tests/scripts/variables/MAKEFLAGS: Expect the new behavior.
2023-04-01 11:13:12 -04:00
Paul Smith
9db74434cd Clean up memory leak warnings from ASAN and Valgrind
* src/main.c (main): Add "sanitize" to .FEATURES if ASAN is enabled.
* src/expand.c (expand_variable_output): Remember "recursive" setting
in case it's changed by the expansion of the variable.
* src/file.c (rehash_file): If we drop a file from the global 'files'
hash, remember it in rehashed_files.  We can't free it because it's
still being referenced (callers will invoke check_renamed()) but
it will be a leak since it's no longer referenced by 'files'.
* src/remake.c (update_file_1): If we drop a dependency, remember it
in dropped_list.  We can't free it because it's still being referenced
by callers but it will be a leak since it's no longer referenced as
a prerequisite.
* tests/scripts/functions/guile: Don't run Guile tests when ASAN is
enabled.
* tests/scripts/functions/wildcard: Enabling ASAN causes glob(3) to
break!  Don't run this test.
* tests/scripts/features/exec: Valgrind's exec() doesn't support
scripts with no shbang.
* tests/scripts/jobserver: Valgrind fails if TMPDIR is set to an
invalid directory: skip those tests.
* tests/scripts/features/output-sync: Ditto.
* tests/scripts/features/temp_stdin: Ditto.
2023-04-01 11:13:12 -04:00
Paul Smith
23f70b0cb8 Create helper functions for pushing file contexts
* src/variable.h (install_file_context, restore_file_context): Add
declarations for new functions.
* src/variable.c (install_file_context, restore_file_context): Define
the new functions.
(lookup_variable_for_file): Call them.
* src/expand.c (recursively_expand_for_file): Ditto.
(allocated_expand_variable_for_file): Ditto.
(expand_string_for_file): Ditto.
2023-04-01 11:13:12 -04:00
Paul Smith
78c8c44326 Add functions to directly expand variables by name
Replace all locally-created "$("+varname+")" and similar constructs
with calls to these new functions.

* src/expand.c (expand_variable_output): Call expand_string_output()
on the expansion of a variable value.  Replaces reference_variable().
(expand_variable_buf): Like expand_variable_output() but return the
starting location of the result.
(allocated_expand_variable): Like expand_variable_buf() but return
an allocated string.
(expand_string_buf): Call expand_variable_output().
* src/variable.h: Declare the new functions.
* src/function.c (func_call): Call expand_variable_output() instead
of expand_string_buf().
* src/main.c (decode_env_switches): Call expand_variable() instead
of expand_string().
* src/remake.c (library_search): Call allocated_expand_variable()
instead of expand_string() plus xstrdup().
* src/vpath.c (build_vpath_lists): Expand VPATH and GPATH using
expand_variable() instead of expand_string().
* src/w32/subproc/sub_proc.c (process_begin): Use expand_variable()
to expand SHELL.  Also use alloc() in case the result is larger than
PATH_MAX.
2023-04-01 11:13:12 -04:00
Paul Smith
caf1d4c28f Clean up expand.c
Clarify the naming and documentation on functions in src/expand.c:
- variable_expand -> expand_string
- variable_expand_string -> expand_string_buf
- variable_expand_for_file -> expand_string_for_file
- allocated_variable_expand -> allocated_expand_string
- allocated_variable_expand_for_file ->
  allocated_expand_string_for_file
Change all callers to use the new names.

* src/variable.h: Rename the functions and macros.
* src/expand.c: Ditto.
* src/file.c: Use the new function names.
* src/function.c: Ditto.
* src/implicit.c: Ditto.
* src/job.c: Ditto.
* src/loadapi.c: Ditto.
* src/main.c: Ditto.
* src/read.c: Ditto.
* src/remake.c: Ditto.
* src/variable.c: Ditto.
* src/vpath.c: Ditto.
* src/w32/subproc/sub_proc.c: Ditto.
2023-03-26 16:48:48 -04:00
Paul Smith
f99d083418 * src/expand.c (swap_variable_buffer): Swap two variable buffers
Return the current buffer instead of freeing it.
(variable_append): Use install/swap to handle variable buffers.
(allocated_variable_expand_for_file): Ditto.
* src/variable.c (shell_result): Ditto.
* src/variable.h: Declare the new function.
2023-03-26 09:24:49 -04:00
Paul Smith
a367c0640f Ensure variable_buffer is always nul-terminated
* src/expand.c (variable_buffer_output): Allocate an extra byte and
set it to nul.  For safety, add assert() on PTR.
(variable_expand_string): Don't call variable_buffer_output just to
add a nul byte.
(allocated_variable_append): Ditto.
2023-03-26 09:24:06 -04:00
Paul Smith
3088e3e698 [SV 63867] Don't use --sort to generate error report tar files
Older versions of GNU tar parse the TAR_OPTIONS variable, but do not
accept the --sort option: remove it before creating the error report
tar files.  Note we still require a modern GNU tar to create release
tar files.  Reported by Dmitry Goncharov <dgoncharov@users.sf.net>

* Makefile.am (check-regression): Remove --sort from TAR_OPTIONS
2023-03-25 16:02:59 -04:00
Paul Smith
bf7f690202 Directly handle $\ line endings
Previously we used the fact that this line ending expanded to "$ "
which would then expand to the empty string.  This has problems if
you enable warnings for undefined variables, so directly implement
this special (but documented) trick in the GNU Make parser.

As a side-effect this also removes all previous whitespace when
in GNU Make mode (not in POSIX mode) just as it would without "$".

* src/misc.c (collapse_continuations): Check for "$\" and remove it.
* tests/scripts/variables/flavors: Add regression tests including
with previous whitespace, and escaped/unescaped "$"
2023-02-26 17:30:15 -05:00
Paul Smith
5d1fe2b16d * src/main.c (define_makefiles): Simplify by using variable_buffer
Toss the previous implementation which first computed a locally
allocated list of options, then used alloca() to create a buffer
of the right size and populate it.  Instead, use variable_buffer
to append to the string directly.  First add all single-letter
options without arguments, then add options with arguments.
2023-02-26 17:15:56 -05:00
Paul Smith
8285852e55 Clean up some preprocessor operations 2023-01-16 13:01:09 -05:00
Paul Smith
9b9f3351d1 Use MK_OS_OS2 macro instead of __EMX__
* src/makeint.h: Set MK_OS_OS2 to 1 if __EMX__ is set.
* src/*: Convert #if refs to __EMX__, to use MK_OS_OS2.
2023-01-16 00:24:13 -05:00
Paul Smith
6f3e9e9b84 Use MK_OS_DOS macro instead of __MSDOS__
* src/configh.dos: Set MK_OS_DOS to 1
* src/*: Convert #if refs to __MSDOS__, to use MK_OS_DOS.
* gl/lib/*: Ditto.
2023-01-16 00:03:13 -05:00
Paul Smith
6128c3e266 Rename WINDOWS32 macro to MK_OS_W32
* configure.ac: Set MK_OS_W32 to 1 if we're on Windows32.
* src/config.h.W32: Ditto.
* mk/Windows32.mk: Ditto.
* src/makeint.h: Convert #if refs to WINDOWS32, to use MK_OS_W32.
* src/*: Ditto.
* src/w32/*: Ditto.
* gl/lib/*: Ditto.
2023-01-15 18:27:13 -05:00
Paul Smith
ceb52b5d1b Rename VMS macro to MK_OS_VMS
* src/makeint.h: Set MK_OS_VMS to 1 if we're on VMS.
* src/*: Convert all #if references to VMS, to use MK_OS_VMS.
* gl/lib/*: Ditto.
2023-01-15 18:04:36 -05:00
Paul Smith
d4692df20d Remove support for AmigaOS
There is a lot of specialized code for supporting AmigaOS and it has
not been maintained for a number of years.  It's highly unlikely that
the latest versions even compile properly on AmigaOS anymore.  After
requesting that someone step forward to own the maintenance of the
port in the GNU Make 4.4 release and getting no takers, I removed it.

* NEWS: Announce the removal.
* README.in: Remove README.Amiga reference.
* README.Amiga: Remove unused file.
* SCOPTIONS: Ditto.
* src/amiga.c: Ditto.
* src/amiga.h: Ditto.
* src/config.ami: Ditto.
* mk/Amiga.mk: Ditto.
* Makefile.am: Remove references to deleted files.
* Basic.mk.template: Ditto.
* maintMakefile: Ditto.
* src/commands.c: Remove ifdef'd Amiga code.
* src/default.c: Ditto.
* src/dir.c: Ditto.
* src/file.c: Ditto.
* src/function.c: Ditto.
* src/job.c: Ditto.
* src/job.h: Ditto.
* src/main.c: Ditto.
* src/os.h: Ditto.
* src/read.c: Ditto.
* src/remake.c: Ditto.
2023-01-15 17:32:15 -05:00
Paul Smith
e6bd61d949 * README.git: Clarify some release steps
* README.in: Update some info and remove some obsolete notes.
2023-02-26 15:52:25 -05:00
Paul Smith
fcefae5ec9 * NEWS: Update for the next release
* configure.ac: Set the version for the next release.
2023-02-26 15:40:18 -05:00
Paul Smith
d66a65ad5a GNU Make release 4.4.1
* NEWS: Set the release number and date.
* configure.ac: Update the version.
* README.git: Remind to update doc/make.1.
* doc/make.1: Update the date.  Fix some "GNU Make" references.
* doc/make.texi: Update the edition.
2023-02-26 13:46:22 -05:00
Paul Smith
8093e2eee3 * tests/scripts/options/dash-l: Simplify the test via the helper
* tests/thelp.pl: Add "exist" and "noexist" operators.
2023-02-26 13:46:02 -05:00
Paul Smith
74dab224b3 * README.W32: Add Windows 11
* build_w32.bat: Ditto.
2023-02-21 20:54:48 -05:00
Paul Smith
8b8cc3a825 Use a recursive environment if any command needs it
We only create one target environment for all commands in a recipe.
Ensure it's set for recursive make if ANY command is recursive, not
just the first one.

* src/job.c (start_job_command): Check for any recursive command.
* tests/scripts/features/jobserver: Test recursion on second line.
2023-02-21 20:53:48 -05:00
Dmitry Goncharov
9b6fedef1c * src/main.c (main): Install suffix rules near pattern updates 2023-02-21 00:04:13 -05:00
Paul Smith
8ddb628927 * Makefile.am: Add mkconfig.h to the test error file 2023-02-20 23:29:26 -05:00
Dmitry Goncharov
e9dd614d73 [SV 63821] Don't set up default suffix rules if makefile sets -r
When built-in rules are disabled by adding -r to MAKEFLAGS in the
makefile, don't add suffix rules at all so that if suffixes are
added back via .SUFFIXES, the rules are still not there.

* src/main.c (main): Set default suffix rules after parsing makefiles.
* src/default.c (install_default_suffix_rules): Install a default
suffix rule only if there is no user defined rule.
* tests/scripts/features/suffixrules: Add tests.
2023-02-20 15:17:24 -05:00
Paul Smith
f5dc17ac2d * tests/scripts/misc/general4: Only test empty PATH on UNIX 2023-02-20 11:11:59 -05:00
Paul Smith
ac159491da * gl/modules/make-glob: Avoid glibc glob if bug #866 is present 2023-02-19 17:43:12 -05:00
Paul Smith
4436655568 * tests/scripts/features/include [AIX]: Set explicit timestamps 2023-02-19 15:35:22 -05:00
Paul Smith
549fc56102 * tests/scripts/features/archives: Set CC properly 2023-02-19 14:49:56 -05:00
Paul Smith
37e0010743 Prerelease GNU Make 4.4.0.91
* NEWS: Update the date.
* configure.ac: Change the release.
2023-02-19 09:53:26 -05:00
Paul Smith
536c3e2b37 * src/makeint.h [CYGWIN]: Use pipe mode for the jobserver 2023-02-19 08:52:02 -05:00
Paul Smith
4c9b922560 Don't block for child exit if other commands have completed
Running regression tests on a single CPU system shows that if a child
exits while we're checking prerequisites we might not notice it, and
then we might block waiting for the next child to exit before we try
to do more work even though we could.

* src/remake.c (update_goal_chain): Remember the command_count before
we start checking prerequisites and if it is different when we restart
at the top of the goal chain then don't block.
2023-02-19 01:27:22 -05:00
Paul Smith
2449ef3c88 Clean up depth handling in debug output
The indentation shown in debug output was misleading.  Increment the
depth when we are working on a prerequisite, not for the current
target.

* src/remake.c (check_dep): Increment depth only on recursion.
(update_file_1): Ditto.  Don't show "Finished..." if prereqs are
still running.
* src/implicit.c (pattern_search): Increment depth for the entire
search.
* tests/scripts/features/output-sync: Support debug output when run
by hand.
2023-02-19 01:25:57 -05:00
Paul Smith
fbf8c940e5 * src/makeint.h (WIN32_LEAN_AND_MEAN) [Windows]: Don't redefine.
Suggested for tcc builds by Christian Jullien <eligis@orange.fr>.
2023-02-19 01:02:16 -05:00
KO Myung-Hun
62194015fa * src/misc.c (ttyname) [OS/2]: Add an implementation for OS/2 kLIBC 2023-02-19 01:02:16 -05:00
Paul Smith
c85f68c4e9 Allow jobserver style to be forced to "pipe"
Some systems that support mkfifo() don't support the usage that GNU
make wants.  Provide a way to force using "pipe" jobserver mode even
when mkfifo() is available.

* src/makeint.h (MK_OS_HURD): Define if we're on Hurd.
(JOBSERVER_USE_FIFO): Define if we have mkfifo() and we're NOT on
Hurd.
* src/main.c (main): Test JOBSERVER_USE_FIFO not HAVE_MKFIFO.
* src/posixos.c (jobserver_setup): Ditto.
* maintMakefile: Create a config check test for forcing "pipe" mode.
* tests/run_make_tests.pl: Show discovered FEATURES in verbose mode.
2023-02-19 01:02:16 -05:00
Paul Smith
ffa28f3914 [SV 63668] Use autoconf to detect the default C++ compiler
* configure.ac: Add AC_PROG_CXX to search for a C++ compiler.
(MAKE_CXX): Add the discovered compiler to config.h.
* src/default.c (default_variables): Use MAKE_CXX as the C++ compiler.
2023-02-05 10:22:13 -05:00
Paul Smith
8f03e69af0 * doc/make.texi: Fix typo (reported by <mao492479407@163.com>) 2023-02-05 09:42:49 -05:00
Paul Smith
e819fc2022 * tests/scripts/variables/MAKEFLAGS: Fix some Perl warnings 2023-02-04 13:12:32 -05:00
Dmitry Goncharov
f21cd822a3 * doc/make.texi: [SV 63689] Fix typos in examples 2023-01-28 13:09:36 -05:00
Paul Smith
2f336608d8 * src/job.c: Switch from bit operators to flags macros
* src/remake.c: Ditto.
2023-01-28 13:05:08 -05:00
Paul Smith
faedfdb0af [SV 63667] In .POSIX, use shell flags -c when ignoring errors
* src/variable.c (lookup_variable_for_file): New function to retrieve
a variable assignment in a file context.
* src/variable.h (lookup_variable_for_file): Declare it.
* src/job.c (construct_command_argv): Look up .SHELLFLAGS.  If .POSIX
is set and we're using the default value, choose -c if we're ignoring
errors else choose -ec.
(construct_command_argv_internal): Ditto.
* tests/scripts/targets/POSIX: Add tests.
2023-01-28 13:04:47 -05:00
Dmitry Goncharov
9709d273b2 * tests/scripts/features/archives: [SV 63688] Quote cmd line vars 2023-01-28 09:46:23 -05:00
Paul Smith
eb0bd1aaec * README.in: Mention README.z/OS 2023-01-28 09:28:18 -05:00
Paul Smith
d2bf740e77 * tests/test_driver.pl: Convert z/OS answers for regex output
Allow z/OS customizations to apply to regex output matching.
* tests/scripts/features/output-sync: Use a regex for Terminated.
* tests/scripts/features/temp_stdin: Ditto.
2023-01-15 16:35:57 -05:00
Paul Smith
a8890796a4 * tests/scripts/features/archives: Use the configured compiler for CC 2023-01-15 16:35:57 -05:00
Paul Smith
be6bb0fd68 * configure.ac: Delay setting HAVE_GUILE until we're sure 2023-01-15 10:27:34 -05:00
Paul Smith
db351fe85b Prerelease GNU Make 4.4.0.90
* NEWS: Update the date.
* README.git: Fix a typo.
* maintMakefile (check-alt-config): Report success.
(upload-*): Use the gnulib gnupload script for uploads.
2023-01-14 17:07:04 -05:00
Paul Smith
8a0d7fd4ef * tests/scripts/features/reinvoke: Warn about closing STDIN.
* tests/scripts/features/temp_stdin: Ditto.
* tests/scripts/options/dash-f: Ditto.
2023-01-11 20:35:11 -05:00
Eli Zaretskii
f51fc130cc [SV 63638] Fix processing PATH on MS-Windows
* src/variable.c (sync_Path_environment): Pass only the value of
PATH to convert_Path_to_windows32, excluding the "PATH=" part.
2023-01-11 15:44:56 +02:00
Paul Smith
b99b6cdf3c Update support for OS/2
Patches provided by KO Myung-Hun <komh78@gmail.com>

* NEWS: Add a note.
* AUTHORS: Add a new author.
* README.OS2: Updates to build instructions.
* src/dir.c (dir_contents_file_exists_p): Use a stack copy when
modifying a const string.
* src/job.c (construct_command_argv_internal): Ditto.
Reuse variables rather than re-defining them.
(exec_command): Cast a const string (we don't change it anyway).
* src/getopt.c (_getopt_initialize): Reference unused variables.
(_getopt_internal): Add block braces to quiet the compiler.
* src/main.c (main): Cast argument to child_execute_job().
* src/posixos.c (set_blocking): Reference unused variables.
* src/remake.c (f_mtime): Delete useless code.
2023-01-08 18:44:25 -05:00
Paul Smith
36f955b0e8 [SV 17448] Ignore whitespace around $(file ...) names
The other issues related to whitespace reported in this bug are
not addressed by this change.

* src/functions.c (func_file): Strip whitespace from the start and
end of the filename provided to the $(file ...) function.
* tests/scripts/functions/file: Add tests for this.
* tests/test_driver.pl: Use 3-arg version of open().
2023-01-08 18:06:54 -05:00
Paul Smith
a275f4e9ab [SV 61218] Ensure MAKEFLAGS is expanded even with -e
If -e was given we weren't expanding MAKEFLAGS before passing it
through the environment to jobs: we don't expand variables we
receive from the environment and when -e is given we set the
origin of MAKEFLAGS to "environment override".  Check for MAKEFLAGS
specifically, which seems like a hack but I don't have a better
idea offhand.

* src/main.c (main): Drive-by: use o_default for MAKEOVERRIDES.
* src/variable.c (target_environment): Always expand MAKEFLAGS
regardless of the origin type.
* tests/scripts/options/dash-e: Create a test.
2023-01-08 16:40:55 -05:00
Paul Smith
11444fb001 [SV 62654] Support GNU Make on z/OS
Original patches provided by Igor Todorovski <itodorov@ca.ibm.com>
Reworked by Paul Smith <psmith@gnu.org>.
Thanks to IBM for providing a test system.

* NEWS: Announce support.
* AUTHORS: Ditto.
* README.zOS: Provide details on building GNU Make on z/OS.
* build.sh (get_mk_var): z/OS sh has a strange bug which causes it to
generate extra lines of output: rework the function to print output
as we compute it instead of collecting it into a variable, which
works around this bug.
* src/makeint.h: Declare MK_OS_ZOS if we're building for z/OS.
* src/arscan.c: Don't include <ar.h> on z/OS.
* src/job.c: We can't change environ in ASCII mode on z/OS.
* src/main.c: Ditto.  Also we can't use pselect() on z/OS.
* src/posixos.c: pselect() seems to hang on z/OS: don't use it.
* tests/run_make_tests.pl: Handle different exit codes on z/OS.
* tests/test_driver.pl: Preserve some special z/OS env.vars.
Add special checks to output comparisons when on z/OS.
* tests/scripts/features/archives: Don't validate names.  Don't
try to compile empty files as IBM compilers complain.
* tests/scripts/features/shell_assignment: Fix octal value of #.
* tests/scripts/features/temp_stdin: Don't print "term".
* tests/scripts/functions/shell: Handle shell exit codes.
* tests/scripts/targets/ONESHELL: Ditto.
* tests/scripts/targets/POSIX: sh -x prints differently.
* tests/scripts/variables/SHELL: Ditto.
2023-01-08 10:45:38 -05:00
Paul Smith
0de7a0d3bf Create src/mkcustom.h which is included by config.h
Put declarations for missing functions which we create in src/misc.c
into a file which is included by config.h via AH_BOTTOM().  This
ensures those prototypes are available, even in files added to
lib/... from gnulib.

* src/mkcustom.h: Add a new file with function declarations.
* configure.ac: Include src/mkcustom.h in config.h with AH_BOTTOM()
* Makefile.am: Add the header to the SRCS list.
* src/makeint.h: Remove content that we added to src/mkcustom.h.
* src/config.ami: Add #include "mkcustom.h" to specialized config.h.
* src/config.h-vms: Ditto.
* src/config.h.W32: Ditto.
* src/configh.dos: Ditto.
2023-01-08 10:45:24 -05:00
Paul Smith
1656cd051c Include <strings.h> globally
Various code uses str{,n}casecmp() so include <strings.h>, if it
exists, everywhere.

* configure.ac: Check for <strings.h> explicitly.
* src/makeint.h: Include it if HAVE_STRINGS_H, for str{,n}casecmp().
* src/job.c: Remove include of <strings.h>.
* src/main.c: Ditto.
2023-01-08 10:24:09 -05:00
Paul Smith
31a1337c23 * gl/lib/glob.c: Don't try to support _LIBC, don't use __stat() 2023-01-07 22:02:06 -05:00
Paul Smith
5ae02ff8c1 [SV 63609] Avoid buffer overrun in --warn-undefined-variables
Reported by Dmitry Goncharov <dgoncharov@users.sf.net>

* src/variable.c (struct defined_vars): Create a struct that holds the
name and length of each variable name.
(warn_undefined): Check the lengths before comparing the contents.
* tests/scripts/options/warn-undefined-variables: Add a test.
2023-01-03 02:14:24 -05:00
Paul Smith
1ceeb8c64b [SV 14927] Allow parallel builds for archives
Compare the timestamp of the object file (if it exists) with the
archived object and if the object file is newer, ensure it's updated
in the archive.

* NEWS: Announce the new capability.
* doc/make.texi (Dangers When Using Archives): Explain how to enable
parallel builds with archives.
* src/remake.c (f_mtime): For archive element files check the mod
time of the object file (if it exists) against the archive object
(if it exists).
* tests/scripts/features/archives: Add tests for this capability.
2023-01-03 01:57:35 -05:00
Paul Smith
8791d2b38e [SV 61463] Don't export inherited private variables
If a parent target has an exported variable that is private, don't
export it in child targets.

* NEWS: Mention this change.
* src/variable.c (target_environment): Ignore private inherited
variables.
* tests/thelp.pl: Add a new "env" operation to show env.var. values.
* tests/scripts/variables/private: Verify this new behavior.
2023-01-02 23:02:33 -05:00
Paul Smith
f91b8bbb34 Update ancient glob/fnmatch implementations
I looked again at trying to use the latest gnulib implemenentations
of GNU glob and fnmatch, and the effort required to extract them
from gnulib and make them portable to systems which don't support
configure is simply far too daunting for me.  However it's clear
that the previous implementations are growing too long on the tooth
to continue to be used without some maintenance, so perform some
upkeep on them.

- Remove support for pre-ANSI function definitions.
- Remove the obsolete "register" keyword.
- Assume standard ISO C90/C99 header file support.
- Assume standard ISO C "void" and "const" support.
- Avoid symbols prefixed with "__" as they're reserved.

* maintMakefile: Add a rule to verify lib has the latest content.
* src/dir.c: Use void* not __ptr_t which was removed.
* gl/lib/glob.c: See above.
* gl/lib/fnmatch.in.h: See above.
* gl/lib/glob.in.h: See above.
* gl/lib/fnmatch.c: See above.  Remove __strchrnul(): it is not
checked anywhere and is only used in one place anyway.
2023-01-02 22:53:05 -05:00
Paul Smith
8dc66b6c31 * doc/make.texi (Special Targets): Fix minor typo
Reported by Andrey Melnikov <vafilor@gmail.com>.
2023-01-02 00:13:28 -05:00
Paul Smith
ccbaf3861d Don't free uninitialized hash_table
* src/dir.c (clear_directory_contents): We use ht_vec to mark when
we have initialized the hash_table: don't free if it's NULL.
(everywhere): Use NULL instead of 0 when working with pointers.
2023-01-01 17:05:12 -05:00
Paul Smith
c4fbfe8b5e * maintMakefile: Add missing quote 2023-01-01 17:05:12 -05:00
Paul Smith
e7ce3a655e Convert references from "GNU make" to "GNU Make" 2023-01-01 17:05:12 -05:00
Paul Smith
c580ebae8d Update to the latest gnulib stable branch
* bootstrap.conf: Request the latest gnulib stable branch.
* README.git: Recommend the argument form of autogen/autopull.
* bootstrap: Import the latest version of bootstrap.
* bootstrap-funclib.sh: Ditto.
* autogen.sh: Ditto.
* autopull.sh: Ditto.
2023-01-01 17:05:12 -05:00
Paul Smith
56d2978141 Update the copyright year on all files 2023-01-01 10:06:01 -05:00
Paul Smith
c91b269f66 Apply spelling fixes discovered by Codespell
* maintMakefile: Apply spelling fixes.
* src/file.c: Ditto.
* src/misc.c: Ditto.
* src/remake.c: Ditto.
* src/vmsjobs.c: Ditto.
* src/w32/pathstuff.c: Ditto.
* tests/test_driver.pl: Ditto.
* tests/run_make_tests.com: Ditto
* tests/scripts/features/implicit_search: Ditto
* tests/scripts/features/output-sync: Ditto
* tests/scripts/features/patternrules: Ditto
* tests/scripts/features/se_explicit: Ditto
* tests/scripts/features/statipattrules: Ditto
* tests/scripts/functions/foreach: Ditto
* tests/scripts/variables/MAKEFLAGS: Ditto
2022-12-31 13:21:09 -05:00
Paul Smith
29f453739f Avoid using false(1) in regression tests
The POSIX standard only requires false(1) to return a "non-zero" exit
code; almost all systems return 1 but some (Solaris!!!) return 255 or
possibly even other values.  Use our helper "fail" instead.

* tests/thelp.pl: Have the "fail" command obey -q.
* tests/scripts/features/parallelism: Helper -q no longer prints fail.
* tests/scripts/targets/POSIX: Replace false with #HELPER# -q fail 1.
* tests/scripts/variables/MAKEFLAGS: Ditto.
* tests/scripts/variables/SHELL: Ditto.
2022-12-31 10:51:24 -05:00
Paul Smith
937e9aa32d Make bootstrap.bat more portable
Using backslashes in a sed command line is tricky as different programs
use them differently as escape sequences.  Eli Zaretskii points out
that Windows "echo" doesn't do any processing, so rework all our sed
invocations to use script files created by echo.

* bootstrap.bat: Use echo to create sed script files instead of -e.
* Basic.mk.template: Fix typo in the comments.
* .gitignore: Ignore any .sed scripts.
2022-12-26 13:10:26 -05:00
Paul Smith
8e9c7db1e1 * NEWS: Add a section for the next release
Add a note for the MAKEFLAGS enhancements.
2022-12-24 15:48:48 -05:00
Paul Smith
15dfad96d7 [SV 63439, SV 63452] Don't warn on undefined internal variables
Don't generate undefined variable warnings for variables that are
internal / special to make and where the empty string is valid.
Rather than defining them to empty, which could introduce unwanted
behavior, keep a list of variable names which we should never warn
about.

* src/variable.h (warn_undefined): Convert the macro to a function.
* src/variable.c (defined_vars): Always "defined" variable names.
(warn_undefined): Implement as a function and check against the
defined_vars before generating a warning.
* src/read.c (read_all_makefiles): No need to reset warning flag.
* src/vpath.c (build_vpath_lists): Ditto.
* tests/scripts/options/warn-undefined-variables: Expand all the
pre-defined variables to ensure warnings are not generated.
2022-12-24 10:52:49 -05:00
Paul Smith
76d2e5d98d [SV 63552] Change directories before constructing include paths
* src/makeint.h (reset_makeflags): New function to handle changing
MAKEFLAGS from within makefiles.  Remove decode_env_switches().
* src/variable.c (set_special_var): Call reset_makeflags() instead
of various internal methods.
* src/main.c (decode_env_switches): Only internal now so make static.
(decode_switches): Don't invoke construct_include_path() yet.
(reset_makeflags): Decode env switches and construct include paths.
(main): Construct include paths after we process -C options.
* tests/scripts/options/dash-C: Rewrite to use new test constructs.
Add a test using both -C and -I together.
Add a test for multiple -C options.
2022-12-24 10:52:43 -05:00
Paul Smith
a581146562 tests [WINDOWS32]: Support Strawberry Perl on Windows
Strawberry Perl has some different behaviors from ActiveState Perl
which impact the test suite:

- Avoid Perl's chomp() as it may not remove CRs; chomp() may remove
  only the final NL but not the CR in a CRNL line ending.
- Strawberry Perl doesn't support ActiveState's system(1, ...) form.
- Strawberry Perl (or msys?) does something weird with "/tmp" when
  provided to exec(), replacing it with the user's %TEMP%.
- Strawberry Perl uses msys paths like /c/foo instead of C:\foo.

* tests/test_driver.pl (get_osname): Strawberry Perl uses 'msys' as
its $^O so if we see that use a port of 'W32'.
(_run_with_timeout): Strawberry Perl doesn't support the special
system(1, ...) form of system() so use POSIX standard fork/exec.
(compare_answer): Paths generated by Strawberry Perl use msys path
format (e.g., /c/foo instead of C:\foo); check for those differences
and compare RE against both the unmodified and modified log.
* tests/run_make_tests.pl (set_defaults): Switch from chomp to s///
to remove CRNL and NL line endings.
* tests/scripts/features/errors: Executing directories on Strawberry
will give an error; translate it to Windows error output format.
* tests/scripts/features/output-sync: Ditto.
* tests/scripts/features/temp_stdin: Ditto.
* tests/scripts/functions/realpath: Ditto.
* tests/scripts/options/dash-I: Ditto.
* tests/scripts/variables/INCLUDE_DIRS: Ditto.
* tests/scripts/misc/close_stdout: /dev/full is reported as existing
on Strawberry Perl, but it doesn't do anything.  Skip the test.
* tests/scripts/variables/MAKEFLAGS: When an argument containing
/tmp is passed to a program via exec(), something replaces it with
the expansion of the %TEMP% variable.  Instead of using /tmp create
a local directory to use.
2022-12-20 02:14:18 -05:00
Paul Smith
b2c7446023 * tests/test_driver.pl: Remember if something failed and report it 2022-12-20 02:07:28 -05:00
Paul Smith
89427039c3 [WINDOWS32] Remove CRNL from FormatMessage() result string
Sometimes the error message is expected to contain a newline, other
times it is not.  Also the result of FormatMessage() sometimes ends
in CRNL already: when printed via fprintf() the final newline is
converted to CRNL, giving an output of CRCRNL which causes tests
to fail to match.  Remove any CR/NL chars from the result string.

* src/job.c (reap_children): Add \n to the error message fprintf.
(exec_command): Ditto.
* src/w32/subproc/w32err.c (map_windows32_error_to_string): Remove
any trailing CR or NL from the string before returning.
2022-12-19 00:20:06 -05:00
Dmitry Goncharov
7d8756a4a3 [SV 63537] Document and test flippable switches
* doc/make.texi (Options/Recursion): Clarify that MAKEFLAGS values
from the environment have precedence over those set in the makefile.
* tests/scripts/variables/MAKEFLAGS: Check boolean switches -k/-S,
-w/--no-print-directory and -s/--no-silent as follows:
1. A switch can be enabled or disabled on the command line.
2. A switch can be enabled or disabled in env.
3. A switch can be enabled or disabled in makefile.
4. Command line beats env and makefile.
5. Env beats makefile.
6. MAKEFLAGS contains each specified switch at parse and build time.
7. If switches are specified in multiple origins, MAKEFLAGS contains
   the winning switch at parse and build time.
8. MAKEFLAGS does not contain the losing switch.
Also test that --debug settings from different origins are combined
together into one option.
2022-12-18 20:06:38 -05:00
Dmitry Goncharov
8e805c7ba6 [SV 63537] Pass enabled-by-default switches to submake
Certain switches, such as -S or --no-silent, turn on behavior that is
enabled by default.  When a switch is specified via the command line,
makefile, or env, ensure the switch is added to MAKEFLAGS.

* src/main.c (struct command_switch): Add bit "specified".
(switches): Initialize command_switch->specified.
(decode_switches): Set command_switch->specified.
(define_makeflags): Check command_switch->specified.
2022-12-18 20:06:38 -05:00
Dmitry Goncharov
132528b266 [SV 63537] Remember the origin of command line options
Certain options can be flipped on and off: -k/-S, -s/--no-silent, and
-w/--no-print-directory.  Ensure they behave as follows:
 1. A switch can be enabled or disabled on the command line.
 2. A switch can be enabled or disabled in env.
 3. A switch can be enabled or disabled in makefile.
 4. Command line beats env and makefile.
 5. Env beats makefile.

* src/main.c: Add variables to hold the origin of relevant options.
(struct command_switch): Add origin field.
(switches): Set a pointer to hold the origin of relevant options.
(decode_switches): For any switch that can be specified in makefile or
env, honor the switch only if cs->origin is not set or the specified
origin beats cs->origin.  Set cs->origin when relevant.
2022-12-18 20:06:38 -05:00
Dmitry Goncharov
8f9e7722ff [SV 63537] Fix setting -w in makefiles
* src/makeint.h: Replace print_directory flag with should_print_dir().
* src/main.c (main): Remove print_directory flag and related code.
(should_print_dir): Create.
* src/output.c (output_dump): Use should_print_dir().
(output_start): Ditto.
2022-12-18 20:06:38 -05:00
Dmitry Goncharov
95c2db7b8d [SV 63484] Force included makefiles to be explicit
Ensure included makefiles are not treated as intermediate, even if
they are created by an implicit rule.
Reported by Patrick Oppenlander <patrick.oppenlander@gmail.com>.

* src/read.c (eval_makefile): Mark makefiles as explicit.
* tests/scripts/features/include: Add a test.
2022-12-18 20:06:38 -05:00
Paul Smith
5d1b757517 [SV 63516] [DOS] Support include files with drivespecs
* src/makeint.h (HAVE_DRIVESPEC): Create a macro to check.
* src/main.c (.FEATURES): Add "dospaths" as a feature.
* src/read.c (eval_makefile) [DOS]: If the included makefile name
starts with a drivespec, don't search the include directories.
* doc/make.texi (Include): Document this behavior.
* tests/scripts/features/include: Add a test.
2022-12-18 20:06:38 -05:00
Paul Smith
c0023150f1 * src/job.c (new_job): [SV 63510] Trace phony prerequisite rebuilds 2022-12-18 14:44:17 -05:00
Paul Smith
a89eef87e6 * configure.ac: Update for a new release
* README.git: Add some packages needed for building from Git.
* AUTHORS: Updates.
2022-12-18 14:44:17 -05:00
Dmitry Goncharov
6164608900 [SV 63417] Ensure global .NOTINTERMEDIATE disables all intermediates
Fix .NOTINTERMEDIATE without prerequisites to disable intermediate
status for all targets.

* src/makeint.h: Declare extern no_intermediates.
* src/main.c: Add global definition of no_intermediates.
* src/file.c: Remove static no_intermediates to use global variable.
(remove_intermediates): Check no_intermediates.
* src/implicit.c (pattern_search): For a file found by implicit search
set file->notintermediate if no_intermediates is set.
* src/remake.c (update_file_1): Don't set file->secondary for a
pre-existing file if no_intermediates is set.  The check for
no_intermediates here is redundant, but won't hurt: keep it in case
things change so that it matters.
* tests/scripts/targets/NOTINTERMEDIATE: Fix a test.
2022-11-28 10:50:55 -05:00
Paul Smith
a99183ed2b * doc/make.texi: Use $(firstword) rather than $(word 1,) 2022-11-28 10:50:55 -05:00
Dmitry Goncharov
dc2d963989 [SV 63347] Always add command line variable assignments to MAKEFLAGS
This commit introduces two visible changes:
1. Keep command line variable assignments in MAKEFLAGS at all times,
   even while parsing makefiles.
2. Define makeflags immediately when a makefile modifies MAKEFLAGS.

The new MAKEFLAGS and MAKEOVERRIDES initialization procedure:
1. decode_switches (argc, argv, o_command) is called to parse command
   line variable assignments.
2. Command line variable assignments go through quote_for_env.
   Initialize -*-command-variables-*- to the quoted values.
3. MAKEOVERRIDES is initialized to refer to -*-command-variables-*-
   with origin o_env to keep the definitions in the database intact.
4. define_makeflags() is called which adds MAKEOVERRIDES to MAKEFLAGS.
5. Makefiles are parsed.  If a makefile modifies MAKEFLAGS, the new
   value of MAKEFLAGS is defined right away.
6. Env switches are decoded again as o_env.  The definitions set by
   decode_switches at step 1 stay intact, as o_command beats o_env.

We must preserve the original intact definitions in order to detect
failure cases; for example:
  $ cat makefile
  all:; $(hello)
  $ make hello='$(world'
  makefile:1: *** unterminated variable reference.  Stop.

* src/makeint.h: Declare enum variable_origin, struct variable and
define_makeflags().  Add parameter origin to decode_env_switches().
* src/main.c (define_makeflags): Remove "all". If a variable is
assigned on the command line then append MAKEOVERRIDES to MAKEFLAGS.
(decode_env_switches): Replace parameter env with origin.
(decode_switches): Replace parameter env with origin.
Treat origin == o_command as env == 0.
(handle_non_switch_argument): Replace parameter env with origin.
Treat origin == o_command as env == 0.
(main): Call decode_switches() with origin==o_command before parsing
makefiles.  Call decode_switches() with origin==o_env after parsing
makefiles.
* src/variable.c (set_special_var): Define makeflags at parse time,
each time a makefile modifies MAKEFLAGS.
(do_variable_definition): Strip command line variable assignments from
MAKEFLAGS before appending extra flags.  set_special_var() adds them
back.
* tests/scripts/variables/MAKEFLAGS: Add tests.
2022-11-28 10:50:55 -05:00
Paul Smith
53b8f6a5da * src/main.c (main): [SV 63373] Don't use macros with memcmp()
Reported by djm <mccannd@uk.ibm.com>
2022-11-16 10:00:34 -05:00
Paul Smith
6c1a6dd77c Add specific hints for errors due to invalid conditionals
* src/read.c (eval): If "missing separator" appears to be due to
missing space after ifeq/ifneq, give a hint about the error.
* tests/scripts/misc/failure: Check for these types of failures.
* tests/scripts/variables/special: Move error checking unrelated
to special variables, to misc/failure.
2022-11-15 10:50:34 -05:00
Dmitry Goncharov
1b51ba1f5d [SV 63333] Be more lenient when failing to create temporary files
If make cannot create a temporary lock file for output sync, continue
without output sync enabled rather than dying.

However, if make cannot store a makefile from stdin to a temporary
file that is still a fatal error.

* misc.c (get_tmppath): Keep running on failure to generate a
temporary file name.
(get_tmpfd): Keep running on failure to get a temporary file.
(get_tmpfile): Keep running on failure to open a temporary file.
Ensure memory is freed if we return an error.
* posixos.c (os_anontmp): Keep running on failure to open an
anonymous temporary file.
* output.c (setup_tmpfile): Print an error on failure to create an
output sync lock file.
* main.c (main): Die on failure to store makefile from stdin to a
temporary file.
* tests/scripts/features/output-sync: Add tests.
* tests/scripts/features/temp_stdin: Ditto.
2022-11-13 16:34:01 -05:00
Paul Smith
4c9d87f4ae Keep going if we can't connect to the jobserver
* src/posixos.c (jobserver_parse_auth): Don't invoke fatal() if we
can't connect to an existing jobserver: just keep going without it.
* src/w32/w32os.c (jobserver_parse_auth): Ditto.
* tests/scripts/features/jobserver: Add a test for invalid FIFO
auth files.
2022-11-13 10:39:48 -05:00
Paul Smith
bb5df35133 * src/dir.c (dir_contents_file_exists_p): Show dir name in error.
If we fail to read a directory show the directory name in the error
message.  Pass struct directory instead of directory_contents to
allow that.
(dir_file_exists_p): Change dir_contents_file_exists_p caller.
(open_dirstrem): Ditto.
2022-11-13 10:39:48 -05:00
Paul Smith
92ab2e642d * src/main.c (main): [SV 63307] Handle SIGPIPE as a fatal signal
Always ignoring SIGPIPE is visible to child processes.
2022-11-13 10:39:48 -05:00
Paul Smith
deb4ff272a [SV 63315] tests: Simplify TERM signaling
Tests that try to kill the make process were not behaving as expected
on OpenBSD: the signal was sent from make to its children but the
sleep didn't die.  Something odd about the way the shell treats TERM.
To reduce platform dependencies add "term" to the helper tool and run
that instead of kill / sleep.

* tests/thelp.pl: Add a new operation "term" that takes a PID.
* tests/scripts/features/output-sync: Use it.
* tests/scripts/features/temp_stdin: Ditto.
2022-11-13 10:39:48 -05:00
Paul Smith
e80ce6fc90 [SV 63315] Allocate function names when defining functions
* src/function.c (define_new_function): Don't keep a pointer to the
user-provided name of a user-defined function: if the .so is unloaded
it will point to garbage.  Add the name to the strcache instead.
2022-11-13 10:39:48 -05:00
Paul Smith
d71c0bb0ce tests: Don't convert \ to / when checking regex's
When tests compare the output they will try converting backslashes
to slashes to see if that works.  When we compare using regex's,
we can't do that because backslashes can escape special characters.

* tests/test_driver.pl (compare_output): Clean up this function.
(compare_answer_vms) [VMS]: Comparing answers on VMS is complex;
move all of it into its own function returning 0/1.
(compare_answer): A new function to compare answers: return 0/1.
Remember the CRLF->LF conversion forever; only check \ -> / when
we compare strings, not regex's.
2022-11-13 10:39:48 -05:00
Justine Tunney
090d99dd2d * src/hash.c (jhash_string): Help the compiler optimize the hash
Invoke memcpy() with a constant length, where possible.

Copyright-paperwork-exempt: yes
2022-11-13 10:38:50 -05:00
Paul Smith
6b45f89adb * src/config.h.W32 [TCC]: Only redefine strtoll if not defined 2022-11-12 10:34:35 -05:00
Eli Zaretskii
11f7198f64 * src/config.h.W32: Fix last change. 2022-11-09 15:15:20 +02:00
Eli Zaretskii
4321c5e562 Fix build with Tiny C
* src/config.h.W32 (strtoll, strtoull) [__TINYC__]: Redirect to
_strtoi64 and _strtoui64, respectively.  Reported by Christian
Jullien <eligis@orange.fr>.
2022-11-05 16:46:58 +02:00
Paul Smith
ed493f6c91 Release GNU Make 4.4
* NEWS: Update the version and date.
* configure.ac: Update the version.
* doc/make.texi: Update the EDITION.
2022-10-31 02:23:04 -04:00
Paul Smith
7c3260bbdd * README.git: Update and clarify release operations 2022-10-31 02:23:04 -04:00
Paul Smith
38b19976f5 Fix issues found by ASAN and Coverity
* tests/test_driver.pl: Preserve the LSAN_OPTIONS variable.
* tests/scripts/targets/ONESHELL: Don't set a local variable.
* tests/scripts/functions/let: Test empty let variable.
* src/posixos.c (osync_parse_mutex): Free existing osync_tmpfile.
* src/misc.c (get_tmpfd): Set umask() before invoking mkstemp().
* src/ar.c (ar_parse_name): Check invalid name (shouldn't happen).
* src/function.c (define_new_function): Free previous function entry
when replacing it with a new one.
* src/job.c (child_execute_job): Initialize pid for safety.
(construct_command_argv_internal): In oneshell mode ensure that the
returned argv has the right format (0th element is a pointer to the
entire buffer).
2022-10-31 02:23:04 -04:00
Paul Smith
1dd52ab472 Avoid C99 constructs
Although gnulib requires C99, most of the code does compile with a
C90 compiler (perhaps with a lot of warnings).  Reinstate our C90
configuration test, and clean up a few C99 things that crept in.

* src/job.c (construct_command_argv_internal): Don't use loop-local
variables or C++ comments.
* src/read.c (eval_makefile): Don't use loop-local variables.
2022-10-29 13:36:21 -04:00
Paul Smith
92789aa2e7 * build.sh: Allow a "keep-going" mode during builds 2022-10-29 13:36:21 -04:00
Paul Smith
4e18732a1d tests: Avoid the use of File::Temp->newdir()
This was added in Perl 5.8 but some systems still only provide older
versions such as Perl 5.6.  We don't really need it anyway.
Paul Eggert <eggert@cs.ucla.edu> reported this issue.

* tests/README: Update this to be a bit more modern.
* tests/test_driver.pl: Delete the $TEMPDIR variable.
* tests/scripts/features/temp_stdin: Use $temppath not $TEMPDIR.
2022-10-29 13:36:21 -04:00
Paul Smith
11f9da227e * src/posixos.c (os_anontmp): [SV 63287] Only fail O_TMPFILE once
Reported by Dmitry Goncharov <dgoncharov@users.sf.net>.
2022-10-29 13:36:21 -04:00
Paul Smith
b92340a1ea [SV 62174] Force locale to be "C" before retrieving error messages
We attempt to do this with POSIX::setlocale() but apparently on some
systems (AIX) this isn't sufficient.  So, in addition force the LC
environment variables to use "C".
Reported by Dmitry Goncharov <dgoncharov@users.sf.net>.

* tests/run_make_tests.pl: Move the global setup into set_default().
Force the %ENV locale variables to use the ones we'll use when running
make, then reset them back again after we find error messages.
2022-10-28 17:39:06 -04:00
Paul Smith
8064aee4f9 * src/job.c: [SV 63185] Don't use ifdef with HAVE_DECL_* macros 2022-10-27 15:20:40 -04:00
Paul Smith
cf78e65fda * tests/scripts/features/exec: Don't test with C shells
Using C shells (csh, tcsh) with make is known to be problematic due
to incorrect ways it handles open file descriptors, at least.  If
the user's shell is *csh then don't try it during exec tests.
2022-10-25 14:49:10 -04:00
Paul Smith
04f0d8427f Increase the test framework timeout from 5s to 60s
It seems that some of the test environments hit the 5s timeout on
some tests.  Since it doesn't really matter, as long as we don't
hang forever, increase the timeout to 60s.

* tests/test_driver.pl: Increase $test_timout to 60.  We don't need
to handle VMS timeouts specially anymore.
* tests/scripts/features/parallelism: We don't need to override the
default timeout anymore.
* tests/scripts/features/patternrules: Remove confusing comment.
2022-10-25 14:44:26 -04:00
Paul Smith
f8401ad28b * Makefile.am (check-regression): Add a random suffix to results file
Put the results into a subdirectory for easy unpacking.
* .gitignore: Ignore it.
2022-10-25 14:42:52 -04:00
Paul Smith
e4b3bf7f97 Release GNU Make 4.3.92
* configure.ac: Modify the release version.
* NEWS: Update the version and date.
2022-10-24 02:14:42 -04:00
Paul Smith
d18a87d0a4 [SV 63260] Don't recurse forever if setup_tmpfile() fails
If we fail during setup_tmpfile() we'll try to write an error, which
will invoke setup_tmpfile() again, etc.  Avoid infinite recursion.
Original patch by Dmitry Goncharov <dgoncharov@users.sf.net>

* src/output.c (setup_tmpfile): Remember we're in this function and
return immediately if we enter it during recursion.
(message): Remember the starting location and use that instead of
fmtbuf.buffer.
(error): Ditto.
(fatal): Ditto.
2022-10-24 01:50:12 -04:00
Paul Smith
41c35f2ffe * src/output.c (_outputs): Don't use invalid output sync FDs
Just write to stdout/stderr in this situation.
2022-10-24 01:50:12 -04:00
Paul Smith
deb4a42c3e * src/misc.c (get_tmpdir): Report errors if tmpdirs are invalid
* src/main.c (main): Set up initial temporary directories.
2022-10-24 01:50:12 -04:00
Dmitry Goncharov
252c26bd20 * src/posixos.c (os_anontmp): If O_TMPFILE fails try dup() method. 2022-10-23 18:41:50 -04:00
Paul Smith
6f8da5f4b8 * src/rule.c (get_rule_defn): Don't use STRING_SIZE_TUPLE in mempcpy
If mempcpy() is a macro then STRING_SIZE_TUPLE won't compile.
2022-10-23 18:41:50 -04:00
Paul Smith
c46b5a9e0e Provide a maintainer-only debug method
Generating debug logs to stdout or stderr makes it impossible to
run tests etc. so create a dumb DBG facility to log to a temp file.
This exists only in maintainer mode and the DBG macro gives a
compile error if it's used in non-maintainer mode.

* src/makeint.h (DBG): Call dbg() in maintainer mode, else error.
(dbg): Define it in maintainer mode.
* src/misc.c (dbg): Open a log file for append, write, then close.
2022-10-23 18:41:50 -04:00
Paul Smith
b4157d2ff4 * configure.ac: Check that we can link with Guile
On multi-arch systems we may be able to find the header file but
not successfully link the library.
2022-10-22 22:40:26 -04:00
Paul Smith
f364e0d8d6 Set PATH_MAX on systems without a default value
Some systems (HURD) use fully-dynamic pathnames, with no limit.
We can't support this without significant effort so for now set
PATH_MAX to a large value.

* src/makeint.h: Set PATH_MAX to 4096 if not set and MAXPATHLEN
is also not set.  Remove MAXPATHLEN setting: we won't use it.
* src/misc.c (get_path_max): If we can't get the path max via
pathconf() use the default PATH_MAX.
* src/dir.c (find_directory) [W32]: Use MAX_PATH not MAXPATHLEN.
(local_stat) [W32]: Ditto.
* src/job.c (create_batch_file) [W32]: Ditto.
* src/remake.c (name_mtime) [W32]: Ditto.
* src/w32/w32os.c (os_anontmp) [W32]: Ditto.
2022-10-22 22:40:26 -04:00
Paul Smith
bb0c05a7f0 [SV 63098] Enhance detection of missing peer also-make targets
The previous attempt to detect missing peer targets for implicit
rules had some holes.  Move the detection to notice_finished_file().

* src/remake.c (check_also_make): If we don't have the current mtime
for the file, obtain it.
(update_goal_chain): Don't call check_also_make() here.
(check_dep): Ditto.
(notice_finished_file): If we finished running an implicit rule that
has also_make targets, invoke check_also_make().
2022-10-22 22:40:26 -04:00
Paul Smith
f987d181c4 Collect failure details when the regression tests fail
* README.in: Add a section on running regression tests.
* Makefile.am (check-regression): Capture the test run output, and
on failure collect configure and test results into a tar file.
2022-10-22 22:40:26 -04:00
Paul Smith
cad3ddd165 Enhance tests to work on different systems
The GNU platform testers reported a number of test errors on
different systems; try to address them.

* tests/thelp.pl: A number of tests timed out with a 4-second
timeout.  Increase the default timeout to 10 seconds.
* tests/run_make_tests.pl: Executing directories on cygwin behaves
differently in Perl than make so skip these tests there.
* tests/scripts/options/symlinks: Check for the symlink feature
in make, rather than whether the system supports them.
* tests/scripts/features/implicit_search: On some systems "false"
exits with a different exit code.  Use the helper instead.
* tests/scripts/features/loadapi: Ditto.
* tests/scripts/features/output-sync: Sleep before make -f bar in
the first test as well as the second one.
* tests/scripts/features/exec: Skip on cygwin, which seems to
be "UNIX" but where scripts don't run normally.
* tests/scripts/misc/fopen-fail: Skip on cygwin, where make
eventually exits with exit code 0 and no error messages.
2022-10-22 22:37:49 -04:00
Dmitry Goncharov
54214176b1 [SV 63243] tests: Avoid SIGTERM racing with make error messages
Original patch from Frank Heckenbach <f.heckenbach@fh-soft.de>.

* tests/scripts/features/output-sync: Introduce a sleep to let make
write its error message.  Some systems use different names for
SIGTERM so match with a regex.
* tests/scripts/features/temp_stdin: Ditto.
2022-10-22 10:02:41 -04:00
Dmitry Goncharov
c2f92c980f [SV 63236] Fix getloadavg related error message on AIX
On AIX getloadavg keeps errno intact when it fails, resulting in a
bogus error message from make.

* src/job.c (load_too_high): Reset errno before calling getloadavg.
2022-10-22 09:45:40 -04:00
Dmitry Goncharov
5b1ca277ca [SV 63248] Ignore SIGPIPE
Don't terminate when make's output is redirected to a pipe and the
reader exits early; e.g.:
  $ echo 'all:; sleep 2' | make -f- -j2 -O |:

This lets us unlink temporary files, and tell the user that make was
not able to write its output.
Reported by Frank Heckenbach <f.heckenbach@fh-soft.de>.

* src/main.c (main): Ignore SIGPIPE.
* src/posixos.c (osync_clear): Fix a memory leak.
2022-10-22 09:45:40 -04:00
221 changed files with 11924 additions and 7149 deletions

4
.ccls
View File

@ -4,7 +4,6 @@ clang
-Isrc
-Ilib
-DLIBDIR="/usr/local/lib"
-DINCLUDEDIR="/usr/local/include"
-DLOCALEDIR="/usr/local/share/locale"
-DMAKE_MAINTAINER_MODE
-pthread
@ -13,7 +12,6 @@ clang
-Wall
-Wextra
-Werror
-Wno-address
-Wwrite-strings
-Wshadow
-Wdeclaration-after-statement
@ -26,3 +24,5 @@ clang
-Wignored-qualifiers
-Wformat-signedness
-Wduplicated-cond
-Wno-address
-Wno-string-compare

14
.clangd Normal file
View File

@ -0,0 +1,14 @@
CompileFlags:
Add: [-xc, -DHAVE_CONFIG_H, -DMAKE_MAINTAINER_MODE, -DLIBDIR="/usr/local/lib", -DLOCALEDIR="/usr/local/share/locale", -I../src, -Isrc, -I../lib, -Ilib, -Wall, -Wextra, -Wwrite-strings, -Wshadow, -Wdeclaration-after-statement, -Wbad-function-cast, -Wformat-security, -Wtype-limits, -Wunused-but-set-parameter, -Wlogical-op, -Wpointer-arith, -Wignored-qualifiers, -Wformat-signedness, -Wduplicated-cond, -Wno-string-compare, -Wno-unused-includes]
---
If:
PathMatch: .*\.h
CompileFlags:
Add: [-xc-header, --include=makeint.h]
---
If:
PathMatch: .*/makeint\.h
Diagnostics:
UnusedIncludes: None

View File

@ -1,5 +1,5 @@
(
(nil . ((bug-reference-bug-regexp . "\\(\\)\\bSV[- ]\\([0-9]+\\)")
(nil . ((bug-reference-bug-regexp . "\\(\\bSV[- ]\\([0-9]+\\)\\)")
(bug-reference-url-format . "https://savannah.gnu.org/bugs/?%s")
(ccls-initialization-options
. (:index (:threads 6

8
.gitignore vendored
View File

@ -37,7 +37,7 @@ configure
stamp-*
.dirstamp
gnulib
convert.sed
*.sed
# Build artifacts
.deps/
@ -59,6 +59,12 @@ WinDebug/
WinRel/
GccDebug/
GccRel/
TccDebug/
TccRel/
# Test artifacts
makeerror-*
test-suite.log
# Distribution artifacts
.dep_segment

14
AUTHORS
View File

@ -32,9 +32,6 @@ GNU Make porting efforts:
John W. Eaton <jwe@bevo.che.wisc.edu>
Martin Zinser <zinser@decus.decus.de>
Port to Amiga by:
Aaron Digulla <digulla@fh-konstanz.de>
Port to MS-Windows (native/MinGW) maintained by:
Eli Zaretskii <eliz@gnu.org>
@ -47,11 +44,16 @@ GNU Make porting efforts:
Earnie Boyd <earnie@uses.sf.net>
Troy Runkel <Troy.Runkel@mathworks.com>
Juan M. Guerrero <juan.guerrero@gmx.de>
KO Myung-Hun <komh78@gmail.com>
Port to z/OS by:
Igor Todorovski <itodorov@ca.ibm.com>
-----------------------------------
Other contributors:
Luke Allardyce <lukeallardyce@gmail.com>
Costas Argyris <costas.argyris@gmail.com>
Aron Barath <baratharon@caesar.elte.hu>
David Boyce <dsb@boyski.com>
Kevin Buettner <kevinb@redhat.com>
@ -61,6 +63,8 @@ Other contributors:
Joe Crayne <oh.hello.joe@gmail.com>
Jeremy Devenport <jeremy.devenport@gmail.com>
Pete Dietl <petedietl@gmail.com>
Aaron Digulla <digulla@fh-konstanz.de>
Hannes Domani <ssbssa@yahoo.de>
Martin Dorey <martin.dorey@hds.com>
Christian Eggers <ceggers@arri.de>
Paul Eggert <eggert@twinsun.com>
@ -93,7 +97,9 @@ Other contributors:
Carl Staelin (Princeton University)
Ian Stewartson (Data Logic Limited)
Tobias Stoeckmann <tobias@stoeckmann.org>
Torbjörn Svensson <torbjorn.svensson@foss.st.com>
Sergei Trofimovich <siarheit@google.com>
Justine Tunney <jtunney@gmail.com>
Marc Ullman <marc@mathworks.com>
Christof Warlich <cwarlich@gmx.de>
Florian Weimer <fweimer@redhat.com>
@ -106,7 +112,7 @@ With suggestions/comments/bug reports from a cast of ... well ...
hundreds, anyway :)
-------------------------------------------------------------------------------
Copyright (C) 1997-2022 Free Software Foundation, Inc.
Copyright (C) 1997-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,16 +1,16 @@
# Basic GNU -*-Makefile-*- to build GNU make
# Basic GNU -*-Makefile-*- to build GNU Make
#
# NOTE:
# If you have no 'make' program at all to process this makefile:
# * On Windows, run ".\buildw32.bat" to bootstrap one.
# * On Windows, run ".\build_w32.bat" to bootstrap one.
# * On MS-DOS, run ".\builddos.bat" to bootstrap one.
#
# Once you have a GNU make program created, you can use it with this makefile
# Once you have a GNU Make program created, you can use it with this makefile
# to keep it up to date if you make changes, as:
#
# make.exe -f Basic.mk
#
# Copyright (C) 2017-2022 Free Software Foundation, Inc.
# Copyright (C) 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@ -37,7 +37,6 @@ loadavg_SOURCES = %loadavg_SOURCES%
alloca_SOURCES = %alloca_SOURCES%
w32_SOURCES = %w32_SOURCES%
vms_SOURCES = %vms_SOURCES%
amiga_SOURCES = %amiga_SOURCES%
remote_SOURCES = $(src)remote-stub.c
@ -60,6 +59,8 @@ BUILT_SOURCES =
OBJECTS = $(patsubst %.c,$(OUTDIR)%.$(OBJEXT),$(prog_SOURCES))
RESOURCE_OBJECTS =
OBJDIRS = $(addsuffix .,$(sort $(dir $(OBJECTS))))
# Use the default value of CC
@ -100,7 +101,7 @@ RM.cmd = rm -f $1
# $(call CP.cmd,<from>,<to>)
CP.cmd = cp $1 $2
CLEANSPACE = $(call RM.cmd,$(OBJECTS) $(PROG) $(BUILT_SOURCES))
CLEANSPACE = $(call RM.cmd,$(OBJECTS) $(RESOURCE_OBJECTS) $(PROG) $(BUILT_SOURCES))
# Load overrides for the above variables.
include $(firstword $(wildcard $(SRCDIR)/mk/$(lastword $(subst -, ,$(MAKE_HOST)).mk)))
@ -109,7 +110,7 @@ VPATH = $(SRCDIR)
all: $(PROG)
$(PROG): $(OBJECTS)
$(PROG): $(OBJECTS) $(RESOURCE_OBJECTS)
$(call LINK.cmd,$^)
$(OBJECTS): $(OUTDIR)%.$(OBJEXT): %.c

View File

@ -1,6 +1,6 @@
# This is a -*-Makefile-*-, or close enough
#
# Copyright (C) 1997-2022 Free Software Foundation, Inc.
# Copyright (C) 1997-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@ -34,10 +34,10 @@ make_SRCS = src/ar.c src/arscan.c src/commands.c src/commands.h \
src/getopt.h src/getopt1.c src/gettext.h src/guile.c \
src/hash.c src/hash.h src/implicit.c src/job.c src/job.h \
src/load.c src/loadapi.c src/main.c src/makeint.h src/misc.c \
src/os.h src/output.c src/output.h src/read.c src/remake.c \
src/rule.c src/rule.h src/shuffle.h src/shuffle.c \
src/mkcustom.h src/os.h src/output.c src/output.h src/read.c \
src/remake.c src/rule.c src/rule.h src/shuffle.h src/shuffle.c \
src/signame.c src/strcache.c src/variable.c src/variable.h \
src/version.c src/vpath.c
src/version.c src/vpath.c src/warning.c src/warning.h
w32_SRCS = src/w32/pathstuff.c src/w32/w32os.c src/w32/compat/dirent.c \
src/w32/compat/posixfcn.c src/w32/include/dirent.h \
@ -46,11 +46,11 @@ w32_SRCS = src/w32/pathstuff.c src/w32/w32os.c src/w32/compat/dirent.c \
src/w32/subproc/misc.c src/w32/subproc/proc.h \
src/w32/subproc/sub_proc.c src/w32/subproc/w32err.c
w32_utf8_SRCS = src/w32/utf8.rc src/w32/utf8.manifest
vms_SRCS = src/vms_exit.c src/vms_export_symbol.c src/vms_progname.c \
src/vmsdir.h src/vmsfunctions.c src/vmsify.c
amiga_SRCS = src/amiga.c src/amiga.h
glob_SRCS = lib/fnmatch.c lib/fnmatch.h lib/glob.c lib/glob.h
alloca_SRCS = lib/alloca.c
@ -58,7 +58,7 @@ alloca_SRCS = lib/alloca.c
loadavg_SRCS = lib/getloadavg.c
make_SOURCES = $(make_SRCS)
EXTRA_make_SOURCES = $(amiga_SRCS) $(vms_SRCS)
EXTRA_make_SOURCES = $(vms_SRCS)
if HAVE_GUILE
_GUILE_CFLAGS = $(GUILE_CFLAGS)
@ -90,6 +90,15 @@ else
make_SOURCES += src/posixos.c
endif
UTF8OBJ = src/w32/utf8.$(OBJEXT)
if HAVE_WINDRES
make_LDADD += $(UTF8OBJ)
endif
$(UTF8OBJ) : $(w32_utf8_SRCS)
$(WINDRES) -o $@ -i $<
if USE_CUSTOMS
make_SOURCES += src/remote-cstms.c
else
@ -98,7 +107,7 @@ endif
# Extra stuff to include in the distribution.
mk_FILES = Basic.mk mk/msdosdjgpp.mk mk/Amiga.mk mk/VMS.mk mk/Windows32.mk
mk_FILES = Basic.mk mk/msdosdjgpp.mk mk/VMS.mk mk/Windows32.mk
# We don't need this, since the standard automake output will do.
#mk/Posix.mk.in
@ -112,14 +121,13 @@ test_FILES = tests/run_make_tests tests/run_make_tests.bat \
# test/scripts are added via dist-hook below.
EXTRA_DIST = ChangeLog INSTALL README build.sh build.cfg.in $(man_MANS) \
src/mkconfig.h README.customs README.OS2 \
README.Amiga SCOPTIONS src/config.ami \
src/mkconfig.h README.customs README.OS2 README.zOS \
README.DOS builddos.bat src/configh.dos \
README.W32 build_w32.bat src/config.h.W32 \
README.VMS makefile.com src/config.h-vms src/vmsjobs.c \
vms_export_symbol_test.com \
src/gmk-default.scm src/gmk-default.h \
$(mk_FILES) $(m4_FILES) $(test_FILES)
$(mk_FILES) $(m4_FILES) $(test_FILES) $(w32_utf8_SRCS)
# --------------- Generate the Guile default module content
@ -137,8 +145,8 @@ src/gmk-default.h: $(top_srcdir)/src/gmk-default.scm
dist-hook:
(cd $(top_srcdir); \
sub=`find tests/scripts -follow \( -name .git -o -name .deps -o -name work -o -name .gitignore -o -name \*.orig -o -name \*.rej -o -name \*~ -o -name \*.out -o -name Makefile \) -prune -o -type f -print`; \
tar chf - $$sub) \
| (cd $(distdir); tar xfBp -)
$(AMTAR) chf - $$sub) \
| (cd $(distdir); $(AMTAR) xfBp -)
# --------------- Local CHECK Section
@ -155,29 +163,45 @@ check-local: check-regression
# > check-regression
#
# Look for the make test suite, and run it if found and we can find perl.
# If we're building outside the tree, we use symlinks to make a local copy of
# the test suite. Unfortunately the test suite itself isn't localizable yet.
#
MAKETESTFLAGS =
.PHONY: check-regression
GMK_OUTDIR=..
GMK_OUTDIR = ..
testlog = test-suite.log
testresult = tests/.test-result
errorpre = makeerror-$(PACKAGE_VERSION)-$(host_triplet)
testfiles = $(testlog) $(testresult) $(errorfile)
MOSTLYCLEANFILES = $(testfiles)
errordetails = config.status config.log src/config.h src/mkconfig.h \
$(testlog) tests/work
# Create a 4-letter random sequence
rand_value = c = "abcdefghijklmnopqrstuvwxyz0123456789"
rand_char = substr(c,int(rand()*36),1)
rand_string = $(AWK) 'BEGIN{srand(); $(rand_value); print $(rand_char) "" $(rand_char) "" $(rand_char) "" $(rand_char);}'
check-regression: tests/config-flags.pm
@if test -f '$(top_srcdir)/tests/run_make_tests'; then \
$(AM_V_at) rm -f $(testfiles)
$(AM_V_at) if test -f '$(top_srcdir)/tests/run_make_tests.pl'; then \
ulimit -n 128; \
if $(PERL) -v >/dev/null 2>&1; then \
case `cd '$(top_srcdir)'; pwd` in `pwd`) : ;; \
*) test -d tests || mkdir tests; \
rm -f srctests; \
if ln -s '$(top_srcdir)/tests' srctests; then \
for f in run_make_tests run_make_tests.pl test_driver.pl scripts thelp.pl; do \
rm -f tests/$$f; ln -s ../srctests/$$f tests; \
done; fi ;; \
esac; \
echo "cd tests && $(PERL) $(PERLFLAGS) ./run_make_tests.pl -srcdir $(abs_top_srcdir) -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)"; \
cd tests && $(PERL) $(PERLFLAGS) ./run_make_tests.pl -srcdir '$(abs_top_srcdir)' -make '$(GMK_OUTDIR)/make$(EXEEXT)' $(MAKETESTFLAGS); \
echo "cd tests && $(PERL) $(PERLFLAGS) $(abs_top_srcdir)/tests/run_make_tests.pl -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)"; \
(cd tests && $(PERL) $(PERLFLAGS) '$(abs_top_srcdir)/tests/run_make_tests.pl' -make '$(GMK_OUTDIR)/make$(EXEEXT)' $(MAKETESTFLAGS); echo $$? >.test-result) 2>&1 | tee $(testlog); \
export TAR_OPTIONS='$(filter-out --sort%,$(TAR_OPTIONS))'; \
er=$$(cat $(testresult)); if test "$$er" -ne 0; then \
dirnm="$(errorpre)-$$($(rand_string))"; fnm="$$dirnm.tar.gz"; \
rm -rf "$$dirnm"; mkdir "$$dirnm"; \
$(AMTAR) chf - $(errordetails) | (cd "$$dirnm"; $(AMTAR) xf -); \
$(AMTAR) chf - "$$dirnm" | eval GZIP= gzip $(GZIP_ENV) -c >"$$fnm"; \
echo "*** Testing FAILED! Details: $$fnm"; \
echo '*** Please report to <$(PACKAGE_BUGREPORT)>'; echo; \
exit $$er; \
fi; \
else \
echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \
fi; \

256
NEWS
View File

@ -1,6 +1,6 @@
GNU Make NEWS -*-indented-text-*-
History of user-visible changes.
18 October 2022
26 February 2023
See the end of this file for copyrights and conditions.
@ -8,8 +8,138 @@ All user-visible changes are more fully described in the GNU Make 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 4.3.91 (18 Oct 2022)
Version 4.4.90 (26 Feb 2023)
A complete list of bugs fixed in this version is available here:
https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&set=custom
* WARNING: Removed AmigaOS support!
This version of GNU Make no longer supports AmigaOS. If you need support
for AmigaOS please use one of the older versions of GNU Make.
* WARNING: Loaded Object ABI incompatibility!
This release changes the loaded object feature from "technology preview" to
fully-supported feature. However, it introduces an ABI incompatibility with
previous releases: the setup function now takes an ABI version as its first
argument. At compile time you can test the GMK_ABI_VERSION constant to
detect which ABI should be used. At runtime your initialization function
can check the provided ABI version to verify it's being loaded correctly.
* WARNING: Backward-incompatibility!
Parsing of the first argument in ifeq/ifneq with () has been cleaned up.
When locating the separating "," any variable reference (single char as well
as using $() or ${}) is skipped. However parentheses that are not part of
or contained in variable references will not be counted. This means that
things like "ifeq ((foo,bar),)" are now syntax errors. Use a variable to
hide the comma if needed: "COMMA = ," / "ifeq ((foo$(COMMA)bar),)".
See https://savannah.gnu.org/bugs/index.php?64402
* WARNING: Backward-incompatibility!
If -e is given all environment variables will now have an origin of
"environment override" even if they are not otherwise set in the makefile.
See https://savannah.gnu.org/bugs/index.php?64803
* WARNING: Backward-incompatibility!
The behavior of appending to pattern-specific variables has been clarified
when combined with command-line settings or -e overrides.
See https://savannah.gnu.org/bugs/index.php?64822
* NOTE: Deprecated behavior.
The check in GNU Make 4.3 for suffix rules with prerequisites didn't check
single-suffix rules, only double-suffix rules. Add the missing check.
* New feature: Any assignment operator can be made conditional
GNU Make has long supported the conditional operator "?=" which creates a
recursive variable set to a value if and only if the variable is not already
defined. In this release, the "?" can precede any assignment operator to
make it conditional. For example, "?:=" creates a simply-expanded variable
and expands the right-hand side if and only if the variable is not already
defined. The constructs "?::=", "?:::=", and "?!=" also behave as expected.
* New feature: Unload function for loaded objects
When a loaded object needs to be unloaded by GNU Make, it will invoke an
unload function (if one is defined) beforehand that allows the object to
perform cleanup operations.
Original idea and implementation: Dmitry Goncharov <dgoncharov@users.sf.net>
* New feature: Makefile warning reporting control
A new option "--warn" controls reporting of warnings for makefiles. Actions
can be set to "ignore", "warn", or "error". Two new warnings are reported:
assigning to invalid variable names, and referencing invalid variable names
(both set to "warn" by default), in addition to the existing warning for
undefined variables (defaults to "ignore"). "--warn-undefined-variables" is
deprecated, and is translated to "--warn=undefined-vars" internally.
* New feature: Control warnings with the .WARNINGS variable
In addition to --warn from the command line, which takes effect for make
invoked recursively, warnings can be controlled only for the current
instance of make using the .WARNINGS variable.
* New feature: Printing targets defined by the makefile
A new option "--print-targets" will print all explicit, non-special targets
defined in the makefiles, one per line, then exit with success. No recipes
are invoked and no makefiles are re-built.
* Warnings for detecting circular dependencies are controllable via warning
reporting, with the name "circular-dep".
* 'make --print-data-base' (or 'make -p') now outputs time of day
using the same form as for file timestamps, e.g., "2023-05-10
10:43:57.570558743". Previously it used the form "Wed May 10
10:43:57 2023", which has less detail and is harder to compare.
* Conditional statements starting with the recipe prefix were sometimes
interpreted in previous versions. As per the documentation, lines starting
with the recipe prefix are now never considered conditional statements.
* Tests in the regression test suite now are run in their own directory to
avoid cross-contamination and allow cleanup if the tests are interrupted.
More information is printed about failing tests.
Version 4.4.1 (26 Feb 2023)
This release is primarily a bug-fix release.
A complete list of bugs fixed in this version is available here:
https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=110&set=custom
* WARNING: Backward-incompatibility!
In previous releases it was not well-defined when updates to MAKEFLAGS made
inside a makefile would be visible. This release ensures they are visible
immediately, even when invoking $(shell ...) functions. Also, command line
variable assignments are now always present in MAKEFLAGS, even when parsing
makefiles.
Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>
* New feature: Parallel builds of archives
Previously it was not possible to use parallel builds with archives. It is
still not possible using the built-in rules, however you can now override
the built-in rules with a slightly different set of rules and use parallel
builds with archive creation. See the "Dangers When Using Archives" section
of the GNU Make manual, and https://savannah.gnu.org/bugs/index.php?14927
* Previously target-specific variables would inherit their "export" capability
from parent target-specific variables even if they were marked private. Now
private parent target-specific variables have no affect. For more details
see https://savannah.gnu.org/bugs/index.php?61463
* Disable FIFO jobserver on GNU/Hurd and Cygwin
Experimentation shows that the new FIFO-based jobserver doesn't work well on
GNU/Hurd or Cygwin: revert these systems to use the pipe-based jobserver.
* Updates to allow building on OS/2
Provided by KO Myung-Hun <komh78@gmail.com>
* New platform: GNU Make is supported on z/OS
Thanks to Igor Todorovski <itodorov@ca.ibm.com> for the patches and testing
assistance.
Version 4.4 (31 Oct 2022)
A complete list of bugs fixed in this version is available here:
@ -100,7 +230,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se
each prerequisite).
* New feature: The .NOTINTERMEDIATE special target
.NOTINTERMEDIATE Disables intermediate behavior for specific files, for all
.NOTINTERMEDIATE disables intermediate behavior for specific files, for all
files built using a pattern, or for the entire makefile.
Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>
@ -186,9 +316,9 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se
* Special targets like .POSIX are detected upon definition, ensuring that any
change in behavior takes effect immediately, before the next line is parsed.
* When the jobserver is enabled and GNU Make decides it is invoking a non-make
sub-process and closes the jobserver pipes, it will now add a new option to
the MAKEFLAGS environment variable that disables the jobserver.
* When the pipe-based jobserver is enabled and GNU Make decides it is invoking
a non-make sub-process and closes the jobserver pipes, it will now add a new
option to the MAKEFLAGS environment variable that disables the jobserver.
This prevents sub-processes that invoke make from accidentally using other
open file descriptors as jobserver pipes. For more information see
https://savannah.gnu.org/bugs/?57242 and https://savannah.gnu.org/bugs/?62397
@ -245,7 +375,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=108&se
warning about this behavior is generated:
warning: ignoring prerequisites on suffix rule definition
The POSIX behavior will be adopted as the only behavior in a future release
of GNU make so please resolve any warnings.
of GNU Make so please resolve any warnings.
* New feature: Grouped explicit targets
Pattern rules have always had the ability to generate multiple targets with
@ -266,7 +396,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=108&se
* Makefiles can now specify the '-j' option in their MAKEFLAGS variable and
this will cause make to enable that parallelism mode.
* GNU make will now use posix_spawn() on systems where it is available.
* GNU Make will now use posix_spawn() on systems where it is available.
If you prefer to use fork/exec even on systems where posix_spawn() is
present, you can use the --disable-posix-spawn option to configure.
Implementation contributed by Aron Barath <baratharon@caesar.elte.hu>
@ -283,17 +413,17 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=108&se
* A new option -E has been added as a short alias for --eval.
* All wildcard expansion within GNU make, including $(wildcard ...), will sort
* All wildcard expansion within GNU Make, including $(wildcard ...), will sort
the results. See https://savannah.gnu.org/bugs/index.php?52076
* Interoperate with newer GNU libc and musl C runtime libraries.
* Performance improvements provided by Paolo Bonzini <pbonzini@redhat.com>
GNU make Developer News
GNU Make Developer News
* Import the GNU standard bootstrap script to replace the hand-rolled
"make update" method for building code from a GNU make Git repository.
"make update" method for building code from a GNU Make Git repository.
* Rework the source distribution to move source files into the src/*
subdirectory. This aligns with modern best practices in GNU.
@ -327,11 +457,11 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&se
The function is expanded to the contents of the file. The contents are
expanded verbatim except that the final newline, if any, is stripped.
* The makefile line numbers shown by GNU make now point directly to the
* The makefile line numbers shown by GNU Make now point directly to the
specific line in the recipe where the failure or warning occurred.
Sample changes suggested by Brian Vandenberg <phantall@gmail.com>
* The interface to GNU make's "jobserver" is stable as documented in the
* The interface to GNU Make's "jobserver" is stable as documented in the
manual, for tools which may want to access it.
WARNING: Backward-incompatibility! The internal-only command line option
@ -366,7 +496,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=105&se
requested mode, then closed again.
* Change the fatal error for mixed explicit and implicit rules, that was
introduced in GNU make 3.82, to a non-fatal error. However, this syntax is
introduced in GNU Make 3.82, to a non-fatal error. However, this syntax is
still deprecated and may return to being illegal in a future version of GNU
make. Makefiles that rely on this syntax should be fixed.
See https://savannah.gnu.org/bugs/?33034
@ -414,7 +544,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&se
single space
* New feature: GNU Guile integration
This version of GNU make can be compiled with 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
@ -446,20 +576,20 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&se
* 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.
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
between the "!" and "=": "variable! = value"
* New feature: "::=" simple assignment operator as defined by POSIX in 2012.
This operator has identical functionality to ":=" in GNU make, but will be
This operator has identical functionality to ":=" in GNU Make, but will be
portable to any implementation of make conforming to a sufficiently new
version of POSIX (see https://austingroupbugs.net/view.php?id=330). It is
not necessary to define the .POSIX target to access this operator.
* New feature: Loadable objects
This version of GNU make contains a "technology preview": the ability to
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
the user and can add extended functionality, usable by makefiles.
@ -467,8 +597,8 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&se
* 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. Once this variable is parsed, GNU make will set it to the
GNU Make-specific flags to allow your makefile to be portable to other
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
@ -509,7 +639,7 @@ A complete list of bugs fixed in this version is available here:
https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&set=custom
* Compiling GNU make now requires a conforming ISO C 1989 compiler and
* Compiling GNU Make now requires a conforming ISO C 1989 compiler and
standard runtime library.
* WARNING: Backward-incompatibility!
@ -517,7 +647,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&se
fundamentally incompatible way: make is required to invoke the shell as if
the '-e' flag were provided. Because this would break many makefiles that
have been written to conform to the original text of the standard, the
default behavior of GNU make remains to invoke the shell with simply '-c'.
default behavior of GNU Make remains to invoke the shell with simply '-c'.
However, any makefile specifying the .POSIX special target will follow the
new POSIX standard and pass '-e' to the shell. See also .SHELLFLAGS
below.
@ -626,9 +756,9 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&se
* A note on appending the redirected output. With this change, a simple
mechanism is implemented to make ">>" work in action lines. In VMS
there is no simple feature like ">>" to have DCL command or program
output redirected and appended to a file. GNU make for VMS already
output redirected and appended to a file. GNU Make for VMS already
implements the redirection of output. If such a redirection is detected,
an ">" on the action line, GNU make creates a DCL command procedure to
an ">" on the action line, GNU Make creates a DCL command procedure to
execute the action and to redirect its output. Based on that, now ">>"
is also recognized and a similar but different command procedure is
created to implement the append. The main idea here is to create a
@ -637,7 +767,7 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&se
in the command procedure to keep changes in make small and simple. This
obviously has some limitations but it seems good enough compared with
the current ">" implementation. (And in my opinion, redirection is not
really what GNU make has to do.) With this approach, it may happen that
really what GNU Make has to do.) With this approach, it may happen that
the temporary file is not yet appended and is left in SYS$SCRATCH.
The temporary file names look like "CMDxxxxx.". Any time the created
command procedure can not complete, this happens. Pressing Ctrl+Y to
@ -660,9 +790,9 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&se
Version 3.81 (01 Apr 2006)
* GNU make is ported to OS/2.
* GNU Make is ported to OS/2.
* GNU make is ported to MinGW. The MinGW build is only supported by
* GNU Make is ported to MinGW. The MinGW build is only supported by
the build_w32.bat batch file; see the file README.W32 for more
details.
@ -670,12 +800,12 @@ Version 3.81 (01 Apr 2006)
Up to and including this release, the '$?' variable does not contain
any prerequisite that does not exist, even though that prerequisite
might have caused the target to rebuild. Starting with the _next_
release of GNU make, '$?' will contain all prerequisites that caused
release of GNU Make, '$?' will contain all prerequisites that caused
the target to be considered out of date.
See https://savannah.gnu.org/bugs/?16051
* WARNING: Backward-incompatibility!
GNU make now implements a generic "second expansion" feature on the
GNU Make now implements a generic "second expansion" feature on the
prerequisites of both explicit and implicit (pattern) rules. In order
to enable this feature, the special target '.SECONDEXPANSION' must be
defined before the first target which takes advantage of it. If this
@ -693,23 +823,23 @@ Version 3.81 (01 Apr 2006)
of this SysV feature you will need to update them.
* WARNING: Backward-incompatibility!
In order to comply with POSIX, the way in which GNU make processes
In order to comply with POSIX, the way in which GNU Make processes
backslash-newline sequences in recipes has changed. If your makefiles
use backslash-newline sequences inside of single-quoted strings in
recipes you will be impacted by this change. See the GNU make manual
recipes you will be impacted by this change. See the GNU Make manual
subsection "Splitting Recipe Lines" (node "Splitting Lines"), in
section "Recipe Syntax", chapter "Writing Recipe in Rules", for
details.
* WARNING: Backward-incompatibility!
Some previous versions of GNU make had a bug where "#" in a function
Some previous versions of GNU Make had a bug where "#" in a function
invocation such as $(shell ...) was treated as a make comment. A
workaround was to escape these with backslashes. This bug has been
fixed: if your makefile uses "\#" in a function invocation the
backslash is now preserved, so you'll need to remove it.
* New command line option: -L (--check-symlink-times). On systems that
support symbolic links, if this option is given then GNU make will
support symbolic links, if this option is given then GNU Make will
use the most recent modification time of any symbolic links that are
used to resolve target files. The default behavior remains as it
always has: use the modification time of the actual target file only.
@ -729,16 +859,16 @@ Version 3.81 (01 Apr 2006)
call are now masked in the context of the inner call.
* Implemented a solution for the "thundering herd" problem with "-j -l".
This version of GNU make uses an algorithm suggested by Thomas Riedl
This version of GNU Make uses an algorithm suggested by Thomas Riedl
<thomas.riedl@siemens.com> to track the number of jobs started in the
last second and artificially adjust GNU make's view of the system's
last second and artificially adjust GNU Make's view of the system's
load average accordingly.
* New special variables available in this release:
- .INCLUDE_DIRS: Expands to a list of directories that make searches
for included makefiles.
- .FEATURES: Contains a list of special features available in this
version of GNU make.
version of GNU Make.
- .DEFAULT_GOAL: Set the name of the default goal make will
use if no goals are provided on the command line.
- MAKE_RESTARTS: If set, then this is the number of times this
@ -776,7 +906,7 @@ Version 3.81 (01 Apr 2006)
it will be set in the environment, just as before.
* On MS Windows systems, explicitly setting SHELL to a pathname ending
in "cmd" or "cmd.exe" (case-insensitive) will force GNU make to use
in "cmd" or "cmd.exe" (case-insensitive) will force GNU Make to use
the DOS command interpreter in batch mode even if a UNIX-like shell
could be found on the system.
@ -808,7 +938,7 @@ Version 3.80 (03 Oct 2002)
requiring that target A will always be rebuilt if target B is updated.
Patch for this feature provided by Greg McGary <greg@mcgary.org>.
* For compatibility with SysV make, GNU make now supports the peculiar
* For compatibility with SysV make, GNU Make now supports the peculiar
syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.
This syntax is only valid within explicit and static pattern rules: it
cannot be used in implicit (suffix or pattern) rules. Edouard G. Parmelan
@ -833,7 +963,7 @@ Version 3.80 (03 Oct 2002)
useful here.
* A new built-in variable is defined, $(MAKEFILE_LIST). It contains a
list of each makefile GNU make has read, or started to read, in the
list of each makefile GNU Make has read, or started to read, in the
order in which they were encountered. So, the last filename in the
list when a makefile is just being read (before any includes) is the
name of the current makefile.
@ -843,7 +973,7 @@ Version 3.80 (03 Oct 2002)
makefiles at that moment.
* A new command line option is defined, -B or --always-make. If
specified GNU make will consider all targets out-of-date even if they
specified GNU Make will consider all targets out-of-date even if they
would otherwise not be.
* The arguments to $(call ...) functions were being stored in $1, $2,
@ -868,7 +998,7 @@ Version 3.80 (03 Oct 2002)
Turkish.
* Updated internationalization support to Gettext 0.11.5.
GNU make now uses Gettext's "external" feature, and does not include
GNU Make now uses Gettext's "external" feature, and does not include
any internationalization code itself. Configure will search your
system for an existing implementation of GNU Gettext (only GNU Gettext
is acceptable) and use it if it exists. If not, NLS will be disabled.
@ -885,7 +1015,7 @@ Version 3.80 (03 Oct 2002)
* This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com.
It is based on the specific version 3.77k and on 3.78.1. 3.77k was done
by Klaus Kämpf <kkaempf@rmi.de>, the code was based on the VMS port of
by Klaus Kämpf <kkaempf@rmi.de>, the code was based on the VMS port of
GNU Make 3.60 by Mike Moretti.
It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and
@ -900,7 +1030,7 @@ Version 3.80 (03 Oct 2002)
available ECOs for VMS V7.1 and newer versions. It is fixed in versions
shipped with newer VMS versions and all ECO kits after October 1999. It
only shows up during the daylight saving time period (DST): stat()
returns a modification time 1 hour ahead. This results in GNU make
returns a modification time 1 hour ahead. This results in GNU Make
warning messages. For a just created source you will see:
$ gmake x.exe
@ -928,11 +1058,11 @@ Version 3.79.1 (23 Jun 2000)
Version 3.79 (04 Apr 2000)
* GNU make optionally supports internationalization and locales via the
* GNU Make optionally supports internationalization and locales via the
GNU gettext (or local gettext if suitable) package. See the ABOUT-NLS
file for more information on configuring GNU make for NLS.
file for more information on configuring GNU Make for NLS.
* Previously, GNU make quoted variables such as MAKEFLAGS and
* Previously, GNU Make quoted variables such as MAKEFLAGS and
MAKEOVERRIDES for proper parsing by the shell. This allowed them to
be used within make build scripts. However, using them there is not
proper behavior: they are meant to be passed to subshells via the
@ -966,12 +1096,12 @@ Version 3.79 (04 Apr 2000)
value is greater than the "end" value. If that's true, nothing is
returned.
* Hartmut Becker provided many updates for the VMS port of GNU make.
* Hartmut Becker provided many updates for the VMS port of GNU Make.
See the README.VMS file for more details.
* VMS-specific changes:
* Fix a problem with automatically remaking makefiles. GNU make uses an
* Fix a problem with automatically remaking makefiles. GNU Make uses an
execve to restart itself after a successful remake of the makefile. On
UNIX systems execve replaces the running program with a new one and
resets all signal handling to the default. On VMS execve creates a child
@ -1049,7 +1179,7 @@ Version 3.78 (22 Sep 1999)
* A "job server" feature, suggested by Howard Chu <hyc@highlandsun.com>.
On systems that support POSIX pipe(2) semantics, GNU make can now pass
On systems that support POSIX pipe(2) semantics, GNU Make can now pass
-jN options to submakes rather than forcing them all to use -j1. The
top make and all its sub-make processes use a pipe to communicate with
each other to ensure that no more than N jobs are started across all
@ -1057,20 +1187,20 @@ Version 3.78 (22 Sep 1999)
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
and standard term "prerequisite", both in the manual and in all GNU Make
output.
* GNU make supports the "big archive" library format introduced in AIX 4.3.
* GNU Make supports the "big archive" library format introduced in AIX 4.3.
* GNU make supports large files on AIX, HP-UX, and IRIX. These changes
* GNU Make supports large files on AIX, HP-UX, and IRIX. These changes
were provided by Paul Eggert <eggert@twinsun.com>. (Large file
support for Solaris and Linux was introduced in 3.77, but the
configuration had issues: these have also been resolved).
* The Windows 95/98/NT (W32) version of GNU make now has native support
* The Windows 95/98/NT (W32) version of GNU Make now has native support
for the Cygnus Cygwin release B20.1 shell (bash).
* The GNU make regression test suite, long available separately "under
* The GNU Make regression test suite, long available separately "under
the table", has been integrated into the release. You can invoke it
by running "make check" in the distribution. Note that it requires
Perl (either Perl 4 or Perl 5) to run.
@ -1113,10 +1243,10 @@ Version 3.77 (28 Jul 1998)
you'll have to escape both of them: "foo : bar\\\=baz".
* A new appendix listing the most common error and warning messages
generated by GNU make, with some explanation, has been added to the
GNU make User's Manual.
generated by GNU Make, with some explanation, has been added to the
GNU Make User's Manual.
* Updates to the GNU make Customs library support (see README.customs).
* Updates to the GNU Make Customs library support (see README.customs).
* Updates to the Windows 95/NT port from Rob Tulloh (see README.W32),
and to the DOS port from Eli Zaretski (see README.DOS).
@ -1125,7 +1255,7 @@ Version 3.77 (28 Jul 1998)
* This is the VMS port of GNU Make.
It is based on the VMS port of GNU Make 3.60 by Mike Moretti.
This port was done by Klaus Kämpf <kkaempf@rmi.de>
This port was done by Klaus Kämpf <kkaempf@rmi.de>
* There is first-level support available from proGIS Software, Germany.
Visit their web-site at https://www.progis.de to get information
@ -1166,7 +1296,7 @@ Version 3.76.1 (19 Sep 1997)
Version 3.76 (16 Sep 1997)
* GNU make now uses automake to control Makefile.in generation. This
* GNU Make now uses automake to control Makefile.in generation. This
should make it more consistent with the GNU standards.
* VPATH functionality has been changed to incorporate the VPATH+ patch,
@ -1181,7 +1311,7 @@ Version 3.76 (16 Sep 1997)
list of words from number S to number E (inclusive) of TEXT.
* Instead of an error, detection of future modification times gives a
warning and continues. The warning is repeated just before GNU make
warning and continues. The warning is repeated just before GNU Make
exits, so it is less likely to be lost.
* Fix the $(basename) and $(suffix) functions so they only operate on
@ -1336,9 +1466,9 @@ Version 3.71 (21 May 1994)
There is no longer a separate distribution containing Info and DVI files.
* You can now set the variables `binprefix' and/or `manprefix' in
Makefile.in (or on the command line when installing) to install GNU make
Makefile.in (or on the command line when installing) to install GNU Make
under a name other than `make' (i.e., ``make binprefix=g install''
installs GNU make as `gmake').
installs GNU Make as `gmake').
* The built-in Texinfo rules use the new variables `TEXI2DVI_FLAGS' for
flags to the `texi2dvi' script, and `MAKEINFO_FLAGS' for flags to the
@ -1818,7 +1948,7 @@ Version 3.05
(Changes from versions 1 through 3.05 were never recorded. Sorry.)
-------------------------------------------------------------------------------
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,80 +0,0 @@
Short: Port of GNU Make with SAS/C (no ixemul.library required)
Author: GNU, Amiga port by Aaron "Optimizer" Digulla
Uploader: Aaron "Optimizer" Digulla (digulla@fh-konstanz.de)
Type: dev/c
This is a pure Amiga port of GNU Make. It needs no extra libraries or
anything. It has the following features (in addition to any features of
GNU Make):
- Runs Amiga-Commands with SystemTags() (Execute)
- Can run multi-line statements
- Allows to use Device-Names in targets:
c:make : make.o
is ok. To distinguish between device-names and target : or ::, MAKE
looks for spaces. If there are any around :, it's taken as a target
delimiter, if there are none, it's taken as the name of a device. Note
that "make:make.o" tries to create "make.o" on the device "make:".
- Replaces @@ by a newline in any command line:
if exists make @@\
delete make.bak quiet @@\
rename make make.bak @@\
endif @@\
$(CC) Link Make.o To make
works. Note that the @@ must stand alone (i.e., "make@@\" is illegal).
Also be careful that there is a space after the "\" (i.e., at the
beginning of the next line).
- Can be made resident to save space and time
- Amiga specific wildcards can be used in $(wildcard ...)
BUGS:
- The line
dummy.h : src/*.c
tries to make dummy.h from "src/*.c" (i.e., no wildcard-expansion takes
place). You have to use "$(wildcard src/*.c)" instead.
COMPILING FROM SCRATCH
----------------------
To recompile, you need SAS/C 6.51.
As of GNU Make 4.3, the build environment has been cleaned up and alternate
make files (including smakefiles) have been removed. If you have an existing
version of GNU Make available you _should_ be able to run:
make -f Basic.mk
However this is untested.
If you have an Amiga system and would like to collaborate on getting
bootstrapping to work properly please contact bug-make@gnu.org.
INSTALLATION
Copy make somewhere in your search path (e.g., sc:c or sc:bin).
If you plan to use recursive makes, install make resident:
Resident make Add
-------------------------------------------------------------------------------
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>.

View File

@ -280,7 +280,7 @@ Bug reports:
-------------------------------------------------------------------------------
Copyright (C) 1996-2022 Free Software Foundation, Inc.
Copyright (C) 1996-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -73,7 +73,7 @@ III. ***** COMPILATION AND INSTALLATION *****
To recreate the configuration files use:
export EMXSHELL=ksh
aclocal -I config
aclocal -I m4
automake
autoconf
autoheader
@ -93,7 +93,7 @@ Recommended environment variables and installation options:
export CFLAGS="-O2 -Zomf -Zmt"
export LDFLAGS="-Zcrtdll -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000"
export RANLIB="echo"
./configure --prefix=x:/usr --infodir=x:/usr/share/info --mandir=x:/usr/share/man --without-included-gettext
./configure --prefix=x:/usr --infodir=x:/usr/share/info --mandir=x:/usr/share/man
make AR=emxomfar
make install
@ -102,6 +102,9 @@ Note: If you use gcc 2.9.x I recommend to set also LIBS="-lgcc"
Note: You can add -DNO_CMD_DEFAULT and -DNO_CHDIR2 to CPPFLAGS.
See section I. for details.
Note: If you use Open Watcom Linker instead of IBM Linker, remove
'-Zlinker /exepack:2' from LDFLAGS.
IV. ***** NLS support *****
@ -160,7 +163,7 @@ from the make source tree.
-------------------------------------------------------------------------------
Copyright (C) 2003-2022 Free Software Foundation, Inc.
Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
This version of GNU Make has been tested on:
Microsoft Windows 2000/XP/2003/Vista/7/8/10
Microsoft Windows 2000/XP/2003/Vista/7/8/10/11
It has also been used on Windows 95/98/NT, and on OS/2.
It builds with the MinGW port of GCC (tested with GCC 3.4.2, 4.8.1,
@ -347,7 +347,7 @@ Bug reports:
is described in the GNU Make manual and the base README.
-------------------------------------------------------------------------------
Copyright (C) 1996-2022 Free Software Foundation, Inc.
Copyright (C) 1996-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -96,7 +96,7 @@ SunOS 4.1.x:
-------------------------------------------------------------------------------
Copyright (C) 1998-2022 Free Software Foundation, Inc.
Copyright (C) 1998-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,7 +1,7 @@
-*-text-*-
-------------------------------------------------------------------------------
Copyright (C) 2002-2022 Free Software Foundation, Inc.
Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -48,8 +48,8 @@ your commit messages (sans the leading TAB of course).
Rule #1: Don't rewrite pushed history on master (no "git push --force").
Rule #2: Feel free to rewrite pushed history on personal branches.
Rule #3: Prefer to squash-merge or rebase + merge --ff-only, rather than
merging from personal branches into master.
Rule #3: Squash-merge or rebase + merge --ff-only, rather than merging from
personal branches into master.
Typical simple workflow might be:
@ -88,10 +88,10 @@ need to install the following extra software:
* autoconf >= 2.69
* automake >= 1.16.1
* gettext
* autopoint
* pkg-config
* texinfo (for makeinfo)
* gettext
* pkg-config
* GCC
* GNU Make (POSIX make is not sufficient)
@ -99,7 +99,10 @@ And any tools that those utilities require (GNU m4, etc.)
To run the tests you must install Perl.
To build a release you'll need to install lzip.
To create dist files you will additionally need:
* lzip (to create tar.lz dist files)
* texlive (or some other TeX package)
GNU Make requires Gnulib to provide some facilities. If you want to maintain
a local installation of gnulib you can set GNULIB_SRCDIR to point to it.
@ -125,11 +128,11 @@ After checking out the code, you will need to run the bootstrap script:
Alternatively you can just pull content from remote locations with:
$ ./autopull.sh
$ ./bootstrap --pull
And/or just re-generate auto-generatable files with:
$ ./autogen.sh
$ ./bootstrap --gen
(Running ./bootstrap does both in one step.)
@ -144,7 +147,7 @@ That is, you can just run:
to build and test GNU Make.
NOTE! This method builds GNU Make in "maintainer mode". Make programs built
in this mode it will be slower, possibly MUCH slower: there are various
in this mode will be slower, possibly MUCH slower: there are various
sanity checks enabled. Further this mode assumes a modern GCC, GNU
libc, and well-formed system headers and enables a high level of
warnings AND enables -Werror to turn warnings into failures.
@ -152,7 +155,8 @@ NOTE! This method builds GNU Make in "maintainer mode". Make programs built
If you want to build from Git with "maintainer mode" disabled, add
"MAKE_MAINTAINER_MODE=" to the make command line. If you want to turn
off the extra warning flags, add "MAKE_CFLAGS=" to the make command
line.
line. If you want to keep the warnings but not fail, add
"EXTRA_CFLAGS=-Wno-error" to the make command line.
For example:
$ ./configure
@ -178,6 +182,9 @@ Note, neither of these methods are tested regularly by the GNU Make
maintainers. Building for Windows from a distribution tarball IS tested
regularly.
NOTE! "Maintainer mode" (see above) IS ENABLED when building from Git using
the build_w32.bat file.
Debugging and Testing
---------------------
@ -203,7 +210,14 @@ work on non-GNU systems (Windows, MacOS, etc.)
make clean
make -j8 CFLAGS='-ggdb3 -fsanitize=address' LDFLAGS='-ggdb3 -fsanitize=address'
(cd tests && ./run_make_tests -make ../make)
Then to check for corruption only but not memory leaks run:
ASAN_OPTIONS='detect_stack_after_use_return=true:detect_leaks=false' make check
To check for leaks too run:
make check
Note that ASAN is reporting many more errors than valgrind. I don't know
which one is wrong: I haven't looked at them closely.
@ -245,39 +259,129 @@ consistent (that's why we don't finalize the Git tag, etc. until the end).
* Update the configure.ac file with the new release number.
* Update the EDITION value in the doc/make.texi file.
* Update the doc/make.1 file with the release date.
* Update the NEWS file with the release number and date.
* Ensure the Savannah bug list URL in the NEWS file uses the correct
"Fixed Release" ID number.
* Run "make distcheck" to be sure it all works.
* Run "make check-alt-config" to be sure alternative configurations work
* Run "make update-makeweb" to get a copy of the GNU Make web pages
* Run "make update-gnuweb" to get a copy of the GNU website boilerplate pages
* Update the web page boilerplate if necessary:
../gnu-www/www/server/standards/patch-from-parent ../make-web/make.html \
../gnu-www/www/server/standards/boilerplate.html
* Run "make gendocs" (requires gnulib) to generate the manual files for
the GNU Make web pages.
* Follow the directions from gendocs for the web page repository
* run "make tag-release" to create a Git tag for the release
* Push everything:
git push --tags origin master
The safest thing is to create an entirely new repository and build the final
package from there:
git clone git://git.savannah.gnu.org/make.git make-release
cd make-release
If you don't want to create a new repository then run "git clean -fdx".
Then:
./bootstrap
./configure
make distcheck
Perform test builds on whichever systems you have access to.
Use a previous announcement as a template to create an announcement in a text
file then sign it with GPG:
gpg --clearsign <announcement.txt>
Or, use your mail client's PGP/GPG signing capabilities.
NOTE! In order to publish a package on the FSF FTP site you need to have my
GPG private key, and my passphrase to unlock it.
Depending on your distribution (whether GnuPG is integrated with your
keyring etc.) the upload operation will either pop up a window asking
for the GPG key passphrase one time, or else it will use the CLI to ask
for the GPG passphrase _THREE_ times. Sigh.
Publishing a Release Candidate
------------------------------
Usually I publish one or two release candidates for people to test before
making an official release. Release candidates use a GNU numbering scheme,
which add a ".9x" release number to the PREVIOUS major release. So the first
release candidate for GNU Make 4.4 would be GNU Make 4.3.90, the second
release candidate would be 4.3.91, etc.
Upload a release candidate using:
make upload-alpha
Announce a release candidate to these mailing lists:
To: bug-make@gnu.org
BCC: help-make@gnu.org, make-w32@gnu.org, make-alpha@gnu.org
You will have to approve the BCC's on the mailing list admin sites. Send
separate copies to (don't use CC as replies will go to these lists):
* coordinator@translationproject.org
* platform-testers@gnu.org
Publishing a Release
--------------------
When publishing a final release there are extra steps that need to be taken:
* Run "make update-makeweb" to get a copy of the GNU Make web pages
* Run "make update-gnuweb" to get a copy of the GNU website boilerplate pages
* Update the web page boilerplate if necessary:
( cd ~/src/make/make-web \
&& ~/src/gnu-www/www/server/standards/patch-from-parent \
make.html \
~/src/gnu-www/www/server/standards/boilerplate.html )
* Run "make gendocs" (requires gnulib) to generate the manual files for
the GNU Make web pages.
* Follow the directions from gendocs for the web page repository
Manage the Savannah project for GNU Make:
>>> This is only for real releases, not release candidate builds <<<
* In Savannah edit the "Component Version" field and choose the "SCM" entry.
Modify the "Value", "Rank", and "Description" values for the to refer to
the new release. The "Rank" field should be 10 less than the previous
release so it orders properly.
* In Savannah modify the "Value", "Rank", and "Description" values for the
current "SCM" entry in both "Component Version" and "Fix Release" fields
to refer to the new release. The "Rank" field should be 10 less than the
previous release so it orders properly.
* In Savannah create a new entry for the "Component Version" and "Fix
Release" fields:
* In Savannah edit the "Fixed Release" field and choose the "SCM" entry.
Modify the "Value", "Rank", and "Description" values for the to refer to
the new release. The "Rank" field should be 10 less than the previous
release so it orders properly.
* In Savannah create a new entry for the "Component Version" field:
- Value: SCM
- Rank: 20
- Descr: Issues found in code retrieved from Source Code Management (Git), rather than a distributed version. Please include the SHA you are working with.
* In Savannah create a new entry for the "Fix Release" field:
- Value: SCM
- Rank: 20
- Descr: Fixed in Source Code Management (Git). The fix will be included in the next release of GNU Make.
Upload a release using:
make upload-ftp
Announce a release to these mailing lists:
To: info-gnu@gnu.org, bug-make@gnu.org
BCC: help-make@gnu.org, make-w32@gnu.org, make-alpha@gnu.org
You will have to approve the BCC's on the mailing list admin sites. Send
separate copies to (don't use CC as replies will go to these lists):
* coordinator@translationproject.org
* platform-testers@gnu.org
Announce on Savannah:
* Add a news item to the Savannah project site.
Start the next release:
* Update configure.ac and add a ".90" to the release number.
@ -285,66 +389,6 @@ Start the next release:
* Update the Savannah URL for the bugs fixed in the NEWS section.
Publishing a Package
--------------------
In order to publish a package on the FSF FTP site, either the release
site ftp://ftp.gnu.org, or the prerelease site ftp://alpha.gnu.org, you
first need to have my GPG private key and my passphrase to unlock it.
And, you can't have them! So there! But, just so I remember here's
what to do:
Make sure the "Steps to Release" are complete and committed and tagged.
git clone git://git.savannah.gnu.org/make.git make-release
cd make-release
<run the commands above to build the release>
make upload-alpha # for alpha.gnu.org (pre-releases)
-OR-
make upload-ftp # for ftp.gnu.org (official releases)
Depending on your distribution (whether GnuPG is integrated with your keyring
etc.) it will either pop up a window asking for your GPG key passphrase one
time, or else it will use the CLI to ask for the GPG passphrase _THREE_ times.
Sigh.
For both final releases and pre-releases, send an email with the URL of
the package to the GNU translation robot to allow the translators to
work on it:
<coordinator@translationproject.org>
Where to Announce
-----------------
Create the announcement in a text file, using 'git shortlog',
then sign it with GPG:
gpg --clearsign <announcement.txt>
Or, use your mail client's PGP/GPG signing capabilities.
Announce the release:
* For release candidate builds:
To: bug-make@gnu.org
CC: coordinator@translationproject.org, platform-testers@gnu.org
BCC: help-make@gnu.org, make-w32@gnu.org, make-alpha@gnu.org
* For release builds
To: info-gnu@gnu.org, bug-make@gnu.org
CC: coordinator@translationproject.org
BCC: help-make@gnu.org, make-w32@gnu.org, make-alpha@gnu.org
* Add a news item to the Savannah project site.
* Add an update to freecode.com (nee freshmeat.net)
Appendix A - For The Brave
--------------------------
@ -360,6 +404,6 @@ For a debugging version:
./bootstrap && ./configure CFLAGS=-g && make check
For a release version
For an optimized version
./bootstrap && ./configure && make check

View File

@ -3,11 +3,15 @@ This directory contains the @PACKAGE_VERSION@ release of @PACKAGE_NAME@.
See the file NEWS for the user-visible changes from previous releases.
In addition, there have been bugs fixed.
>> If you are trying to build GNU Make from a Git clone rather than a
>> downloaded source distribution, see the README.git file for instructions.
Please check the system-specific notes below for any caveats related to your
operating system.
If you are trying to build GNU Make from a Git clone rather than a downloaded
source distribution, see the README.git file for instructions.
This README assumes you are building on a POSIX-based operating system.
For ports to other operating systems please see the system-specific README
files, as described in the "Ports" section below.
For source distribution building and installation instructions, see the file
INSTALL.
@ -29,6 +33,7 @@ GNU Make is copyright by the Free Software Foundation. Copyright notices
condense sequential years into a range; e.g. "1987-1994" means all years
from 1987 to 1994 inclusive.
Downloading
-----------
@ -66,6 +71,19 @@ You can find most information concerning the development of GNU Make at
this site.
Regression Tests
----------------
GNU Make contains a suite of regression tests. To run them use "make check"
after building GNU Make. If they fail a tar package will be created
containing useful information, which can be emailed (as an attachment) to
the <bug-make@gnu.org> mailing list.
Please note that since these tests rely on known-good-output comparisons,
they can show spurious failures on some systems (particularly non-POSIX systems
such as Windows).
Bug Reporting
-------------
@ -127,16 +145,6 @@ known to be broken to be checked in. Use at your own risk.
System-specific Notes
---------------------
It has been reported that the XLC 1.2 compiler on AIX 3.2 is buggy such
that if you compile make with 'cc -O' on AIX 3.2, it will not work
correctly. It is said that using 'cc' without '-O' does work.
The standard /bin/sh on SunOS 4.1.3_U1 and 4.1.4 is broken and cannot be
used to configure GNU Make. Please install a different shell such as
bash or pdksh in order to run "configure". See this message for more
information:
https://mail.gnu.org/archive/html/bug-autoconf/2003-10/msg00190.html
One area that is often a problem in configuration and porting is the code
to check the system's current load average. To make it easier to test and
debug this code, you can do 'make check-loadavg' to see if it works
@ -169,7 +177,7 @@ Ports
- See README.VMS for details about GNU Make on OpenVMS.
- See README.Amiga for details about GNU Make on AmigaDOS.
- See README.zOS for details about GNU Make on z/OS.
- See README.W32 for details about GNU Make on Windows NT, 95, or 98.
@ -186,13 +194,13 @@ Ports
it you should start by asking on those mailing lists and forums.
Please note there are two _separate_ ports of GNU Make for Microsoft
systems: a native Windows tool built with (for example) MSVC or Cygwin,
and a DOS-based tool built with DJGPP. Please be sure you are looking
systems: a native Windows port built with (for example) MSVC or MinGW,
and a DOS-based port built with DJGPP. Please be sure you are looking
at the right README!
-------------------------------------------------------------------------------
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

83
README.zOS Normal file
View File

@ -0,0 +1,83 @@
-*-text-*-
GNU Make has been ported to z/OS, tested on z/OS V2R4.
PREREQUISITES
-------------
Building GNU Make requires certain tools be installed on your z/OS system.
These tools can be downloaded from: https://github.com/ZOSOpenTools
For detailed instructions on how to set up these tools, visit
https://zosopentools.github.io/meta/#/Guides/Pre-req
You will need curl, tar, and gzip to download and unpack the GNU Make release
package, but presumably you've already worked this out if you're reading this
document!
You will need the IBM C/C++ compiler. You can download a web deliverable
add-on feature to your XL C/C++ compiler here:
https://www-40.ibm.com/servers/resourcelink/svc00100.nsf/pages/xlCC++V241ForZOsV24
Alternatively, you can install and manage C/C++ for Open Enterprise Languages
on z/OS using RedHat OpenShift Container Platform and IBM Z and Cloud
Modernization Stack.
GNU Make has a dependency on the ZOSLIB library, which is documented here:
https://zosopentools.github.io/meta/#/Guides/Zoslib.
To obtain the latest release of zoslib, you can download it from here:
https://github.com/ZOSOpenTools/zoslibport/releases.
BUILDING
--------
If you are trying to build from a checked-out Git workspace, see README.git.
Before building GNU Make, you will need to ensure that the following
environment variables are set, to turn on z/OS enhanced ASCII support:
export _BPXK_AUTOCVT=ON
export _CEE_RUNOPTS="$_CEE_RUNOPTS FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)"
export _TAG_REDIR_ERR=txt
export _TAG_REDIR_IN=txt
export _TAG_REDIR_OUT=txt
To ensure proper functioning of xlclang, set the following environment
variables before building:
export _CC_CCMODE=1
export _C89_CCMODE=1
export _CXX_CCMODE=1
Set PATH_TO_ZOSLIB to the location of your zoslib installation; e.g.:
PATH_TO_ZOSLIB=$HOME/zopen/prod/zoslib
Invoke ./configure as follows:
./configure \
CC=xlclang \
CPPFLAGS="-DNSIG=42 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE -D_OPEN_SYS_FILE_EXT=1 -D_AE_BIMODAL=1 -D_ENHANCED_ASCII_EXT=0xFFFFFFF -DZOSLIB_OVERRIDE_CLIB=1" \
CFLAGS="-qascii -std=gnu11 -qnocsect -qenum=int -I$PATH_TO_ZOSLIB/include" \
LDFLAGS="-L$PATH_TO_ZOSLIB/lib" \
LIBS="-lzoslib $PATH_TO_ZOSLIB/lib/CXXRT64.x"
If you have an instance of make already available you can build with:
make
If not, you can build with:
./build.sh
TESTING
-------
To run the regression tests you'll need to install Perl and enable it.
Then you can run:
./make check
INSTALLING
----------
Copy the "make" program to wherever you want it to be installed, on your PATH.

View File

@ -1,13 +0,0 @@
ERRORREXX
OPTIMIZE
NOVERSION
OPTIMIZERTIME
OPTIMIZERALIAS
DEFINE HAVE_CONFIG_H
DEFINE INCLUDEDIR="include:"
DEFINE LIBDIR="lib:"
DEFINE NO_ALLOCA
DEFINE NO_ARCHIVES
IGNORE=161
IGNORE=100
STARTUP=cres

View File

@ -101,7 +101,7 @@ The Rest of the List
-------------------------------------------------------------------------------
Copyright (C) 1997-2022 Free Software Foundation, Inc.
Copyright (C) 1997-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -4,7 +4,7 @@
# also regenerates all aclocal.m4, config.h.in, Makefile.in, configure files
# with new versions of autoconf or automake.
# Copyright (C) 2003-2022 Free Software Foundation, Inc.
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -30,457 +30,10 @@
# Alternatively, you can use an autogen.sh script that is specific
# to your package.
scriptversion=2022-07-24.15; # UTC
me="$0"
medir=`dirname "$me"`
# Read the function library and the configuration.
. "$medir"/bootstrap-funclib.sh
# Ensure that CDPATH is not set. Otherwise, the output from cd
# would cause trouble in at least one use below.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Environment variables that may be set by the user.
: "${AUTOPOINT=autopoint}"
: "${AUTORECONF=autoreconf}"
if test "$vc_ignore" = auto; then
vc_ignore=
test -d .git && vc_ignore=.gitignore
test -d CVS && vc_ignore="$vc_ignore .cvsignore"
fi
usage() {
cat <<EOF
Usage: $me [OPTION]...
Bootstrap this package from the checked-out sources.
Optional environment variables:
GNULIB_SRCDIR Specifies the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
you want to use these sources.
Options:
--copy copy files instead of creating symbolic links
--force attempt to bootstrap even if the sources seem
not to have been checked out
EOF
bootstrap_print_option_usage_hook
cat <<EOF
If the file bootstrap.conf exists in the same directory as this script, its
contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Gnulib sources are assumed to be present:
* in \$GNULIB_SRCDIR, if that environment variable is set,
* otherwise, in the 'gnulib' submodule, if such a submodule is configured,
* otherwise, in the 'gnulib' subdirectory.
Running without arguments will suffice in most cases.
EOF
}
# Parse options.
# Whether to use copies instead of symlinks.
copy=false
for option
do
case $option in
--help)
usage
exit;;
--version)
set -e
echo "autogen.sh $scriptversion"
echo "$copyright"
exit 0
;;
--force)
checkout_only_file=;;
--copy)
copy=true;;
*)
bootstrap_option_hook $option || die "$option: unknown option";;
esac
done
test -z "$GNULIB_SRCDIR" || test -d "$GNULIB_SRCDIR" \
|| die "Error: \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory"
if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Running this script from a non-checked-out distribution is risky."
fi
if $use_gnulib; then
if test -z "$GNULIB_SRCDIR"; then
gnulib_path=$(test -f .gitmodules && git config --file .gitmodules submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
GNULIB_SRCDIR=$gnulib_path
fi
fi
version_controlled_file() {
parent=$1
file=$2
if test -d .git; then
git rm -n "$file" > /dev/null 2>&1
elif test -d .svn; then
svn log -r HEAD "$file" > /dev/null 2>&1
elif test -d CVS; then
grep -F "/${file##*/}/" "$parent/CVS/Entries" 2>/dev/null |
grep '^/[^/]*/[0-9]' > /dev/null
else
warn_ "no version control for $file?"
false
fi
}
# Strip blank and comment lines to leave significant entries.
gitignore_entries() {
sed '/^#/d; /^$/d' "$@"
}
# If $STR is not already on a line by itself in $FILE, insert it at the start.
# Entries are inserted at the start of the ignore list to ensure existing
# entries starting with ! are not overridden. Such entries support
# whitelisting exceptions after a more generic blacklist pattern.
insert_if_absent() {
file=$1
str=$2
test -f $file || touch $file
test -r $file || die "Error: failed to read ignore file: $file"
duplicate_entries=$(gitignore_entries $file | sort | uniq -d)
if [ "$duplicate_entries" ] ; then
die "Error: Duplicate entries in $file: " $duplicate_entries
fi
linesold=$(gitignore_entries $file | wc -l)
linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l)
if [ $linesold != $linesnew ] ; then
{ echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \
|| die "insert_if_absent $file $str: failed"
fi
}
# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with
# insert_if_absent.
insert_vc_ignore() {
vc_ignore_file="$1"
pattern="$2"
case $vc_ignore_file in
*.gitignore)
# A .gitignore entry that does not start with '/' applies
# recursively to subdirectories, so prepend '/' to every
# .gitignore entry.
pattern=$(echo "$pattern" | sed s,^,/,);;
esac
insert_if_absent "$vc_ignore_file" "$pattern"
}
symlink_to_dir()
{
src=$1/$2
dst=${3-$2}
test -f "$src" && {
# If the destination directory doesn't exist, create it.
# This is required at least for "lib/uniwidth/cjk.h".
dst_dir=$(dirname "$dst")
if ! test -d "$dst_dir"; then
mkdir -p "$dst_dir"
# If we've just created a directory like lib/uniwidth,
# tell version control system(s) it's ignorable.
# FIXME: for now, this does only one level
parent=$(dirname "$dst_dir")
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_vc_ignore $ig "${dst_dir##*/}"
done
fi
if $copy; then
{
test ! -h "$dst" || {
echo "$me: rm -f $dst" &&
rm -f "$dst"
}
} &&
test -f "$dst" &&
cmp -s "$src" "$dst" || {
echo "$me: cp -fp $src $dst" &&
cp -fp "$src" "$dst"
}
else
# Leave any existing symlink alone, if it already points to the source,
# so that broken build tools that care about symlink times
# aren't confused into doing unnecessary builds. Conversely, if the
# existing symlink's timestamp is older than the source, make it afresh,
# so that broken tools aren't confused into skipping needed builds. See
# <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00326.html>.
test -h "$dst" &&
src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 &&
dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 &&
test "$src_i" = "$dst_i" &&
both_ls=$(ls -dt "$src" "$dst") &&
test "X$both_ls" = "X$dst$nl$src" || {
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
*//* | */../* | */./* | /*/*/*/*/*/)
die "invalid symlink calculation: $src -> $dst";;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
echo "$me: ln -fs $dot_dots$src $dst" &&
ln -fs "$dot_dots$src" "$dst"
}
fi
}
}
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
found_aux_dir=no
grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'])' configure.ac \
>/dev/null && found_aux_dir=yes
grep '^[ ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
>/dev/null && found_aux_dir=yes
test $found_aux_dir = yes \
|| die "configure.ac lacks 'AC_CONFIG_AUX_DIR([$build_aux])'; add it"
# If $build_aux doesn't exist, create it now, otherwise some bits
# below will malfunction. If creating it, also mark it as ignored.
if test ! -d $build_aux; then
mkdir $build_aux
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
insert_vc_ignore $dot_ig $build_aux
done
fi
check_build_prerequisites false
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
# but that's not portable enough (e.g., for Solaris).
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
&& use_libtool=1
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
&& use_libtool=1
if test $use_libtool = 1; then
find_tool LIBTOOLIZE glibtoolize libtoolize
fi
if $use_gnulib; then
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
<$gnulib_tool || exit $?
fi
# NOTE: we have to be careful to run both autopoint and libtoolize
# before gnulib-tool, since gnulib-tool is likely to provide newer
# versions of files "installed" by these two programs.
# Then, *after* gnulib-tool (see below), we have to be careful to
# run autoreconf in such a way that it does not run either of these
# two just-pre-run programs.
# Import from gettext.
with_gettext=yes
grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
with_gettext=no
if test $with_gettext = yes || test $use_libtool = 1; then
tempbase=.bootstrap$$
trap "rm -f $tempbase.0 $tempbase.1" 1 2 13 15
> $tempbase.0 > $tempbase.1 &&
find . ! -type d -print | sort > $tempbase.0 || exit
if test $with_gettext = yes; then
# Released autopoint has the tendency to install macros that have been
# obsoleted in current gnulib, so run this before gnulib-tool.
echo "$0: $AUTOPOINT --force"
$AUTOPOINT --force || exit
fi
# Autoreconf runs aclocal before libtoolize, which causes spurious
# warnings if the initial aclocal is confused by the libtoolized
# (or worse out-of-date) macro directory.
# libtoolize 1.9b added the --install option; but we support back
# to libtoolize 1.5.22, where the install action was default.
if test $use_libtool = 1; then
install=
case $($LIBTOOLIZE --help) in
*--install*) install=--install ;;
esac
echo "running: $LIBTOOLIZE $install --copy"
$LIBTOOLIZE $install --copy
fi
find . ! -type d -print | sort >$tempbase.1
old_IFS=$IFS
IFS=$nl
for file in $(comm -13 $tempbase.0 $tempbase.1); do
IFS=$old_IFS
parent=${file%/*}
version_controlled_file "$parent" "$file" || {
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_vc_ignore "$ig" "${file##*/}"
done
}
done
IFS=$old_IFS
rm -f $tempbase.0 $tempbase.1
trap - 1 2 13 15
fi
# Import from gnulib.
if $use_gnulib; then
gnulib_tool_options="\
--no-changelog\
--aux-dir=$build_aux\
--doc-base=$doc_base\
--lib=$gnulib_name\
--m4-base=$m4_base/\
--source-base=$source_base/\
--tests-base=$tests_base\
--local-dir=$local_gl_dir\
$gnulib_tool_option_extras\
"
if test $use_libtool = 1; then
case "$gnulib_tool_options " in
*' --libtool '*) ;;
*) gnulib_tool_options="$gnulib_tool_options --libtool" ;;
esac
fi
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules \
|| die "gnulib-tool failed"
for file in $gnulib_files; do
symlink_to_dir "$GNULIB_SRCDIR" $file \
|| die "failed to symlink $file"
done
fi
bootstrap_post_import_hook \
|| die "bootstrap_post_import_hook failed"
# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some
# gnulib-populated directories. Such .m4 files would cause aclocal to fail.
# The following requires GNU find 4.2.3 or newer. Considering the usual
# portability constraints of this script, that may seem a very demanding
# requirement, but it should be ok. Ignore any failure, which is fine,
# since this is only a convenience to help developers avoid the relatively
# unusual case in which a symlinked-to .m4 file is git-removed from gnulib
# between successive runs of this script.
find "$m4_base" "$source_base" \
-depth \( -name '*.m4' -o -name '*.[ch]' \) \
-type l -xtype l -delete > /dev/null 2>&1
# Invoke autoreconf with --force --install to ensure upgrades of tools
# such as ylwrap.
AUTORECONFFLAGS="--verbose --install --force -I $m4_base $ACLOCAL_FLAGS"
# Some systems (RHEL 5) are using ancient autotools, for which the
# --no-recursive option had not been invented. Detect that lack and
# omit the option when it's not supported. FIXME in 2017: remove this
# hack when RHEL 5 autotools are updated, or when they become irrelevant.
case $($AUTORECONF --help) in
*--no-recursive*) AUTORECONFFLAGS="$AUTORECONFFLAGS --no-recursive";;
esac
# Tell autoreconf not to invoke autopoint or libtoolize; they were run above.
echo "running: AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS"
AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS \
|| die "autoreconf failed"
# Get some extra files from gnulib, overriding existing files.
for file in $gnulib_extra_files; do
case $file in
*/INSTALL) dst=INSTALL;;
build-aux/*) dst=$build_aux/${file#build-aux/};;
*) dst=$file;;
esac
symlink_to_dir "$GNULIB_SRCDIR" $file $dst \
|| die "failed to symlink $file"
done
if test $with_gettext = yes; then
# Create gettext configuration.
echo "$0: Creating po/Makevars from po/Makevars.template ..."
rm -f po/Makevars
sed '
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^COPYRIGHT_HOLDER *=/s/=.*/= '"$COPYRIGHT_HOLDER"'/
/^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$MSGID_BUGS_ADDRESS"'|
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' po/Makevars.template >po/Makevars \
|| die 'cannot generate po/Makevars'
# If the 'gettext' module is in use, grab the latest Makefile.in.in.
# If only the 'gettext-h' module is in use, assume autopoint already
# put the correct version of this file into place.
case $gnulib_modules in
*gettext-h*) ;;
*gettext*)
cp $GNULIB_SRCDIR/build-aux/po/Makefile.in.in po/Makefile.in.in \
|| die "cannot create po/Makefile.in.in"
;;
esac
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
rm -f runtime-po/Makevars
sed '
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
/^subdir *=.*/s/=.*/= runtime-po/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
}
' po/Makevars.template >runtime-po/Makevars \
|| die 'cannot generate runtime-po/Makevars'
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
fi
fi
bootstrap_epilogue
echo "$0: done. Now you can run './configure'."
# ----------------------------------------------------------------------------
# Local Variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
autogen "$@"

View File

@ -2,7 +2,7 @@
# Convenience script for fetching auxiliary files that are omitted from
# the version control repository of this package.
# Copyright (C) 2003-2022 Free Software Foundation, Inc.
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -28,246 +28,10 @@
# Alternatively, you can use an autopull.sh script that is specific
# to your package.
scriptversion=2022-07-24.15; # UTC
me="$0"
medir=`dirname "$me"`
# Read the function library and the configuration.
. "$medir"/bootstrap-funclib.sh
# Ensure that CDPATH is not set. Otherwise, the output from cd
# would cause trouble in at least one use below.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
usage() {
cat <<EOF
Usage: $me [OPTION]...
Bootstrap this package from the checked-out sources.
Optional environment variables:
GNULIB_SRCDIR Specifies the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
you want to use these sources.
GNULIB_REFDIR Specifies the local directory where a gnulib
repository (with a .git subdirectory) resides.
Use this if you already have gnulib sources
and history on your machine, and do not want
to waste your bandwidth downloading them again.
GNULIB_URL Cloneable URL of the gnulib repository.
Options:
--bootstrap-sync if this bootstrap script is not identical to
the version in the local gnulib sources,
update this script, and then restart it with
/bin/sh or the shell \$CONFIG_SHELL
--no-bootstrap-sync do not check whether bootstrap is out of sync
--force attempt to bootstrap even if the sources seem
not to have been checked out
--no-git do not use git to update gnulib. Requires that
\$GNULIB_SRCDIR or the --gnulib-srcdir option
points to a gnulib repository with the correct
revision
--skip-po do not download po files
EOF
bootstrap_print_option_usage_hook
cat <<EOF
If the file bootstrap.conf exists in the same directory as this script, its
contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Gnulib sources can be fetched in various ways:
* If the environment variable GNULIB_SRCDIR is set (either as an
environment variable or via the --gnulib-srcdir option), then sources
are fetched from that local directory. If it is a git repository and
the configuration variable GNULIB_REVISION is set in bootstrap.conf,
then that revision is checked out.
* Otherwise, if this package is in a git repository with a 'gnulib'
submodule configured, then that submodule is initialized and updated
and sources are fetched from there. If GNULIB_REFDIR is set (either
as an environment variable or via the --gnulib-refdir option) and is
a git repository, then it is used as a reference.
* Otherwise, if the 'gnulib' directory does not exist, Gnulib sources
are cloned into that directory using git from \$GNULIB_URL, defaulting
to $default_gnulib_url.
If the configuration variable GNULIB_REVISION is set in bootstrap.conf,
then that revision is checked out.
* Otherwise, the existing Gnulib sources in the 'gnulib' directory are
used. If it is a git repository and the configuration variable
GNULIB_REVISION is set in bootstrap.conf, then that revision is
checked out.
If you maintain a package and want to pin a particular revision of the
Gnulib sources that has been tested with your package, then there are
two possible approaches: either configure a 'gnulib' submodule with the
appropriate revision, or set GNULIB_REVISION (and if necessary
GNULIB_URL) in bootstrap.conf.
Running without arguments will suffice in most cases.
EOF
}
# Parse options.
# Use git to update gnulib sources
use_git=true
for option
do
case $option in
--help)
usage
exit;;
--version)
set -e
echo "autopull.sh $scriptversion"
echo "$copyright"
exit 0
;;
--skip-po)
SKIP_PO=t;;
--force)
checkout_only_file=;;
--bootstrap-sync)
bootstrap_sync=true;;
--no-bootstrap-sync)
bootstrap_sync=false;;
--no-git)
use_git=false;;
*)
bootstrap_option_hook $option || die "$option: unknown option";;
esac
done
$use_git || test -n "$GNULIB_SRCDIR" \
|| die "Error: --no-git requires \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option"
test -z "$GNULIB_SRCDIR" || test -d "$GNULIB_SRCDIR" \
|| die "Error: \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory"
if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Running this script from a non-checked-out distribution is risky."
fi
check_build_prerequisites $use_git
if $use_gnulib || $bootstrap_sync; then
prepare_GNULIB_SRCDIR
if $bootstrap_sync; then
upgrade_bootstrap
fi
fi
# Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6.
# Also find the compatible sha1 utility on the BSDs
if test x"$SKIP_PO" = x; then
find_tool SHA1SUM sha1sum gsha1sum shasum sha1
fi
# See if we can use gnulib's git-merge-changelog merge driver.
if $use_git && test -d .git && check_exists git; then
if git config merge.merge-changelog.driver >/dev/null ; then
:
elif check_exists git-merge-changelog; then
echo "$0: initializing git-merge-changelog driver"
git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'
git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'
else
echo "$0: consider installing git-merge-changelog from gnulib"
fi
fi
# ----------------------------- Get translations. -----------------------------
download_po_files() {
subdir=$1
domain=$2
echo "$me: getting translations into $subdir for $domain..."
cmd=$(printf "$po_download_command_format" "$subdir" "$domain")
eval "$cmd"
}
# Mirror .po files to $po_dir/.reference and copy only the new
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
# Note po files that exist locally only are left in $po_dir but will
# not be included in LINGUAS and hence will not be distributed.
update_po_files() {
# Directory containing primary .po files.
# Overwrite them only when we're sure a .po file is new.
po_dir=$1
domain=$2
# Mirror *.po files into this dir.
# Usually contains *.s1 checksum files.
ref_po_dir="$po_dir/.reference"
test -d $ref_po_dir || mkdir $ref_po_dir || return
download_po_files $ref_po_dir $domain \
&& ls "$ref_po_dir"/*.po 2>/dev/null |
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS" || return
langs=$(cd $ref_po_dir && echo *.po | sed 's/\.po//g')
test "$langs" = '*' && langs=x
for po in $langs; do
case $po in x) continue;; esac
new_po="$ref_po_dir/$po.po"
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! $SHA1SUM -c "$cksum_file" < "$new_po" > /dev/null 2>&1; then
echo "$me: updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" \
&& $SHA1SUM < "$new_po" > "$cksum_file" || return
fi
done
}
case $SKIP_PO in
'')
if test -d po; then
update_po_files po $package || exit
fi
if test -d runtime-po; then
update_po_files runtime-po $package-runtime || exit
fi;;
esac
# -----------------------------------------------------------------------------
bootstrap_post_pull_hook \
|| die "bootstrap_post_pull_hook failed"
# Don't proceed if there are uninitialized submodules. In particular,
# autogen.sh will remove dangling links, which might be links into
# uninitialized submodules.
# But it's OK if the 'gnulib' submodule is uninitialized, as long as
# GNULIB_SRCDIR is set.
if $use_git; then
# Uninitialized submodules are listed with an initial dash.
uninitialized=`git submodule | grep '^-' | awk '{ print $2 }'`
if test -n "$GNULIB_SRCDIR"; then
uninitialized=`echo "$uninitialized" | grep -v '^gnulib$'`
fi
if test -n "$uninitialized"; then
die "Some git submodules are not initialized: "`echo "$uninitialized" | tr '\n' ',' | sed -e 's|,$|.|'`" Either use option '--no-git', or run 'git submodule update --init' and bootstrap again."
fi
fi
echo "$0: done. Now you can run './autogen.sh'."
# ----------------------------------------------------------------------------
# Local Variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
autopull "$@"

View File

@ -1,7 +1,9 @@
#! /bin/sh
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2022 Free Software Foundation, Inc.
scriptversion=2022-12-27.07; # UTC
# Copyright (C) 2003-2023 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -26,8 +28,6 @@
# Please report bugs or propose patches to bug-gnulib@gnu.org.
scriptversion=2022-07-29.23; # UTC
me="$0"
medir=`dirname "$me"`
@ -48,6 +48,11 @@ Optional environment variables:
GNULIB_URL Cloneable URL of the gnulib repository.
Options:
--pull Do phase 1: pull files from network
--gen Do phase 2: generate from local files.
(The default is to do both phases.)
--gnulib-srcdir=DIRNAME specify the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
@ -59,11 +64,13 @@ Options:
and history on your machine, and do not want
to waste your bandwidth downloading them again.
Defaults to \$GNULIB_REFDIR
--bootstrap-sync if this bootstrap script is not identical to
the version in the local gnulib sources,
update this script, and then restart it with
/bin/sh or the shell \$CONFIG_SHELL
--no-bootstrap-sync do not check whether bootstrap is out of sync
--copy copy files instead of creating symbolic links
--force attempt to bootstrap even if the sources seem
not to have been checked out
@ -118,6 +125,10 @@ EOF
# Parse options.
# Whether to pull and generate.
pull=false
gen=false
# Whether to use copies instead of symlinks.
copy=false
@ -132,10 +143,14 @@ do
exit;;
--version)
set -e
echo "bootstrap $scriptversion"
echo "bootstrap $scriptversion lib $scriptlibversion"
echo "$copyright"
exit 0
;;
--pull)
pull=true;;
--gen)
gen=true;;
--gnulib-srcdir=*)
GNULIB_SRCDIR=${option#--gnulib-srcdir=};;
--gnulib-refdir=*)
@ -157,6 +172,9 @@ do
esac
done
# Default is to do both.
$pull || $gen || pull=true gen=true
$use_git || test -n "$GNULIB_SRCDIR" \
|| die "Error: --no-git requires \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option"
test -z "$GNULIB_SRCDIR" || test -d "$GNULIB_SRCDIR" \
@ -168,12 +186,6 @@ fi
check_build_prerequisites $use_git
if ! test -f "$medir"/bootstrap-funclib.sh; then
# We have only completed the first phase of an upgrade from a bootstrap
# version < 2022-07-24. Need to do the second phase now.
bootstrap_sync=true
fi
if $bootstrap_sync; then
prepare_GNULIB_SRCDIR
upgrade_bootstrap
@ -183,25 +195,25 @@ fi
echo "$0: Bootstrapping from checked-out $package sources..."
# Pass GNULIB_SRCDIR to autopull.sh and autogen.sh.
# Pass GNULIB_SRCDIR and GNULIB_REFDIR to any subsidiary commands that care.
export GNULIB_SRCDIR
# Pass GNULIB_REFDIR to autopull.sh.
export GNULIB_REFDIR
if $use_git || test -z "$SKIP_PO"; then
"$medir"/autopull.sh \
if $pull && { $use_git || test -z "$SKIP_PO"; }; then
autopull \
`if $bootstrap_sync; then echo ' --bootstrap-sync'; else echo ' --no-bootstrap-sync'; fi` \
`if test -z "$checkout_only_file"; then echo ' --force'; fi` \
`if ! $use_git; then echo ' --no-git'; fi` \
`if test -n "$SKIP_PO"; then echo ' --skip-po'; fi` \
|| die "autopull.sh failed."
|| die "could not fetch auxiliary files"
fi
"$medir"/autogen.sh \
if $gen; then
autogen \
`if $copy; then echo ' --copy'; fi` \
`if test -z "$checkout_only_file"; then echo ' --force'; fi` \
|| die "autogen.sh failed."
|| die "could not generate auxiliary files"
fi
# ----------------------------------------------------------------------------

View File

@ -1,6 +1,8 @@
# A library of shell functions for autopull.sh, autogen.sh, and bootstrap.
# Copyright (C) 2003-2022 Free Software Foundation, Inc.
scriptlibversion=2022-12-27.16; # UTC
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -23,8 +25,6 @@
# file also maintained in your version control; gnulib comes with a
# template build-aux/bootstrap.conf to get you started.
scriptversion=2022-07-24.15; # UTC
nl='
'
@ -38,7 +38,7 @@ PERL="${PERL-perl}"
default_gnulib_url=https://git.savannah.gnu.org/git/gnulib.git
# Copyright year, for the --version output.
copyright_year=`echo "$scriptversion" | sed -e 's/[^0-9].*//'`
copyright_year=`echo "$scriptlibversion" | sed -e 's/[^0-9].*//'`
copyright="Copyright (C) ${copyright_year} Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
@ -501,7 +501,7 @@ prepare_GNULIB_SRCDIR ()
elif [ ! -d "$gnulib_path" ]; then
echo "$0: getting gnulib files..."
trap cleanup_gnulib 1 2 13 15
trap cleanup_gnulib HUP INT PIPE TERM
shallow=
if test -z "$GNULIB_REVISION"; then
@ -531,7 +531,7 @@ prepare_GNULIB_SRCDIR ()
git -C "$gnulib_path" reset --hard FETCH_HEAD
fi
trap - 1 2 13 15
trap - HUP INT PIPE TERM
fi
fi
GNULIB_SRCDIR=$gnulib_path
@ -554,18 +554,28 @@ prepare_GNULIB_SRCDIR ()
upgrade_bootstrap ()
{
{ cmp -s "$medir"/bootstrap "$GNULIB_SRCDIR/top/bootstrap" \
&& cmp -s "$medir"/bootstrap-funclib.sh "$GNULIB_SRCDIR/top/bootstrap-funclib.sh" \
&& cmp -s "$medir"/autopull.sh "$GNULIB_SRCDIR/top/autopull.sh" \
&& cmp -s "$medir"/autogen.sh "$GNULIB_SRCDIR/top/autogen.sh"; \
} || {
echo "$0: updating bootstrap & companions and restarting..."
if test -f "$medir"/bootstrap-funclib.sh; then
update_lib=true
{ cmp -s "$medir"/bootstrap "$GNULIB_SRCDIR/top/bootstrap" \
&& cmp -s "$medir"/bootstrap-funclib.sh "$GNULIB_SRCDIR/top/bootstrap-funclib.sh" \
&& cmp -s "$medir"/autopull.sh "$GNULIB_SRCDIR/top/autopull.sh" \
&& cmp -s "$medir"/autogen.sh "$GNULIB_SRCDIR/top/autogen.sh"; \
}
else
update_lib=false
cmp -s "$medir"/bootstrap "$GNULIB_SRCDIR/build-aux/bootstrap"
fi || {
if $update_lib; then
echo "$0: updating bootstrap & companions and restarting..."
else
echo "$0: updating bootstrap and restarting..."
fi
case $(sh -c 'echo "$1"' -- a) in
a) ignored=--;;
*) ignored=ignored;;
esac
exec sh -c \
'{ if test -f "$1"; then cp "$1" "$3"; else cp "$2" "$3"; fi; } && { if test -f "$4"; then cp "$4" "$5"; else rm -f "$5"; fi; } && { if test -f "$6"; then cp "$6" "$7"; else rm -f "$7"; fi; } && { if test -f "$8"; then cp "$8" "$9"; else rm -f "$9"; fi; } && shift && shift && shift && shift && shift && shift && shift && shift && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
'{ if '$update_lib' && test -f "$1"; then cp "$1" "$3"; else cp "$2" "$3"; fi; } && { if '$update_lib' && test -f "$4"; then cp "$4" "$5"; else rm -f "$5"; fi; } && { if '$update_lib' && test -f "$6"; then cp "$6" "$7"; else rm -f "$7"; fi; } && { if '$update_lib' && test -f "$8"; then cp "$8" "$9"; else rm -f "$9"; fi; } && shift && shift && shift && shift && shift && shift && shift && shift && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
$ignored \
"$GNULIB_SRCDIR/top/bootstrap" "$GNULIB_SRCDIR/build-aux/bootstrap" "$medir/bootstrap" \
"$GNULIB_SRCDIR/top/bootstrap-funclib.sh" "$medir/bootstrap-funclib.sh" \
@ -583,11 +593,692 @@ else
use_gnulib=true
fi
# -------- Fetch auxiliary files from the network. --------------------------
autopull_usage() {
cat <<EOF
Usage: $me [OPTION]...
Bootstrap this package from the checked-out sources.
Optional environment variables:
GNULIB_SRCDIR Specifies the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
you want to use these sources.
GNULIB_REFDIR Specifies the local directory where a gnulib
repository (with a .git subdirectory) resides.
Use this if you already have gnulib sources
and history on your machine, and do not want
to waste your bandwidth downloading them again.
GNULIB_URL Cloneable URL of the gnulib repository.
Options:
--bootstrap-sync if this bootstrap script is not identical to
the version in the local gnulib sources,
update this script, and then restart it with
/bin/sh or the shell \$CONFIG_SHELL
--no-bootstrap-sync do not check whether bootstrap is out of sync
--force attempt to bootstrap even if the sources seem
not to have been checked out
--no-git do not use git to update gnulib. Requires that
\$GNULIB_SRCDIR or the --gnulib-srcdir option
points to a gnulib repository with the correct
revision
--skip-po do not download po files
EOF
bootstrap_print_option_usage_hook
cat <<EOF
If the file bootstrap.conf exists in the same directory as this script, its
contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Gnulib sources can be fetched in various ways:
* If the environment variable GNULIB_SRCDIR is set (either as an
environment variable or via the --gnulib-srcdir option), then sources
are fetched from that local directory. If it is a git repository and
the configuration variable GNULIB_REVISION is set in bootstrap.conf,
then that revision is checked out.
* Otherwise, if this package is in a git repository with a 'gnulib'
submodule configured, then that submodule is initialized and updated
and sources are fetched from there. If GNULIB_REFDIR is set (either
as an environment variable or via the --gnulib-refdir option) and is
a git repository, then it is used as a reference.
* Otherwise, if the 'gnulib' directory does not exist, Gnulib sources
are cloned into that directory using git from \$GNULIB_URL, defaulting
to $default_gnulib_url.
If the configuration variable GNULIB_REVISION is set in bootstrap.conf,
then that revision is checked out.
* Otherwise, the existing Gnulib sources in the 'gnulib' directory are
used. If it is a git repository and the configuration variable
GNULIB_REVISION is set in bootstrap.conf, then that revision is
checked out.
If you maintain a package and want to pin a particular revision of the
Gnulib sources that has been tested with your package, then there are
two possible approaches: either configure a 'gnulib' submodule with the
appropriate revision, or set GNULIB_REVISION (and if necessary
GNULIB_URL) in bootstrap.conf.
Running without arguments will suffice in most cases.
EOF
}
# Fetch auxiliary files that are omitted from the version control
# repository of this package.
autopull()
{
# Ensure that CDPATH is not set. Otherwise, the output from cd
# would cause trouble in at least one use below.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Parse options.
# Use git to update gnulib sources
use_git=true
for option
do
case $option in
--help)
autopull_usage
return;;
--version)
set -e
echo "autopull.sh $scriptlibversion"
echo "$copyright"
return 0
;;
--skip-po)
SKIP_PO=t;;
--force)
checkout_only_file=;;
--bootstrap-sync)
bootstrap_sync=true;;
--no-bootstrap-sync)
bootstrap_sync=false;;
--no-git)
use_git=false;;
*)
bootstrap_option_hook $option || die "$option: unknown option";;
esac
done
$use_git || test -n "$GNULIB_SRCDIR" \
|| die "Error: --no-git requires \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option"
test -z "$GNULIB_SRCDIR" || test -d "$GNULIB_SRCDIR" \
|| die "Error: \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory"
if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Running this script from a non-checked-out distribution is risky."
fi
check_build_prerequisites $use_git
if $use_gnulib || $bootstrap_sync; then
prepare_GNULIB_SRCDIR
if $bootstrap_sync; then
upgrade_bootstrap
fi
fi
# Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6.
# Also find the compatible sha1 utility on the BSDs
if test x"$SKIP_PO" = x; then
find_tool SHA1SUM sha1sum gsha1sum shasum sha1
fi
# See if we can use gnulib's git-merge-changelog merge driver.
if $use_git && test -d .git && check_exists git; then
if git config merge.merge-changelog.driver >/dev/null ; then
:
elif check_exists git-merge-changelog; then
echo "$0: initializing git-merge-changelog driver"
git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'
git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'
else
echo "$0: consider installing git-merge-changelog from gnulib"
fi
fi
case $SKIP_PO in
'')
if test -d po; then
update_po_files po $package || return
fi
if test -d runtime-po; then
update_po_files runtime-po $package-runtime || return
fi;;
esac
# ---------------------------------------------------------------------------
bootstrap_post_pull_hook \
|| die "bootstrap_post_pull_hook failed"
# Don't proceed if there are uninitialized submodules. In particular,
# autogen.sh will remove dangling links, which might be links into
# uninitialized submodules.
# But it's OK if the 'gnulib' submodule is uninitialized, as long as
# GNULIB_SRCDIR is set.
if $use_git; then
# Uninitialized submodules are listed with an initial dash.
uninitialized=`git submodule | grep '^-' | awk '{ print $2 }'`
if test -n "$GNULIB_SRCDIR"; then
uninitialized=`echo "$uninitialized" | grep -v '^gnulib$'`
fi
if test -n "$uninitialized"; then
die "Some git submodules are not initialized: "`echo "$uninitialized" | tr '\n' ',' | sed -e 's|,$|.|'`" Either use option '--no-git', or run 'git submodule update --init' and bootstrap again."
fi
fi
echo "$0: done. Now you can run './autogen.sh'."
}
# ----------------------------- Get translations. -----------------------------
download_po_files() {
subdir=$1
domain=$2
echo "$me: getting translations into $subdir for $domain..."
cmd=$(printf "$po_download_command_format" "$subdir" "$domain")
eval "$cmd"
}
# Mirror .po files to $po_dir/.reference and copy only the new
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
# Note po files that exist locally only are left in $po_dir but will
# not be included in LINGUAS and hence will not be distributed.
update_po_files() {
# Directory containing primary .po files.
# Overwrite them only when we're sure a .po file is new.
po_dir=$1
domain=$2
# Mirror *.po files into this dir.
# Usually contains *.s1 checksum files.
ref_po_dir="$po_dir/.reference"
test -d $ref_po_dir || mkdir $ref_po_dir || return
download_po_files $ref_po_dir $domain \
&& ls "$ref_po_dir"/*.po 2>/dev/null |
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS" || return
langs=$(cd $ref_po_dir && echo *.po | sed 's/\.po//g')
test "$langs" = '*' && langs=x
for po in $langs; do
case $po in x) continue;; esac
new_po="$ref_po_dir/$po.po"
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! $SHA1SUM -c "$cksum_file" < "$new_po" > /dev/null 2>&1; then
echo "$me: updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" \
&& $SHA1SUM < "$new_po" > "$cksum_file" || return
fi
done
}
# -------- Generate files automatically from existing sources. --------------
autogen_usage() {
cat <<EOF
Usage: $me [OPTION]...
Bootstrap this package from the checked-out sources.
Optional environment variables:
GNULIB_SRCDIR Specifies the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
you want to use these sources.
Options:
--copy copy files instead of creating symbolic links
--force attempt to bootstrap even if the sources seem
not to have been checked out
EOF
bootstrap_print_option_usage_hook
cat <<EOF
If the file bootstrap.conf exists in the same directory as this script, its
contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Gnulib sources are assumed to be present:
* in \$GNULIB_SRCDIR, if that environment variable is set,
* otherwise, in the 'gnulib' submodule, if such a submodule is configured,
* otherwise, in the 'gnulib' subdirectory.
Running without arguments will suffice in most cases.
EOF
}
version_controlled_file() {
parent=$1
file=$2
if test -d .git; then
git rm -n "$file" > /dev/null 2>&1
elif test -d .svn; then
svn log -r HEAD "$file" > /dev/null 2>&1
elif test -d CVS; then
grep -F "/${file##*/}/" "$parent/CVS/Entries" 2>/dev/null |
grep '^/[^/]*/[0-9]' > /dev/null
else
warn_ "no version control for $file?"
false
fi
}
# Strip blank and comment lines to leave significant entries.
gitignore_entries() {
sed '/^#/d; /^$/d' "$@"
}
# If $STR is not already on a line by itself in $FILE, insert it at the start.
# Entries are inserted at the start of the ignore list to ensure existing
# entries starting with ! are not overridden. Such entries support
# whitelisting exceptions after a more generic blacklist pattern.
insert_if_absent() {
file=$1
str=$2
test -f $file || touch $file
test -r $file || die "Error: failed to read ignore file: $file"
duplicate_entries=$(gitignore_entries $file | sort | uniq -d)
if [ "$duplicate_entries" ] ; then
die "Error: Duplicate entries in $file: " $duplicate_entries
fi
linesold=$(gitignore_entries $file | wc -l)
linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l)
if [ $linesold != $linesnew ] ; then
{ echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \
|| die "insert_if_absent $file $str: failed"
fi
}
# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with
# insert_if_absent.
insert_vc_ignore() {
vc_ignore_file="$1"
pattern="$2"
case $vc_ignore_file in
*.gitignore)
# A .gitignore entry that does not start with '/' applies
# recursively to subdirectories, so prepend '/' to every
# .gitignore entry.
pattern=$(echo "$pattern" | sed s,^,/,);;
esac
insert_if_absent "$vc_ignore_file" "$pattern"
}
symlink_to_dir()
{
src=$1/$2
dst=${3-$2}
test -f "$src" && {
# If the destination directory doesn't exist, create it.
# This is required at least for "lib/uniwidth/cjk.h".
dst_dir=$(dirname "$dst")
if ! test -d "$dst_dir"; then
mkdir -p "$dst_dir"
# If we've just created a directory like lib/uniwidth,
# tell version control system(s) it's ignorable.
# FIXME: for now, this does only one level
parent=$(dirname "$dst_dir")
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_vc_ignore $ig "${dst_dir##*/}"
done
fi
if $copy; then
{
test ! -h "$dst" || {
echo "$me: rm -f $dst" &&
rm -f "$dst"
}
} &&
test -f "$dst" &&
cmp -s "$src" "$dst" || {
echo "$me: cp -fp $src $dst" &&
cp -fp "$src" "$dst"
}
else
# Leave any existing symlink alone, if it already points to the source,
# so that broken build tools that care about symlink times
# aren't confused into doing unnecessary builds. Conversely, if the
# existing symlink's timestamp is older than the source, make it afresh,
# so that broken tools aren't confused into skipping needed builds. See
# <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00326.html>.
test -h "$dst" &&
src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 &&
dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 &&
test "$src_i" = "$dst_i" &&
both_ls=$(ls -dt "$src" "$dst") &&
test "X$both_ls" = "X$dst$nl$src" || {
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
*//* | */../* | */./* | /*/*/*/*/*/)
die "invalid symlink calculation: $src -> $dst";;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
echo "$me: ln -fs $dot_dots$src $dst" &&
ln -fs "$dot_dots$src" "$dst"
}
fi
}
}
# Regenerate all autogeneratable files that are omitted from the
# version control repository. In particular, regenerate all
# aclocal.m4, config.h.in, Makefile.in, configure files with new
# versions of autoconf or automake.
autogen()
{
# Ensure that CDPATH is not set. Otherwise, the output from cd
# would cause trouble in at least one use below.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Environment variables that may be set by the user.
: "${AUTOPOINT=autopoint}"
: "${AUTORECONF=autoreconf}"
if test "$vc_ignore" = auto; then
vc_ignore=
test -d .git && vc_ignore=.gitignore
test -d CVS && vc_ignore="$vc_ignore .cvsignore"
fi
# Parse options.
# Whether to use copies instead of symlinks.
copy=false
for option
do
case $option in
--help)
autogen_usage
return;;
--version)
set -e
echo "autogen.sh $scriptlibversion"
echo "$copyright"
return 0
;;
--force)
checkout_only_file=;;
--copy)
copy=true;;
*)
bootstrap_option_hook $option || die "$option: unknown option";;
esac
done
test -z "$GNULIB_SRCDIR" || test -d "$GNULIB_SRCDIR" \
|| die "Error: \$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory"
if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Running this script from a non-checked-out distribution is risky."
fi
if $use_gnulib; then
if test -z "$GNULIB_SRCDIR"; then
gnulib_path=$(test -f .gitmodules && git config --file .gitmodules submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
GNULIB_SRCDIR=$gnulib_path
fi
fi
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
found_aux_dir=no
grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'])' configure.ac \
>/dev/null && found_aux_dir=yes
grep '^[ ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
>/dev/null && found_aux_dir=yes
test $found_aux_dir = yes \
|| die "configure.ac lacks 'AC_CONFIG_AUX_DIR([$build_aux])'; add it"
# If $build_aux doesn't exist, create it now, otherwise some bits
# below will malfunction. If creating it, also mark it as ignored.
if test ! -d $build_aux; then
mkdir $build_aux
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
insert_vc_ignore $dot_ig $build_aux
done
fi
check_build_prerequisites false
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
# but that's not portable enough (e.g., for Solaris).
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
&& use_libtool=1
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
&& use_libtool=1
if test $use_libtool = 1; then
find_tool LIBTOOLIZE glibtoolize libtoolize
fi
if $use_gnulib; then
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
<$gnulib_tool || return
fi
# NOTE: we have to be careful to run both autopoint and libtoolize
# before gnulib-tool, since gnulib-tool is likely to provide newer
# versions of files "installed" by these two programs.
# Then, *after* gnulib-tool (see below), we have to be careful to
# run autoreconf in such a way that it does not run either of these
# two just-pre-run programs.
# Import from gettext.
with_gettext=yes
grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
with_gettext=no
if test $with_gettext = yes || test $use_libtool = 1; then
tempbase=.bootstrap$$
trap "rm -f $tempbase.0 $tempbase.1" HUP INT PIPE TERM
> $tempbase.0 > $tempbase.1 &&
find . ! -type d -print | sort > $tempbase.0 || return
if test $with_gettext = yes; then
# Released autopoint has the tendency to install macros that have been
# obsoleted in current gnulib, so run this before gnulib-tool.
echo "$0: $AUTOPOINT --force"
$AUTOPOINT --force || return
fi
# Autoreconf runs aclocal before libtoolize, which causes spurious
# warnings if the initial aclocal is confused by the libtoolized
# (or worse out-of-date) macro directory.
# libtoolize 1.9b added the --install option; but we support back
# to libtoolize 1.5.22, where the install action was default.
if test $use_libtool = 1; then
install=
case $($LIBTOOLIZE --help) in
*--install*) install=--install ;;
esac
echo "running: $LIBTOOLIZE $install --copy"
$LIBTOOLIZE $install --copy
fi
find . ! -type d -print | sort >$tempbase.1
old_IFS=$IFS
IFS=$nl
for file in $(comm -13 $tempbase.0 $tempbase.1); do
IFS=$old_IFS
parent=${file%/*}
version_controlled_file "$parent" "$file" || {
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_vc_ignore "$ig" "${file##*/}"
done
}
done
IFS=$old_IFS
rm -f $tempbase.0 $tempbase.1
trap - HUP INT PIPE TERM
fi
# Import from gnulib.
if $use_gnulib; then
gnulib_tool_options="\
--no-changelog\
--aux-dir=$build_aux\
--doc-base=$doc_base\
--lib=$gnulib_name\
--m4-base=$m4_base/\
--source-base=$source_base/\
--tests-base=$tests_base\
--local-dir=$local_gl_dir\
$gnulib_tool_option_extras\
"
if test $use_libtool = 1; then
case "$gnulib_tool_options " in
*' --libtool '*) ;;
*) gnulib_tool_options="$gnulib_tool_options --libtool" ;;
esac
fi
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules \
|| die "gnulib-tool failed"
for file in $gnulib_files; do
symlink_to_dir "$GNULIB_SRCDIR" $file \
|| die "failed to symlink $file"
done
fi
bootstrap_post_import_hook \
|| die "bootstrap_post_import_hook failed"
# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some
# gnulib-populated directories. Such .m4 files would cause aclocal to fail.
# The following requires GNU find 4.2.3 or newer. Considering the usual
# portability constraints of this script, that may seem a very demanding
# requirement, but it should be ok. Ignore any failure, which is fine,
# since this is only a convenience to help developers avoid the relatively
# unusual case in which a symlinked-to .m4 file is git-removed from gnulib
# between successive runs of this script.
find "$m4_base" "$source_base" \
-depth \( -name '*.m4' -o -name '*.[ch]' \) \
-type l -xtype l -delete > /dev/null 2>&1
# Invoke autoreconf with --force --install to ensure upgrades of tools
# such as ylwrap.
AUTORECONFFLAGS="--verbose --install --force -I $m4_base $ACLOCAL_FLAGS"
# Some systems (RHEL 5) are using ancient autotools, for which the
# --no-recursive option had not been invented. Detect that lack and
# omit the option when it's not supported. FIXME in 2017: remove this
# hack when RHEL 5 autotools are updated, or when they become irrelevant.
case $($AUTORECONF --help) in
*--no-recursive*) AUTORECONFFLAGS="$AUTORECONFFLAGS --no-recursive";;
esac
# Tell autoreconf not to invoke autopoint or libtoolize; they were run above.
echo "running: AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS"
AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS \
|| die "autoreconf failed"
# Get some extra files from gnulib, overriding existing files.
for file in $gnulib_extra_files; do
case $file in
*/INSTALL) dst=INSTALL;;
build-aux/*) dst=$build_aux/${file#build-aux/};;
*) dst=$file;;
esac
symlink_to_dir "$GNULIB_SRCDIR" $file $dst \
|| die "failed to symlink $file"
done
if test $with_gettext = yes; then
# Create gettext configuration.
echo "$0: Creating po/Makevars from po/Makevars.template ..."
rm -f po/Makevars
sed '
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^COPYRIGHT_HOLDER *=/s/=.*/= '"$COPYRIGHT_HOLDER"'/
/^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$MSGID_BUGS_ADDRESS"'|
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' po/Makevars.template >po/Makevars \
|| die 'cannot generate po/Makevars'
# If the 'gettext' module is in use, grab the latest Makefile.in.in.
# If only the 'gettext-h' module is in use, assume autopoint already
# put the correct version of this file into place.
case $gnulib_modules in
*gettext-h*) ;;
*gettext*)
cp $GNULIB_SRCDIR/build-aux/po/Makefile.in.in po/Makefile.in.in \
|| die "cannot create po/Makefile.in.in"
;;
esac
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
rm -f runtime-po/Makevars
sed '
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
/^subdir *=.*/s/=.*/= runtime-po/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
}
' po/Makevars.template >runtime-po/Makevars \
|| die 'cannot generate runtime-po/Makevars'
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
fi
fi
bootstrap_epilogue
echo "$0: done. Now you can run './configure'."
}
# ----------------------------------------------------------------------------
# Local Variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-start: "scriptlibversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"

View File

@ -1,5 +1,5 @@
@echo off
:: Copyright (C) 2018-2022 Free Software Foundation, Inc.
:: Copyright (C) 2018-2024 Free Software Foundation, Inc.
:: This file is part of GNU Make.
::
:: GNU Make is free software; you can redistribute it and/or modify it under
@ -45,6 +45,13 @@ call :Download lib intprops-internal.h
echo -- Configuring the workspace
copy /Y gl\lib\*.* lib > nul
:: In general it's tricky to use special characters as arguments to a program
:: in Windows batch files; the quoting rules are obscure and have changed over
:: time which means older systems may behave differently. However, Windows
:: echo is a dumb program that just writes out its command line without much
:: interpreting: all we have to be careful of is ^ quoting. So, use echo
:: to create script files to use with sed -f rather than using sed -e.
:: Create a sed script to convert templates
if exist convert.sed del /Q convert.sed
echo s,@PACKAGE@,make,g > convert.sed
@ -56,9 +63,17 @@ if ERRORLEVEL 1 goto Failed
echo s,@PACKAGE_TARNAME@,make,g >> convert.sed
if ERRORLEVEL 1 goto Failed
echo s,@PACKAGE_URL@,https://www.gnu.org/software/make/,g >> convert.sed
sed -n "s/^AC_INIT(\[GNU.Make\],\[\([0-9.]*\)\].*/s,@PACKAGE_VERSION@,\1,g/p" configure.ac >> convert.sed
echo s/^^AC_INIT^(\[GNU.Make\],\[\^([0-9.]*\^)\].*/s,@PACKAGE_VERSION@,\1,g/p > cac.sed
sed -n -f cac.sed configure.ac >> convert.sed
if ERRORLEVEL 1 goto Failed
sed -z -e s/\\\n//g -e "s/[ \t][ \t]*/ /g" -e "s, [^ ]*\.h,,g" -e "s,src/,$(src),g" -e "s,lib/,$(lib),g" Makefile.am | sed -n "s/^\([A-Za-z0-9]*\)_SRCS *= *\(.*\)/s,%%\1_SOURCES%%,\2,/p" >> convert.sed
:: Get the list of sources from Makefile.am
echo s,\\\n,,g > mam.sed
echo s,[ \t][ \t]*, ,g >> mam.sed
echo s, [^^ ]*\.h,,g >> mam.sed
echo s,src/,$^(src^),g >> mam.sed
echo s,lib/,$^(lib^),g >> mam.sed
echo s/^^\^([A-Za-z0-9]*\^)_SRCS *= *\^(.*\^)/s,%%\1_SOURCES%%,\2,/p > mam2.sed
sed -z -f mam.sed Makefile.am | sed -n -f mam2.sed >> convert.sed
if ERRORLEVEL 1 goto Failed
echo - Creating Basic.mk
@ -70,12 +85,22 @@ if ERRORLEVEL 1 goto Failed
echo - Creating src\gmk-default.h
echo static const char *const GUILE_module_defn = ^" \ > src\gmk-default.h
sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\\/" src\gmk-default.scm >> src\gmk-default.h
echo s/;.*// > gmk.sed
echo /^^[ \t]*$/d >> gmk.sed
echo s/"/\\"/g >> gmk.sed
echo s/$/ \\/ >> gmk.sed
sed -f gmk.sed src\gmk-default.scm >> src\gmk-default.h
if ERRORLEVEL 1 goto Failed
echo ^";>> src\gmk-default.h
:: These files would be created by bootstrap; they are not needed on Windows
:: but our makefile depends on them
echo >> lib\alloca.in.h
del /Q convert.sed cac.sed mam.sed mam2.sed gmk.sed
echo.
echo Done. Run build_w32.bat to build GNU make.
echo Done. Run build_w32.bat to build GNU Make.
goto :EOF
:Download

View File

@ -1,6 +1,6 @@
# Bootstrap configuration. -*-shell-script-*-
# Copyright (C) 2018-2022 Free Software Foundation, Inc.
# Copyright (C) 2018-2024 Free Software Foundation, Inc.
# GNU Make is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
@ -19,7 +19,7 @@
checkout_only_file=README.git
# Choose a specific version of gnulib, when checking out
GNULIB_REVISION=stable-202207
GNULIB_REVISION=stable-202407
# Always copy files rather than symlink
copy=true
@ -42,8 +42,8 @@ vc_ignore=
# Build prerequisites
buildreq="\
autoconf 2.69
automake 1.16.1
autoconf 2.72
automake 1.16.5
"
gnulib_name=libgnu

View File

@ -1,7 +1,7 @@
# Configuration for building GNU Make in the absence of any 'make' program.
# @configure_input@
# Copyright (C) 1993-2022 Free Software Foundation, Inc.
# Copyright (C) 1993-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,7 +1,7 @@
#!/bin/sh
# Shell script to build GNU Make in the absence of any 'make' program.
# Copyright (C) 1993-2022 Free Software Foundation, Inc.
# Copyright (C) 1993-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@ -20,6 +20,11 @@
# Get configure-generated values
. ./build.cfg
die () { echo "$*" 1>&2; exit 1; }
usage () { echo "$0 [-k]"; exit $1; }
keep_going=false
: ${OUTDIR:=.}
OUTLIB="$OUTDIR/lib"
@ -37,24 +42,19 @@ defines="-DLOCALEDIR=\"$localedir\" -DLIBDIR=\"$libdir\" -DINCLUDEDIR=\"$include
# Print the value to stdout.
get_mk_var ()
{
file=$1
var=$2
val=
v=$(sed -e :a -e '/\\$/N; s/\\\n//; ta' "$file" | sed -n "s=^ *$var *\= *==p")
v=$(sed -e :a -e '/\\$/N; s/\\\n//; ta' "$1" | sed -n "s=^ *$2 *\= *==p")
for w in $v; do
case $w in
(\$[\(\{]*[\)\}]) w=${w#\$[\(\{]}; w=$(get_mk_var "$file" "${w%[\)\}]}") ;;
(\$[\(\{]*[\)\}]) w=${w#\$[\(\{]}; (get_mk_var "$1" "${w%[\)\}]}") ;;
(*) echo "$w" ;;
esac
val="${val:+$val }$w"
done
printf '%s\n' "$val"
}
# Compile source files. Object files are put into $objs.
compile ()
{
success=true
objs=
for ofile in "$@"; do
# We should try to use a Makefile variable like libgnu_a_SOURCES or
@ -65,10 +65,18 @@ compile ()
esac
echo "compiling $file..."
of="$OUTDIR/$ofile"
mkdir -p "${of%/*}"
$CC $cflags $CPPFLAGS $CFLAGS -c -o "$of" "$top_srcdir/$file"
mkdir -p "${of%/*}" || exit 1
if $CC $cflags $CPPFLAGS $CFLAGS -c -o "$of" "$top_srcdir/$file"; then
: worked
else
$keep_going || die "Compilation failed."
success=false
fi
objs="${objs:+$objs }$of"
done
$success
}
# Use config.status to convert a .in file. Output file is put into $out.
@ -130,28 +138,39 @@ done
# Get object files from the Makefile
OBJS=$(get_mk_var Makefile make_OBJECTS | sed "s=\$[\(\{]OBJEXT[\)\}]=$OBJEXT=g")
# Exit as soon as any command fails.
set -e
while test -n "$1"; do
case $1 in
(-k) keep_going=true; shift ;;
(--) shift; break ;;
(-[h?]) usage 0 ;;
(-*) echo "Unknown option: $1"; usage 1 ;;
esac
done
test -z "$1" || die "Unknown argument: $*"
# Generate gnulib header files that would normally be created by make
set -e
for b in $(get_mk_var lib/Makefile BUILT_SOURCES); do
convert $b
done
set +e
# Build the gnulib library
cflags="$DEFS -I$OUTLIB -Ilib -I$top_srcdir/lib -I$OUTDIR/src -Isrc -I$top_srcdir/src"
compile $LIBOBJS
compile $LIBOBJS || die "Compilation failed."
echo "creating libgnu.a..."
$AR $ARFLAGS "$OUTLIB"/libgnu.a $objs
$AR $ARFLAGS "$OUTLIB"/libgnu.a $objs || die "Archive of libgnu failed."
# Compile the source files into those objects.
cflags="$DEFS $defines -I$OUTDIR/src -Isrc -I$top_srcdir/src -I$OUTLIB -Ilib -I$top_srcdir/lib"
compile $OBJS
compile $OBJS || die "Compilation failed."
# Link all the objects together.
echo "linking make..."
$CC $CFLAGS $LDFLAGS -L"$OUTLIB" $objs -lgnu $LOADLIBES -o "$OUTDIR/makenew$EXEEXT"
mv -f "$OUTDIR/makenew$EXEEXT" "$OUTDIR/make$EXEEXT"
$CC $CFLAGS $LDFLAGS -L"$OUTLIB" -o "$OUTDIR/makenew$EXEEXT" $objs -lgnu $LOADLIBES || die "Link failed."
mv -f "$OUTDIR/makenew$EXEEXT" "$OUTDIR/make$EXEEXT" || exit 1
echo done.

View File

@ -1,5 +1,5 @@
@echo off
:: Copyright (C) 1996-2022 Free Software Foundation, Inc.
:: Copyright (C) 1996-2024 Free Software Foundation, Inc.
:: This file is part of GNU Make.
::
:: GNU Make is free software; you can redistribute it and/or modify it under
@ -28,12 +28,13 @@ if "%1" == "-h" goto Usage
if "%1" == "--help" goto Usage
echo.
echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8/10
echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8/10/11
echo.
set MAKE=gnumake
set GUILE=Y
set COMPILER=cl.exe
set RC=rc.exe
set O=obj
set ARCH=x64
set DEBUG=N
@ -81,6 +82,7 @@ goto ParseSW
:SetCC
set COMPILER=gcc
set RC=windres
set O=o
echo - Building with GCC
shift
@ -88,6 +90,7 @@ goto ParseSW
:SetTCC
set COMPILER=tcc
set RC=windres
set O=o
echo - Building with TinyC
shift
@ -103,7 +106,7 @@ if "%COMPILER%" == "tcc" goto FindTcc
call %COMPILER% >nul 2>&1
if not ERRORLEVEL 1 goto FoundMSVC
:: Visual Studio 17 and above provides the "vswhere" tool
:: Visual Studio 15 2017 and above provides the "vswhere" tool
call :FindVswhere
if ERRORLEVEL 1 goto LegacyVS
@ -183,7 +186,7 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% /D MAKE_MAINTAINER_MODE"
:: Unfortunately this also shows a "usage" note; I can't find anything better.
echo.
call %COMPILER%
goto Build
goto FindRC
:FindGcc
set OUTDIR=.\GccRel
@ -197,7 +200,7 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE"
:: Show the compiler version that we found
echo.
call %COMPILER% --version
if not ERRORLEVEL 1 goto Build
if not ERRORLEVEL 1 goto FindRC
echo No %COMPILER% found.
exit 1
@ -212,11 +215,20 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE"
:: Show the compiler version that we found
echo.
call %COMPILER% -v
if not ERRORLEVEL 1 goto Build
if not ERRORLEVEL 1 goto FindRC
echo No %COMPILER% found.
exit 1
:FindRC
set HAVE_RC=Y
call where %RC% >nul 2>&1
if not ERRORLEVEL 1 goto Build
echo.
echo %RC% was not found. Building without UTF-8 resource.
set HAVE_RC=N
:Build
echo.
:: Clean the directory if it exists
if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR%
@ -271,6 +283,7 @@ call :Compile src/strcache
call :Compile src/variable
call :Compile src/version
call :Compile src/vpath
call :Compile src/warning
call :Compile src/w32/pathstuff
call :Compile src/w32/w32os
call :Compile src/w32/compat/posixfcn
@ -284,6 +297,9 @@ call :Compile lib/getloadavg
:: Compile dirent unless it is supported by compiler library (like with gcc).
if "%DIRENT%" == "Y" call :Compile src\w32\compat\dirent
:: Compile UTF-8 resource if a resource compiler is available.
if "%HAVE_RC%" == "Y" call :ResourceCompile src/w32/utf8
call :Link
echo.
@ -331,6 +347,30 @@ call %COMPILER% -mthreads -Wall -std=c11 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR
@echo off
goto CompileDone
:ResourceCompile
if "%VERBOSE%" == "N" echo - Compiling %1.rc
echo %LNKOUT%/%1.%O% >>%OUTDIR%\link.sc
if exist "%OUTDIR%\%1.%O%" del "%OUTDIR%\%1.%O%"
if "%COMPILER%" == "gcc" goto GccResourceCompile
if "%COMPILER%" == "tcc" goto TccResourceCompile
:: MSVC Resource Compile
if "%VERBOSE%" == "Y" echo on
call %RC% /fo %OUTDIR%\%1.%O% %1.rc
@echo off
goto CompileDone
:GccResourceCompile
:: GCC Resource Compile
if "%VERBOSE%" == "Y" echo on
call %RC% -o %OUTDIR%/%1.%O% -i %1.rc
@echo off
goto CompileDone
:TccResourceCompile
:: TCC Resource Compile
goto GccResourceCompile
:CompileDone
if not exist "%OUTDIR%\%1.%O%" exit 1
goto :EOF

View File

@ -1,5 +1,5 @@
@echo off
rem Copyright (C) 1998-2022 Free Software Foundation, Inc.
rem Copyright (C) 1998-2024 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
@ -56,6 +56,7 @@ gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/s
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/implicit.c -o implicit.o
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/default.c -o default.o
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/variable.c -o variable.o
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/warning.c -o warning.o
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/expand.c -o expand.o
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/function.c -o function.o
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/vpath.c -o vpath.o
@ -74,7 +75,7 @@ gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/l
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/lib/fnmatch.c -o lib/fnmatch.o
@echo off
echo commands.o > respf.$$$
for %%f in (job output dir file misc main read remake rule implicit default variable load) do echo %%f.o >> respf.$$$
for %%f in (job output dir file misc main read remake rule implicit default variable warning load) do echo %%f.o >> respf.$$$
for %%f in (expand function vpath hash strcache version ar arscan signame remote-stub getopt getopt1 shuffle) do echo %%f.o >> respf.$$$
for %%f in (lib\glob lib\fnmatch) do echo %%f.o >> respf.$$$
gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/guile.c -o guile.o

View File

@ -1,6 +1,6 @@
# Process this file with autoconf to produce a configure script.
#
# Copyright (C) 1993-2022 Free Software Foundation, Inc.
# Copyright (C) 1993-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.
AC_INIT([GNU Make],[4.3.91],[bug-make@gnu.org])
AC_INIT([GNU Make],[4.4.90],[bug-make@gnu.org])
AC_PREREQ([2.69])
@ -37,6 +37,8 @@ AM_INIT_AUTOMAKE([1.16.1 foreign -Werror -Wall])
# Checks for programs.
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_PROG_CXX
AC_DEFINE_UNQUOTED(MAKE_CXX, ["$CXX"], [Default C++ compiler.])
# Configure gnulib
gl_EARLY
@ -64,9 +66,9 @@ AC_SEARCH_LIBS([getpwnam], [sun])
AC_HEADER_DIRENT
AC_HEADER_STAT
AC_CHECK_HEADERS([stdlib.h locale.h unistd.h limits.h fcntl.h string.h \
memory.h sys/param.h sys/resource.h sys/timeb.h sys/time.h \
sys/select.h sys/file.h spawn.h])
AC_CHECK_HEADERS([stdlib.h string.h strings.h locale.h unistd.h limits.h \
memory.h sys/param.h sys/resource.h sys/time.h sys/select.h \
sys/file.h fcntl.h spawn.h])
AM_PROG_CC_C_O
AC_C_CONST
@ -175,18 +177,40 @@ AS_IF([test "x$with_guile" != xno],
AC_MSG_RESULT([$guile_version])
AS_IF([test "$have_guile" = yes],
[ PKG_CHECK_MODULES(GUILE, [guile-$guile_version])
# Unfortunately Guile requires a C99 compiler but GNU make doesn't, so
# verify we can actually compile the header.
# Unfortunately pkg doesn't help in multi-arch environments where the
# package is installed for some architectures but not others; we need
# to try to link.
keep_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $pkg_cv_GUILE_CFLAGS"
keep_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $GUILE_CFLAGS"
LIBS="$LIBS $GUILE_LIBS"
AC_CHECK_HEADER([libguile.h],
[AC_DEFINE([HAVE_GUILE], [1], [Embed GNU Guile support])],
[have_guile=yes],
[have_guile=no],
[/* Avoid configuration error warnings. */])
AS_IF([test "$have_guile" = yes],
[ AC_MSG_CHECKING([whether we can link GNU Guile])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <libguile.h>
static void *
guile_init (void *arg)
{
(void) arg;
return 0;
}
]], [[
scm_with_guile (guile_init, 0);
]])],
[have_guile=yes],
[have_guile=no])
AC_MSG_RESULT([$have_guile])])
CPPFLAGS="$keep_CPPFLAGS"
LIBS="$keep_LIBS"
])
])
AS_IF([test "$have_guile" = yes],
[AC_DEFINE([HAVE_GUILE], [1], [Embed GNU Guile support])])
AM_CONDITIONAL([HAVE_GUILE], [test "$have_guile" = "yes"])
AC_CHECK_DECLS([sys_siglist, _sys_siglist, __sys_siglist], , ,
@ -298,7 +322,7 @@ AS_CASE([$host_os], [os2*|mingw*], [make_cv_job_server=yes])
AS_CASE([/$make_cv_job_server/$user_job_server/],
[*/no/*], [: no jobserver],
[AC_DEFINE(MAKE_JOBSERVER, 1,
[Define to 1 to enable job server support in GNU make.])
[Define to 1 to enable job server support in GNU Make.])
])
# If dl*() functions are supported we can enable the load operation
@ -321,7 +345,7 @@ AS_IF([test "$make_cv_load" = yes], [
AS_CASE([/$make_cv_load/$user_load/],
[*/no/*], [make_cv_load=no],
[AC_DEFINE(MAKE_LOAD, 1,
[Define to 1 to enable 'load' support in GNU make.])
[Define to 1 to enable 'load' support in GNU Make.])
])
# If we want load support, we might need to link with export-dynamic.
@ -329,14 +353,14 @@ AS_CASE([/$make_cv_load/$user_load/],
# For example passing -rdynamic to the SunPRO linker gives a warning
# but succeeds and creates a shared object, not an executable!
AS_IF([test "$make_cv_load" = yes], [
AC_MSG_CHECKING([If the linker accepts -Wl,--export-dynamic])
AC_MSG_CHECKING([if the linker accepts -Wl,--export-dynamic])
old_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])],
[AC_MSG_RESULT([yes])
AC_SUBST([AM_LDFLAGS], [-Wl,--export-dynamic])],
[AC_MSG_RESULT([no])
AC_MSG_CHECKING([If the linker accepts -rdynamic])
AC_MSG_CHECKING([if the linker accepts -rdynamic])
LDFLAGS="$old_LDFLAGS -rdynamic"
AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])],
[AC_MSG_RESULT([yes])
@ -420,13 +444,18 @@ AC_SUBST([MAKE_HOST])
w32_target_env=no
AM_CONDITIONAL([WINDOWSENV], [false])
AM_CONDITIONAL([HAVE_WINDRES], [false])
AS_CASE([$host],
[*-*-mingw32],
[AM_CONDITIONAL([WINDOWSENV], [true])
w32_target_env=yes
AC_DEFINE([WINDOWS32], [1], [Build for the WINDOWS32 API.])
AC_DEFINE([MK_OS_W32], [1], [Build for the Windows32 API.])
AC_DEFINE([HAVE_DOS_PATHS], [1], [Support DOS-style pathnames.])
# Windows host tools.
# If windres is available, make will use UTF-8.
AC_CHECK_TOOL([WINDRES], [windres], [:])
AM_CONDITIONAL([HAVE_WINDRES], [test "$WINDRES" != ':'])
])
AC_DEFINE_UNQUOTED([PATH_SEPARATOR_CHAR],['$PATH_SEPARATOR'],
@ -451,6 +480,10 @@ AC_SUBST_FILE([MAINT_MAKEFILE])
# Allow building with dmalloc
AM_WITH_DMALLOC
# Add custom header to config.h
AH_BOTTOM([/* Include customized declarations. */
#include "../src/mkcustom.h"])
# Forcibly disable SET_MAKE. If it's set it breaks things like the test
# scripts, etc.
SET_MAKE=
@ -470,7 +503,7 @@ AS_CASE([$with_customs],
[ echo
echo "WARNING: '$with_customs/lib' does not appear to contain the"
echo " Customs library. You must build and install Customs"
echo " before compiling GNU make."
echo " before compiling GNU Make."
echo
])])
@ -478,7 +511,7 @@ AS_IF([test "x$has_wait_nohang" = xno],
[ echo
echo "WARNING: Your system has neither waitpid() nor wait3()."
echo " Without one of these, signal handling is unreliable."
echo " You should be aware that running GNU make with -j"
echo " You should be aware that running GNU Make with -j"
echo " could result in erratic behavior."
echo
])

1
doc/.gitignore vendored
View File

@ -1,4 +1,5 @@
manual/
make.t2d/
make.t2p/
gendocs_template
fdl.texi

View File

@ -1,5 +1,5 @@
# -*-Makefile-*-, or close enough
# Copyright (C) 2000-2022 Free Software Foundation, Inc.
# Copyright (C) 2000-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,6 +1,6 @@
.TH MAKE 1 "31 May 2022" "GNU" "User Commands"
.TH MAKE 1 "26 May 2023" "GNU" "User Commands"
.SH NAME
make \- GNU make utility to maintain groups of programs
make \- GNU Make utility to maintain groups of programs
.SH SYNOPSIS
.B make
[\fIOPTION\fR]... [\fITARGET\fR]...
@ -76,9 +76,8 @@ listing, right near other important files such as
The first name checked,
.IR GNUmakefile ,
is not recommended for most makefiles. You should use this name if you have a
makefile that is specific to GNU
.BR make ,
and will not be understood by other versions of
makefile that is specific to GNU Make, and will not be understood by other
versions of
.BR make .
If
.I makefile
@ -271,10 +270,15 @@ reading the makefiles; then execute as usual or as otherwise
specified.
This also prints the version information given by the
.B \-v
switch (see below).
To print the data base without trying to remake any files, use
switch (see below). To print the built-in data base only, use
.IR "make \-p \-f/dev/null" .
.TP 0.5i
\fB\-\-print\-targets\fR
Print each target defined as a result of reading the makefiles, one target per
line, then exit with success. Implicit rule targets are not printed, nor are
special targets (target names that consist of "." followed by all upper-case
letters). No recipe commands are invoked and no makefiles are rebuilt.
.TP 0.5i
\fB\-q\fR, \fB\-\-question\fR
``Question mode''.
Do not run any commands, or print anything; just return an exit status
@ -365,12 +369,59 @@ command on the given file before running
except that the modification time is changed only in the imagination of
.BR make .
.TP 0.5i
\fB\-\-warn\fR[=\fIARG[\fR,\fIARG\fR]]
Control warning reporting for makefiles. This option can appear multiple times.
In case of conflicts, later settings override earlier settings.
.I ARG
can be an action; one of
.IR ignore ,
.IR warn ,
or
.I error
to set the default action for all warnings, or it can be a specific warning:
.I circular-dep
(finding a circular dependency),
.I invalid-ref
(referencing an invalid variable name),
.I invalid-var
(assigning to an invalid variable name),
or
.I undefined-var
(referencing an undefined variable). The behavior of each warning can be set
by adding
.BI : action
after the warning name. If an action is not specified the default is
.IR warn .
If no
.I ARG
is provided the action for all warnings is
.IR warn .
If no
.B \-\-warn
option is provided the default action for
.I invalid-var
and
.I invalid-ref
is
.I warn
and the default action for
.I undefined-var
is
.IR ignore .
.TP 0.5i
.B \-\-warn\-undefined\-variables
Warn when an undefined variable is referenced.
A deprecated alternative for
.BR \-\-warn=undefined-var .
.TP 0.5i
.B \-
This option alone (not as an argument to the
.B \-f
option) is ignored, unless a target named
.B \-
is defined in the makefile, in which case that target is added to the makefile
goals.
.SH "EXIT STATUS"
GNU
.B make
exits with a status of zero if all makefiles were successfully parsed
GNU Make exits with a status of zero if all makefiles were successfully parsed
and no targets that were built failed. A status of one will be returned
if the
.B \-q
@ -398,9 +449,9 @@ This manual page contributed by Dennis Morse of Stanford University.
Further updates contributed by Mike Frysinger. It has been reworked by Roland
McGrath. Maintained by Paul Smith.
.SH "COPYRIGHT"
Copyright \(co 1992-1993, 1996-2022 Free Software Foundation, Inc.
Copyright \(co 1992\(en1993, 1996\(en2024 Free Software Foundation, Inc.
This file is part of
.IR "GNU make" .
.IR "GNU Make" .
.LP
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2023 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
@ -13,9 +13,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
along with this library; see the file COPYING.LIB.
If not, see <https://www.gnu.org/licenses/>. */
#if HAVE_CONFIG_H
# include <config.h>
@ -128,48 +127,20 @@ extern char *getenv ();
extern int errno;
# endif
/* This function doesn't exist on most systems. */
# if !defined HAVE___STRCHRNUL && !defined _LIBC
static char *
__strchrnul (s, c)
const char *s;
int c;
{
char *result = strchr (s, c);
if (result == NULL)
result = strchr (s, '\0');
return result;
}
# endif
# ifndef internal_function
/* Inside GNU libc we mark some function in a special way. In other
environments simply ignore the marking. */
# define internal_function
# endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
static int internal_fnmatch __P ((const char *pattern, const char *string,
int no_leading_period, int flags))
internal_function;
static int
internal_function
internal_fnmatch (pattern, string, no_leading_period, flags)
const char *pattern;
const char *string;
int no_leading_period;
int flags;
internal_fnmatch (const char *pattern, const char *string,
int no_leading_period, int flags)
{
register const char *p = pattern, *n = string;
register unsigned char c;
const char *p = pattern, *n = string;
unsigned char c;
/* Note that this evaluates C many times. */
# ifdef _LIBC
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
# define FOLD(c) (unsigned char)((flags & FNM_CASEFOLD) ? tolower (c) : (c))
# else
# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
# define FOLD(c) (unsigned char)((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
# endif
while ((c = *p++) != '\0')
@ -237,7 +208,9 @@ internal_fnmatch (pattern, string, no_leading_period, flags)
{
const char *endp;
endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
endp = strchr (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
if (endp == NULL)
endp = n + strlen (n);
if (c == '[')
{
@ -292,7 +265,7 @@ internal_fnmatch (pattern, string, no_leading_period, flags)
{
/* Nonzero if the sense of the character class is inverted. */
static int posixly_correct;
register int not;
int not;
char cold;
if (posixly_correct == 0)
@ -478,10 +451,7 @@ internal_fnmatch (pattern, string, no_leading_period, flags)
int
fnmatch (pattern, string, flags)
const char *pattern;
const char *string;
int flags;
fnmatch (const char *pattern, const char *string, int flags)
{
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2023 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
@ -13,9 +13,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
along with this library; see the file COPYING.LIB.
If not, see <https://www.gnu.org/licenses/>. */
#ifndef _FNMATCH_H
#define _FNMATCH_H 1
@ -24,27 +23,6 @@ USA. */
extern "C" {
#endif
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
# if !defined __GLIBC__
# undef __P
# define __P(protos) protos
# endif
#else /* Not C++ or ANSI C. */
# undef __P
# define __P(protos) ()
/* We can get away without defining `const' here only because in this file
it is used only inside the prototype for `fnmatch', which is elided in
non-ANSI C where `const' is problematical. */
#endif /* C++ or ANSI C. */
#ifndef const
# if (defined __STDC__ && __STDC__) || defined __cplusplus || defined WINDOWS32
# define __const const
# else
# define __const
# endif
#endif
/* We #undef these before defining them because some losing systems
(HP-UX A.08.07 for example) define these in <unistd.h>. */
#undef FNM_PATHNAME
@ -75,8 +53,7 @@ extern "C" {
/* Match NAME against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
extern int fnmatch __P ((__const char *__pattern, __const char *__name,
int __flags));
extern int fnmatch (const char *pattern, const char *name, int flags);
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 Free
Software Foundation, Inc.
/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2023 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@ -12,9 +12,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
along with this library; see the file COPYING.LIB.
If not, see <https://www.gnu.org/licenses/>. */
/* AIX requires this to be the first thing in the file. */
#if defined _AIX && !defined __GNUC__
@ -38,9 +37,6 @@ USA. */
/* #define NDEBUG 1 */
#include <assert.h>
#include <stdio.h> /* Needed on stupid SunOS for assert. */
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
@ -50,7 +46,9 @@ USA. */
it is simpler to just do this in the source for each such file. */
#define GLOB_INTERFACE_VERSION 1
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
#if defined _LIBC
# define ELIDE_CODE
#elif defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
# include <gnu-versions.h>
# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
# define ELIDE_CODE
@ -63,7 +61,7 @@ USA. */
# include <stddef.h>
#endif
#if defined HAVE_UNISTD_H || defined _LIBC
#if defined HAVE_UNISTD_H
# include <unistd.h>
# ifndef POSIX
# ifdef _POSIX_VERSION
@ -72,7 +70,7 @@ USA. */
# endif
#endif
#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
#if !defined _AMIGA && !MK_OS_VMS && !MK_OS_W32
# include <pwd.h>
#endif
@ -83,11 +81,6 @@ extern int errno;
# define __set_errno(val) errno = (val)
#endif
#ifndef NULL
# define NULL 0
#endif
#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
@ -108,7 +101,6 @@ extern int errno;
# endif /* HAVE_VMSDIR_H */
#endif
/* In GNU systems, <dirent.h> defines this macro for us. */
#ifdef _D_NAMLEN
# undef NAMLEN
@ -122,7 +114,7 @@ extern int errno;
#endif
#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
#if (defined POSIX || MK_OS_W32) && !defined __GNU_LIBRARY__
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1
@ -130,49 +122,10 @@ extern int errno;
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
#endif /* POSIX */
#if defined STDC_HEADERS || defined __GNU_LIBRARY__
# include <stdlib.h>
# include <string.h>
# define ANSI_STRING
#else /* No standard headers. */
#include <stdlib.h>
#include <string.h>
extern char *getenv ();
# ifdef HAVE_STRING_H
# include <string.h>
# define ANSI_STRING
# else
# include <strings.h>
# endif
# ifdef HAVE_MEMORY_H
# include <memory.h>
# endif
extern char *malloc (), *realloc ();
extern void free ();
extern void qsort ();
extern void abort (), exit ();
#endif /* Standard headers. */
#ifndef ANSI_STRING
# ifndef bzero
extern void bzero ();
# endif
# ifndef bcopy
extern void bcopy ();
# endif
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# define strrchr rindex
/* memset is only used for zero here, but let's be paranoid. */
# define memset(s, better_be_zero, n) \
((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
#endif /* Not ANSI_STRING. */
#if !defined HAVE_STRCOLL && !defined _LIBC
#if !defined HAVE_STRCOLL
# define strcoll strcmp
#endif
@ -182,32 +135,6 @@ extern void bcopy ();
# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
#endif
#if !defined __GNU_LIBRARY__ && !defined __DJGPP__
# ifdef __GNUC__
__inline
# endif
# ifndef __SASC
# ifdef WINDOWS32
static void *
my_realloc (void *p, unsigned int n)
# else
static char *
my_realloc (p, n)
char *p;
unsigned int n;
# endif
{
/* These casts are the for sake of the broken Ultrix compiler,
which warns of illegal pointer combinations otherwise. */
if (p == NULL)
return (char *) malloc (n);
return (char *) realloc (p, n);
}
# define realloc my_realloc
# endif /* __SASC */
#endif /* __GNU_LIBRARY__ || __DJGPP__ */
#if !defined __alloca && !defined __GNU_LIBRARY__
# ifdef __GNUC__
@ -218,18 +145,17 @@ my_realloc (p, n)
# include <alloca.h>
# else /* Not HAVE_ALLOCA_H. */
# ifndef _AIX
# ifdef WINDOWS32
# if MK_OS_W32
# include <malloc.h>
# else
extern char *alloca ();
# endif /* WINDOWS32 */
# endif /* MK_OS_W32 */
# endif /* Not _AIX. */
# endif /* sparc or HAVE_ALLOCA_H. */
# endif /* GCC. */
#endif
#ifndef __GNU_LIBRARY__
# define __stat stat
# ifdef STAT_MACROS_BROKEN
# undef S_ISDIR
# endif
@ -238,25 +164,6 @@ extern char *alloca ();
# endif
#endif
#ifdef _LIBC
# undef strdup
# define strdup(str) __strdup (str)
# define sysconf(id) __sysconf (id)
# define closedir(dir) __closedir (dir)
# define opendir(name) __opendir (name)
# define readdir(str) __readdir (str)
# define getpwnam_r(name, bufp, buf, len, res) \
__getpwnam_r (name, bufp, buf, len, res)
# ifndef __stat
# define __stat(fname, buf) __xstat (_STAT_VER, fname, buf)
# endif
#endif
#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
# undef size_t
# define size_t unsigned int
#endif
/* Some system header files erroneously define these.
We want our own definitions from <fnmatch.h> to take precedence. */
#ifndef __GNU_LIBRARY__
@ -284,30 +191,26 @@ extern char *alloca ();
# define __alloca alloca
#endif
#if !defined __stat
# define __stat stat
#endif
#ifdef HAVE_GETLOGIN_R
extern int getlogin_r __P ((char *, size_t));
extern int getlogin_r (char *, size_t);
#else
extern char *getlogin __P ((void));
extern char *getlogin (void);
#endif
static
#if __GNUC__ - 0 >= 2
inline
#endif
const char *next_brace_sub __P ((const char *begin));
static int glob_in_dir __P ((const char *pattern, const char *directory,
int flags,
int (*errfunc) (const char *, int),
glob_t *pglob));
static int prefix_array __P ((const char *prefix, char **array, size_t n));
static int collated_compare __P ((const __ptr_t, const __ptr_t));
const char *next_brace_sub (const char *begin);
static int glob_in_dir (const char *pattern, const char *directory,
int flags,
int (*errfunc) (const char *, int),
glob_t *pglob);
static int prefix_array (const char *prefix, char **array, size_t n);
static int collated_compare (const void *, const void *);
#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
int __glob_pattern_p __P ((const char *pattern, int quote));
#if !defined NO_GLOB_PATTERN_P
int __glob_pattern_p (const char *pattern, int quote);
#endif
/* Find the end of the sub-pattern in a brace expression. We define
@ -317,8 +220,7 @@ static
inline
#endif
const char *
next_brace_sub (begin)
const char *begin;
next_brace_sub (const char *begin)
{
unsigned int depth = 0;
const char *cp = begin;
@ -364,11 +266,8 @@ next_brace_sub (begin)
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
Otherwise, `glob' returns zero. */
int
glob (pattern, flags, errfunc, pglob)
const char *pattern;
int flags;
int (*errfunc) __P ((const char *, int));
glob_t *pglob;
glob (const char *pattern, int flags,
int (*errfunc) (const char *, int), glob_t *pglob)
{
const char *filename;
const char *dirname;
@ -516,14 +415,14 @@ glob (pattern, flags, errfunc, pglob)
/* Find the filename. */
filename = strrchr (pattern, '/');
#if defined __MSDOS__ || defined WINDOWS32
#if MK_OS_DOS || MK_OS_W32
/* The case of "d:pattern". Since `:' is not allowed in
file names, we can safely assume that wherever it
happens in pattern, it signals the filename part. This
is so we could some day support patterns like "[a-z]:foo". */
if (filename == NULL)
filename = strchr (pattern, ':');
#endif /* __MSDOS__ || WINDOWS32 */
#endif /* MK_OS_DOS || MK_OS_W32 */
if (filename == NULL)
{
/* This can mean two things: a simple name or "~name". The later
@ -560,7 +459,7 @@ glob (pattern, flags, errfunc, pglob)
{
char *newp;
dirlen = filename - pattern;
#if defined __MSDOS__ || defined WINDOWS32
#if MK_OS_DOS || MK_OS_W32
if (*filename == ':'
|| (filename > pattern + 1 && filename[-1] == ':'))
{
@ -594,7 +493,7 @@ glob (pattern, flags, errfunc, pglob)
++filename;
if (filename[0] == '\0'
#if defined __MSDOS__ || defined WINDOWS32
#if MK_OS_DOS || MK_OS_W32
&& dirname[dirlen - 1] != ':'
&& (dirlen < 3 || dirname[dirlen - 2] != ':'
|| dirname[dirlen - 1] != '/')
@ -618,13 +517,13 @@ glob (pattern, flags, errfunc, pglob)
oldcount = pglob->gl_pathc;
#ifndef VMS
#if !MK_OS_VMS
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
{
if (dirname[1] == '\0' || dirname[1] == '/')
{
/* Look up home directory. */
#ifdef VMS
#if MK_OS_VMS
/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
const char *home_dir = getenv ("SYS$LOGIN");
#else
@ -634,11 +533,11 @@ glob (pattern, flags, errfunc, pglob)
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS:";
# else
# ifdef WINDOWS32
# if MK_OS_W32
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "c:/users/default"; /* poor default */
# else
# ifdef VMS
# if MK_OS_VMS
/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS$DISK:[]";
@ -647,7 +546,7 @@ glob (pattern, flags, errfunc, pglob)
{
int success;
char *name;
# if defined HAVE_GETLOGIN_R || defined _LIBC
# if defined HAVE_GETLOGIN_R
size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
if (buflen == 0)
@ -663,7 +562,7 @@ glob (pattern, flags, errfunc, pglob)
if (success)
{
struct passwd *p;
# if defined HAVE_GETPWNAM_R || defined _LIBC
# if defined HAVE_GETPWNAM_R
size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
char *pwtmpbuf;
struct passwd pwbuf;
@ -701,8 +600,8 @@ glob (pattern, flags, errfunc, pglob)
else
home_dir = "~"; /* No luck. */
}
# endif /* VMS */
# endif /* WINDOWS32 */
# endif /* MK_OS_VMS */
# endif /* MK_OS_W32 */
# endif
/* Now construct the full directory. */
if (dirname[1] == '\0')
@ -722,7 +621,7 @@ glob (pattern, flags, errfunc, pglob)
dirname = newp;
}
}
# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
# if !defined _AMIGA && !MK_OS_W32 && !MK_OS_VMS
else
{
char *end_name = strchr (dirname, '/');
@ -748,7 +647,7 @@ glob (pattern, flags, errfunc, pglob)
/* Look up specific user's home directory. */
{
struct passwd *p;
# if defined HAVE_GETPWNAM_R || defined _LIBC
# if defined HAVE_GETPWNAM_R
size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
char *pwtmpbuf;
struct passwd pwbuf;
@ -802,9 +701,9 @@ glob (pattern, flags, errfunc, pglob)
home directory. */
return GLOB_NOMATCH;
}
# endif /* Not Amiga && not WINDOWS32 && not VMS. */
# endif /* Not Amiga && not MK_OS_W32 && not MK_OS_VMS. */
}
#endif /* Not VMS. */
#endif /* Not MK_OS_VMS. */
/* Now test whether we looked for "~" or "~NAME". In this case we
can give the answer now. */
@ -816,7 +715,7 @@ glob (pattern, flags, errfunc, pglob)
if ((flags & GLOB_NOCHECK)
|| (((flags & GLOB_ALTDIRFUNC)
? (*pglob->gl_stat) (dirname, &st)
: __stat (dirname, &st)) == 0
: stat (dirname, &st)) == 0
&& S_ISDIR (st.st_mode)))
{
pglob->gl_pathv
@ -833,7 +732,7 @@ glob (pattern, flags, errfunc, pglob)
while (pglob->gl_pathc < pglob->gl_offs)
pglob->gl_pathv[pglob->gl_pathc++] = NULL;
#if defined HAVE_STRDUP || defined _LIBC
#if defined HAVE_STRDUP
pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
#else
{
@ -865,7 +764,7 @@ glob (pattern, flags, errfunc, pglob)
have to glob for the directory, and then glob for
the pattern in each directory found. */
glob_t dirs;
register size_t i;
size_t i;
status = glob (dirname,
((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
@ -879,7 +778,7 @@ glob (pattern, flags, errfunc, pglob)
appending the results to PGLOB. */
for (i = 0; i < dirs.gl_pathc; ++i)
{
int old_pathc;
size_t old_pathc;
#ifdef SHELL
{
@ -962,7 +861,7 @@ glob (pattern, flags, errfunc, pglob)
/* First check whether this really is a directory. */
if (((flags & GLOB_ALTDIRFUNC)
? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
? (*pglob->gl_stat) (dir, &st) : stat (dir, &st)) != 0
|| !S_ISDIR (st.st_mode))
/* No directory, ignore this entry. */
continue;
@ -1038,7 +937,7 @@ glob (pattern, flags, errfunc, pglob)
for (i = oldcount; i < pglob->gl_pathc; ++i)
if (((flags & GLOB_ALTDIRFUNC)
? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
: __stat (pglob->gl_pathv[i], &st)) == 0
: stat (pglob->gl_pathv[i], &st)) == 0
&& S_ISDIR (st.st_mode))
{
size_t len = strlen (pglob->gl_pathv[i]) + 2;
@ -1056,12 +955,12 @@ glob (pattern, flags, errfunc, pglob)
if (!(flags & GLOB_NOSORT))
{
/* Sort the vector. */
int non_sort = oldcount;
size_t non_sort = oldcount;
if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
non_sort = pglob->gl_offs;
qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
qsort ((void *) &pglob->gl_pathv[non_sort],
pglob->gl_pathc - non_sort,
sizeof (char *), collated_compare);
}
@ -1072,25 +971,22 @@ glob (pattern, flags, errfunc, pglob)
/* Free storage allocated in PGLOB by a previous `glob' call. */
void
globfree (pglob)
register glob_t *pglob;
globfree (glob_t *pglob)
{
if (pglob->gl_pathv != NULL)
{
register size_t i;
size_t i;
for (i = 0; i < pglob->gl_pathc; ++i)
if (pglob->gl_pathv[i] != NULL)
free ((__ptr_t) pglob->gl_pathv[i]);
free ((__ptr_t) pglob->gl_pathv);
free (pglob->gl_pathv[i]);
free (pglob->gl_pathv);
}
}
/* Do a collated comparison of A and B. */
static int
collated_compare (a, b)
const __ptr_t a;
const __ptr_t b;
collated_compare (const void *a, const void *b)
{
const char *const s1 = *(const char *const * const) a;
const char *const s2 = *(const char *const * const) b;
@ -1110,15 +1006,12 @@ collated_compare (a, b)
A slash is inserted between DIRNAME and each elt of ARRAY,
unless DIRNAME is just "/". Each old element of ARRAY is freed. */
static int
prefix_array (dirname, array, n)
const char *dirname;
char **array;
size_t n;
prefix_array (const char *dirname, char **array, size_t n)
{
register size_t i;
size_t i;
size_t dirlen = strlen (dirname);
#if defined __MSDOS__ || defined WINDOWS32
int sep_char = '/';
#if MK_OS_DOS || MK_OS_W32
char sep_char = '/';
# define DIRSEP_CHAR sep_char
#else
# define DIRSEP_CHAR '/'
@ -1128,7 +1021,7 @@ prefix_array (dirname, array, n)
/* DIRNAME is just "/", so normal prepending would get us "//foo".
We want "/foo" instead, so don't prepend any chars from DIRNAME. */
dirlen = 0;
#if defined __MSDOS__ || defined WINDOWS32
#if MK_OS_DOS || MK_OS_W32
else if (dirlen > 1)
{
if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
@ -1150,7 +1043,7 @@ prefix_array (dirname, array, n)
if (new == NULL)
{
while (i > 0)
free ((__ptr_t) array[--i]);
free (array[--i]);
return 1;
}
@ -1165,7 +1058,7 @@ prefix_array (dirname, array, n)
new[dirlen] = DIRSEP_CHAR;
memcpy (&new[dirlen + 1], array[i], eltlen);
#endif
free ((__ptr_t) array[i]);
free (array[i]);
array[i] = new;
}
@ -1174,15 +1067,13 @@ prefix_array (dirname, array, n)
/* We must not compile this function twice. */
#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
#if !defined NO_GLOB_PATTERN_P
/* Return nonzero if PATTERN contains any metacharacters.
Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
int
__glob_pattern_p (pattern, quote)
const char *pattern;
int quote;
__glob_pattern_p (const char *pattern, int quote)
{
register const char *p;
const char *p;
int open = 0;
for (p = pattern; *p != '\0'; ++p)
@ -1209,9 +1100,6 @@ __glob_pattern_p (pattern, quote)
return 0;
}
# ifdef _LIBC
weak_alias (__glob_pattern_p, glob_pattern_p)
# endif
#endif
@ -1220,14 +1108,10 @@ weak_alias (__glob_pattern_p, glob_pattern_p)
The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
The GLOB_APPEND flag is assumed to be set (always appends). */
static int
glob_in_dir (pattern, directory, flags, errfunc, pglob)
const char *pattern;
const char *directory;
int flags;
int (*errfunc) __P ((const char *, int));
glob_t *pglob;
glob_in_dir (const char *pattern, const char *directory, int flags,
int (*errfunc) (const char *, int), glob_t *pglob)
{
__ptr_t stream = NULL;
void *stream = NULL;
struct globlink
{
@ -1239,7 +1123,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
int meta;
int save;
#ifdef VMS
#if MK_OS_VMS
if (*directory == 0)
directory = "[]";
#endif
@ -1271,7 +1155,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
# endif
if (((flags & GLOB_ALTDIRFUNC)
? (*pglob->gl_stat) (fullname, &st)
: __stat (fullname, &st)) == 0)
: stat (fullname, &st)) == 0)
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
@ -1298,7 +1182,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
{
stream = ((flags & GLOB_ALTDIRFUNC)
? (*pglob->gl_opendir) (directory)
: (__ptr_t) opendir (directory));
: (void *) opendir (directory));
if (stream == NULL)
{
if (errno != ENOTDIR
@ -1350,10 +1234,9 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
if (new->name == NULL)
goto memory_error;
#ifdef HAVE_MEMPCPY
*((char *) mempcpy ((__ptr_t) new->name, name, len))
= '\0';
*((char *) mempcpy (new->name, name, len)) = '\0';
#else
memcpy ((__ptr_t) new->name, name, len);
memcpy (new->name, name, len);
new->name[len] = '\0';
#endif
new->next = names;
@ -1428,7 +1311,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
while (names != NULL)
{
if (names->name != NULL)
free ((__ptr_t) names->name);
free (names->name);
names = names->next;
}
return GLOB_NOSPACE;

View File

@ -1,5 +1,5 @@
/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998 Free Software Foundation,
Inc.
/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998, 2023 Free Software
Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@ -12,67 +12,18 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
along with this library; see the file COPYING.LIB.
If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GLOB_H
#define _GLOB_H 1
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#undef __ptr_t
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
# if !defined __GLIBC__
# undef __P
# undef __PMT
# define __P(protos) protos
# define __PMT(protos) protos
# if !defined __GNUC__ || __GNUC__ < 2
# undef __const
# define __const const
# endif
# endif
# define __ptr_t void *
#else /* Not C++ or ANSI C. */
# undef __P
# undef __PMT
# define __P(protos) ()
# define __PMT(protos) ()
# undef __const
# define __const
# define __ptr_t char *
#endif /* C++ or ANSI C. */
/* We need `size_t' for the following definitions. */
#ifndef __size_t
# if defined __FreeBSD__
# define __size_t size_t
# else
# if defined __GNUC__ && __GNUC__ >= 2
typedef __SIZE_TYPE__ __size_t;
# else
/* This is a guess. */
/*hb
* Conflicts with DECCs already defined type __size_t.
* Defining an own type with a name beginning with '__' is no good.
* Anyway if DECC is used and __SIZE_T is defined then __size_t is
* already defined (and I hope it's exactly the one we need here).
*/
# if !(defined __DECC && defined __SIZE_T)
typedef unsigned long int __size_t;
# endif
# endif
# endif
#else
/* The GNU CC stddef.h version defines __size_t as empty. We need a real
definition. */
# undef __size_t
# define __size_t size_t
#endif
/* Bits set in the FLAGS argument to `glob'. */
#define GLOB_ERR (1 << 0)/* Return on read errors. */
#define GLOB_MARK (1 << 1)/* Append a slash to each name. */
@ -115,26 +66,26 @@ typedef unsigned long int __size_t;
#endif
/* Structure describing a globbing run. */
#if !defined _AMIGA && !defined VMS /* Buggy compiler. */
#if !defined _AMIGA && !MK_OS_VMS /* Buggy compiler. */
struct stat;
#endif
typedef struct
{
__size_t gl_pathc; /* Count of paths matched by the pattern. */
size_t gl_pathc; /* Count of paths matched by the pattern. */
char **gl_pathv; /* List of matched pathnames. */
__size_t gl_offs; /* Slots to reserve in `gl_pathv'. */
size_t gl_offs; /* Slots to reserve in `gl_pathv'. */
int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */
/* If the GLOB_ALTDIRFUNC flag is set, the following functions
are used instead of the normal file access functions. */
void (*gl_closedir) __PMT ((void *));
struct dirent *(*gl_readdir) __PMT ((void *));
__ptr_t (*gl_opendir) __PMT ((__const char *));
int (*gl_lstat) __PMT ((__const char *, struct stat *));
#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
int (*gl_stat) __PMT ((__const char *, struct stat *, ...));
void (*gl_closedir) (void *);
struct dirent *(*gl_readdir) (void *);
void * (*gl_opendir) (const char *);
int (*gl_lstat) (const char *, struct stat *);
#if MK_OS_VMS && defined(__DECC) && !defined(_POSIX_C_SOURCE)
int (*gl_stat) (const char *, struct stat *, ...);
#else
int (*gl_stat) __PMT ((__const char *, struct stat *));
int (*gl_stat) (const char *, struct stat *);
#endif
} glob_t;
@ -142,18 +93,18 @@ typedef struct
struct stat64;
typedef struct
{
__size_t gl_pathc;
size_t gl_pathc;
char **gl_pathv;
__size_t gl_offs;
size_t gl_offs;
int gl_flags;
/* If the GLOB_ALTDIRFUNC flag is set, the following functions
are used instead of the normal file access functions. */
void (*gl_closedir) __PMT ((void *));
struct dirent64 *(*gl_readdir) __PMT ((void *));
__ptr_t (*gl_opendir) __PMT ((__const char *));
int (*gl_lstat) __PMT ((__const char *, struct stat64 *));
int (*gl_stat) __PMT ((__const char *, struct stat64 *));
void (*gl_closedir) (void *);
struct dirent64 *(*gl_readdir) (void *);
void * (*gl_opendir) (const char *);
int (*gl_lstat) (const char *, struct stat64 *);
int (*gl_stat) (const char *, struct stat64 *);
} glob64_t;
#endif
@ -162,11 +113,11 @@ typedef struct
# define globfree globfree64
#else
# ifdef _LARGEFILE64_SOURCE
extern int glob64 __P ((__const char *__pattern, int __flags,
int (*__errfunc) (__const char *, int),
glob64_t *__pglob));
extern int glob64 (const char *pattern, int flags,
int (*errfunc) (const char *, int),
glob64_t *pglob);
extern void globfree64 __P ((glob64_t *__pglob));
extern void globfree64 (glob64_t *pglob);
# endif
#endif
@ -179,18 +130,18 @@ extern void globfree64 __P ((glob64_t *__pglob));
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
Otherwise, `glob' returns zero. */
#if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2
extern int glob __P ((__const char *__pattern, int __flags,
int (*__errfunc) (__const char *, int),
glob_t *__pglob));
extern int glob (const char *pattern, int flags,
int (*errfunc) (const char *, int),
glob_t *pglob);
/* Free storage allocated in PGLOB by a previous `glob' call. */
extern void globfree __P ((glob_t *__pglob));
extern void globfree (glob_t *pglob);
#else
extern int glob __P ((__const char *__pattern, int __flags,
int (*__errfunc) (__const char *, int),
glob_t *__pglob)) __asm__ ("glob64");
extern int glob (const char *pattern, int flags,
int (*errfunc) (const char *, int),
glob_t *pglob) __asm__ ("glob64");
extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64");
extern void globfree (glob_t *pglob) __asm__ ("globfree64");
#endif
@ -200,7 +151,7 @@ extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64");
This function is not part of the interface specified by POSIX.2
but several programs want to use it. */
extern int glob_pattern_p __P ((__const char *__pattern, int __quote));
extern int glob_pattern_p (const char *pattern, int quote);
#endif
#ifdef __cplusplus

View File

@ -1,7 +1,7 @@
dnl acinclude.m4 -- Extra macros needed for GNU make.
dnl acinclude.m4 -- Extra macros needed for GNU Make.
dnl
dnl Automake will incorporate this into its generated aclocal.m4.
dnl Copyright (C) 1998-2022 Free Software Foundation, Inc.
dnl Copyright (C) 1998-2024 Free Software Foundation, Inc.
dnl This file is part of GNU Make.
dnl
dnl GNU Make is free software; you can redistribute it and/or modify it under
@ -43,8 +43,8 @@ AC_MSG_RESULT(working...)
cf_cv_netlibs=""
cf_test_netlibs=yes
AC_CHECK_FUNCS(gethostname,,[
CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[
CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])])
CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[
CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])])
#
# FIXME: sequent needs this library (i.e., -lsocket -linet -lnsl), but
# I don't know the entrypoints - 97/7/22 TD
@ -52,12 +52,12 @@ AC_CHECK_LIB(inet,main,cf_cv_netlibs="-linet $cf_cv_netlibs")
#
if test "$ac_cv_func_lsocket" != no ; then
AC_CHECK_FUNCS(socket,,[
CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[
CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])])
CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[
CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])])
fi
#
AC_CHECK_FUNCS(gethostbyname,,[
CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)])
CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)])
])
LIBS="$LIBS $cf_cv_netlibs"
test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&AC_FD_MSG
@ -77,14 +77,14 @@ dnl used (autoconf does not distinguish between a null token and one that is
dnl set to 'no').
AC_DEFUN([CF_RECHECK_FUNC],[
AC_CHECK_LIB($2,$1,[
CF_UPPER(cf_tr_func,$1)
AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1])
ac_cv_func_$1=yes
$3="-l$2 [$]$3"],[
ac_cv_func_$1=unknown
unset ac_cv_func_$1 2>/dev/null
$4],
[[$]$3])
CF_UPPER(cf_tr_func,$1)
AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1])
ac_cv_func_$1=yes
$3="-l$2 [$]$3"],[
ac_cv_func_$1=unknown
unset ac_cv_func_$1 2>/dev/null
$4],
[[$]$3])
])dnl
dnl ---------------------------------------------------------------------------
dnl Make an uppercase version of a variable
@ -118,7 +118,7 @@ AC_DEFUN([AC_STRUCT_ST_MTIM_NSEC],
CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val"
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/stat.h>
], [struct stat s; s.ST_MTIM_NSEC;],
], [struct stat s; s.ST_MTIM_NSEC;],
[ac_cv_struct_st_mtim_nsec=$ac_val; break])
done
CPPFLAGS="$ac_save_CPPFLAGS"
@ -126,7 +126,7 @@ AC_DEFUN([AC_STRUCT_ST_MTIM_NSEC],
if test $ac_cv_struct_st_mtim_nsec != no; then
AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec],
[Define if struct stat contains a nanoseconds field])
[Define if struct stat contains a nanoseconds field])
fi
]
)

View File

@ -1,7 +1,7 @@
# Test if the system uses DOS-style pathnames (drive specs and backslashes)
# By Paul Smith <psmith@gnu.org>. Based on dos.m4 by Jim Meyering.
#
# Copyright (C) 1993-2022 Free Software Foundation, Inc.
# Copyright (C) 1993-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,7 +1,7 @@
# Check for getloadavg.
# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2022 Free Software
# Foundation, Inc.
# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2024 Free
# Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -160,7 +160,7 @@ AC_CHECK_HEADERS([nlist.h],
])dnl
])# gl_PREREQ_GETLOADAVG
# ---- GNU make
# ---- GNU Make
# These macros are imported from stdlib which we don't want to include
# Only the getloadavg content is imported.

View File

@ -1,5 +1,5 @@
Description:
GNU make version of fnmatch()/glob() functions. This is a holdover from
GNU Make version of fnmatch()/glob() functions. This is a holdover from
a very old version of the globbing library.
Files:
@ -10,21 +10,59 @@ lib/glob.in.h
configure.ac:
# Check the system to see if it provides GNU glob. If not, use our
# local version.
AC_CACHE_CHECK([if system libc has GNU glob], [make_cv_sys_gnu_glob],
[ AC_EGREP_CPP([gnu glob],[
#include <features.h>
#include <glob.h>
#include <fnmatch.h>
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
# include <gnu-versions.h>
# if _GNU_GLOB_INTERFACE_VERSION == 1 || _GNU_GLOB_INTERFACE_VERSION == 2
gnu glob
# endif
#endif],
[make_cv_sys_gnu_glob=yes],
[make_cv_sys_gnu_glob=no])])
# local version. Also avoid versions of glibc which have symlink bug
# https://sourceware.org/bugzilla/show_bug.cgi?id=866 (test from gnulib)
AC_CACHE_CHECK([if system libc has working GNU glob], [make_cv_sys_gnu_glob],[
if ln -s conf-doesntexist conf$$-globtest 2>/dev/null; then
make_check_symlink=yes
else
make_check_symlink=no
fi
if test $cross_compiling = yes || test $make_check_symlink = no; then
# When cross-compiling or without symlink support, check the version
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <features.h>
#include <gnu-versions.h>
#include <glob.h>
#include <fnmatch.h>
]],
[[
#if _GNU_GLOB_INTERFACE_VERSION == 0
GNU glob not available in libc
#elif __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 27)
GNU glob in libc has dangling symlink bug
#endif
]])],
[make_cv_sys_gnu_glob=yes],
[make_cv_sys_gnu_glob=no])
else
# Check for GNU glob, and that it handles dangling symlinks properly
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <features.h>
#include <gnu-versions.h>
#include <glob.h>
#include <fnmatch.h>
]],
[[
#if _GNU_GLOB_INTERFACE_VERSION == 0
return 1;
#else
glob_t found;
if (glob ("conf*-globtest", 0, 0, &found) == GLOB_NOMATCH)
return 1;
globfree (&found);
#endif
]])],
[make_cv_sys_gnu_glob=yes],
[make_cv_sys_gnu_glob=no],
[dnl We don't get here.
:
])
fi
test $make_check_symlink = no || rm -f conf$$-globtest
])
# Tell automake about this, so it can build the right .c files.
AM_CONDITIONAL([USE_SYSTEM_GLOB], [test "$make_cv_sys_gnu_glob" = yes])

View File

@ -1,5 +1,5 @@
Description:
Install m4 macros for GNU make.
Install m4 macros for GNU Make.
Files:
m4/acinclude.m4

View File

@ -1,5 +1,5 @@
# Maintainer-only makefile segment. This contains things that are relevant
# only if you have the full copy of the GNU make sources from the Git
# only if you have the full copy of the GNU Make sources from the Git
# tree, not a dist copy.
# --------------------- #
@ -20,7 +20,7 @@ SRCROOTDIR ?= $(HOME)/src
# Where to put the CVS checkout of the GNU web repository
GNUWEBDIR ?= $(SRCROOTDIR)/gnu-www
# Where to put the CVS checkout of the GNU make web repository
# Where to put the CVS checkout of the GNU Make web repository
MAKEWEBDIR ?= $(SRCROOTDIR)/make/make-web
# Enable Perl warnings for the test suite
@ -34,7 +34,10 @@ MAKE_CFLAGS := -C -Wall -Wextra -Werror -Wwrite-strings -Wshadow \
-Wtype-limits -Wunused-but-set-parameter -Wlogical-op -Wpointer-arith \
-Wignored-qualifiers -Wformat-signedness -Wduplicated-cond
AM_CFLAGS += $(MAKE_CFLAGS)
# Allow extra options without overriding MAKE_CFLAGS
EXTRA_CFLAGS :=
AM_CFLAGS += $(MAKE_CFLAGS) $(EXTRA_CFLAGS)
# Unfortunately the Guile headers are sometimes broken. Convince GCC
# to treat them as system headers so warnings are ignored.
@ -67,7 +70,6 @@ Basic.mk: Basic.mk.template .dep_segment Makefile
sed -e 's@%make_SOURCES%@$(call cvt,src,$(make_SRCS))@g' \
-e 's@%w32_SOURCES%@$(call cvt,src,$(w32_SRCS))@g' \
-e 's@%vms_SOURCES%@$(call cvt,src,$(vms_SRCS))@g' \
-e 's@%amiga_SOURCES%@$(call cvt,src,$(amiga_SRCS))@g' \
-e 's@%loadavg_SOURCES%@$(call cvt,lib,$(loadavg_SRCS))@g' \
-e 's@%alloca_SOURCES%@$(call cvt,lib,$(alloca_SRCS))@g' \
-e 's@%glob_SOURCES%@$(call cvt,lib,$(glob_SRCS))@g' \
@ -238,16 +240,26 @@ export TAR_OPTIONS := --mode=u+w,go-w --owner=0 --group=0 --numeric-owner --sort
# but add a new check to be sure it doesn't happen again.
mk_dist_files = AUTHORS ChangeLog COPYING INSTALL README src/mkconfig.h
dist: mk-distcheck
dist: mk-dist mk-distcheck
.PHONY: mk-distcheck
mk-distcheck: distdir
@echo "Checking for extra installed files..."
for fn in $(mk_dist_files); do \
@for fn in $(mk_dist_files); do \
test -f '$(distdir)'/"$$fn" \
|| { echo "Missing dist file: $$fn"; exit 1; }; \
done; true
# Make sure that the files in lib/ have been updated from the files in gl/lib/
GL_LIB_FILES := $(wildcard gl/lib/*)
mk-dist:
@echo "Checking gl/lib files..."
@for fn in $(GL_LIB_FILES); do \
cmp $$fn $${fn##gl/} \
|| { echo "Run ./bootstrap --gen ?"; exit 1; }; \
done; true
# ---------------------------------- #
# Alternative configuration checks. #
@ -259,10 +271,12 @@ CFGCHECK_BUILDFLAGS =
# as well, and that will fail.
CFGCHECK_MAKEFLAGS = # CFLAGS='$(AM_CFLAGS)'
# This test can no longer be run: now that we rely on gnulib we must use C99+
# We don't support C90 anymore, strictly, but this test still works (with lots
# of warnings) and it helps us avoid egregious incompatibilities.
checkcfg.strict-c90: CFGCHECK_CONFIGFLAGS = CFLAGS='-std=c90 -pedantic'
checkcfg.strict-c90: CFGCHECK_MAKEFLAGS =
checkcfg.job-pipe: CFGCHECK_CONFIGFLAGS = CPPFLAGS=-DJOBSERVER_USE_FIFO=0
checkcfg.no-jobserver:CFGCHECK_CONFIGFLAGS = --disable-job-server
checkcfg.no-load: CFGCHECK_CONFIGFLAGS = --disable-load
checkcfg.no-guile: CFGCHECK_CONFIGFLAGS = --without-guile
@ -277,6 +291,8 @@ checkcfg.no-sync: CFGCHECK_CONFIGFLAGS = CPPFLAGS=-DNO_OUTPUT_SYNC
checkcfg.no-archives: CFGCHECK_CONFIGFLAGS = CPPFLAGS=-DNO_ARCHIVES
CONFIG_CHECKS := \
checkcfg.strict-c90 \
checkcfg.job-pipe \
checkcfg.no-jobserver \
checkcfg.no-load \
checkcfg.no-guile \
@ -288,14 +304,15 @@ CONFIG_CHECKS := \
.PHONY: check-alt-config
check-alt-config: $(CONFIG_CHECKS)
@echo --- $@ SUCCESS
# Trick GNU make so it doesn't run the submake as a recursive make.
# Trick GNU Make so it doesn't run the submake as a recursive make.
NR_MAKE = $(MAKE)
# Check builds both with build.sh and with make
build.sh_SCRIPT = exec >>'checkcfg.$*.log' 2>&1; set -x; \
cd $(distdir)/_build \
&& OUTDIR=_bld ../build.sh $(CFGCHECK_BUILD_FLAGS) \
&& OUTDIR=_bld ../build.sh -k $(CFGCHECK_BUILD_FLAGS) \
&& _bld/make GMK_OUTDIR=../_bld $(AM_MAKEFLAGS) check-local \
&& _bld/make GMK_OUTDIR=../_bld $(AM_MAKEFLAGS) clean
@ -340,7 +357,7 @@ checkcfg.basicmk: checkcfg.% : distdir
&& cd $(distdir) \
&& ./configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) $(DISTCHECK_CONFIGURE_FLAGS) \
&& $(NR_MAKE) $(AM_MAKEFLAGS) -f Basic.mk $(CFGCHECK_MAKEFLAGS)' \
&& $(NR_MAKE) $(AM_MAKEFLAGS) -f Basic.mk '$(CFGCHECK_MAKEFLAGS)' \
&& ./make $(AM_MAKEFLAGS) -f Basic.mk check \
&& ./make $(AM_MAKEFLAGS) -f Basic.mk clean
@ -391,7 +408,7 @@ makeweb-repo = $(USER)@cvs.sv.gnu.org:/web/make
gnuweb-repo = :pserver:anonymous@cvs.sv.gnu.org:/web/www
gnuweb-dir = www/server/standards
# Get the GNU make web page boilerplate etc.
# Get the GNU Make web page boilerplate etc.
update-makeweb:
test -d '$(MAKEWEBDIR)' || mkdir -p '$(MAKEWEBDIR)'
test -d '$(MAKEWEBDIR)'/CVS \
@ -491,48 +508,18 @@ tag-release:
# Sign it with my key. If you don't have my key/passphrase then sorry,
# you're SOL! :)
GPG = gpg
GPGFLAGS = -u $(GPG_KEYID)
DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES))
DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES))
# A simple rule to test signing, etc.
.PHONY: distsign
distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
%.sig : %
@echo "Signing file '$<':"
$(GPG) $(GPGFLAGS) -o "$@" -b "$<"
%.directive.asc: %
@echo "Creating signed directive file '$@':"
@( \
echo 'version: 1.2'; \
echo 'directory: make'; \
echo 'filename: $*'; \
echo 'comment: Official upload of $(PACKAGE_NAME) version $(PACKAGE_VERSION)'; \
) > "$*.directive"
$(GPG) $(GPGFLAGS) -o "$@" --clearsign "$*.directive"
@rm -f "$*.directive"
# Upload the artifacts
FTPPUT := $(firstword $(shell command -v ncftpput) $(wildcard $(GNULIBDIR)/build-aux/ncftpput-ftp) invalid)
gnu-upload-host = ftp-upload.gnu.org
gnu-upload-dir = /incoming
GNUPLOAD := $(GNULIBDIR)/build-aux/gnupload
UPLOADS = upload-alpha upload-ftp
.PHONY: $(UPLOADS)
$(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
$(FTPPUT) "$(gnu-upload-host)" "$(gnu-upload-dir)/$(@:upload-%=%)" $^
$(UPLOADS): upload-%: $(DIST_ARCHIVES)
$(GNUPLOAD) --user "$(GPG_KEYID)" --to "$*.gnu.org:make" -- $^
# Rebuild Makefile.in if this file is modifed.
# Rebuild Makefile.in if this file is modified.
Makefile.in: maintMakefile
# Copyright (C) 1997-2022 Free Software Foundation, Inc.
# Copyright (C) 1997-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -154,7 +154,7 @@ $ exit
$ endsubroutine : compileit
$!
$!-----------------------------------------------------------------------------
$!Copyright (C) 1996-2022 Free Software Foundation, Inc.
$!Copyright (C) 1996-2024 Free Software Foundation, Inc.
$!This file is part of GNU Make.
$!
$!GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,45 +0,0 @@
# GNU -*-Makefile-*- to build GNU make on Amiga
#
# Amiga overrides for use with Basic.mk.
#
# Copyright (C) 2017-2022 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.
CC = sc
LD = $(CC) Link
MKDIR.cmd = makedir $1
RM.cmd = delete $1
CP.cmd = copy $1 To $2
CPPFLAGS =
CFLAGS =
LDFLAGS =
prog_SOURCES += $(alloca_SOURCES) $(loadavg_SOURCES) $(glob_SOURCES) $(amiga_SOURCES)
BUILT_SOURCES += $(lib)alloca.h $(lib)fnmatch.h $(lib)glob.h
extra_CPPFLAGS = IDir $(OUTDIR)src IDir $(SRCDIR)/src IDir $(OUTDIR)lib IDir $(SRCDIR)/lib
C_SOURCE =
OUTPUT_OPTION =
LDFLAGS = From LIB:cres.o
LDLIBS = Lib LIB:sc.lib LIB:amiga.lib
LINK_OUTPUT = To $@
$(OUTDIR)src/config.h: $(SRCDIR)/src/config.ami
$(call CP.cmd,$<,$@)

View File

@ -1,8 +1,8 @@
# GNU -*-Makefile-*- to build GNU make on POSIX systems
# GNU -*-Makefile-*- to build GNU Make on POSIX systems
#
# POSIX overrides for use with Basic.mk.
#
# Copyright (C) 2017-2022 Free Software Foundation, Inc.
# Copyright (C) 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,8 +1,8 @@
# GNU -*-Makefile-*- to build GNU make on VMS
# GNU -*-Makefile-*- to build GNU Make on VMS
#
# VMS overrides for use with Basic.mk.
#
# Copyright (C) 2017-2022 Free Software Foundation, Inc.
# Copyright (C) 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,8 +1,8 @@
# GNU -*-Makefile-*- to build GNU make on Windows
# GNU -*-Makefile-*- to build GNU Make on Windows
#
# Windows overrides for use with Basic.mk.
#
# Copyright (C) 2017-2022 Free Software Foundation, Inc.
# Copyright (C) 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@ -30,6 +30,8 @@ P2W = $(subst /,\,$1)
prog_SOURCES += $(loadavg_SOURCES) $(glob_SOURCES) $(w32_SOURCES)
utf8_SOURCES = $(src)w32/utf8.rc $(src)w32/utf8.manifest
BUILT_SOURCES += $(lib)alloca.h $(lib)fnmatch.h $(lib)glob.h
w32_LIBS = kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 \
@ -41,9 +43,10 @@ LDFLAGS =
# --- Visual Studio
msvc_CC = cl.exe
msvc_RC = rc.exe
msvc_LD = link.exe
msvc_CPPFLAGS = /DHAVE_CONFIG_H /DWINDOWS32 /DWIN32 /D_CONSOLE
msvc_CPPFLAGS = /DHAVE_CONFIG_H /DMK_OS_W32=1 /DWIN32 /D_CONSOLE
msvc_CPPFLAGS += /I$(OUTDIR)src /I$(SRCDIR)/src /I$(SRCDIR)/src/w32/include /I$(OUTDIR)lib /I$(SRCDIR)/lib
msvc_CFLAGS = /nologo /MT /W4 /EHsc
@ -54,6 +57,7 @@ msvc_LDFLAGS = /nologo /SUBSYSTEM:console /PDB:$(BASE_PROG).pdb
msvc_LDLIBS = $(addsuffix .lib,$(w32_LIBS))
msvc_C_SOURCE = /c
msvc_RC_SOURCE =
msvc_OUTPUT_OPTION = /Fo$@
msvc_LINK_OUTPUT = /OUT:$@
@ -68,6 +72,7 @@ debug_msvc_LDFLAGS = /DEBUG
# --- GCC
gcc_CC = gcc
gcc_RC = windres
gcc_LD = $(gcc_CC)
release_gcc_OUTDIR = ./GccRel/
@ -79,6 +84,7 @@ gcc_LDFLAGS = -mthreads -gdwarf-2 -g3
gcc_LDLIBS = $(addprefix -l,$(w32_libs))
gcc_C_SOURCE = -c
gcc_RC_SOURCE = -i
gcc_OUTPUT_OPTION = -o $@
gcc_LINK_OUTPUT = -o $@
@ -87,6 +93,7 @@ release_gcc_CFLAGS = -O2
# ---
RES_COMPILE.cmd = $(RC) $(OUTPUT_OPTION) $(RC_SOURCE) $1
LINK.cmd = $(LD) $(extra_LDFLAGS) $(LDFLAGS) $(TARGET_ARCH) $1 $(LDLIBS) $(LINK_OUTPUT)
CHECK.cmd = cmd /c cd tests \& .\run_make_tests.bat -make ../$(PROG)
@ -96,9 +103,11 @@ RM.cmd = cmd /c del /F /Q $(call P2W,$1)
CP.cmd = cmd /c copy /Y $(call P2W,$1 $2)
CC = $($(TOOLCHAIN)_CC)
RC = $($(TOOLCHAIN)_RC)
LD = $($(TOOLCHAIN)_LD)
C_SOURCE = $($(TOOLCHAIN)_C_SOURCE)
RC_SOURCE = $($(TOOLCHAIN)_RC_SOURCE)
OUTPUT_OPTION = $($(TOOLCHAIN)_OUTPUT_OPTION)
LINK_OUTPUT = $($(TOOLCHAIN)_LINK_OUTPUT)
@ -120,3 +129,11 @@ LDLIBS = $(call _CUSTOM,LDLIBS)
$(OUTDIR)src/config.h: $(SRCDIR)/src/config.h.W32
$(call CP.cmd,$<,$@)
w32_UTF8OBJ = $(OUTDIR)src/w32/utf8.$(OBJEXT)
$(w32_UTF8OBJ): $(utf8_SOURCES)
$(call RES_COMPILE.cmd,$<)
ifneq (, $(shell where $(RC) 2>nul))
RESOURCE_OBJECTS = $(w32_UTF8OBJ)
endif

View File

@ -1,8 +1,8 @@
# GNU -*-Makefile-*- to build GNU make on MS-DOS with DJGPP
# GNU -*-Makefile-*- to build GNU Make on MS-DOS with DJGPP
#
# MS-DOS overrides for use with Basic.mk.
#
# Copyright (C) 2017-2022 Free Software Foundation, Inc.
# Copyright (C) 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -13,6 +13,7 @@ hr
id
it
ja
ka
ko
lt
nl

View File

@ -1,5 +1,5 @@
# List of source files containing translatable strings.
# Copyright (C) 2000-2022 Free Software Foundation, Inc.
# Copyright (C) 2000-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# GNU Make is free software; you can redistribute it and/or modify it under
@ -31,7 +31,6 @@ src/load.c
src/main.c
src/misc.c
src/output.c
src/output.h
src/posixos.c
src/read.c
src/remake.c
@ -41,8 +40,9 @@ src/shuffle.c
src/signame.c
src/strcache.c
src/variable.c
src/variable.h
src/vmsfunctions.c
src/vmsjobs.c
src/vpath.c
src/warning.c
src/warning.h
src/w32/w32os.c

View File

@ -1,9 +1,9 @@
#!/bin/sh
#
# Copyright (C) 2014-2022 Free Software Foundation, Inc.
# Copyright (C) 2014-2024 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# Update GNU make copyrights using gnulib update-copyright
# Update GNU Make copyrights using gnulib update-copyright
EXCLUDE='^\(\.[a-z].*\|.*/\.[a-z].*\|.*COPYING\|src/hash\.[ch]\|ChangeLog.*\|.*/ChangeLog.*\|INSTALL\|doc/make\.texi\|bootstrap\)$'
@ -31,7 +31,7 @@ run () {
if $force; then
: just do it
elif test ! -f src/makeint.h; then
die "Run in the root of the GNU make workspace"
die "Run in the root of the GNU Make workspace"
elif test -f configure; then
die "Run in a clean workspace (git clean -fdX)"
fi

View File

@ -1,113 +0,0 @@
/* Running commands on Amiga
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. */
#include "makeint.h"
#include "variable.h"
#include "amiga.h"
#include <assert.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>
static const char Amiga_version[] = "$VER: Make 3.74.3 (12.05.96) \n"
"Amiga Port by A. Digulla (digulla@home.lake.de)";
int
MyExecute (char **argv)
{
char * buffer, * ptr;
char ** aptr;
int len = 0;
int status;
for (aptr=argv; *aptr; aptr++)
{
len += strlen (*aptr) + 4;
}
buffer = AllocMem (len, MEMF_ANY);
if (!buffer)
O (fatal, NILF, "MyExecute: Cannot allocate space for calling a command");
ptr = buffer;
for (aptr=argv; *aptr; aptr++)
{
if (((*aptr)[0] == ';' && !(*aptr)[1]))
{
*ptr ++ = '"';
ptr = stpcpy (ptr, *aptr);
*(ptr++) = '"';
}
else if ((*aptr)[0] == '@' && (*aptr)[1] == '@' && !(*aptr)[2])
{
*ptr ++ = '\n';
continue;
}
else
ptr = stpcpy (ptr, *aptr);
*ptr ++ = ' ';
*ptr = 0;
}
ptr[-1] = '\n';
status = SystemTags (buffer,
SYS_UserShell, TRUE,
TAG_END);
FreeMem (buffer, len);
if (SetSignal (0L,0L) & SIGBREAKF_CTRL_C)
status = 20;
/* Warnings don't count */
if (status == 5)
status = 0;
return status;
}
char *
wildcard_expansion (char *wc, char *o)
{
# define PATH_SIZE 1024
struct AnchorPath * apath;
if ( (apath = AllocMem (sizeof (struct AnchorPath) + PATH_SIZE,
MEMF_CLEAR))
)
{
apath->ap_Strlen = PATH_SIZE;
if (MatchFirst (wc, apath) == 0)
{
do
{
o = variable_buffer_output (o, apath->ap_Buf,
strlen (apath->ap_Buf));
o = variable_buffer_output (o, " ",1);
} while (MatchNext (apath) == 0);
}
MatchEnd (apath);
FreeMem (apath, sizeof (struct AnchorPath) + PATH_SIZE);
}
return o;
}

View File

@ -1,18 +0,0 @@
/* Definitions for amiga specific things
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. */
int MyExecute (char ** argv);
char * wildcard_expansion (char * wc, char * o);

View File

@ -1,5 +1,5 @@
/* Interface to 'ar' archives for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
@ -36,7 +36,7 @@ ar_name (const char *name)
const char *p = strchr (name, '(');
const char *end;
if (p == 0 || p == name)
if (p == NULL || p == name)
return 0;
end = p + strlen (p) - 1;
@ -61,6 +61,9 @@ ar_parse_name (const char *name, char **arname_p, char **memname_p)
*arname_p = xstrdup (name);
p = strchr (*arname_p, '(');
/* This is never called unless ar_name() is true so p cannot be NULL. */
if (!p)
OS (fatal, NILF, "INTERNAL: ar_parse_name: bad name '%s'", *arname_p);
*(p++) = '\0';
p[strlen (p) - 1] = '\0';
*memname_p = p;
@ -117,7 +120,7 @@ ar_member_date (const char *name)
/* Set the archive-member NAME's modtime to now. */
#ifdef VMS
#if MK_OS_VMS
int
ar_touch (const char *name)
{
@ -145,7 +148,7 @@ ar_touch (const char *name)
switch (ar_member_touch (arname, memname))
{
case -1:
OS (error, NILF, _("touch: Archive '%s' does not exist"), arname);
OS (error, NILF, _("touch: archive '%s' does not exist"), arname);
break;
case -2:
OS (error, NILF, _("touch: '%s' is not a valid archive"), arname);
@ -155,21 +158,21 @@ ar_touch (const char *name)
break;
case 1:
OSS (error, NILF,
_("touch: Member '%s' does not exist in '%s'"), memname, arname);
_("touch: member '%s' does not exist in '%s'"), memname, arname);
break;
case 0:
val = 0;
break;
default:
OS (error, NILF,
_("touch: Bad return code from ar_member_touch on '%s'"), name);
_("touch: bad return code from ar_member_touch on '%s'"), name);
}
free (arname);
return val;
}
#endif /* !VMS */
#endif /* !MK_OS_VMS */
/* State of an 'ar_glob' run, passed to 'ar_glob_match'. */
@ -184,7 +187,7 @@ struct ar_glob_state
{
const char *arname;
const char *pattern;
#ifdef VMS
#if MK_OS_VMS
char *suffix;
#endif
size_t size;
@ -207,7 +210,7 @@ ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
{
/* We have a match. Add it to the chain. */
struct nameseq *new = xcalloc (state->size);
#ifdef VMS
#if MK_OS_VMS
if (state->suffix)
new->name = strcache_add(
concat(5, state->arname, "(", mem, state->suffix, ")"));
@ -265,7 +268,7 @@ ar_glob (const char *arname, const char *member_pattern, size_t size)
struct nameseq *n;
const char **names;
unsigned int i;
#ifdef VMS
#if MK_OS_VMS
char *vms_member_pattern;
#endif
if (! ar_glob_pattern_p (member_pattern, 1))
@ -275,7 +278,7 @@ ar_glob (const char *arname, const char *member_pattern, size_t size)
ar_glob_match will accumulate them in STATE.chain. */
state.arname = arname;
state.pattern = member_pattern;
#ifdef VMS
#if MK_OS_VMS
{
/* In a copy of the pattern, find the suffix, save it and remove it from
the pattern */
@ -296,7 +299,7 @@ ar_glob (const char *arname, const char *member_pattern, size_t size)
state.n = 0;
ar_scan (arname, ar_glob_match, &state);
#ifdef VMS
#if MK_OS_VMS
/* Deallocate any duplicated string */
free(vms_member_pattern);
if (state.suffix)

View File

@ -1,5 +1,5 @@
/* Library function for scanning an archive file.
Copyright (C) 1987-2022 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -29,7 +29,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef NO_ARCHIVES
#ifdef VMS
#if MK_OS_VMS
#include <lbrdef.h>
#include <mhddef.h>
#include <credef.h>
@ -289,11 +289,11 @@ ar_scan (const char *archive, ar_member_func_t function, const void *varg)
return -2;
}
#else /* !VMS */
#else /* !MK_OS_VMS */
/* SCO Unix's compiler defines both of these. */
#ifdef M_UNIX
#undef M_XENIX
#ifdef M_UNIX
#undef M_XENIX
#endif
/* On the sun386i and in System V rel 3, ar.h defines two different archive
@ -302,7 +302,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *varg)
to have a nonzero value. */
#if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
#undef PORTAR
#undef PORTAR
#ifdef M_XENIX
/* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
@ -330,8 +330,8 @@ ar_scan (const char *archive, ar_member_func_t function, const void *varg)
# define __AR_BIG__
#endif
#ifndef WINDOWS32
# if !defined (__ANDROID__) && !defined (__BEOS__)
#if !MK_OS_W32
# if !defined (__ANDROID__) && !defined (__BEOS__) && !defined(MK_OS_ZOS)
# include <ar.h>
# else
/* These platforms don't have <ar.h> but have archives in the same format
@ -395,16 +395,12 @@ parse_int (const char *ptr, const size_t len, const int base, uintmax_t max,
while (ptr < ep && *ptr != ' ')
{
uintmax_t nv;
if (*ptr < '0' || *ptr > maxchar)
if (*ptr < '0' || *ptr > maxchar
|| INT_MULTIPLY_WRAPV (val, base, &val)
|| INT_ADD_WRAPV (val, *ptr - '0', &val)
|| val > max)
OSSS (fatal, NILF,
_("Invalid %s for archive %s member %s"), type, archive, name);
nv = (val * base) + (*ptr - '0');
if (nv < val || nv > max)
OSSS (fatal, NILF,
_("Invalid %s for archive %s member %s"), type, archive, name);
val = nv;
_("invalid %s for archive %s member %s"), type, archive, name);
++ptr;
}
@ -841,7 +837,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
close (desc);
return -2;
}
#endif /* !VMS */
#endif /* !MK_OS_VMS */
/* Return nonzero iff NAME matches MEM.
If TRUNCATED is nonzero, MEM may be truncated to
@ -852,11 +848,16 @@ ar_name_equal (const char *name, const char *mem, int truncated)
{
const char *p;
/* GNU ar allows -P to preserve parent paths, so test the literal name
before stripping off the directory. */
if (streq (name, mem))
return 1;
p = strrchr (name, '/');
if (p != 0)
name = p + 1;
#ifndef VMS
#if !MK_OS_VMS
if (truncated)
{
#ifdef AIAMAG
@ -896,10 +897,10 @@ ar_name_equal (const char *name, const char *mem, int truncated)
match = !strcasecmp (name, mem);
return match;
}
#endif /* !VMS */
#endif /* !MK_OS_VMS */
}
#ifndef VMS
#if !MK_OS_VMS
/* ARGSUSED */
static intmax_t
ar_member_pos (int desc UNUSED, const char *mem, int truncated,
@ -953,7 +954,7 @@ ar_member_touch (const char *arname, const char *memname)
if (r < 0)
goto lose;
/* Advance member's time to that time */
#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || MK_OS_W32
datelen = snprintf (TOCHAR (ar_hdr.ar_date), sizeof ar_hdr.ar_date,
"%" PRIdMAX, (intmax_t) statbuf.st_mtime);
if (! (0 <= datelen && datelen < (int) sizeof ar_hdr.ar_date))

View File

@ -1,5 +1,5 @@
/* Command processing for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -21,12 +21,12 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "variable.h"
#include "job.h"
#include "commands.h"
#ifdef WINDOWS32
#if MK_OS_W32
#include <windows.h>
#include "w32err.h"
#endif
#if VMS
#if MK_OS_VMS
# define FILE_LIST_SEPARATOR (vms_comma_separator ? ',' : ' ')
#else
# define FILE_LIST_SEPARATOR ' '
@ -313,7 +313,7 @@ set_file_variables (struct file *file, const char *stem)
DEFINE_VARIABLE ("|", 1, bar_value);
}
#undef DEFINE_VARIABLE
#undef DEFINE_VARIABLE
}
/* Chop CMDS up into individual command lines if necessary.
@ -376,7 +376,7 @@ chop_commands (struct commands *cmds)
if (nlines == USHRT_MAX)
ON (fatal, &cmds->fileinfo,
_("Recipe has too many lines (limit %hu)"), nlines);
_("recipe has too many lines (limit %hu)"), nlines);
if (nlines == max)
{
@ -483,7 +483,7 @@ volatile sig_atomic_t handling_fatal_signal = 0;
void
fatal_error_signal (int sig)
{
#ifdef __MSDOS__
#if MK_OS_DOS
extern int dos_status, dos_command_running;
if (dos_command_running)
@ -494,15 +494,8 @@ fatal_error_signal (int sig)
}
remove_intermediates (1);
exit (EXIT_FAILURE);
#else /* not __MSDOS__ */
#ifdef _AMIGA
remove_intermediates (1);
if (sig == SIGINT)
fputs (_("*** Break.\n"), stderr);
exit (10);
#else /* not Amiga */
#ifdef WINDOWS32
#else /* not MK_OS_DOS */
#if MK_OS_W32
extern HANDLE main_thread;
/* Windows creates a separate thread for handling Ctrl+C, so we need
@ -588,7 +581,7 @@ fatal_error_signal (int sig)
exit (MAKE_TROUBLE);
#endif
#ifdef WINDOWS32
#if MK_OS_W32
if (main_thread)
CloseHandle (main_thread);
/* Cannot call W32_kill with a pid (it needs a handle). The exit
@ -599,9 +592,8 @@ fatal_error_signal (int sig)
will be unblocked when we return and arrive then to kill us. */
if (kill (make_pid (), sig) < 0)
pfatal_with_name ("kill");
#endif /* not WINDOWS32 */
#endif /* not Amiga */
#endif /* not __MSDOS__ */
#endif /* not MK_OS_W32 */
#endif /* not MK_OS_DOS */
}
/* Delete FILE unless it's precious or not actually a file (phony),
@ -626,11 +618,11 @@ delete_target (struct file *file, const char *on_behalf_of)
{
if (on_behalf_of)
OSS (error, NILF,
_("*** [%s] Archive member '%s' may be bogus; not deleted"),
_("*** [%s] archive member '%s' may be bogus; not deleted"),
on_behalf_of, file->name);
else
OS (error, NILF,
_("*** Archive member '%s' may be bogus; not deleted"),
_("*** archive member '%s' may be bogus; not deleted"),
file->name);
}
return;
@ -644,9 +636,9 @@ delete_target (struct file *file, const char *on_behalf_of)
{
if (on_behalf_of)
OSS (error, NILF,
_("*** [%s] Deleting file '%s'"), on_behalf_of, file->name);
_("*** [%s] deleting file '%s'"), on_behalf_of, file->name);
else
OS (error, NILF, _("*** Deleting file '%s'"), file->name);
OS (error, NILF, _("*** deleting file '%s'"), file->name);
if (unlink (file->name) < 0
&& errno != ENOENT) /* It disappeared; so what. */
perror_with_name ("unlink: ", file->name);

View File

@ -1,5 +1,5 @@
/* Definition of data structures describing shell commands for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,331 +0,0 @@
/* config.h -- hand-massaged for Amiga -*-C-*-
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. */
#include "mkconfig.h"
#define MK_AMIGAOS 1
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
/* #undef _ALL_SOURCE */
#endif
/* Define if using alloca.c. */
#define C_ALLOCA
/* Define if the closedir function returns void instead of int. */
/* #undef CLOSEDIR_VOID */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define for DGUX with <sys/dg_sys_info.h>. */
/* #undef DGUX */
/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
not define. */
#define intmax_t long
/* Define to 'unsigned long' or 'unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long
/* Define to 'int' if <sys/types.h> doesn't define. */
#define gid_t int
/* Define if you have alloca, as a function or macro. */
/* #undef HAVE_ALLOCA */
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
/* #undef HAVE_ALLOCA_H */
/* Define to 1 if you have the declaration of 'getloadavg'. */
/* #undef HAVE_DECL_GETLOADAVG */
/* Define if your system has a working fnmatch function. */
/* #undef HAVE_FNMATCH */
/* Define if you have the getmntent function. */
/* #undef HAVE_GETMNTENT */
/* Embed GNU Guile support */
/* #undef HAVE_GUILE */
/* Define if the 'long double' type works. */
/* #undef HAVE_LONG_DOUBLE */
/* Define if you support file names longer than 14 characters. */
#define HAVE_LONG_FILE_NAMES 1
/* Define if you have a working 'mmap' system call. */
/* #undef HAVE_MMAP */
/* Define if system calls automatically restart after interruption
by a signal. */
/* #undef HAVE_RESTARTABLE_SYSCALLS */
/* Define if your struct stat has st_blksize. */
/* #undef HAVE_ST_BLKSIZE */
/* Define if your struct stat has st_blocks. */
/* #undef HAVE_ST_BLOCKS */
/* Define if you have the strcoll function and it is properly defined. */
#define HAVE_STRCOLL 1
/* Define if your struct stat has st_rdev. */
#define HAVE_ST_RDEV 1
/* Define if you have the strftime function. */
#define HAVE_STRFTIME 1
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
/* #undef HAVE_SYS_WAIT_H */
/* Define if your struct tm has tm_zone. */
/* #undef HAVE_TM_ZONE */
/* Define if you don't have tm_zone but do have the external array
tzname. */
#define HAVE_TZNAME 1
/* Define if you have <unistd.h>. */
#define HAVE_UNISTD_H 1
/* Define if utime(file, NULL) sets file's timestamp to the present. */
/* #undef HAVE_UTIME_NULL */
/* Define if you have the wait3 system call. */
/* #undef HAVE_WAIT3 */
/* Define if on MINIX. */
/* #undef _MINIX */
/* Define if your struct nlist has an n_un member. */
/* #undef NLIST_NAME_UNION */
/* Define if you have <nlist.h>. */
/* #undef NLIST_STRUCT */
/* Define if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Define to 'int' if <sys/types.h> doesn't define. */
#define pid_t int
/* Define if the system does not provide POSIX.1 features except
with this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define if you need to in order for stat and other things to work. */
/* #undef _POSIX_SOURCE */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#define STACK_DIRECTION -1
/* Define if the 'S_IS*' macros in <sys/stat.h> do not work properly. */
/* #undef STAT_MACROS_BROKEN */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS
/* Define on System V Release 4. */
/* #undef SVR4 */
/* Define if 'sys_siglist' is declared by <signal.h>. */
/* #undef SYS_SIGLIST_DECLARED */
/* Define to 'int' if <sys/types.h> doesn't define. */
#define uid_t int
/* Define for Encore UMAX. */
/* #undef UMAX */
/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
instead of <sys/cpustats.h>. */
/* #undef UMAX4_3 */
/* Define to the name of the SCCS 'get' command. */
#define SCCS_GET "get"
/* Define this if the SCCS 'get' command understands the '-G<file>' option. */
/* #undef SCCS_GET_MINUS_G */
/* Define this to enable job server support in GNU make. */
/* #undef MAKE_JOBSERVER */
/* Define to be the nanoseconds member of struct stat's st_mtim,
if it exists. */
/* #undef ST_MTIM_NSEC */
/* Define this if the C library defines the variable 'sys_siglist'. */
/* #undef HAVE_SYS_SIGLIST */
/* Define this if the C library defines the variable '_sys_siglist'. */
/* #undef HAVE__SYS_SIGLIST */
/* Define this if you have the 'union wait' type in <sys/wait.h>. */
/* #undef HAVE_UNION_WAIT */
/* Define if you have the dup2 function. */
/* #undef HAVE_DUP2 */
/* Define if you have the getcwd function. */
#define HAVE_GETCWD 1
/* Define if you have the getgroups function. */
/* #undef HAVE_GETGROUPS */
/* Define if you have the gethostbyname function. */
/* #undef HAVE_GETHOSTBYNAME */
/* Define if you have the gethostname function. */
/* #undef HAVE_GETHOSTNAME */
/* Define if you have the memmove function. */
#define HAVE_MEMMOVE 1
/* Define if you have the mktemp function. */
#define HAVE_MKTEMP 1
/* Define if you have the psignal function. */
/* #undef HAVE_PSIGNAL */
/* Define if you have the pstat_getdynamic function. */
/* #undef HAVE_PSTAT_GETDYNAMIC */
/* Define if you have the setegid function. */
/* #undef HAVE_SETEGID */
/* Define if you have the seteuid function. */
/* #undef HAVE_SETEUID */
/* Define if you have the setlinebuf function. */
/* #undef HAVE_SETLINEBUF */
/* Define if you have the setregid function. */
/* #undef HAVE_SETREGID */
/* Define if you have the setreuid function. */
/* #undef HAVE_SETREUID */
/* Define if you have the sigsetmask function. */
/* #undef HAVE_SIGSETMASK */
/* Define if you have the socket function. */
/* #undef HAVE_SOCKET */
/* Define to 1 if you have the strcasecmp function. */
/* #undef HAVE_STRCASECMP */
/* Define to 1 if you have the strcmpi function. */
/* #undef HAVE_STRCMPI */
/* Define to 1 if you have the stricmp function. */
/* #undef HAVE_STRICMP */
/* Define if you have the strsignal function. */
/* #undef HAVE_STRSIGNAL */
/* Define if you have the strtoll function. */
/* #undef HAVE_STRTOLL */
/* Define if you have the wait3 function. */
/* #undef HAVE_WAIT3 */
/* Define if you have the waitpid function. */
/* #undef HAVE_WAITPID */
/* Define if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define if you have the <mach/mach.h> header file. */
/* #undef HAVE_MACH_MACH_H */
/* Define if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H */
/* Define if you have the <ndir.h> header file. */
/* #undef HAVE_NDIR_H */
/* Define if you have the <stdlib.h> header file. */
/* #undef HAVE_STDLIB_H */
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if you have the <sys/dir.h> header file. */
#define HAVE_SYS_DIR_H 1
/* Define if you have the <sys/ndir.h> header file. */
/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <sys/param.h> header file. */
/* #undef HAVE_SYS_PARAM_H */
/* Define if you have the <sys/timeb.h> header file. */
/* #undef HAVE_SYS_TIMEB_H */
/* Define if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H */
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the dgc library (-ldgc). */
/* #undef HAVE_LIBDGC */
/* Define if you have the kstat library (-lkstat). */
/* #undef HAVE_LIBKSTAT */
/* Define to 1 if you have the `isatty' function. */
/* #undef HAVE_ISATTY */
/* Define to 1 if you have the `ttyname' function. */
/* #undef HAVE_TTYNAME */
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
/* Output sync support */
#define NO_OUTPUT_SYNC
/* Define for Case Insensitive behavior */
#define HAVE_CASE_INSENSITIVE_FS
/* Build host information. */
#define MAKE_HOST "Amiga"
/* Define to `int' if <sys/types.h> does not define. */
#define ssize_t int

View File

@ -1,6 +1,6 @@
/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> -*-C-*-
Copyright (C) 1996-2022 Free Software Foundation, Inc.
Copyright (C) 1996-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -17,7 +17,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "mkconfig.h"
#define MK_VMS 1
#define MK_OS_VMS 1
/* Pull in types.h here to get __CRTL_VER defined for old versions of the
compiler which don't define it. */
@ -213,7 +213,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define this if the SCCS 'get' command understands the '-G<file>' option. */
/* #undef SCCS_GET_MINUS_G */
/* Define this to enable job server support in GNU make. */
/* Define this to enable job server support in GNU Make. */
/* #undef MAKE_JOBSERVER */
/* Define to be the nanoseconds member of struct stat's st_mtim,
@ -339,11 +339,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 1 if you have the <sys/param.h> header file. */
/* #undef HAVE_SYS_PARAM_H */
/* Define to 1 if you have the <sys/timeb.h> header file. */
#ifndef __GNUC__
#define HAVE_SYS_TIMEB_H 1
#endif
/* Define to 1 if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H */
@ -428,3 +423,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Build host information. */
#define MAKE_HOST "VMS"
/* Include customized declarations. */
#include "../src/mkcustom.h"

View File

@ -1,6 +1,6 @@
/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*-
Copyright (C) 1996-2022 Free Software Foundation, Inc.
Copyright (C) 1996-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -17,10 +17,8 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "mkconfig.h"
#define MK_W32 1
/* Build for the WINDOWS32 API. */
#define WINDOWS32 1
/* Build for the Windows32 API. */
#define MK_OS_W32 1
/* Suppress some Visual C++ warnings.
Maybe after the code cleanup for ISO C we can remove some/all of these. */
@ -344,6 +342,14 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 1 if you have the `strtoll' function. */
#define HAVE_STRTOLL 1
#ifdef __TINYC__
# ifndef strtoll
# define strtoll _strtoi64
# endif
# ifndef strtoull
# define strtoull _strtoui64
# endif
#endif
/* Define to 1 if `d_type' is a member of `struct dirent'. */
/* SV 57152: MinGW64 version of dirent doesn't support d_type. */
@ -382,9 +388,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/timeb.h> header file. */
#define HAVE_SYS_TIMEB_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#ifdef __MINGW32__
#define HAVE_SYS_TIME_H 1
@ -449,10 +452,10 @@ char *ttyname (int);
/* Build host information. */
#define MAKE_HOST "Windows32"
/* Define to 1 to enable job server support in GNU make. */
/* Define to 1 to enable job server support in GNU Make. */
#define MAKE_JOBSERVER 1
/* Define to 1 to enable 'load' support in GNU make. */
/* Define to 1 to enable 'load' support in GNU Make. */
#define MAKE_LOAD 1
/* Define to 1 to enable symbolic link timestamp checking. */
@ -621,3 +624,6 @@ char *ttyname (int);
#ifdef HAVE_CYGWIN_SHELL
#undef BATCH_MODE_ONLY_SHELL
#endif
/* Include customized declarations. */
#include "../src/mkcustom.h"

View File

@ -1,6 +1,6 @@
/* configh.dos -- hand-massaged config.h file for MS-DOS builds -*-C-*-
Copyright (C) 1994-2022 Free Software Foundation, Inc.
Copyright (C) 1994-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -17,7 +17,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "mkconfig.h"
#define MK_DJGPP 1
#define MK_OS_DOS 1
/* Include this header to make __DJGPP_MINOR__ available because DJGPP ports
of GCC 4.3.0 and later no longer do it automatically. */
@ -109,3 +109,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 'unsigned long' or 'unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long long
/* Include customized declarations. */
#include "../src/mkcustom.h"

View File

@ -1,5 +1,5 @@
/* Debugging macros and interface.
Copyright (C) 1999-2022 Free Software Foundation, Inc.
Copyright (C) 1999-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
/* Data base of default implicit rules for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -27,7 +27,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define GCC_IS_NATIVE if gcc is the native development environment on
your system (gcc/bison/flex vs cc/yacc/lex). */
#if defined(__MSDOS__) || defined(__EMX__)
#if MK_OS_DOS || MK_OS_OS2
# define GCC_IS_NATIVE
#endif
@ -36,14 +36,14 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
'.s' must come last, so that a '.o' file will be made from
a '.c' or '.p' or ... file rather than from a .s file. */
static char default_suffixes[]
#ifdef VMS
static const char default_suffixes[]
#if MK_OS_VMS
/* VMS should include all UNIX/POSIX + some VMS extensions */
= ".out .exe .a .olb .hlb .tlb .mlb .ln .o .obj .c .cxx .cc .cpp .pas .p \
.for .f .r .y .l .ym .yl .mar .s .ss .i .ii .mod .sym .def .h .info .dvi \
.tex .texinfo .texi .txinfo .mem .hlp .brn .rnh .rno .rnt .rnx .w .ch .cweb \
.web .com .sh .elc .el";
#elif defined(__EMX__)
#elif MK_OS_OS2
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .web .sh .elc .el .obj .exe .dll .lib";
@ -53,9 +53,9 @@ static char default_suffixes[]
.w .ch .web .sh .elc .el";
#endif
static struct pspec default_pattern_rules[] =
static const struct pspec default_pattern_rules[] =
{
#ifdef VMS
#if MK_OS_VMS
{ "(%)", "%",
"@if f$$search(\"$@\") .eqs. \"\" then $(LIBRARY)/CREATE/"
"$(or "
@ -76,7 +76,7 @@ static struct pspec default_pattern_rules[] =
/* The X.out rules are only in BSD's default set because
BSD Make has no null-suffix rules, so 'foo.out' and
'foo' are the same thing. */
#ifdef VMS
#if MK_OS_VMS
{ "%.exe", "%",
"$(CP) $< $@" },
@ -93,9 +93,9 @@ static struct pspec default_pattern_rules[] =
{ 0, 0, 0 }
};
static struct pspec default_terminal_rules[] =
static const struct pspec default_terminal_rules[] =
{
#ifdef VMS
#if MK_OS_VMS
/* RCS. */
{ "%", "%$$5lv", /* Multinet style */
@ -124,13 +124,13 @@ static struct pspec default_terminal_rules[] =
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
{ "%", "SCCS/s.%",
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
#endif /* !VMS */
#endif /* !MK_OS_VMS */
{ 0, 0, 0 }
};
static const char *default_suffix_rules[] =
static const char *const default_suffix_rules[] =
{
#ifdef VMS
#if MK_OS_VMS
".o",
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@",
".obj",
@ -263,7 +263,7 @@ static const char *default_suffix_rules[] =
".l.ln",
"@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
#else /* ! VMS */
#else /* ! MK_OS_VMS */
".o",
"$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@",
@ -326,19 +326,19 @@ static const char *default_suffix_rules[] =
".c.ln",
"$(LINT.c) -C$* $<",
".y.ln",
#ifndef __MSDOS__
"$(YACC.y) $< \n $(LINT.c) -C$* y.tab.c \n $(RM) y.tab.c",
#else
#if MK_OS_DOS
"$(YACC.y) $< \n $(LINT.c) -C$* y_tab.c \n $(RM) y_tab.c",
#else
"$(YACC.y) $< \n $(LINT.c) -C$* y.tab.c \n $(RM) y.tab.c",
#endif
".l.ln",
"@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
".y.c",
#ifndef __MSDOS__
"$(YACC.y) $< \n mv -f y.tab.c $@",
#else
#if MK_OS_DOS
"$(YACC.y) $< \n mv -f y_tab.c $@",
#else
"$(YACC.y) $< \n mv -f y.tab.c $@",
#endif
".l.c",
"@$(RM) $@ \n $(LEX.l) $< > $@",
@ -393,14 +393,14 @@ static const char *default_suffix_rules[] =
".web.tex",
"$(WEAVE) $<",
#endif /* !VMS */
#endif /* !MK_OS_VMS */
0, 0,
};
static const char *default_variables[] =
static const char *const default_variables[] =
{
#ifdef VMS
#if MK_OS_VMS
#ifdef __ALPHA
"ARCH", "ALPHA",
#endif
@ -515,7 +515,7 @@ static const char *default_variables[] =
"CP", "copy",
".LIBPATTERNS", "%.olb lib%.a",
#else /* !VMS */
#else /* !MK_OS_VMS */
"AR", "ar",
#ifdef _AIX
@ -527,18 +527,24 @@ static const char *default_variables[] =
"AS", "as",
#ifdef GCC_IS_NATIVE
"CC", "gcc",
# ifdef __MSDOS__
"CXX", "gpp", /* g++ is an invalid name on MSDOS */
# else
"CXX", "gcc",
# endif /* __MSDOS__ */
"OBJC", "gcc",
#else
"CC", "cc",
"CXX", "g++",
"OBJC", "cc",
#endif
#ifdef MAKE_CXX
"CXX", MAKE_CXX,
#else
# ifdef GCC_IS_NATIVE
# ifdef MK_OS_DOS
"CXX", "gpp", /* g++ is an invalid name on MSDOS */
# else
"CXX", "gcc",
# endif /* __MSDOS__ */
# else
"CXX", "g++",
# endif
#endif
/* This expands to $(CO) $(COFLAGS) $< $@ if $@ does not exist,
and to the empty string if $@ does exist. */
"CHECKOUT,v", "+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)",
@ -546,17 +552,17 @@ static const char *default_variables[] =
"COFLAGS", "",
"CPP", "$(CC) -E",
#ifdef CRAY
#ifdef CRAY
"CF77PPFLAGS", "-P",
"CF77PP", "/lib/cpp",
"CFT", "cft77",
"CF", "cf77",
"FC", "$(CF)",
#else /* Not CRAY. */
#ifdef _IBMR2
#else /* Not CRAY. */
#ifdef _IBMR2
"FC", "xlf",
#else
#ifdef __convex__
#ifdef __convex__
"FC", "fc",
#else
"FC", "f77",
@ -576,10 +582,10 @@ static const char *default_variables[] =
#endif
"LINT", "lint",
"M2C", "m2c",
#ifdef pyr
#ifdef pyr
"PC", "pascal",
#else
#ifdef CRAY
#ifdef CRAY
"PC", "PASCAL",
"SEGLDR", "segldr",
#else
@ -650,23 +656,21 @@ static const char *default_variables[] =
"OUTPUT_OPTION", "-o $@",
#endif
#ifdef SCCS_GET_MINUS_G
#ifdef SCCS_GET_MINUS_G
"SCCS_OUTPUT_OPTION", "-G$@",
#endif
#if defined(_AMIGA)
".LIBPATTERNS", "%.lib",
#elif defined(__MSDOS__)
#if MK_OS_DOS
".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a",
#elif defined(__APPLE__)
".LIBPATTERNS", "lib%.dylib lib%.a",
#elif defined(__CYGWIN__) || defined(WINDOWS32)
#elif defined(__CYGWIN__) || MK_OS_W32
".LIBPATTERNS", "lib%.dll.a %.dll.a lib%.a %.lib lib%.dll %.dll",
#else
".LIBPATTERNS", "lib%.so lib%.a",
#endif
#endif /* !VMS */
#endif /* !MK_OS_VMS */
/* Make this assignment to avoid undefined variable warnings. */
GNUMAKEFLAGS_NAME, "",
0, 0
@ -701,9 +705,9 @@ set_default_suffixes (void)
installed after. */
void
install_default_suffix_rules (void)
install_default_suffix_rules ()
{
const char **s;
const char *const *s;
if (no_builtin_rules_flag)
return;
@ -711,14 +715,16 @@ install_default_suffix_rules (void)
for (s = default_suffix_rules; *s != 0; s += 2)
{
struct file *f = enter_file (strcache_add (s[0]));
/* This function should run before any makefile is parsed. */
assert (f->cmds == 0);
f->cmds = xmalloc (sizeof (struct commands));
f->cmds->fileinfo.filenm = 0;
f->cmds->commands = xstrdup (s[1]);
f->cmds->command_lines = 0;
f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
f->builtin = 1;
/* Install the default rule only if there is no user defined rule. */
if (!f->cmds)
{
f->cmds = xmalloc (sizeof (struct commands));
f->cmds->fileinfo.filenm = NULL;
f->cmds->commands = xstrdup (s[1]);
f->cmds->command_lines = NULL;
f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
f->builtin = 1;
}
}
}
@ -728,7 +734,7 @@ install_default_suffix_rules (void)
void
install_default_implicit_rules (void)
{
struct pspec *p;
const struct pspec *p;
if (no_builtin_rules_flag)
return;
@ -743,7 +749,7 @@ install_default_implicit_rules (void)
void
define_default_variables (void)
{
const char **s;
const char *const *s;
if (no_builtin_variables_flag)
return;
@ -755,8 +761,8 @@ define_default_variables (void)
void
undefine_default_variables (void)
{
const char **s;
const char *const *s;
for (s = default_variables; *s != 0; s += 2)
undefine_variable_global (s[0], strlen (s[0]), o_default);
undefine_variable_global (NILF, s[0], strlen (s[0]), o_default);
}

View File

@ -1,5 +1,5 @@
/* Definitions of dependency data structures for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -42,7 +42,6 @@ struct nameseq
explicit is set when implicit rule search is performed and the prerequisite
does not contain %. When explicit is set the file is not intermediate. */
#define DEP(_t) \
NAMESEQ (_t); \
struct file *file; \
@ -89,7 +88,7 @@ struct goaldep
#define PARSE_SIMPLE_SEQ(_s,_t) \
(_t *)parse_file_seq ((_s),sizeof (_t),MAP_NUL,NULL,PARSEFS_NONE)
#ifdef VMS
#if MK_OS_VMS
void *parse_file_seq ();
#else
void *parse_file_seq (char **stringp, size_t size,
@ -132,6 +131,7 @@ SI void free_goal_chain (struct goaldep *g) { free_dep_chain((struct dep *)g); }
# define free_goal_chain(_g) free_ns_chain ((struct nameseq *)(_g))
#endif
struct dep *copy_dep (const struct dep *d);
struct dep *copy_dep_chain (const struct dep *d);
struct goaldep *read_all_makefiles (const char **makefiles);

289
src/dir.c
View File

@ -1,5 +1,5 @@
/* Directory hashing for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -20,10 +20,10 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "dep.h"
#include "debug.h"
#ifdef HAVE_DIRENT_H
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
# ifdef VMS
# if MK_OS_VMS
/* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */
const char *vmsify (const char *name, int type);
# endif
@ -50,7 +50,7 @@ const char *vmsify (const char *name, int type);
# define NAMLEN(d) _D_NAMLEN(d)
#endif
#if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
#if (defined (POSIX) || MK_OS_VMS || MK_OS_W32) && !defined (__GNU_LIBRARY__)
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1
@ -60,7 +60,7 @@ const char *vmsify (const char *name, int type);
# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
#endif /* POSIX */
#ifdef __MSDOS__
#if MK_OS_DOS
#include <ctype.h>
#include <fcntl.h>
@ -76,12 +76,12 @@ dosify (const char *filename)
char *df;
int i;
if (filename == 0 || _USE_LFN)
if (filename == NULL || _USE_LFN)
return filename;
/* FIXME: what about filenames which violate
8+3 constraints, like "config.h.in", or ".emacs"? */
if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0)
if (strpbrk (filename, "\"*+,;<=>?[\\]|") != NULL)
return filename;
df = dos_filename;
@ -105,19 +105,15 @@ dosify (const char *filename)
++filename;
if (*filename == '.')
return filename;
*df = 0;
*df = '\0';
return dos_filename;
}
#endif /* __MSDOS__ */
#endif /* MK_OS_DOS */
#ifdef WINDOWS32
#if MK_OS_W32
#include "pathstuff.h"
#endif
#ifdef _AMIGA
#include <ctype.h>
#endif
#ifdef HAVE_CASE_INSENSITIVE_FS
static const char *
downcase (const char *filename)
@ -125,8 +121,8 @@ downcase (const char *filename)
static PATH_VAR (new_filename);
char *df;
if (filename == 0)
return 0;
if (filename == NULL)
return NULL;
df = new_filename;
while (*filename != '\0')
@ -135,13 +131,13 @@ downcase (const char *filename)
++filename;
}
*df = 0;
*df = '\0';
return new_filename;
}
#endif /* HAVE_CASE_INSENSITIVE_FS */
#ifdef VMS
#if MK_OS_VMS
static char *
downcase_inplace(char *filename)
@ -203,14 +199,14 @@ vmsstat_dir (const char *name, struct stat *st)
DIR *dir;
dir = opendir (name);
if (dir == 0)
if (dir == NULL)
return -1;
closedir (dir);
s = strchr (name, ':'); /* find device */
if (s)
{
/* to keep the compiler happy we said "const char *name", now we cheat */
*s++ = 0;
*s++ = '\0';
st->st_dev = (char *)vms_hash (name);
h = vms_hash (s);
*(s-1) = ':';
@ -231,7 +227,7 @@ vmsstat_dir (const char *name, struct stat *st)
# define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)
#endif /* _USE_STD_STAT */
#endif /* VMS */
#endif /* MK_OS_VMS */
/* Never have more than this many directories open at once. */
@ -248,8 +244,8 @@ static unsigned int open_directories = 0;
struct directory_contents
{
dev_t dev; /* Device and inode numbers of this dir. */
#ifdef WINDOWS32
/* Inode means nothing on WINDOWS32. Even file key information is
#if MK_OS_W32
/* Inode means nothing on Windows32. Even file key information is
* unreliable because it is random per file open and undefined for remote
* filesystems. The most unique attribute I can come up with is the fully
* qualified name of the directory. Beware though, this is also
@ -262,12 +258,12 @@ struct directory_contents
# define FS_NTFS 0x2
# define FS_UNKNOWN 0x4
#else
# ifdef VMS_INO_T
# if MK_OS_VMS_INO_T
ino_t ino[3];
# else
ino_t ino;
# endif
#endif /* WINDOWS32 */
#endif /* MK_OS_W32 */
struct hash_table dirfiles; /* Files in this directory. */
unsigned long counter; /* command_count value when last read. */
DIR *dirstream; /* Stream reading this directory. */
@ -281,9 +277,10 @@ clear_directory_contents (struct directory_contents *dc)
{
--open_directories;
closedir (dc->dirstream);
dc->dirstream = 0;
dc->dirstream = NULL;
}
hash_free (&dc->dirfiles, 1);
if (dc->dirfiles.ht_vec != NULL)
hash_free (&dc->dirfiles, 1);
return NULL;
}
@ -294,12 +291,12 @@ directory_contents_hash_1 (const void *key_0)
const struct directory_contents *key = key_0;
unsigned long hash;
#ifdef WINDOWS32
#if MK_OS_W32
hash = 0;
ISTRING_HASH_1 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
#else
# ifdef VMS_INO_T
# if MK_OS_VMS_INO_T
hash = (((unsigned int) key->dev << 4)
^ ((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
@ -307,7 +304,7 @@ directory_contents_hash_1 (const void *key_0)
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
# endif
#endif /* WINDOWS32 */
#endif /* MK_OS_W32 */
return hash;
}
@ -317,12 +314,12 @@ directory_contents_hash_2 (const void *key_0)
const struct directory_contents *key = key_0;
unsigned long hash;
#ifdef WINDOWS32
#if MK_OS_W32
hash = 0;
ISTRING_HASH_2 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
#else
# ifdef VMS_INO_T
# if MK_OS_VMS_INO_T
hash = (((unsigned int) key->dev << 4)
^ ~((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
@ -330,7 +327,7 @@ directory_contents_hash_2 (const void *key_0)
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
# endif
#endif /* WINDOWS32 */
#endif /* MK_OS_W32 */
return hash;
}
@ -353,7 +350,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
const struct directory_contents *y = yv;
int result;
#ifdef WINDOWS32
#if MK_OS_W32
ISTRING_COMPARE (x->path_key, y->path_key, result);
if (result)
return result;
@ -361,7 +358,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
if (result)
return result;
#else
# ifdef VMS_INO_T
# if MK_OS_VMS_INO_T
result = MAKECMP(x->ino[0], y->ino[0]);
if (result)
return result;
@ -376,7 +373,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
if (result)
return result;
# endif
#endif /* WINDOWS32 */
#endif /* MK_OS_W32 */
return MAKECMP(x->dev, y->dev);
}
@ -456,7 +453,7 @@ dirfile_hash_cmp (const void *xv, const void *yv)
#define DIRFILE_BUCKETS 107
#endif
static int dir_contents_file_exists_p (struct directory_contents *dir,
static int dir_contents_file_exists_p (struct directory *dir,
const char *filename);
static struct directory *find_directory (const char *name);
@ -474,7 +471,7 @@ find_directory (const char *name)
struct stat st;
int r;
#ifdef WINDOWS32
#if MK_OS_W32
char *w32_path;
#endif
@ -502,7 +499,7 @@ find_directory (const char *name)
size_t len = strlen (name);
dir = xmalloc (sizeof (struct directory));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
#if defined(HAVE_CASE_INSENSITIVE_FS) && MK_OS_VMS
/* Todo: Why is this only needed on VMS? */
{
char *lname = downcase_inplace (xstrdup (name));
@ -519,9 +516,9 @@ find_directory (const char *name)
dir->counter = command_count;
/* See if the directory exists. */
#if defined(WINDOWS32)
#if MK_OS_W32
{
char tem[MAXPATHLEN], *tstart, *tend;
char tem[MAX_PATH+1], *tstart, *tend;
size_t len = strlen (name);
/* Remove any trailing slashes. Windows32 stat fails even on
@ -547,11 +544,11 @@ find_directory (const char *name)
memset (&dc_key, '\0', sizeof (dc_key));
dc_key.dev = st.st_dev;
#ifdef WINDOWS32
#if MK_OS_W32
dc_key.path_key = w32_path = w32ify (name, 1);
dc_key.ctime = st.st_ctime;
#else
# ifdef VMS_INO_T
# if MK_OS_VMS_INO_T
dc_key.ino[0] = st.st_ino[0];
dc_key.ino[1] = st.st_ino[1];
dc_key.ino[2] = st.st_ino[2];
@ -565,7 +562,7 @@ find_directory (const char *name)
if (HASH_VACANT (dc))
{
/* Nope; this really is a directory we haven't seen before. */
#ifdef WINDOWS32
#if MK_OS_W32
char fs_label[BUFSIZ];
char fs_type[BUFSIZ];
unsigned long fs_serno;
@ -576,11 +573,11 @@ find_directory (const char *name)
dc = xcalloc (sizeof (struct directory_contents));
*dc = dc_key;
#ifdef WINDOWS32
#if MK_OS_W32
dc->path_key = xstrdup (w32_path);
dc->mtime = st.st_mtime;
/* NTFS is the only WINDOWS32 filesystem that bumps mtime on a
/* NTFS is the only Windows32 filesystem that bumps mtime on a
directory when files are added/deleted from a directory. */
w32_path[3] = '\0';
if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label),
@ -593,7 +590,7 @@ find_directory (const char *name)
dc->fs_flags = FS_NTFS;
else
dc->fs_flags = FS_UNKNOWN;
#endif /* WINDOWS32 */
#endif /* MK_OS_W32 */
hash_insert_at (&directory_contents, dc, dc_slot);
}
@ -601,7 +598,7 @@ find_directory (const char *name)
/* Point the name-hashed entry for DIR at its contents data. */
dir->contents = dc;
/* If the contents have changed, we need to reseet. */
/* If the contents have changed, we need to reseed. */
if (dc->counter != command_count)
{
if (dc->counter)
@ -610,10 +607,9 @@ find_directory (const char *name)
dc->counter = command_count;
ENULLLOOP (dc->dirstream, opendir (name));
if (dc->dirstream == 0)
/* Couldn't open the directory. Mark this by setting the
'files' member to a nil pointer. */
dc->dirfiles.ht_vec = 0;
if (dc->dirstream == NULL)
/* Couldn't open the directory: mark this by setting files to NULL. */
dc->dirfiles.ht_vec = NULL;
else
{
hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
@ -623,7 +619,7 @@ find_directory (const char *name)
if (open_directories == MAX_OPEN_DIRECTORIES)
/* We have too many directories open already.
Read the entire directory and then close it. */
dir_contents_file_exists_p (dc, 0);
dir_contents_file_exists_p (dir, NULL);
}
}
@ -634,21 +630,22 @@ find_directory (const char *name)
FILENAME must contain no slashes. */
static int
dir_contents_file_exists_p (struct directory_contents *dir,
dir_contents_file_exists_p (struct directory *dir,
const char *filename)
{
struct dirfile *df;
struct dirent *d;
#ifdef WINDOWS32
struct directory_contents *dc = dir->contents;
#if MK_OS_W32
struct stat st;
int rehash = 0;
#endif
if (dir == 0 || dir->dirfiles.ht_vec == 0)
if (dc == NULL || dc->dirfiles.ht_vec == NULL)
/* The directory could not be stat'd or opened. */
return 0;
#ifdef __MSDOS__
#if MK_OS_DOS
filename = dosify (filename);
#endif
@ -656,11 +653,17 @@ dir_contents_file_exists_p (struct directory_contents *dir,
filename = downcase (filename);
#endif
#ifdef __EMX__
if (filename != 0)
_fnlwr (filename); /* lower case for FAT drives */
#if MK_OS_OS2
if (filename != NULL)
{
size_t len = strlen (filename);
char *fname = alloca (len + 1);
memcpy (fname, filename, len + 1);
_fnlwr (fname); /* lower case for FAT drives */
filename = fname;
}
#endif
if (filename != 0)
if (filename != NULL)
{
struct dirfile dirfile_key;
@ -671,7 +674,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
}
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
df = hash_find_item (&dir->dirfiles, &dirfile_key);
df = hash_find_item (&dc->dirfiles, &dirfile_key);
if (df)
return !df->impossible;
}
@ -679,25 +682,25 @@ dir_contents_file_exists_p (struct directory_contents *dir,
/* The file was not found in the hashed list.
Try to read the directory further. */
if (dir->dirstream == 0)
if (dc->dirstream == NULL)
{
#ifdef WINDOWS32
#if MK_OS_W32
/*
* Check to see if directory has changed since last read. FAT
* filesystems force a rehash always as mtime does not change
* on directories (ugh!).
*/
if (dir->path_key)
if (dc->path_key)
{
if ((dir->fs_flags & FS_FAT) != 0)
if ((dc->fs_flags & FS_FAT) != 0)
{
dir->mtime = time ((time_t *) 0);
dc->mtime = time (NULL);
rehash = 1;
}
else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
else if (stat (dc->path_key, &st) == 0 && st.st_mtime > dc->mtime)
{
/* reset date stamp to show most recent re-process. */
dir->mtime = st.st_mtime;
dc->mtime = st.st_mtime;
rehash = 1;
}
@ -706,8 +709,8 @@ dir_contents_file_exists_p (struct directory_contents *dir,
return 0;
/* make sure directory can still be opened; if not return. */
dir->dirstream = opendir (dir->path_key);
if (!dir->dirstream)
dc->dirstream = opendir (dc->path_key);
if (!dc->dirstream)
return 0;
}
else
@ -723,15 +726,15 @@ dir_contents_file_exists_p (struct directory_contents *dir,
struct dirfile dirfile_key;
struct dirfile **dirfile_slot;
ENULLLOOP (d, readdir (dir->dirstream));
if (d == 0)
ENULLLOOP (d, readdir (dc->dirstream));
if (d == NULL)
{
if (errno)
pfatal_with_name ("INTERNAL: readdir");
OSS (fatal, NILF, "readdir %s: %s", dir->name, strerror (errno));
break;
}
#if defined(VMS) && defined(HAVE_DIRENT_H)
#if MK_OS_VMS && defined(HAVE_DIRENT_H)
/* In VMS we get file versions too, which have to be stripped off.
Some versions of VMS return versions on Unix files even when
the feature option to strip them is set. */
@ -747,8 +750,8 @@ dir_contents_file_exists_p (struct directory_contents *dir,
len = NAMLEN (d);
dirfile_key.name = d->d_name;
dirfile_key.length = len;
dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
#ifdef WINDOWS32
dirfile_slot = (struct dirfile **) hash_find_slot (&dc->dirfiles, &dirfile_key);
#if MK_OS_W32
/*
* If re-reading a directory, don't cache files that have
* already been discovered.
@ -757,7 +760,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
#endif
{
df = xmalloc (sizeof (struct dirfile));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
#if MK_OS_VMS && defined(HAVE_CASE_INSENSITIVE_FS)
/* TODO: Why is this only needed on VMS? */
df->name = strcache_add_len (downcase_inplace (d->d_name), len);
#else
@ -768,21 +771,22 @@ dir_contents_file_exists_p (struct directory_contents *dir,
#endif
df->length = len;
df->impossible = 0;
hash_insert_at (&dir->dirfiles, df, dirfile_slot);
hash_insert_at (&dc->dirfiles, df, dirfile_slot);
}
/* Check if the name matches the one we're searching for. */
if (filename != 0 && patheq (d->d_name, filename))
if (filename != NULL && patheq (d->d_name, filename))
return 1;
}
/* If the directory has been completely read in,
close the stream and reset the pointer to nil. */
if (d == 0)
if (d == NULL)
{
--open_directories;
closedir (dir->dirstream);
dir->dirstream = 0;
closedir (dc->dirstream);
dc->dirstream = NULL;
}
return 0;
}
@ -793,16 +797,11 @@ dir_contents_file_exists_p (struct directory_contents *dir,
int
dir_file_exists_p (const char *dirname, const char *filename)
{
#ifdef VMS
if ((filename != NULL) && (dirname != NULL))
{
int want_vmsify;
want_vmsify = (strpbrk (dirname, ":<[") != NULL);
if (want_vmsify)
filename = vmsify (filename, 0);
}
#if MK_OS_VMS
if (filename && dirname && strpbrk (dirname, ":<[") != NULL)
filename = vmsify (filename, 0);
#endif
return dir_contents_file_exists_p (find_directory (dirname)->contents,
return dir_contents_file_exists_p (find_directory (dirname),
filename);
}
@ -821,23 +820,23 @@ file_exists_p (const char *name)
#endif
dirend = strrchr (name, '/');
#ifdef VMS
if (dirend == 0)
#if MK_OS_VMS
if (dirend == NULL)
{
dirend = strrchr (name, ']');
dirend == NULL ? dirend : dirend++;
}
if (dirend == 0)
if (dirend == NULL)
{
dirend = strrchr (name, '>');
dirend == NULL ? dirend : dirend++;
}
if (dirend == 0)
if (dirend == NULL)
{
dirend = strrchr (name, ':');
dirend == NULL ? dirend : dirend++;
}
#endif /* VMS */
#endif /* MK_OS_VMS */
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
@ -849,12 +848,8 @@ file_exists_p (const char *name)
dirend = name + 1;
}
#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifndef _AMIGA
if (dirend == NULL)
return dir_file_exists_p (".", name);
#else /* !AMIGA */
return dir_file_exists_p ("", name);
#endif /* AMIGA */
slash = dirend;
if (dirend == name)
@ -873,7 +868,7 @@ file_exists_p (const char *name)
p[dirend - name] = '\0';
dirname = p;
}
#ifdef VMS
#if MK_OS_VMS
if (*slash == '/')
slash++;
#else
@ -895,7 +890,7 @@ file_impossible (const char *filename)
struct dirfile *new;
dirend = strrchr (p, '/');
#ifdef VMS
#if MK_OS_VMS
if (dirend == NULL)
{
dirend = strrchr (p, ']');
@ -923,12 +918,8 @@ file_impossible (const char *filename)
dirend = p + 1;
}
#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifdef _AMIGA
dir = find_directory ("");
#else /* !AMIGA */
if (dirend == NULL)
dir = find_directory (".");
#endif /* AMIGA */
else
{
const char *dirname;
@ -950,7 +941,7 @@ file_impossible (const char *filename)
dirname = cp;
}
dir = find_directory (dirname);
#ifdef VMS
#if MK_OS_VMS
if (*slash == '/')
filename = p = slash + 1;
else
@ -960,22 +951,20 @@ file_impossible (const char *filename)
#endif
}
if (dir->contents == 0)
if (dir->contents == NULL)
/* The directory could not be stat'd. We allocate a contents
structure for it, but leave it out of the contents hash table. */
dir->contents = xcalloc (sizeof (struct directory_contents));
if (dir->contents->dirfiles.ht_vec == 0)
{
hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
}
if (dir->contents->dirfiles.ht_vec == NULL)
hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
/* Make a new entry and put it in the table. */
new = xmalloc (sizeof (struct dirfile));
new->length = strlen (filename);
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
#if defined(HAVE_CASE_INSENSITIVE_FS) && MK_OS_VMS
/* todo: Why is this only needed on VMS? */
new->name = strcache_add_len (downcase (filename), new->length);
#else
@ -994,12 +983,12 @@ file_impossible_p (const char *filename)
struct directory_contents *dir;
struct dirfile *dirfile;
struct dirfile dirfile_key;
#ifdef VMS
#if MK_OS_VMS
int want_vmsify = 0;
#endif
dirend = strrchr (filename, '/');
#ifdef VMS
#if MK_OS_VMS
if (dirend == NULL)
{
want_vmsify = (strpbrk (filename, "]>:^") != NULL);
@ -1021,12 +1010,8 @@ file_impossible_p (const char *filename)
dirend = filename + 1;
}
#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifdef _AMIGA
dir = find_directory ("")->contents;
#else /* !AMIGA */
if (dirend == NULL)
dir = find_directory (".")->contents;
#endif /* AMIGA */
else
{
const char *dirname;
@ -1048,7 +1033,7 @@ file_impossible_p (const char *filename)
dirname = cp;
}
dir = find_directory (dirname)->contents;
#ifdef VMS
#if MK_OS_VMS
if (*slash == '/')
filename = slash + 1;
else
@ -1058,17 +1043,17 @@ file_impossible_p (const char *filename)
#endif
}
if (dir == 0 || dir->dirfiles.ht_vec == 0)
if (dir == NULL || dir->dirfiles.ht_vec == NULL)
/* There are no files entered for this directory. */
return 0;
#ifdef __MSDOS__
#if MK_OS_DOS
filename = dosify (filename);
#endif
#ifdef HAVE_CASE_INSENSITIVE_FS
filename = downcase (filename);
#endif
#ifdef VMS
#if MK_OS_VMS
if (want_vmsify)
filename = vmsify (filename, 1);
#endif
@ -1100,7 +1085,7 @@ print_dir_data_base (void)
unsigned int impossible;
struct directory **dir_slot;
struct directory **dir_end;
#ifdef WINDOWS32
#if MK_OS_W32
char buf[INTSTR_LENGTH + 1];
#endif
@ -1115,10 +1100,10 @@ print_dir_data_base (void)
struct directory *dir = *dir_slot;
if (! HASH_VACANT (dir))
{
if (dir->contents == 0)
if (dir->contents == NULL)
printf (_("# %s: could not be stat'd.\n"), dir->name);
else if (dir->contents->dirfiles.ht_vec == 0)
#ifdef WINDOWS32
else if (dir->contents->dirfiles.ht_vec == NULL)
#if MK_OS_W32
printf (_("# %s (key %s, mtime %s): could not be opened.\n"),
dir->name, dir->contents->path_key,
make_ulltoa ((unsigned long long)dir->contents->mtime, buf));
@ -1151,7 +1136,7 @@ print_dir_data_base (void)
++f;
}
}
#ifdef WINDOWS32
#if MK_OS_W32
printf (_("# %s (key %s, mtime %s): "),
dir->name, dir->contents->path_key,
make_ulltoa ((unsigned long long)dir->contents->mtime, buf));
@ -1174,7 +1159,7 @@ print_dir_data_base (void)
else
printf ("%u", im);
fputs (_(" impossibilities"), stdout);
if (dir->contents->dirstream == 0)
if (dir->contents->dirstream == NULL)
puts (".");
else
puts (_(" so far."));
@ -1208,34 +1193,34 @@ struct dirstream
};
/* Forward declarations. */
static __ptr_t open_dirstream (const char *);
static struct dirent *read_dirstream (__ptr_t);
static void *open_dirstream (const char *);
static struct dirent *read_dirstream (void *);
static __ptr_t
static void *
open_dirstream (const char *directory)
{
struct dirstream *new;
struct directory *dir = find_directory (directory);
if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0)
if (dir->contents == NULL || dir->contents->dirfiles.ht_vec == NULL)
/* DIR->contents is nil if the directory could not be stat'd.
DIR->contents->dirfiles is nil if it could not be opened. */
return 0;
return NULL;
/* Read all the contents of the directory now. There is no benefit
in being lazy, since glob will want to see every file anyway. */
dir_contents_file_exists_p (dir->contents, 0);
dir_contents_file_exists_p (dir, NULL);
new = xmalloc (sizeof (struct dirstream));
new->contents = dir->contents;
new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec;
return (__ptr_t) new;
return new;
}
static struct dirent *
read_dirstream (__ptr_t stream)
read_dirstream (void *stream)
{
static char *buf;
static size_t bufsz;
@ -1279,7 +1264,7 @@ read_dirstream (__ptr_t stream)
}
}
return 0;
return NULL;
}
/* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a
@ -1289,8 +1274,8 @@ read_dirstream (__ptr_t stream)
* On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
* regular file; fix that here.
*/
#if !defined(stat) && !defined(WINDOWS32) || defined(VMS)
# ifndef VMS
#if !defined(stat) && !MK_OS_W32 || MK_OS_VMS
# if !MK_OS_VMS
# ifndef HAVE_SYS_STAT_H
int stat (const char *path, struct stat *sbuf);
# endif
@ -1306,7 +1291,7 @@ static int
local_stat (const char *path, struct stat *buf)
{
int e;
#ifdef WINDOWS32
#if MK_OS_W32
size_t plen = strlen (path);
/* Make sure the parent of "." exists and is a directory, not a
@ -1314,10 +1299,10 @@ local_stat (const char *path, struct stat *buf)
foo/. => foo without checking first that foo is a directory. */
if (plen > 2 && path[plen - 1] == '.' && ISDIRSEP (path[plen - 2]))
{
char parent[MAXPATHLEN+1];
char parent[MAX_PATH+1];
strncpy (parent, path, MAXPATHLEN);
parent[MIN(plen - 2, MAXPATHLEN)] = '\0';
strncpy (parent, path, MAX_PATH);
parent[MIN(plen - 2, MAX_PATH)] = '\0';
if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode))
return -1;
}
@ -1329,8 +1314,8 @@ local_stat (const char *path, struct stat *buf)
#endif
/* Similarly for lstat. */
#if !defined(lstat) && !defined(WINDOWS32) || defined(VMS)
# ifndef VMS
#if !defined(lstat) && !MK_OS_W32 || MK_OS_VMS
# if !MK_OS_VMS
# ifndef HAVE_SYS_STAT_H
int lstat (const char *path, struct stat *sbuf);
# endif
@ -1341,7 +1326,7 @@ int lstat (const char *path, struct stat *sbuf);
# endif
# endif
# define local_lstat lstat
#elif defined(WINDOWS32)
#elif MK_OS_W32
/* Windows doesn't support lstat(). */
# define local_lstat local_stat
#else

View File

@ -1,5 +1,5 @@
/* Variable expansion functions for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -24,6 +24,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "job.h"
#include "variable.h"
#include "rule.h"
#include "warning.h"
/* Initially, any errors reported when expanding strings will be reported
against the file where the error appears. */
@ -46,29 +47,33 @@ const floc **expanding_var = &reading_file;
static size_t variable_buffer_length;
char *variable_buffer;
/* Subroutine of variable_expand and friends:
The text to add is LENGTH chars starting at STRING to the variable_buffer.
The text is added to the buffer at PTR, and the updated pointer into
the buffer is returned as the value. Thus, the value returned by
each call to variable_buffer_output should be the first argument to
the following call. */
/* Append LENGTH chars of STRING at PTR which must point into variable_buffer.
The buffer will always be kept nul-terminated.
The updated pointer into the buffer is returned as the value. Thus, the
value returned by each call to variable_buffer_output should be the first
argument to the following call. */
char *
variable_buffer_output (char *ptr, const char *string, size_t length)
{
size_t newlen = length + (ptr - variable_buffer);
if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)
assert (ptr >= variable_buffer);
assert (ptr < variable_buffer + variable_buffer_length);
if (newlen + VARIABLE_BUFFER_ZONE + 1 > variable_buffer_length)
{
size_t offset = ptr - variable_buffer;
variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
? newlen + 100
: 2 * variable_buffer_length);
variable_buffer = xrealloc (variable_buffer, variable_buffer_length);
variable_buffer = xrealloc (variable_buffer, variable_buffer_length + 1);
ptr = variable_buffer + offset;
}
return mempcpy (ptr, string, length);
ptr = mempcpy (ptr, string, length);
*ptr = '\0';
return ptr;
}
/* Return a pointer to the beginning of the variable buffer.
@ -79,16 +84,58 @@ initialize_variable_output ()
{
/* If we don't have a variable output buffer yet, get one. */
if (variable_buffer == 0)
if (!variable_buffer)
{
variable_buffer_length = 200;
variable_buffer = xmalloc (variable_buffer_length);
variable_buffer[0] = '\0';
}
variable_buffer[0] = '\0';
return variable_buffer;
}
/* Install a new variable_buffer context, returning the current one for
safe-keeping. */
void
install_variable_buffer (char **bufp, size_t *lenp)
{
*bufp = variable_buffer;
*lenp = variable_buffer_length;
variable_buffer = NULL;
initialize_variable_output ();
}
/* Free the current variable_buffer and restore a previously-saved one.
*/
void
restore_variable_buffer (char *buf, size_t len)
{
free (variable_buffer);
variable_buffer = buf;
variable_buffer_length = len;
}
/* Restore a previously-saved variable_buffer context, and return the
current one.
*/
char *
swap_variable_buffer (char *buf, size_t len)
{
char *p = variable_buffer;
variable_buffer = buf;
variable_buffer_length = len;
return p;
}
/* Recursively expand V. The returned string is malloc'd. */
static char *allocated_variable_append (const struct variable *v);
@ -99,15 +146,16 @@ recursively_expand_for_file (struct variable *v, struct file *file)
char *value;
const floc *this_var;
const floc **saved_varp;
struct variable_set_list *save = 0;
struct variable_set_list *savev = 0;
int set_reading = 0;
size_t nl = strlen (v->name);
struct variable *parent = NULL;
/* If we're expanding to put into the environment of a shell function then
ignore any recursion issues: for backward-compatibility we will use
the value of the environment variable we were started with. */
if (v->expanding && env_recursion)
{
size_t nl = strlen (v->name);
char **ep;
DB (DB_VERBOSE,
(_("%s:%lu: not recursively expanding %s to export to shell function\n"),
@ -116,7 +164,7 @@ recursively_expand_for_file (struct variable *v, struct file *file)
/* We could create a hash for the original environment for speed, but a
reasonably written makefile shouldn't hit this situation... */
for (ep = environ; *ep != 0; ++ep)
if ((*ep)[nl] == '=' && strncmp (*ep, v->name, nl) == 0)
if (strncmp (*ep, v->name, nl) == 0 && (*ep)[nl] == '=')
return xstrdup ((*ep) + nl + 1);
/* If there's nothing in the parent environment, use the empty string.
@ -146,76 +194,184 @@ recursively_expand_for_file (struct variable *v, struct file *file)
if (!v->exp_count)
/* Expanding V causes infinite recursion. Lose. */
OS (fatal, *expanding_var,
_("Recursive variable '%s' references itself (eventually)"),
_("recursive variable '%s' references itself (eventually)"),
v->name);
--v->exp_count;
}
if (file)
{
save = current_variable_set_list;
current_variable_set_list = file->variables;
}
install_file_context (file, &savev, NULL);
v->expanding = 1;
if (v->append)
{
/* Find a parent definition which is marked override. */
struct variable_set_list *sl;
for (sl = current_variable_set_list; sl && !parent; sl = sl->next)
{
struct variable *vp = lookup_variable_in_set (v->name, nl, sl->set);
if (vp && vp != v && vp->origin == o_override)
parent = vp;
}
}
if (parent)
/* PARENT is an override, V is appending. If V is also an override:
override hello := first
al%: override hello += second
Then construct the value from its appended parts in the parent sets.
Else if V is not an override:
override hello := first
al%: hello += second
Then ignore the value of V and use the value of PARENT. */
value = v->origin == o_override
? allocated_variable_append (v)
: xstrdup (parent->value);
else if (v->origin == o_command || v->origin == o_env_override)
/* Avoid appending to a pattern-specific variable, unless the origin of this
pattern-specific variable beats or equals the origin of one of the parent
definitions of this variable.
This is needed, because if there is a command line definition or an env
override, then the value defined in the makefile should only be appended
in the case of a file override.
In the presence of command line definition or env override and absence of
makefile override, the value should be expanded, rather than appended. In
this case, at parse time record_target_var already set the value of this
pattern-specific variable to the value defined on the command line or to
the env override value.
User provided a command line definition or an env override.
PARENT does not have an override directive, so ignore it. */
value = allocated_expand_string (v->value);
else if (v->append)
/* Construct the value from its appended parts in the parent sets. */
value = allocated_variable_append (v);
else
value = allocated_variable_expand (v->value);
/* A definition without appending. */
value = allocated_expand_string (v->value);
v->expanding = 0;
if (set_reading)
reading_file = 0;
if (file)
current_variable_set_list = save;
restore_file_context (savev, NULL);
expanding_var = saved_varp;
return value;
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long. */
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
The result is written to PTR which must point into the variable_buffer.
Returns a pointer to the new end of the variable_buffer. */
#ifdef __GNUC__
__inline
#endif
static char *
reference_variable (char *o, const char *name, size_t length)
char *
expand_variable_output (char *ptr, const char *name, size_t length)
{
struct variable *v;
unsigned int recursive;
char *value;
v = lookup_variable (name, length);
if (v == 0)
if (!v)
warn_undefined (name, length);
/* If there's no variable by that name or it has no value, stop now. */
if (v == 0 || (*v->value == '\0' && !v->append))
return o;
if (!v || (v->value[0] == '\0' && !v->append))
return ptr;
value = (v->recursive ? recursively_expand (v) : v->value);
/* Remember this since expansion could change it. */
recursive = v->recursive;
o = variable_buffer_output (o, value, strlen (value));
value = recursive ? recursively_expand (v) : v->value;
if (v->recursive)
ptr = variable_buffer_output (ptr, value, strlen (value));
if (recursive)
free (value);
return o;
return ptr;
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
The result is written to BUF which must point into the variable_buffer.
If BUF is NULL, start at the beginning of the current variable_buffer.
Returns a pointer to the START of the expanded value of the variable.
The returned value is located inside variable_buffer.
The returned value is valid until the next call to one of the functions
which use variable_buffer. expand_variable_buf may reallocate
variable_buffer and render the passed-in BUF invalid. */
char *
expand_variable_buf (char *buf, const char *name, size_t length)
{
size_t offs;
if (!buf)
buf = initialize_variable_output ();
assert (buf >= variable_buffer);
assert (buf < variable_buffer + variable_buffer_length);
offs = buf - variable_buffer;
expand_variable_output (buf, name, length);
return variable_buffer + offs;
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
Returns an allocated buffer containing the value. */
char *
allocated_expand_variable (const char *name, size_t length)
{
char *obuf;
size_t olen;
install_variable_buffer (&obuf, &olen);
expand_variable_output (variable_buffer, name, length);
return swap_variable_buffer (obuf, olen);
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long.
Error messages refer to the file and line where FILE's commands were found.
Expansion uses FILE's variable set list.
Returns an allocated buffer containing the value. */
char *
allocated_expand_variable_for_file (const char *name, size_t length, struct file *file)
{
char *result;
struct variable_set_list *savev;
const floc *savef;
if (!file)
return allocated_expand_variable (name, length);
install_file_context (file, &savev, &savef);
result = allocated_expand_variable (name, length);
restore_file_context (savev, savef);
return result;
}
/* Scan STRING for variable references and expansion-function calls. Only
LENGTH bytes of STRING are actually scanned. If LENGTH is -1, scan until
a null byte is found.
LENGTH bytes of STRING are actually scanned.
If LENGTH is SIZE_MAX, scan until a null byte is found.
Write the results to LINE, which must point into 'variable_buffer'. If
LINE is NULL, start at the beginning of the buffer.
Return a pointer to LINE, or to the beginning of the buffer if LINE is
Write the results to BUF, which must point into variable_buffer. If
BUF is NULL, start at the beginning of the current variable_buffer.
Return a pointer to BUF, or to the beginning of the new buffer if BUF is
NULL.
*/
char *
variable_expand_string (char *line, const char *string, size_t length)
expand_string_buf (char *buf, const char *string, size_t length)
{
struct variable *v;
const char *p, *p1;
@ -223,16 +379,13 @@ variable_expand_string (char *line, const char *string, size_t length)
char *o;
size_t line_offset;
if (!line)
line = initialize_variable_output ();
o = line;
line_offset = line - variable_buffer;
if (!buf)
buf = initialize_variable_output ();
o = buf;
line_offset = buf - variable_buffer;
if (length == 0)
{
variable_buffer_output (o, "", 1);
return variable_buffer;
}
return variable_buffer;
/* We need a copy of STRING: due to eval, it's possible that it will get
freed as we process it (it might be the value of a variable that's reset
@ -271,47 +424,40 @@ variable_expand_string (char *line, const char *string, size_t length)
{
char openparen = *p;
char closeparen = (openparen == '(') ? ')' : '}';
const char *begp;
const char *beg = p + 1;
char *op;
char *abeg = NULL;
const char *end, *colon;
op = o;
begp = p;
if (handle_function (&op, &begp))
{
o = op;
p = begp;
break;
}
if (handle_function (&o, &p))
break;
/* Is there a variable reference inside the parens or braces?
If so, expand it before expanding the entire reference. */
end = strchr (beg, closeparen);
if (end == 0)
if (end == NULL)
/* Unterminated variable reference. */
O (fatal, *expanding_var, _("unterminated variable reference"));
p1 = lindex (beg, end, '$');
if (p1 != 0)
if (p1 != NULL)
{
/* BEG now points past the opening paren or brace.
Count parens or braces until it is matched. */
int count = 0;
int count = 1;
for (p = beg; *p != '\0'; ++p)
{
if (*p == openparen)
++count;
else if (*p == closeparen && --count < 0)
else if (*p == closeparen && --count == 0)
break;
}
/* If COUNT is >= 0, there were unmatched opening parens
/* If COUNT is > 0, there were unmatched opening parens
or braces, so we go to the simple case of a variable name
such as '$($(a)'. */
if (count < 0)
if (count == 0)
{
abeg = expand_argument (beg, p); /* Expand the name. */
/* Expand the name. */
abeg = expand_argument (beg, p);
beg = abeg;
end = strchr (beg, '\0');
}
@ -401,7 +547,7 @@ variable_expand_string (char *line, const char *string, size_t length)
if (colon == 0)
/* This is an ordinary variable reference.
Look up the value of the variable. */
o = reference_variable (o, beg, end - beg);
o = expand_variable_output (o, beg, end - beg);
free (abeg);
}
@ -413,7 +559,7 @@ variable_expand_string (char *line, const char *string, size_t length)
/* A $ followed by a random char is a variable reference:
$a is equivalent to $(a). */
o = reference_variable (o, p, 1);
o = expand_variable_output (o, p, 1);
break;
}
@ -426,21 +572,10 @@ variable_expand_string (char *line, const char *string, size_t length)
free (save);
variable_buffer_output (o, "", 1);
return (variable_buffer + line_offset);
}
/* Scan LINE for variable references and expansion-function calls.
Build in 'variable_buffer' the result of expanding the references and calls.
Return the address of the resulting string, which is null-terminated
and is valid only until the next time this function is called. */
char *
variable_expand (const char *line)
{
return variable_expand_string (NULL, line, SIZE_MAX);
}
/* Expand an argument for an expansion function.
The text starting at STR and ending at END is variable-expanded
into a null-terminated string that is returned as the value.
@ -457,7 +592,7 @@ expand_argument (const char *str, const char *end)
return xstrdup ("");
if (!end || *end == '\0')
return allocated_variable_expand (str);
return allocated_expand_string (str);
if (end - str + 1 > 1000)
tmp = alloc = xmalloc (end - str + 1);
@ -467,44 +602,53 @@ expand_argument (const char *str, const char *end)
memcpy (tmp, str, end - str);
tmp[end - str] = '\0';
r = allocated_variable_expand (tmp);
r = allocated_expand_string (tmp);
free (alloc);
return r;
}
/* Expand LINE for FILE. Error messages refer to the file and line where
FILE's commands were found. Expansion uses FILE's variable set list. */
/* Expand STRING for FILE, into the current variable_buffer.
Error messages refer to the file and line where FILE's commands were found.
Expansion uses FILE's variable set list. */
char *
variable_expand_for_file (const char *line, struct file *file)
expand_string_for_file (const char *string, struct file *file)
{
char *result;
struct variable_set_list *savev;
const floc *savef;
if (file == 0)
return variable_expand (line);
if (!file)
return expand_string (string);
savev = current_variable_set_list;
current_variable_set_list = file->variables;
install_file_context (file, &savev, &savef);
savef = reading_file;
if (file->cmds && file->cmds->fileinfo.filenm)
reading_file = &file->cmds->fileinfo;
else
reading_file = 0;
result = expand_string (string);
result = variable_expand (line);
current_variable_set_list = savev;
reading_file = savef;
restore_file_context (savev, savef);
return result;
}
/* Like expand_string_for_file, but the returned string is malloc'd. */
char *
allocated_expand_string_for_file (const char *string, struct file *file)
{
char *obuf;
size_t olen;
install_variable_buffer (&obuf, &olen);
expand_string_for_file (string, file);
return swap_variable_buffer (obuf, olen);
}
/* Like allocated_variable_expand, but for += target-specific variables.
/* Like allocated_expand_string, but for += target-specific variables.
First recursively construct the variable value from its appended parts in
any upper variable sets. Then expand the resulting value. */
@ -546,7 +690,7 @@ variable_append (const char *name, size_t length,
if (! v->recursive)
return variable_buffer_output (buf, v->value, strlen (v->value));
buf = variable_expand_string (buf, v->value, strlen (v->value));
buf = expand_string_buf (buf, v->value, strlen (v->value));
return (buf + strlen (buf));
}
@ -554,68 +698,13 @@ variable_append (const char *name, size_t length,
static char *
allocated_variable_append (const struct variable *v)
{
char *val;
/* Construct the appended variable value. */
char *obuf;
size_t olen;
char *obuf = variable_buffer;
size_t olen = variable_buffer_length;
install_variable_buffer (&obuf, &olen);
variable_buffer = 0;
variable_append (v->name, strlen (v->name), current_variable_set_list, 1);
val = variable_append (v->name, strlen (v->name),
current_variable_set_list, 1);
variable_buffer_output (val, "", 1);
val = variable_buffer;
variable_buffer = obuf;
variable_buffer_length = olen;
return val;
}
/* Like variable_expand_for_file, but the returned string is malloc'd.
This function is called a lot. It wants to be efficient. */
char *
allocated_variable_expand_for_file (const char *line, struct file *file)
{
char *value;
char *obuf = variable_buffer;
size_t olen = variable_buffer_length;
variable_buffer = 0;
value = variable_expand_for_file (line, file);
variable_buffer = obuf;
variable_buffer_length = olen;
return value;
}
/* Install a new variable_buffer context, returning the current one for
safe-keeping. */
void
install_variable_buffer (char **bufp, size_t *lenp)
{
*bufp = variable_buffer;
*lenp = variable_buffer_length;
variable_buffer = 0;
initialize_variable_output ();
}
/* Restore a previously-saved variable_buffer setting (free the current one).
*/
void
restore_variable_buffer (char *buf, size_t len)
{
free (variable_buffer);
variable_buffer = buf;
variable_buffer_length = len;
return swap_variable_buffer (obuf, olen);
}

View File

@ -1,5 +1,5 @@
/* Target file management for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -26,6 +26,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "debug.h"
#include "hash.h"
#include "shuffle.h"
#include "rule.h"
/* Remember whether snap_deps has been invoked: we need this to be sure we
@ -60,12 +61,17 @@ file_hash_cmp (const void *x, const void *y)
static struct hash_table files;
/* We can't free files we take out of the hash table, because they are still
likely pointed to in various places. The check_renamed() will be used if
we come across these, to find the new correct file. This is mainly to
prevent leak checkers from complaining. */
static struct file **rehashed_files = NULL;
static size_t rehashed_files_len = 0;
#define REHASHED_FILES_INCR 5
/* Whether or not .SECONDARY with no prerequisites was given. */
static int all_secondary = 0;
/* Whether or not .NOTINTERMEDIATE with no prerequisites was given. */
static int no_intermediates = 0;
/* Access the hash table of all file records.
lookup_file given a name, return the struct file * for that name,
or nil if there is none.
@ -76,7 +82,7 @@ lookup_file (const char *name)
{
struct file *f;
struct file file_key;
#ifdef VMS
#if MK_OS_VMS
int want_vmsify;
#ifndef WANT_CASE_SENSITIVE_TARGETS
char *lname;
@ -88,7 +94,7 @@ lookup_file (const char *name)
/* This is also done in parse_file_seq, so this is redundant
for names read from makefiles. It is here for names passed
on the command line. */
#ifdef VMS
#if MK_OS_VMS
want_vmsify = (strpbrk (name, "]>:^") != NULL);
# ifndef WANT_CASE_SENSITIVE_TARGETS
if (*name != '.')
@ -119,12 +125,8 @@ lookup_file (const char *name)
if (*name == '\0')
{
/* It was all slashes after a dot. */
#if defined(_AMIGA)
name = "";
#else
name = "./";
#endif
#if defined(VMS)
#if MK_OS_VMS
/* TODO - This section is probably not needed. */
if (want_vmsify)
name = "[]";
@ -132,7 +134,7 @@ lookup_file (const char *name)
}
file_key.hname = name;
f = hash_find_item (&files, &file_key);
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
#if MK_OS_VMS && !defined(WANT_CASE_SENSITIVE_TARGETS)
if (*name != '.')
free (lname);
#endif
@ -156,7 +158,7 @@ enter_file (const char *name)
assert (*name != '\0');
assert (! verify_flag || strcache_iscached (name));
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
#if MK_OS_VMS && !defined(WANT_CASE_SENSITIVE_TARGETS)
if (*name != '.')
{
const char *n;
@ -224,8 +226,7 @@ rehash_file (struct file *from_file, const char *to_hname)
/* Find the end of the renamed list for the "from" file. */
file_key.hname = from_file->hname;
while (from_file->renamed != 0)
from_file = from_file->renamed;
check_renamed (from_file);
if (file_hash_cmp (from_file, &file_key))
/* hname changed unexpectedly!! */
abort ();
@ -269,19 +270,19 @@ rehash_file (struct file *from_file, const char *to_hname)
if (to_file->cmds->fileinfo.filenm != 0)
error (&from_file->cmds->fileinfo,
l + strlen (to_file->cmds->fileinfo.filenm) + INTSTR_LENGTH,
_("Recipe was specified for file '%s' at %s:%lu,"),
_("recipe was specified for file '%s' at %s:%lu,"),
from_file->name, from_file->cmds->fileinfo.filenm,
from_file->cmds->fileinfo.lineno);
else
error (&from_file->cmds->fileinfo, l,
_("Recipe for file '%s' was found by implicit rule search,"),
_("recipe for file '%s' was found by implicit rule search,"),
from_file->name);
l += strlen (to_hname);
error (&from_file->cmds->fileinfo, l,
_("but '%s' is now considered the same file as '%s'."),
_("but '%s' is now considered the same file as '%s'"),
from_file->name, to_hname);
error (&from_file->cmds->fileinfo, l,
_("Recipe for '%s' will be ignored in favor of the one for '%s'."),
_("recipe for '%s' will be ignored in favor of the one for '%s'"),
from_file->name, to_hname);
}
}
@ -334,10 +335,17 @@ rehash_file (struct file *from_file, const char *to_hname)
MERGE (notintermediate);
MERGE (ignore_vpath);
MERGE (snapped);
MERGE (suffix);
#undef MERGE
to_file->builtin = 0;
from_file->renamed = to_file;
if (rehashed_files_len % REHASHED_FILES_INCR == 0)
rehashed_files = xrealloc (rehashed_files,
sizeof (struct file *) * (rehashed_files_len + REHASHED_FILES_INCR));
rehashed_files[rehashed_files_len++] = from_file;
}
/* Rename FILE to NAME. This is not as simple as resetting
@ -368,7 +376,7 @@ remove_intermediates (int sig)
int doneany = 0;
/* If there's no way we will ever remove anything anyway, punt early. */
if (question_flag || touch_flag || all_secondary)
if (question_flag || touch_flag || all_secondary || no_intermediates)
return;
if (sig && just_print_flag)
@ -404,7 +412,7 @@ remove_intermediates (int sig)
{
if (sig)
OS (error, NILF,
_("*** Deleting intermediate file '%s'"), f->name);
_("*** deleting intermediate file '%s'"), f->name);
else
{
if (! doneany)
@ -424,7 +432,10 @@ remove_intermediates (int sig)
}
if (status < 0)
{
perror_with_name ("\nunlink: ", f->name);
if (doneany)
fputs ("\n", stdout);
fflush (stdout);
perror_with_name ("unlink: ", f->name);
/* Start printing over. */
doneany = 0;
}
@ -643,7 +654,7 @@ expand_deps (struct file *f)
set_file_variables (f, d->stem ? d->stem : f->stem);
/* Perform second expansion. */
p = variable_expand_for_file (d->name, f);
p = expand_string_for_file (d->name, f);
/* Free the un-expanded name. */
free ((char*)d->name);
@ -695,7 +706,7 @@ struct dep *
expand_extra_prereqs (const struct variable *extra)
{
struct dep *d;
struct dep *prereqs = extra ? split_prereqs (variable_expand (extra->value)) : NULL;
struct dep *prereqs = extra ? split_prereqs (expand_string (extra->value)) : NULL;
for (d = prereqs; d; d = d->next)
{
@ -716,6 +727,7 @@ snap_file (const void *item, void *arg)
{
struct file *f = (struct file*)item;
struct dep *prereqs = NULL;
struct dep *d;
/* If we're not doing second expansion then reset updating. */
if (!second_expansion)
@ -731,18 +743,26 @@ snap_file (const void *item, void *arg)
/* If .NOTINTERMEDIATE is set with no deps, mark all targets as
notintermediate, unless the target is a prereq of .INTERMEDIATE. */
if (no_intermediates && !f->intermediate && !f->secondary)
f->notintermediate = 1;
f->notintermediate = 1;
/* If .EXTRA_PREREQS is set, add them as ignored by automatic variables. */
if (f->variables)
prereqs = expand_extra_prereqs (lookup_variable_in_set (STRING_SIZE_TUPLE(".EXTRA_PREREQS"), f->variables->set));
{
prereqs = expand_extra_prereqs (lookup_variable_in_set (
STRING_SIZE_TUPLE(".EXTRA_PREREQS"), f->variables->set));
if (second_expansion)
for (d = prereqs; d; d = d->next)
{
if (!d->name)
d->name = xstrdup (d->file->name);
d->need_2nd_expansion = 1;
}
}
else if (f->is_target)
prereqs = copy_dep_chain (arg);
if (prereqs)
{
struct dep *d;
for (d = prereqs; d; d = d->next)
if (streq (f->name, dep_name (d)))
/* Skip circular dependencies. */
@ -810,7 +830,7 @@ snap_deps (void)
else
no_intermediates = 1;
/* The same file connot be both .INTERMEDIATE and .NOTINTERMEDIATE.
/* The same file cannot be both .INTERMEDIATE and .NOTINTERMEDIATE.
However, it is possible for a file to be .INTERMEDIATE and also match a
.NOTINTERMEDIATE pattern. In that case, the intermediate file has
priority over the notintermediate pattern. This priority is enforced by
@ -943,7 +963,7 @@ file_timestamp_cons (const char *fname, time_t stamp, long int ns)
ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
file_timestamp_sprintf (buf, ts);
OSS (error, NILF,
_("%s: Timestamp out of range; substituting %s"), f, buf);
_("%s: timestamp out of range: substituting %s"), f, buf);
}
return ts;
@ -1010,22 +1030,20 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
if (tm)
{
intmax_t year = tm->tm_year;
sprintf (p, "%04" PRIdMAX "-%02d-%02d %02d:%02d:%02d",
year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
p += sprintf (p, "%04" PRIdMAX "-%02d-%02d %02d:%02d:%02d",
year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
else if (t < 0)
sprintf (p, "%" PRIdMAX, (intmax_t) t);
p += sprintf (p, "%" PRIdMAX, (intmax_t) t);
else
sprintf (p, "%" PRIuMAX, (uintmax_t) t);
p += strlen (p);
p += sprintf (p, "%" PRIuMAX, (uintmax_t) t);
/* Append nanoseconds as a fraction, but remove trailing zeros. We don't
know the actual timestamp resolution, since clock_getres applies only to
local times, whereas this timestamp might come from a remote filesystem.
So removing trailing zeros is the best guess that we can do. */
sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
p += strlen (p) - 1;
p += sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts)) - 1;
while (*p == '0')
p--;
p += *p != '.';
@ -1035,7 +1053,7 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
/* Print the data base of files. */
void
static void
print_prereqs (const struct dep *deps)
{
const struct dep *ood = 0;
@ -1111,6 +1129,9 @@ print_file (const void *item)
puts (_("# File is a prerequisite of .NOTINTERMEDIATE."));
if (f->secondary)
puts (_("# File is secondary (prerequisite of .SECONDARY)."));
if (f->is_explicit)
puts (_("# File is explicitly mentioned."));
if (f->also_make != 0)
{
const struct dep *d;
@ -1186,6 +1207,34 @@ print_file_data_base (void)
fputs (_("\n# files hash-table stats:\n# "), stdout);
hash_print_stats (&files, stdout);
}
static void
print_target (const void *item)
{
const struct file *f = item;
if (!f->is_target || f->suffix)
return;
/* Ignore any special targets, as defined by POSIX. */
if (f->name[0] == '.' && isupper ((unsigned char)f->name[1]))
{
const char *cp = f->name + 1;
while (*(++cp) != '\0')
if (!isupper ((unsigned char)*cp))
break;
if (*cp == '\0')
return;
}
puts (f->name);
}
void
print_targets (void)
{
hash_map (&files, print_target);
}
/* Verify the integrity of the data base of files. */
@ -1193,7 +1242,7 @@ print_file_data_base (void)
do{ \
if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \
error (NULL, strlen (_p->name) + CSTRLEN (# _n) + strlen (_p->_n), \
_("%s: Field '%s' not cached: %s"), _p->name, # _n, _p->_n); \
_("%s: field '%s' not cached: %s"), _p->name, # _n, _p->_n); \
}while(0)
static void

View File

@ -1,5 +1,5 @@
/* Definition of target file data structures for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -113,6 +113,7 @@ struct file
--shuffle passes through the graph. */
unsigned int snapped:1; /* True if the deps of this file have been
secondary expanded. */
unsigned int suffix:1; /* True if this is a suffix rule. */
};
@ -134,8 +135,8 @@ void notice_finished_file (struct file *file);
void init_hash_files (void);
void verify_file_data_base (void);
char *build_target_list (char *old_list);
void print_prereqs (const struct dep *deps);
void print_file_data_base (void);
void print_targets (void);
int try_implicit_rule (struct file *file, unsigned int depth);
int stemlen_compare (const void *v1, const void *v2);

View File

@ -1,5 +1,5 @@
/* Builtin function expansion for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -23,10 +23,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "commands.h"
#include "debug.h"
#ifdef _AMIGA
#include "amiga.h"
#endif
struct function_table_entry
{
@ -524,7 +520,7 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
int is_suffix = funcname[0] == 's';
int is_notdir = !is_suffix;
int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0);
#ifdef VMS
#if MK_OS_VMS
/* For VMS list_iterator points to a comma separated list. To use the common
[find_]next_token, create a local copy and replace the commas with
spaces. Obviously, there is a problem if there is a ',' in the VMS filename
@ -569,7 +565,7 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
if (is_notdir || p >= p2)
{
#ifdef VMS
#if MK_OS_VMS
if (vms_comma_separator)
o = variable_buffer_output (o, ",", 1);
else
@ -600,7 +596,7 @@ func_basename_dir (char *o, char **argv, const char *funcname)
int is_basename = funcname[0] == 'b';
int is_dir = !is_basename;
int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;
#ifdef VMS
#if MK_OS_VMS
/* As in func_notdir_suffix ... */
char *vms_p3 = alloca (strlen(p3) + 1);
int i;
@ -629,7 +625,7 @@ func_basename_dir (char *o, char **argv, const char *funcname)
o = variable_buffer_output (o, p2, 2);
#endif
else if (is_dir)
#ifdef VMS
#if MK_OS_VMS
{
extern int vms_report_unix_paths;
if (vms_report_unix_paths)
@ -638,17 +634,13 @@ func_basename_dir (char *o, char **argv, const char *funcname)
o = variable_buffer_output (o, "[]", 2);
}
#else
#ifndef _AMIGA
o = variable_buffer_output (o, "./", 2);
#else
; /* Just a nop... */
#endif /* AMIGA */
#endif /* !VMS */
#endif /* !MK_OS_VMS */
else
/* The entire name is the basename. */
o = variable_buffer_output (o, p2, len);
#ifdef VMS
#if MK_OS_VMS
if (vms_comma_separator)
o = variable_buffer_output (o, ",", 1);
else
@ -745,8 +737,7 @@ func_words (char *o, char **argv, const char *funcname UNUSED)
while (find_next_token (&word_iterator, NULL) != 0)
++i;
sprintf (buf, "%u", i);
o = variable_buffer_output (o, buf, strlen (buf));
o = variable_buffer_output (o, buf, sprintf (buf, "%u", i));
return o;
}
@ -893,7 +884,7 @@ func_foreach (char *o, char **argv, const char *funcname UNUSED)
free (var->value);
var->value = xstrndup (p, len);
result = allocated_variable_expand (body);
result = allocated_expand_string (body);
o = variable_buffer_output (o, result, strlen (result));
o = variable_buffer_output (o, " ", 1);
@ -923,8 +914,6 @@ func_let (char *o, char **argv, const char *funcname UNUSED)
const char *vp;
const char *vp_next = varnames;
const char *list_iterator = list;
char *p;
size_t len;
size_t vlen;
push_new_variable_scope ();
@ -934,8 +923,9 @@ func_let (char *o, char **argv, const char *funcname UNUSED)
NEXT_TOKEN (vp_next);
while (*vp_next != '\0')
{
p = find_next_token (&list_iterator, &len);
if (*list_iterator != '\0')
size_t len;
char *p = find_next_token (&list_iterator, &len);
if (p && *list_iterator != '\0')
{
++list_iterator;
p[len] = '\0';
@ -953,7 +943,7 @@ func_let (char *o, char **argv, const char *funcname UNUSED)
/* Expand the body in the context of the arguments, adding the result to
the variable buffer. */
o = variable_expand_string (o, body, SIZE_MAX);
o = expand_string_buf (o, body, SIZE_MAX);
pop_variable_scope ();
free (varnames);
@ -1183,16 +1173,17 @@ func_error (char *o, char **argv, const char *funcname)
case 'i':
{
size_t len = strlen (argv[0]);
char *msg = alloca (len + 2);
char *msg = xmalloc (len + 2);
memcpy (msg, argv[0], len);
msg[len] = '\n';
msg[len + 1] = '\0';
outputs (0, msg);
free (msg);
break;
}
default:
OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname);
OS (fatal, *expanding_var, "INTERNAL: func_error: '%s'", funcname);
}
/* The warning function expands to the empty string. */
@ -1336,6 +1327,8 @@ func_intcmp (char *o, char **argv, const char *funcname UNUSED)
cmp = (llen > rlen) - (llen < rlen);
if (cmp == 0)
cmp = memcmp (lnum, rnum, llen);
if (lsign < 0)
cmp *= -1;
}
argv += 2;
@ -1528,12 +1521,8 @@ func_and (char *o, char **argv, const char *funcname UNUSED)
static char *
func_wildcard (char *o, char **argv, const char *funcname UNUSED)
{
#ifdef _AMIGA
o = wildcard_expansion (argv[0], o);
#else
char *p = string_glob (argv[0]);
o = variable_buffer_output (o, p, strlen (p));
#endif
return o;
}
@ -1630,7 +1619,7 @@ shell_completed (int exit_code, int exit_sig)
define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
}
#ifdef WINDOWS32
#if MK_OS_W32
/*untested*/
#include <windows.h>
@ -1681,11 +1670,11 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
if (hIn == INVALID_HANDLE_VALUE)
{
ON (error, NILF,
_("windows32_openpipe: DuplicateHandle(In) failed (e=%lu)\n"), e);
_("windows32_openpipe: DuplicateHandle(In) failed (e=%lu)"), e);
return -1;
}
}
tmpErr = (HANDLE)_get_osfhandle (errfd);
tmpErr = get_handle_for_fd (errfd);
if (DuplicateHandle (GetCurrentProcess (), tmpErr,
GetCurrentProcess (), &hErr,
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
@ -1705,14 +1694,14 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
if (hErr == INVALID_HANDLE_VALUE)
{
ON (error, NILF,
_("windows32_openpipe: DuplicateHandle(Err) failed (e=%lu)\n"), e);
_("windows32_openpipe: DuplicateHandle(Err) failed (e=%lu)"), e);
return -1;
}
}
if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0))
{
ON (error, NILF, _("CreatePipe() failed (e=%lu)\n"), GetLastError());
ON (error, NILF, _("CreatePipe() failed (e=%lu)"), GetLastError());
return -1;
}
@ -1720,7 +1709,7 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
if (!hProcess)
{
O (error, NILF, _("windows32_openpipe(): process_init_fd() failed\n"));
O (error, NILF, _("windows32_openpipe(): process_init_fd() failed"));
return -1;
}
@ -1760,7 +1749,7 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
#endif
#ifdef __MSDOS__
#if MK_OS_DOS
FILE *
msdos_openpipe (int* pipedes, int *pidp, char *text)
{
@ -1819,7 +1808,7 @@ msdos_openpipe (int* pipedes, int *pidp, char *text)
Do shell spawning, with the naughty bits for different OSes.
*/
#ifdef VMS
#if MK_OS_VMS
/* VMS can't do $(shell ...) */
@ -1834,22 +1823,21 @@ func_shell_base (char *o, char **argv, int trim_newlines)
#define func_shell 0
#else
#ifndef _AMIGA
char *
func_shell_base (char *o, char **argv, int trim_newlines)
{
struct childbase child = {0};
char *batch_filename = NULL;
int errfd;
#ifdef __MSDOS__
#if MK_OS_DOS
FILE *fpipe;
#endif
char **command_argv = NULL;
int pipedes[2];
pid_t pid;
#ifndef __MSDOS__
#ifdef WINDOWS32
#if !MK_OS_DOS
#if MK_OS_W32
/* Reset just_print_flag. This is needed on Windows when batch files
are used to run the commands, because we normally refrain from
creating batch files under -n. */
@ -1862,12 +1850,12 @@ func_shell_base (char *o, char **argv, int trim_newlines)
&batch_filename);
if (command_argv == 0)
{
#ifdef WINDOWS32
#if MK_OS_W32
just_print_flag = j_p_f;
#endif
return o;
}
#endif /* !__MSDOS__ */
#endif /* !MK_OS_DOS */
/* Set up the output in case the shell writes something. */
output_start ();
@ -1877,7 +1865,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
child.environment = target_environment (NULL, 0);
#if defined(__MSDOS__)
#if MK_OS_DOS
fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
if (pipedes[0] < 0)
{
@ -1886,7 +1874,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
goto done;
}
#elif defined(WINDOWS32)
#elif MK_OS_W32
windows32_openpipe (pipedes, errfd, &pid, command_argv, child.environment);
/* Restore the value of just_print_flag. */
just_print_flag = j_p_f;
@ -1932,7 +1920,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
/* Record the PID for reap_children. */
shell_function_pid = pid;
#ifndef __MSDOS__
#if !MK_OS_DOS
shell_function_completed = 0;
/* Close the write side of the pipe. We test for -1, since
@ -1963,7 +1951,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
buffer[i] = '\0';
/* Close the read side of the pipe. */
#ifdef __MSDOS__
#if MK_OS_DOS
if (fpipe)
{
int st = pclose (fpipe);
@ -2008,100 +1996,12 @@ func_shell_base (char *o, char **argv, int trim_newlines)
return o;
}
#else /* _AMIGA */
/* Do the Amiga version of func_shell. */
char *
func_shell_base (char *o, char **argv, int trim_newlines)
{
/* Amiga can't fork nor spawn, but I can start a program with
redirection of my choice. However, this means that we
don't have an opportunity to reopen stdout to trap it. Thus,
we save our own stdout onto a new descriptor and dup a temp
file's descriptor onto our stdout temporarily. After we
spawn the shell program, we dup our own stdout back to the
stdout descriptor. The buffer reading is the same as above,
except that we're now reading from a file. */
#include <dos/dos.h>
#include <proto/dos.h>
BPTR child_stdout;
char tmp_output[FILENAME_MAX];
size_t maxlen = 200, i;
int cc;
char * buffer, * ptr;
char ** aptr;
size_t len = 0;
char* batch_filename = NULL;
/* Construct the argument list. */
command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
&batch_filename);
if (command_argv == 0)
return o;
/* Note the mktemp() is a security hole, but this only runs on Amiga.
Ideally we would use get_tmpfile(), but this uses a special Open(), not
fopen(), and I'm not familiar enough with the code to mess with it. */
strcpy (tmp_output, "t:MakeshXXXXXXXX");
mktemp (tmp_output);
child_stdout = Open (tmp_output, MODE_NEWFILE);
for (aptr=command_argv; *aptr; aptr++)
len += strlen (*aptr) + 1;
buffer = xmalloc (len + 1);
ptr = buffer;
for (aptr=command_argv; *aptr; aptr++)
{
strcpy (ptr, *aptr);
ptr += strlen (ptr) + 1;
*(ptr++) = ' ';
*ptr = '\0';
}
ptr[-1] = '\n';
Execute (buffer, NULL, child_stdout);
free (buffer);
Close (child_stdout);
child_stdout = Open (tmp_output, MODE_OLDFILE);
buffer = xmalloc (maxlen);
i = 0;
do
{
if (i == maxlen)
{
maxlen += 512;
buffer = xrealloc (buffer, maxlen + 1);
}
cc = Read (child_stdout, &buffer[i], maxlen - i);
if (cc > 0)
i += cc;
} while (cc > 0);
Close (child_stdout);
fold_newlines (buffer, &i, trim_newlines);
o = variable_buffer_output (o, buffer, i);
free (buffer);
return o;
}
#endif /* _AMIGA */
static char *
func_shell (char *o, char **argv, const char *funcname UNUSED)
{
return func_shell_base (o, argv, 1);
}
#endif /* !VMS */
#endif /* !MK_OS_VMS */
#ifdef EXPERIMENTAL
@ -2112,7 +2012,8 @@ static char *
func_eq (char *o, char **argv, char *funcname UNUSED)
{
int result = ! strcmp (argv[0], argv[1]);
o = variable_buffer_output (o, result ? "1" : "", result);
if (result)
o = variable_buffer_output (o, "1", 1);
return o;
}
@ -2127,7 +2028,8 @@ func_not (char *o, char **argv, char *funcname UNUSED)
int result = 0;
NEXT_TOKEN (s);
result = ! (*s);
o = variable_buffer_output (o, result ? "1" : "", result);
if (result)
o = variable_buffer_output (o, "1", 1);
return o;
}
#endif
@ -2207,7 +2109,7 @@ abspath (const char *name, char *apath)
apath[3] = '/';
dest++;
root_len++;
/* strncpy above copied one character too many. */
/* memcpy above copied one character too many. */
name--;
}
else
@ -2217,7 +2119,7 @@ abspath (const char *name, char *apath)
for (start = end = name; *start != '\0'; start = end)
{
size_t len;
ptrdiff_t len;
/* Skip sequence of multiple path-separators. */
while (ISDIRSEP (*start))
@ -2245,7 +2147,7 @@ abspath (const char *name, char *apath)
if (! ISDIRSEP (dest[-1]))
*dest++ = '/';
if (dest + len >= apath_limit)
if (apath_limit - dest <= len)
return NULL;
dest = mempcpy (dest, start, len);
@ -2276,13 +2178,13 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED)
{
if (len < GET_PATH_MAX)
{
char *rp;
char *rp, *inend;
struct stat st;
PATH_VAR (in);
PATH_VAR (out);
strncpy (in, path, len);
in[len] = '\0';
inend = mempcpy (in, path, len);
*inend = '\0';
#ifdef HAVE_REALPATH
ENULLLOOP (rp, realpath (in, out));
@ -2327,6 +2229,10 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
if (fn[0] == '>')
{
size_t len;
const char *end;
const char *start;
char *nm;
FILE *fp;
const char *mode = "w";
@ -2337,14 +2243,21 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
mode = "a";
++fn;
}
NEXT_TOKEN (fn);
if (fn[0] == '\0')
start = next_token (fn);
if (start[0] == '\0')
O (fatal, *expanding_var, _("file: missing filename"));
ENULLLOOP (fp, fopen (fn, mode));
end = end_of_token (start);
len = end - start;
nm = alloca (len + 1);
memcpy (nm, start, len);
nm[len] = '\0';
ENULLLOOP (fp, fopen (nm, mode));
if (fp == NULL)
OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
OSS (fatal, reading_file, _("open: %s: %s"), nm, strerror (errno));
/* We've changed the contents of a directory, possibly.
Another option would be to look up the directory we changed and reset
@ -2357,30 +2270,44 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
int nl = l == 0 || argv[1][l-1] != '\n';
if (fputs (argv[1], fp) == EOF || (nl && fputc ('\n', fp) == EOF))
OSS (fatal, reading_file, _("write: %s: %s"), fn, strerror (errno));
OSS (fatal, reading_file, _("write: %s: %s"), nm, strerror (errno));
}
if (fclose (fp))
OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
OSS (fatal, reading_file, _("close: %s: %s"), nm, strerror (errno));
}
else if (fn[0] == '<')
{
size_t n = 0;
size_t len;
const char *end;
const char *start;
char *nm;
FILE *fp;
++fn;
NEXT_TOKEN (fn);
if (fn[0] == '\0')
start = next_token (fn + 1);
if (start[0] == '\0')
O (fatal, *expanding_var, _("file: missing filename"));
if (argv[1])
O (fatal, *expanding_var, _("file: too many arguments"));
ENULLLOOP (fp, fopen (fn, "r"));
end = end_of_token (start);
len = end - start;
nm = alloca (len + 1);
memcpy (nm, start, len);
nm[len] = '\0';
ENULLLOOP (fp, fopen (nm, "r"));
if (fp == NULL)
{
if (errno == ENOENT)
return o;
OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
{
DB (DB_VERBOSE, (_("file: Failed to open '%s': %s\n"),
nm, strerror (errno)));
return o;
}
OSS (fatal, reading_file, _("open: %s: %s"), nm, strerror (errno));
}
while (1)
@ -2394,12 +2321,12 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
}
if (ferror (fp))
if (errno != EINTR)
OSS (fatal, reading_file, _("read: %s: %s"), fn, strerror (errno));
OSS (fatal, reading_file, _("read: %s: %s"), nm, strerror (errno));
if (feof (fp))
break;
}
if (fclose (fp))
OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
OSS (fatal, reading_file, _("close: %s: %s"), nm, strerror (errno));
/* Remove trailing newline. */
if (n && o[-1] == '\n')
@ -2426,9 +2353,9 @@ func_abspath (char *o, char **argv, const char *funcname UNUSED)
{
PATH_VAR (in);
PATH_VAR (out);
char *inend = mempcpy (in, path, len);
strncpy (in, path, len);
in[len] = '\0';
*inend = '\0';
if (abspath (in, out))
{
@ -2464,54 +2391,52 @@ static char *func_call (char *o, char **argv, const char *funcname);
#define FT_ENTRY(_name, _min, _max, _exp, _func) \
{ { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0, 0 }
static struct function_table_entry function_table_init[] =
static const struct function_table_entry function_table_init[] =
{
/* Name MIN MAX EXP? Function */
FT_ENTRY ("abspath", 0, 1, 1, func_abspath),
FT_ENTRY ("addprefix", 2, 2, 1, func_addsuffix_addprefix),
FT_ENTRY ("addsuffix", 2, 2, 1, func_addsuffix_addprefix),
FT_ENTRY ("and", 1, 0, 0, func_and),
FT_ENTRY ("basename", 0, 1, 1, func_basename_dir),
FT_ENTRY ("call", 1, 0, 1, func_call),
FT_ENTRY ("dir", 0, 1, 1, func_basename_dir),
FT_ENTRY ("notdir", 0, 1, 1, func_notdir_suffix),
FT_ENTRY ("subst", 3, 3, 1, func_subst),
FT_ENTRY ("suffix", 0, 1, 1, func_notdir_suffix),
FT_ENTRY ("error", 0, 1, 1, func_error),
FT_ENTRY ("eval", 0, 1, 1, func_eval),
FT_ENTRY ("file", 1, 2, 1, func_file),
FT_ENTRY ("filter", 2, 2, 1, func_filter_filterout),
FT_ENTRY ("filter-out", 2, 2, 1, func_filter_filterout),
FT_ENTRY ("findstring", 2, 2, 1, func_findstring),
FT_ENTRY ("firstword", 0, 1, 1, func_firstword),
FT_ENTRY ("flavor", 0, 1, 1, func_flavor),
FT_ENTRY ("foreach", 3, 3, 0, func_foreach),
FT_ENTRY ("if", 2, 3, 0, func_if),
FT_ENTRY ("info", 0, 1, 1, func_error),
FT_ENTRY ("intcmp", 2, 5, 0, func_intcmp),
FT_ENTRY ("join", 2, 2, 1, func_join),
FT_ENTRY ("lastword", 0, 1, 1, func_lastword),
FT_ENTRY ("let", 3, 3, 0, func_let),
FT_ENTRY ("notdir", 0, 1, 1, func_notdir_suffix),
FT_ENTRY ("or", 1, 0, 0, func_or),
FT_ENTRY ("origin", 0, 1, 1, func_origin),
FT_ENTRY ("patsubst", 3, 3, 1, func_patsubst),
FT_ENTRY ("realpath", 0, 1, 1, func_realpath),
FT_ENTRY ("shell", 0, 1, 1, func_shell),
FT_ENTRY ("sort", 0, 1, 1, func_sort),
FT_ENTRY ("strip", 0, 1, 1, func_strip),
FT_ENTRY ("subst", 3, 3, 1, func_subst),
FT_ENTRY ("suffix", 0, 1, 1, func_notdir_suffix),
FT_ENTRY ("value", 0, 1, 1, func_value),
FT_ENTRY ("warning", 0, 1, 1, func_error),
FT_ENTRY ("wildcard", 0, 1, 1, func_wildcard),
FT_ENTRY ("word", 2, 2, 1, func_word),
FT_ENTRY ("wordlist", 3, 3, 1, func_wordlist),
FT_ENTRY ("words", 0, 1, 1, func_words),
FT_ENTRY ("origin", 0, 1, 1, func_origin),
FT_ENTRY ("foreach", 3, 3, 0, func_foreach),
FT_ENTRY ("let", 3, 3, 0, func_let),
FT_ENTRY ("call", 1, 0, 1, func_call),
FT_ENTRY ("info", 0, 1, 1, func_error),
FT_ENTRY ("error", 0, 1, 1, func_error),
FT_ENTRY ("warning", 0, 1, 1, func_error),
FT_ENTRY ("intcmp", 2, 5, 0, func_intcmp),
FT_ENTRY ("if", 2, 3, 0, func_if),
FT_ENTRY ("or", 1, 0, 0, func_or),
FT_ENTRY ("and", 1, 0, 0, func_and),
FT_ENTRY ("value", 0, 1, 1, func_value),
FT_ENTRY ("eval", 0, 1, 1, func_eval),
FT_ENTRY ("file", 1, 2, 1, func_file),
#ifdef EXPERIMENTAL
FT_ENTRY ("eq", 2, 2, 1, func_eq),
FT_ENTRY ("not", 0, 1, 1, func_not),
#endif
};
#define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
/* These must come after the definition of function_table. */
@ -2560,7 +2485,8 @@ expand_builtin_function (char *o, unsigned int argc, char **argv,
/* Check for a function invocation in *STRINGP. *STRINGP points at the
opening ( or { and is not null-terminated. If a function invocation
is found, expand it into the buffer at *OP, updating *OP, incrementing
*STRINGP past the reference and returning nonzero. If not, return zero. */
*STRINGP past the reference, and return nonzero.
If no function is found, return zero and don't change *OP or *STRINGP. */
int
handle_function (char **op, const char **stringp)
@ -2588,10 +2514,10 @@ handle_function (char **op, const char **stringp)
beg += entry_p->len;
NEXT_TOKEN (beg);
/* Find the end of the function invocation, counting nested use of
whichever kind of parens we use. Since we're looking, count commas
to get a rough estimate of how many arguments we might have. The
count might be high, but it'll never be low. */
/* Find the end of the function invocation, counting nested use of whichever
kind of parens we use. Don't use skip_reference so we can count commas
to get a rough estimate of how many arguments we might have. The count
might be high, but it'll never be low. */
for (nargs=1, end=beg; *end != '\0'; ++end)
if (!STOP_SET (*end, MAP_VARSEP|MAP_COMMA))
@ -2687,7 +2613,6 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{
static unsigned int max_args = 0;
char *fname;
char *body;
size_t flen;
unsigned int i;
int saved_args;
@ -2725,13 +2650,6 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
if (v == 0 || *v->value == '\0')
return o;
body = alloca (flen + 4);
body[0] = '$';
body[1] = '(';
memcpy (body + 2, fname, flen);
body[flen+2] = ')';
body[flen+3] = '\0';
/* Set up arguments $(1) .. $(N). $(0) is the function name. */
push_new_variable_scope ();
@ -2740,8 +2658,7 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{
char num[INTSTR_LENGTH];
sprintf (num, "%u", i);
define_variable (num, strlen (num), *argv, o_automatic, 0);
define_variable (num, sprintf (num, "%u", i), *argv, o_automatic, 0);
}
/* If the number of arguments we have is < max_args, it means we're inside
@ -2753,18 +2670,17 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{
char num[INTSTR_LENGTH];
sprintf (num, "%u", i);
define_variable (num, strlen (num), "", o_automatic, 0);
define_variable (num, sprintf (num, "%u", i), "", o_automatic, 0);
}
/* Expand the body in the context of the arguments, adding the result to
/* Expand the function in the context of the arguments, adding the result to
the variable buffer. */
v->exp_count = EXP_COUNT_MAX;
saved_args = max_args;
max_args = i;
o = variable_expand_string (o, body, flen+3);
o = expand_variable_output (o, fname, flen);
max_args = saved_args;
v->exp_count = 0;
@ -2788,20 +2704,20 @@ define_new_function (const floc *flocp, const char *name,
len = e - name;
if (len == 0)
O (fatal, flocp, _("Empty function name"));
O (fatal, flocp, _("empty function name"));
if (*name == '.' || *e != '\0')
OS (fatal, flocp, _("Invalid function name: %s"), name);
OS (fatal, flocp, _("invalid function name: %s"), name);
if (len > 255)
OS (fatal, flocp, _("Function name too long: %s"), name);
OS (fatal, flocp, _("function name too long: %s"), name);
if (min > 255)
ONS (fatal, flocp,
_("Invalid minimum argument count (%u) for function %s"), min, name);
_("invalid minimum argument count (%u) for function %s"), min, name);
if (max > 255 || (max && max < min))
ONS (fatal, flocp,
_("Invalid maximum argument count (%u) for function %s"), max, name);
_("invalid maximum argument count (%u) for function %s"), max, name);
ent = xmalloc (sizeof (struct function_table_entry));
ent->name = name;
ent->name = strcache_add (name);
ent->len = (unsigned char) len;
ent->minimum_args = (unsigned char) min;
ent->maximum_args = (unsigned char) max;
@ -2811,15 +2727,16 @@ define_new_function (const floc *flocp, const char *name,
ent->adds_command = 1;
ent->fptr.alloc_func_ptr = func;
hash_insert (&function_table, ent);
ent = hash_insert (&function_table, ent);
free (ent);
}
void
hash_init_function_table (void)
{
hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
hash_init (&function_table, ARRAYLEN (function_table_init) * 2,
function_table_entry_hash_1, function_table_entry_hash_2,
function_table_entry_hash_cmp);
hash_load (&function_table, function_table_init,
FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
ARRAYLEN (function_table_init), sizeof (struct function_table_entry));
}

View File

@ -3,7 +3,7 @@ NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it!
Copyright (C) 1987-2022 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@gnu.org.
@ -68,7 +68,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
# include <unistd.h>
#endif /* GNU C library. */
#ifdef VMS
#if MK_OS_VMS
# include <unixlib.h>
# if HAVE_STRING_H - 0
# include <string.h>
@ -436,6 +436,10 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring)
nonoption_flags_len = 0;
#endif
/* Make the compiler happy. */
(void)argc;
(void)argv;
return optstring;
}
@ -677,17 +681,18 @@ _getopt_internal (int argc, char *const *argv, const char *optstring,
else
{
if (opterr)
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
_("%s: option '--%s' doesn't allow an argument\n"),
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
_("%s: option '%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], pfound->name);
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
_("%s: option '--%s' doesn't allow an argument\n"),
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
_("%s: option '%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
optopt = pfound->val;

View File

@ -1,5 +1,5 @@
/* Declarations for getopt.
Copyright (C) 1989-2022 Free Software Foundation, Inc.
Copyright (C) 1989-2024 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@gnu.org.

View File

@ -1,5 +1,5 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987-1994, 1996-2022 Free Software Foundation, Inc.
Copyright (C) 1987-1994, 1996-2024 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@gnu.org.

View File

@ -1,5 +1,5 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-2022 Free Software Foundation, Inc.
Copyright (C) 1995-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
;; Contents of the (gnu make) Guile module
;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Contents of the (GNU Make) Guile module
;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; This file is part of GNU Make.
;;
;; GNU Make is free software; you can redistribute it and/or modify it under
@ -17,7 +17,7 @@
(define (to-string-maybe x)
(cond
;; In GNU make, "false" is the empty string
;; In GNU Make, "false" is the empty string
((or (not x)
(unspecified? x)
(variable? x)
@ -45,7 +45,7 @@
(walk x)
(string-join (reverse! acc))))
;; Return the value of the GNU make variable V
;; Return the value of the GNU Make variable V
(define (gmk-var v)
(gmk-expand (format #f "$(~a)" (obj-to-str v))))

View File

@ -1,7 +1,6 @@
/* External interfaces usable by dynamic objects loaded into GNU Make.
--THIS API IS A "TECHNOLOGY PREVIEW" ONLY. IT IS NOT A STABLE INTERFACE--
Copyright (C) 2013-2022 Free Software Foundation, Inc.
Copyright (C) 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -19,6 +18,8 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GNUMAKE_H_
#define _GNUMAKE_H_
#define GMK_ABI_VERSION 1
/* Specify the location of elements read from makefiles. */
typedef struct
{
@ -28,6 +29,23 @@ typedef struct
typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);
/* When an object is loaded by GNU Make, a setup method will be invoked.
The name of the method is either derived from the filename of the object,
or specified explicitly in the makefile. It has the signature:
int <setup_fn> (unsigned int abi_version, const gmk_floc *flocp);
The abi_version will be set to GMK_ABI_VERSION.
When an object is unloaded by GNU Make, an unload method will be invoked.
The name of the method is derived from the filename of the object, with
_gmk_unload appended. It has the signature:
void <object>_gmk_unload (void);
There will only be one unload method invoked regardless of the number of
setup methods within the object. */
#ifdef _WIN32
# ifdef GMK_BUILDING_MAKE
# define GMK_EXPORT __declspec(dllexport)
@ -38,26 +56,26 @@ typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);
# define GMK_EXPORT
#endif
/* Free memory returned by the gmk_expand() function. */
/* Free memory returned by the gmk_expand() and gmk_free() functions. */
GMK_EXPORT void gmk_free (char *str);
/* Allocate memory in GNU make's context. */
/* Allocate memory in GNU Make's context. */
GMK_EXPORT char *gmk_alloc (unsigned int len);
/* Run $(eval ...) on the provided string BUFFER. */
GMK_EXPORT void gmk_eval (const char *buffer, const gmk_floc *floc);
/* Run GNU make expansion on the provided string STR.
/* Run GNU Make expansion on the provided string STR.
Returns an allocated buffer that the caller must free with gmk_free(). */
GMK_EXPORT char *gmk_expand (const char *str);
/* Register a new GNU make function NAME (maximum of 255 chars long).
/* 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
the appropriate arguments.
The return value of FUNC must be either NULL, in which case it expands to
the empty string, or a pointer to the result of the expansion in a string
created by gmk_alloc(). GNU make will free the memory when it's done.
created by gmk_alloc(). GNU Make will free the memory when it's done.
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).

View File

@ -1,5 +1,5 @@
/* GNU Guile interface for GNU Make.
Copyright (C) 2011-2022 Free Software Foundation, Inc.
Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -47,7 +47,7 @@ cvt_scm_to_str (SCM obj)
return scm_to_locale_string (scm_call_1 (obj_to_str, obj));
}
/* Perform the GNU make expansion function. */
/* Perform the GNU Make expansion function. */
static SCM
guile_expand_wrapper (SCM obj)
{
@ -65,7 +65,7 @@ guile_expand_wrapper (SCM obj)
return ret;
}
/* Perform the GNU make eval function. */
/* Perform the GNU Make eval function. */
static SCM
guile_eval_wrapper (SCM obj)
{
@ -77,24 +77,24 @@ guile_eval_wrapper (SCM obj)
return SCM_BOOL_F;
}
/* Invoked by scm_c_define_module(), in the context of the GNU make module. */
/* Invoked by scm_c_define_module(), in the context of the GNU Make module. */
static void
guile_define_module (void *data UNUSED)
{
/* Ingest the predefined Guile module for GNU make. */
/* Ingest the predefined Guile module for GNU Make. */
#include "gmk-default.h"
/* Register a subr for GNU make's eval capability. */
/* Register a subr for GNU Make's eval capability. */
scm_c_define_gsubr ("gmk-expand", 1, 0, 0, (GSUBR_TYPE) guile_expand_wrapper);
/* Register a subr for GNU make's eval capability. */
/* Register a subr for GNU Make's eval capability. */
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);
}
/* Initialize the GNU make Guile module. */
/* Initialize the GNU Make Guile module. */
static void *
guile_init (void *arg UNUSED)
{
@ -104,7 +104,7 @@ guile_init (void *arg UNUSED)
/* Get a reference to the object-to-string translator, for later. */
obj_to_str = scm_variable_ref (scm_c_module_lookup (make_mod, "obj-to-str"));
/* Import the GNU make module exports into the generic space. */
/* Import the GNU Make module exports into the generic space. */
scm_c_eval_string ("(use-modules (gnu make))");
return NULL;

View File

@ -33,7 +33,7 @@ static unsigned long round_up_2 __P((unsigned long rough));
potentially hit every slot in the table during collision
resolution. */
void *hash_deleted_item = &hash_deleted_item;
const void *hash_deleted_item = &hash_deleted_item;
/* Force the table size to be a power of two, possibly rounding up the
given size. */
@ -65,10 +65,10 @@ hash_init (struct hash_table *ht, unsigned long size,
/* Load an array of items into 'ht'. */
void
hash_load (struct hash_table *ht, void *item_table,
hash_load (struct hash_table *ht, const void *item_table,
unsigned long cardinality, unsigned long size)
{
char *items = (char *) item_table;
const char *items = (const char *) item_table;
while (cardinality--)
{
hash_insert (ht, items);
@ -361,7 +361,7 @@ round_up_2 (unsigned long n)
#define sum_get_unaligned_32(r, p) \
do { \
unsigned int val; \
memcpy(&val, (p), 4); \
memcpy (&val, (p), 4); \
r += val; \
} while(0);
@ -413,13 +413,16 @@ jhash(unsigned const char *k, int length)
#define UINTSZ sizeof (unsigned int)
#ifdef WORDS_BIGENDIAN
/* The ifs are ordered from the first byte in memory to the last. */
/* The ifs are ordered from the first byte in memory to the last.
Help the compiler optimize by using static memcpy length. */
#define sum_up_to_nul(r, p, plen, flag) \
do { \
unsigned int val = 0; \
size_t pn = (plen); \
size_t n = pn < UINTSZ ? pn : UINTSZ; \
memcpy (&val, (p), n); \
if (pn >= UINTSZ) \
memcpy (&val, (p), UINTSZ); \
else \
memcpy (&val, (p), pn); \
if ((val & 0xFF000000) == 0) \
flag = 1; \
else if ((val & 0xFF0000) == 0) \
@ -432,13 +435,16 @@ jhash(unsigned const char *k, int length)
#else
/* First detect the presence of zeroes. If there is none, we can
sum the 4 bytes directly. Otherwise, the ifs are ordered as in the
big endian case, from the first byte in memory to the last. */
big endian case, from the first byte in memory to the last.
Help the compiler optimize by using static memcpy length. */
#define sum_up_to_nul(r, p, plen, flag) \
do { \
unsigned int val = 0; \
size_t pn = (plen); \
size_t n = pn < UINTSZ ? pn : UINTSZ; \
memcpy (&val, (p), n); \
if (pn >= UINTSZ) \
memcpy (&val, (p), UINTSZ); \
else \
memcpy (&val, (p), pn); \
flag = ((val - 0x01010101) & ~val) & 0x80808080; \
if (!flag) \
r += val; \

View File

@ -20,7 +20,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <ctype.h>
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
#if defined __cplusplus || (defined __STDC__ && __STDC__) || MK_OS_W32
# if !defined __GLIBC__ || !defined __P
# undef __P
# define __P(protos) protos
@ -57,7 +57,7 @@ typedef int (*qsort_cmp_t) __P((void const *, void const *));
void hash_init __P((struct hash_table *ht, unsigned long size,
hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp));
void hash_load __P((struct hash_table *ht, void *item_table,
void hash_load __P((struct hash_table *ht, const void *item_table,
unsigned long cardinality, unsigned long size));
void **hash_find_slot __P((struct hash_table *ht, void const *key));
void *hash_find_item __P((struct hash_table *ht, void const *key));
@ -76,7 +76,7 @@ void **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compar
extern unsigned jhash(unsigned char const *key, int n);
extern unsigned jhash_string(unsigned char const *key);
extern void *hash_deleted_item;
extern const void *hash_deleted_item;
#define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item)

View File

@ -1,5 +1,5 @@
/* Implicit rule searching for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -87,12 +87,10 @@ get_next_word (const char *buffer, size_t *length)
return 0;
/* We already found the first value of "c", above. */
while (1)
{
char closeparen;
int count;
/* Each time through the loop, "c" has the current char
and "p" points to the next char. */
switch (c)
{
case '\0':
@ -101,31 +99,8 @@ get_next_word (const char *buffer, size_t *length)
goto done_word;
case '$':
c = *(p++);
if (c == '$')
break;
/* This is a variable reference, so read it to the matching
close paren. */
if (c == '(')
closeparen = ')';
else if (c == '{')
closeparen = '}';
else
/* This is a single-letter variable reference. */
break;
for (count = 0; *p != '\0'; ++p)
{
if (*p == c)
++count;
else if (*p == closeparen && --count < 0)
{
++p;
break;
}
}
/* This is a variable reference, so skip it. */
p = skip_reference (p);
break;
case '|':
@ -272,6 +247,8 @@ pattern_search (struct file *file, int archive,
PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */
++depth;
#ifndef NO_ARCHIVES
if (archive || ar_name (filename))
lastslash = 0;
@ -282,7 +259,7 @@ pattern_search (struct file *file, int archive,
but not counting any slash at the end. (foo/bar/ counts as
bar/ in directory foo/, not empty in directory foo/bar/.) */
lastslash = memrchr (filename, '/', namelen - 1);
#ifdef VMS
#if MK_OS_VMS
if (lastslash == NULL)
lastslash = strrchr (filename, ']');
if (lastslash == NULL)
@ -355,7 +332,7 @@ pattern_search (struct file *file, int archive,
check_lastslash = 0;
if (lastslash)
{
#ifdef VMS
#if MK_OS_VMS
check_lastslash = strpbrk (target, "/]>:") == NULL;
#else
check_lastslash = strchr (target, '/') == 0;
@ -704,7 +681,7 @@ pattern_search (struct file *file, int archive,
}
/* Perform the 2nd expansion. */
p = variable_expand_for_file (depname, file);
p = expand_string_for_file (depname, file);
dptr = &dl;
/* Parse the results into a deps list. */
@ -893,7 +870,7 @@ pattern_search (struct file *file, int archive,
if (pattern_search (int_file,
0,
depth + 1,
depth,
recursions + 1,
allow_compat_rules))
{
@ -1008,7 +985,7 @@ pattern_search (struct file *file, int archive,
f->also_make = imf->also_make;
f->is_target = 1;
f->is_explicit |= imf->is_explicit || pat->is_explicit;
f->notintermediate |= imf->notintermediate;
f->notintermediate |= imf->notintermediate || no_intermediates;
f->intermediate |= !f->is_explicit && !f->notintermediate;
f->tried_implicit = 1;
@ -1090,7 +1067,7 @@ pattern_search (struct file *file, int archive,
{
if (f->precious)
file->precious = 1;
if (f->notintermediate)
if (f->notintermediate || no_intermediates)
file->notintermediate = 1;
}
}
@ -1123,7 +1100,7 @@ pattern_search (struct file *file, int archive,
{
if (f->precious)
new->file->precious = 1;
if (f->notintermediate)
if (f->notintermediate || no_intermediates)
new->file->notintermediate = 1;
}
@ -1139,6 +1116,8 @@ pattern_search (struct file *file, int archive,
free (tryrules);
free (deplist);
--depth;
if (rule)
{
DBS (DB_IMPLICIT, (_("Found implicit rule '%s' for '%s'.\n"),

631
src/job.c

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Definitions for managing subprocesses in GNU Make.
Copyright (C) 1992-2022 Free Software Foundation, Inc.
Copyright (C) 1992-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -18,7 +18,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Structure describing a running or dead child process. */
#ifdef VMS
#if MK_OS_VMS
#define VMSCHILD \
char *comname; /* Temporary command file name */ \
int efn; /* Completion event flag number */ \
@ -80,11 +80,7 @@ char **construct_command_argv (char *line, char **restp, struct file *file,
pid_t child_execute_job (struct childbase *child, int good_stdin, char **argv);
#ifdef _AMIGA
void exec_command (char **argv) NORETURN;
#else
pid_t exec_command (char **argv, char **envp);
#endif
void unblock_all_sigs (void);

View File

@ -1,5 +1,5 @@
/* Loading dynamic objects for GNU Make.
Copyright (C) 2012-2022 Free Software Foundation, Inc.
Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -24,8 +24,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <errno.h>
#define SYMBOL_EXTENSION "_gmk_setup"
#include "debug.h"
#include "filedef.h"
#include "variable.h"
@ -35,21 +33,33 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
# define RTLD_GLOBAL 0
#endif
#define GMK_SETUP "_gmk_setup"
#define GMK_UNLOAD "_gmk_unload"
typedef int (*setup_func_t)(unsigned int abi, const floc *flocp);
typedef void (*unload_func_t)(void);
struct load_list
{
struct load_list *next;
const char *name;
void *dlp;
unload_func_t unload;
};
static struct load_list *loaded_syms = NULL;
static load_func_t
static setup_func_t
load_object (const floc *flocp, int noerror, const char *ldname,
const char *symname)
const char *setupnm)
{
static void *global_dl = NULL;
load_func_t symp;
char *buf;
const char *fp;
char *endp;
void *dlp;
struct load_list *new;
setup_func_t symp;
if (! global_dl)
{
@ -57,66 +67,101 @@ load_object (const floc *flocp, int noerror, const char *ldname,
if (! global_dl)
{
const char *err = dlerror ();
OS (fatal, flocp, _("Failed to open global symbol table: %s"), err);
OS (fatal, flocp, _("failed to open global symbol table: %s"), err);
}
}
symp = (load_func_t) dlsym (global_dl, symname);
/* Find the prefix of the ldname. */
fp = strrchr (ldname, '/');
#ifdef HAVE_DOS_PATHS
if (fp)
{
const char *fp2 = strchr (fp, '\\');
if (fp2 > fp)
fp = fp2;
}
else
fp = strrchr (ldname, '\\');
/* The (improbable) case of d:foo. */
if (fp && *fp && fp[1] == ':')
fp++;
#endif
if (!fp)
fp = ldname;
else
++fp;
endp = buf = alloca (strlen (fp) + CSTRLEN (GMK_UNLOAD) + 1);
while (isalnum ((unsigned char) *fp) || *fp == '_')
*(endp++) = *(fp++);
/* If we didn't find a symbol name yet, construct it from the prefix. */
if (! setupnm)
{
memcpy (endp, GMK_SETUP, CSTRLEN (GMK_SETUP) + 1);
setupnm = buf;
}
DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), setupnm, ldname));
symp = (setup_func_t) dlsym (global_dl, setupnm);
if (symp)
return symp;
/* If the path has no "/", try the current directory first. */
dlp = NULL;
if (! strchr (ldname, '/')
#ifdef HAVE_DOS_PATHS
&& ! strchr (ldname, '\\')
#endif
)
dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
/* If we haven't opened it yet, try the default search path. */
if (! dlp)
dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
/* Still no? Then fail. */
if (! dlp)
{
const char *err = dlerror ();
if (noerror)
DB (DB_BASIC, ("%s\n", err));
else
OS (error, flocp, "%s", err);
return NULL;
}
DB (DB_VERBOSE, (_("Loaded shared object %s\n"), ldname));
/* Assert that the GPL license symbol is defined. */
symp = (setup_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
if (! symp)
OS (fatal, flocp,
_("loaded object %s is not declared to be GPL compatible"), ldname);
symp = (setup_func_t) dlsym (dlp, setupnm);
if (! symp)
{
struct load_list *new;
void *dlp = NULL;
/* If the path has no "/", try the current directory first. */
if (! strchr (ldname, '/')
#ifdef HAVE_DOS_PATHS
&& ! strchr (ldname, '\\')
#endif
)
dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
/* If we haven't opened it yet, try the default search path. */
if (! dlp)
dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
/* Still no? Then fail. */
if (! dlp)
{
const char *err = dlerror ();
if (noerror)
DB (DB_BASIC, ("%s\n", err));
else
OS (error, flocp, "%s", err);
return NULL;
}
DB (DB_VERBOSE, (_("Loaded shared object %s\n"), ldname));
/* Assert that the GPL license symbol is defined. */
symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
if (! symp)
OS (fatal, flocp,
_("Loaded object %s is not declared to be GPL compatible"),
ldname);
symp = (load_func_t) dlsym (dlp, symname);
if (! symp)
{
const char *err = dlerror ();
OSSS (fatal, flocp, _("Failed to load symbol %s from %s: %s"),
symname, ldname, err);
}
/* Add this symbol to a trivial lookup table. This is not efficient but
it's highly unlikely we'll be loading lots of objects, and we only
need it to look them up on unload, if we rebuild them. */
new = xmalloc (sizeof (struct load_list));
new->name = xstrdup (ldname);
new->dlp = dlp;
new->next = loaded_syms;
loaded_syms = new;
const char *err = dlerror ();
OSSS (fatal, flocp, _("failed to load symbol %s from %s: %s"),
setupnm, ldname, err);
}
new = xcalloc (sizeof (struct load_list));
new->next = loaded_syms;
loaded_syms = new;
new->name = ldname;
new->dlp = dlp;
/* Compute the name of the unload function and look it up. */
memcpy (endp, GMK_UNLOAD, CSTRLEN (GMK_UNLOAD) + 1);
new->unload = (unload_func_t) dlsym (dlp, buf);
if (new->unload)
DB (DB_VERBOSE, (_("Detected symbol %s in %s\n"), buf, ldname));
return symp;
}
@ -124,12 +169,11 @@ int
load_file (const floc *flocp, struct file *file, int noerror)
{
const char *ldname = file->name;
size_t nmlen = strlen (ldname);
char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
char *symname = NULL;
char *buf;
char *setupnm = NULL;
const char *fp;
int r;
load_func_t symp;
setup_func_t symp;
/* Break the input into an object file name and a symbol name. If no symbol
name was provided, compute one from the object file name. */
@ -148,18 +192,18 @@ load_file (const floc *flocp, struct file *file, int noerror)
++fp;
if (fp == ep)
OS (fatal, flocp, _("Empty symbol name for load: %s"), ldname);
OS (fatal, flocp, _("empty symbol name for load: %s"), ldname);
/* Make a copy of the ldname part. */
memcpy (new, ldname, l);
new[l] = '\0';
ldname = new;
nmlen = l;
buf = alloca (strlen (ldname) + 1);
memcpy (buf, ldname, l);
buf[l] = '\0';
ldname = buf;
/* Make a copy of the symbol name part. */
symname = new + l + 1;
memcpy (symname, fp, ep - fp);
symname[ep - fp] = '\0';
setupnm = buf + l + 1;
memcpy (setupnm, fp, ep - fp);
setupnm[ep - fp] = '\0';
}
}
@ -173,49 +217,21 @@ load_file (const floc *flocp, struct file *file, int noerror)
if (file && file->loaded)
return -1;
/* If we didn't find a symbol name yet, construct it from the ldname. */
if (! symname)
{
char *p = new;
fp = strrchr (ldname, '/');
#ifdef HAVE_DOS_PATHS
if (fp)
{
const char *fp2 = strchr (fp, '\\');
if (fp2 > fp)
fp = fp2;
}
else
fp = strrchr (ldname, '\\');
/* The (improbable) case of d:foo. */
if (fp && *fp && fp[1] == ':')
fp++;
#endif
if (!fp)
fp = ldname;
else
++fp;
while (isalnum ((unsigned char) *fp) || *fp == '_')
*(p++) = *(fp++);
strcpy (p, SYMBOL_EXTENSION);
symname = new;
}
DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, ldname));
/* Load it! */
symp = load_object (flocp, noerror, ldname, symname);
symp = load_object (flocp, noerror, ldname, setupnm);
if (! symp)
return 0;
/* Invoke the symbol. */
r = (*symp) (flocp);
/* Invoke the setup function. */
{
unsigned int abi = GMK_ABI_VERSION;
r = (*symp) (abi, flocp);
}
/* If the load didn't fail, add the file to the .LOADED variable. */
if (r)
do_variable_definition(flocp, ".LOADED", ldname, o_file, f_append_value, 0);
do_variable_definition(flocp, ".LOADED", ldname, o_file, f_append_value, 0,
s_global);
return r;
}
@ -223,22 +239,53 @@ load_file (const floc *flocp, struct file *file, int noerror)
int
unload_file (const char *name)
{
int rc = 0;
struct load_list *d;
struct load_list **dp = &loaded_syms;
for (d = loaded_syms; d != NULL; d = d->next)
if (streq (d->name, name) && d->dlp)
{
DB (DB_VERBOSE, (_("Unloading shared object %s\n"), name));
rc = dlclose (d->dlp);
if (rc)
perror_with_name ("dlclose: ", d->name);
else
d->dlp = NULL;
break;
}
/* Unload and remove the entry for this file. */
while (*dp != NULL)
{
struct load_list *d = *dp;
return rc;
if (streq (d->name, name))
{
int rc;
DB (DB_VERBOSE, (_("Unloading shared object %s\n"), name));
if (d->unload)
(*d->unload) ();
rc = dlclose (d->dlp);
if (rc)
perror_with_name ("dlclose: ", d->name);
*dp = d->next;
free (d);
return rc;
}
dp = &d->next;
}
return 0;
}
void
unload_all ()
{
while (loaded_syms)
{
struct load_list *d = loaded_syms;
loaded_syms = loaded_syms->next;
if (d->unload)
(*d->unload) ();
if (dlclose (d->dlp))
perror_with_name ("dlclose: ", d->name);
free (d);
}
}
#else
@ -248,7 +295,7 @@ load_file (const floc *flocp, struct file *file UNUSED, int noerror)
{
if (! noerror)
O (fatal, flocp,
_("The 'load' operation is not supported on this platform"));
_("'load' is not supported on this platform"));
return 0;
}
@ -256,7 +303,12 @@ load_file (const floc *flocp, struct file *file UNUSED, int noerror)
int
unload_file (const char *name UNUSED)
{
O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported");
O (fatal, NILF, "INTERNAL: cannot unload when load is not supported");
}
void
unload_all ()
{
}
#endif /* MAKE_LOAD */

View File

@ -1,5 +1,5 @@
/* API for GNU Make dynamic objects.
Copyright (C) 2013-2022 Free Software Foundation, Inc.
Copyright (C) 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -70,7 +70,7 @@ gmk_eval (const char *buffer, const gmk_floc *gfloc)
char *
gmk_expand (const char *ref)
{
return allocated_variable_expand (ref);
return allocated_expand_string (ref);
}
/* Register a function to be called from makefiles. */

1067
src/main.c

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Miscellaneous global declarations and portability cruft for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -18,28 +18,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because makeint.h was found in $srcdir). */
#include <config.h>
#undef HAVE_CONFIG_H
#define HAVE_CONFIG_H 1
/* Specify we want GNU source code. This must be defined before any
system headers are included. */
#define _GNU_SOURCE 1
/* AIX requires this to be the first thing in the file. */
#if HAVE_ALLOCA_H
# include <alloca.h>
#else
# ifdef _AIX
#pragma alloca
# else
# if !defined(__GNUC__) && !defined(WINDOWS32)
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
/* Some versions of GCC (e.g., 10.x) set the warn_unused_result attribute on
__builtin_alloca. This causes alloca(0) to fail and is not easily worked
@ -66,12 +44,12 @@ char *alloca ();
Be sure to use the local one, and not one installed on the system.
Define GMK_BUILDING_MAKE for proper selection of dllexport/dllimport
declarations for MS-Windows. */
#ifdef WINDOWS32
#if MK_OS_W32
# define GMK_BUILDING_MAKE
#endif
#include "gnumake.h"
#ifdef CRAY
#ifdef CRAY
/* This must happen before #include <signal.h> so
that the declaration therein is changed. */
# define signal bsdsignal
@ -82,18 +60,12 @@ char *alloca ();
# define __NO_STRING_INLINES
#endif
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_SYS_TIMEB_H
/* SCO 3.2 "devsys 4.2" has a prototype for 'ftime' in <time.h> that bombs
unless <sys/timeb.h> has been included first. */
# include <sys/timeb.h>
#endif
#if HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@ -105,7 +77,23 @@ char *alloca ();
extern int errno;
#endif
/* Define macros specifying which OS we are building for. */
#if __gnu_hurd__
# define MK_OS_HURD 1
#endif
#if __CYGWIN__
# define MK_OS_CYGWIN 1
#endif
#if defined(__MVS__)
# define MK_OS_ZOS 1
#endif
#if defined(__EMX__)
# define MK_OS_OS2 1
#endif
#ifdef __VMS
# define MK_OS_VMS 1
/* In strict ANSI mode, VMS compilers should not be defining the
VMS macro. Define it here instead of a bulk edit for the correct code.
*/
@ -114,11 +102,11 @@ extern int errno;
# endif
#endif
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
# include <unistd.h>
/* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get
POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself! */
# if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS)
# if defined (_POSIX_VERSION) && !defined (ultrix) && !MK_OS_VMS
# define POSIX 1
# endif
#endif
@ -144,31 +132,25 @@ extern int errno;
# include <vfork.h>
#endif
#ifdef HAVE_LIMITS_H
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifndef PATH_MAX
# ifndef POSIX
# ifdef MAXPATHLEN
# define PATH_MAX MAXPATHLEN
# else
/* Some systems (HURD) have fully dynamic pathnames with no maximum.
Ideally we'd support this but it will take some work. */
# define PATH_MAX 4096
# endif
#endif
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
#ifdef PATH_MAX
# define GET_PATH_MAX PATH_MAX
# define PATH_VAR(var) char var[PATH_MAX+1]
#else
# define NEED_GET_PATH_MAX 1
# define GET_PATH_MAX (get_path_max ())
# define PATH_VAR(var) char *var = alloca (GET_PATH_MAX+1)
unsigned int get_path_max (void);
#endif
#define GET_PATH_MAX PATH_MAX
#define PATH_VAR(var) char var[PATH_MAX+1]
#ifndef CHAR_BIT
# define CHAR_BIT 8
@ -178,6 +160,10 @@ unsigned int get_path_max (void);
# define USHRT_MAX 65535
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)~(size_t)0)
#endif
/* Nonzero if the integer type T is signed.
Use <= to avoid GCC warnings about always-false expressions. */
#define INTEGER_TYPE_SIGNED(t) ((t) -1 <= 0)
@ -208,7 +194,7 @@ unsigned int get_path_max (void);
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifdef VMS
#if MK_OS_VMS
# include <fcntl.h>
# include <types.h>
# include <unixlib.h>
@ -250,8 +236,6 @@ extern int vms_unix_simulation;
# ifdef HAVE_STRING_H
# include <string.h>
# define ANSI_STRING 1
# else
# include <strings.h>
# endif
# ifdef HAVE_MEMORY_H
# include <memory.h>
@ -277,16 +261,16 @@ void exit (int) NORETURN;
# define EXIT_FAILURE 1
#endif
#ifndef ANSI_STRING
#ifndef ANSI_STRING
/* SCO Xenix has a buggy macro definition in <string.h>. */
#undef strerror
#undef strerror
#if !defined(__DECC)
char *strerror (int errnum);
#endif
#endif /* !ANSI_STRING. */
#undef ANSI_STRING
#undef ANSI_STRING
#if HAVE_INTTYPES_H
# include <inttypes.h>
@ -295,6 +279,10 @@ char *strerror (int errnum);
# include <stdint.h>
#endif
#if HAVE_STRINGS_H
# include <strings.h> /* Needed for strcasecmp / strncasecmp. */
#endif
#if defined _MSC_VER || defined __MINGW32__
# define MK_PRI64_PREFIX "I64"
#else
@ -375,7 +363,7 @@ extern mode_t umask (mode_t);
# include <direct.h>
#endif
#ifdef WINDOWS32
#if MK_OS_W32
# include <fcntl.h>
# include <malloc.h>
# define pipe(_p) _pipe((_p), 512, O_BINARY)
@ -405,14 +393,17 @@ extern int unixy_shell;
# endif
/* Include only the minimal stuff from windows.h. */
# define WIN32_LEAN_AND_MEAN
#endif /* WINDOWS32 */
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
#endif /* MK_OS_W32 */
/* ALL_SET() evaluates the second argument twice. */
#define ANY_SET(_v,_m) (((_v)&(_m)) != 0)
#define NONE_SET(_v,_m) (! ANY_SET ((_v),(_m)))
#define ALL_SET(_v,_m) (((_v)&(_m)) == (_m))
/* Bitmasks for the STOPCHAR array. */
#define MAP_NUL 0x0001
#define MAP_BLANK 0x0002 /* space, TAB */
#define MAP_NEWLINE 0x0004
@ -432,7 +423,7 @@ extern int unixy_shell;
/* The set of characters which are directory separators is OS-specific. */
#define MAP_DIRSEP 0x8000
#ifdef VMS
#if MK_OS_VMS
# define MAP_VMSCOMMA MAP_COMMA
#else
# define MAP_VMSCOMMA 0x0000
@ -449,7 +440,7 @@ extern int unixy_shell;
# define PATH_SEPARATOR_CHAR ';'
# define MAP_PATHSEP MAP_SEMI
#elif !defined(PATH_SEPARATOR_CHAR)
# if defined (VMS)
# if MK_OS_VMS
# define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':')
# define MAP_PATHSEP (vms_comma_separator ? MAP_COMMA : MAP_SEMI)
# else
@ -462,14 +453,13 @@ extern int unixy_shell;
# define MAP_PATHSEP MAP_SEMI
#elif PATH_SEPARATOR_CHAR == ','
# define MAP_PATHSEP MAP_COMMA
#else
# error "Unknown PATH_SEPARATOR_CHAR"
#endif
#define STOP_SET(_v,_m) ANY_SET(stopchar_map[(unsigned char)(_v)],(_m))
/* True if C is a directory separator on the current system. */
#define ISDIRSEP(c) STOP_SET((c),MAP_DIRSEP)
/* True if C is whitespace but not newline. */
#define ISBLANK(c) STOP_SET((c),MAP_BLANK)
/* True if C is whitespace including newlines. */
@ -479,6 +469,18 @@ extern int unixy_shell;
/* Move S past all whitespace (including newlines). */
#define NEXT_TOKEN(s) while (ISSPACE (*(s))) ++(s)
/* True if C is a directory separator on the current system. */
#define ISDIRSEP(c) STOP_SET((c),MAP_DIRSEP)
/* True if S starts with a drive specifier. */
#if defined(HAVE_DOS_PATHS)
# define HAS_DRIVESPEC(_s) ((((_s)[0] >= 'a' && (_s)[0] <= 'z') \
|| ((_s)[0] >= 'A' && (_s)[0] <= 'Z')) \
&& (_s)[1] == ':')
#else
# define HAS_DRIVESPEC(_s) 0
#endif
/* We can't run setrlimit when using posix_spawn. */
#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) && !defined(USE_POSIX_SPAWN)
# define SET_STACK_SIZE
@ -492,8 +494,13 @@ extern struct rlimit stack_limit;
#define NILF ((floc *)0)
/* Number of elements in an array. */
#define ARRAYLEN(_a) (sizeof (_a) / sizeof ((_a)[0]))
/* Number of characters in a string constant. Does NOT include the \0 byte. */
#define CSTRLEN(_s) (sizeof (_s)-1)
/* Only usable when NOT calling a macro: only use it for local functions. */
#define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s)
/* The number of bytes needed to represent the largest signed and unsigned
@ -509,7 +516,7 @@ extern struct rlimit stack_limit;
# define TTYNAME(_f) DEFAULT_TTYNAME
#endif
#ifdef VMS
#if MK_OS_VMS
# define DEFAULT_TMPDIR "/sys$scratch/"
#elif defined(P_tmpdir)
# define DEFAULT_TMPDIR P_tmpdir
@ -537,6 +544,8 @@ void error (const floc *flocp, size_t length, const char *fmt, ...)
ATTRIBUTE ((__format__ (__printf__, 3, 4)));
void fatal (const floc *flocp, size_t length, const char *fmt, ...)
ATTRIBUTE ((noreturn, __format__ (__printf__, 3, 4)));
char *format (const char *prefix, size_t length, const char *fmt, ...)
ATTRIBUTE ((__format__ (__printf__, 3, 4)));
void out_of_memory (void) NORETURN;
/* When adding macros to this list be sure to update the value of
@ -555,7 +564,12 @@ void out_of_memory (void) NORETURN;
#define ONS(_t,_a,_f,_n,_s) _t((_a), INTSTR_LENGTH + strlen (_s), \
(_f), (_n), (_s))
void decode_env_switches (const char*, size_t line);
enum variable_origin;
struct variable;
void reset_makeflags (enum variable_origin origin);
struct variable *define_makeflags (int makefile);
int should_print_dir (void);
void temp_stdin_unlink (void);
void die (int) NORETURN;
void pfatal_with_name (const char *) NORETURN;
@ -575,6 +589,7 @@ char *xstrndup (const char *, size_t);
char *find_next_token (const char **, size_t *);
char *next_token (const char *);
char *end_of_token (const char *);
char *skip_reference (const char *);
void collapse_continuations (char *);
char *lindex (const char *, const char *, int);
int alpha_compare (const void *, const void *);
@ -606,7 +621,7 @@ typedef intmax_t (*ar_member_func_t) (int desc, const char *mem, int truncated,
intmax_t ar_scan (const char *archive, ar_member_func_t function,
const void *arg);
int ar_name_equal (const char *name, const char *mem, int truncated);
#ifndef VMS
#if !MK_OS_VMS
int ar_member_touch (const char *arname, const char *memname);
#endif
#endif
@ -649,29 +664,33 @@ const char *strcache_add_len (const char *str, size_t len);
int guile_gmake_setup (const floc *flocp);
/* Loadable object support. Sets to the strcached name of the loaded file. */
typedef int (*load_func_t)(const floc *flocp);
int load_file (const floc *flocp, struct file *file, int noerror);
int unload_file (const char *name);
void unload_all (void);
/* Maintainer mode support */
#ifdef MAKE_MAINTAINER_MODE
# define SPIN(_s) spin (_s)
void spin (const char* suffix);
# define DBG(_f) dbg _f
void dbg (const char *fmt, ...);
#else
# define SPIN(_s)
/* Never put this code into Git or a release. */
# define DBG(_f) compile-error
#endif
/* We omit these declarations on non-POSIX systems which define _POSIX_VERSION,
because such systems often declare them in header files anyway. */
#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32)
#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !MK_OS_W32
# ifndef VMS
# if !MK_OS_VMS
long int lseek ();
# endif
# ifdef HAVE_GETCWD
# if !defined(VMS) && !defined(__DECC)
# ifdef HAVE_GETCWD
# if !MK_OS_VMS && !defined(__DECC)
char *getcwd (void);
# endif
# else
@ -686,9 +705,6 @@ char *getwd (void);
# define strcasecmp stricmp
# elif HAVE_STRCMPI
# define strcasecmp strcmpi
# else
/* Create our own, in misc.c */
int strcasecmp (const char *s1, const char *s2);
# endif
#endif
@ -697,22 +713,9 @@ int strcasecmp (const char *s1, const char *s2);
# define strncasecmp strnicmp
# elif HAVE_STRNCMPI
# define strncasecmp strncmpi
# else
/* Create our own, in misc.c */
int strncasecmp (const char *s1, const char *s2, size_t n);
# endif
#endif
#if !HAVE_MEMPCPY
/* Create our own, in misc.c */
void *mempcpy (void *dest, const void *src, size_t n);
#endif
#if !HAVE_STPCPY
/* Create our own, in misc.c */
char *stpcpy (char *dest, const char *src);
#endif
#define OUTPUT_SYNC_NONE 0
#define OUTPUT_SYNC_LINE 1
#define OUTPUT_SYNC_TARGET 2
@ -729,10 +732,10 @@ extern unsigned short stopchar_map[];
extern int just_print_flag, run_silent, ignore_errors_flag, keep_going_flag;
extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
extern int print_version_flag, print_directory, check_symlink_flag;
extern int warn_undefined_variables_flag, posix_pedantic;
extern int print_version_flag, check_symlink_flag, posix_pedantic;
extern int not_parallel, second_expansion, clock_skew_detected;
extern int rebuilding_makefiles, one_shell, output_sync, verify_flag;
extern int export_all_variables;
extern unsigned long command_count;
extern const char *default_shell;
@ -743,11 +746,27 @@ extern int batch_mode_shell;
#define GNUMAKEFLAGS_NAME "GNUMAKEFLAGS"
#define MAKEFLAGS_NAME "MAKEFLAGS"
#define MAKELEVEL_NAME "MAKELEVEL"
#define MAKELEVEL_LENGTH (CSTRLEN (MAKELEVEL_NAME))
/* Resetting the command script introduction prefix character. */
#define RECIPEPREFIX_NAME ".RECIPEPREFIX"
#define RECIPEPREFIX_DEFAULT '\t'
extern char cmd_prefix;
/* Setting warning actions. */
#define WARNINGS_NAME ".WARNINGS"
extern unsigned int no_intermediates;
#if HAVE_MKFIFO
/* It seems that mkfifo() is not working correctly, or at least not the way
GNU make wants it to work, on: GNU/Hurd, Cygwin, OS2; don't use it there. */
# if !defined(JOBSERVER_USE_FIFO) && !MK_OS_HURD && !MK_OS_CYGWIN && !MK_OS_OS2
# define JOBSERVER_USE_FIFO 1
# endif
#endif
#define JOBSERVER_AUTH_OPT "jobserver-auth"
extern char *jobserver_auth;
@ -756,7 +775,7 @@ extern double max_load_average;
extern const char *program;
#ifdef VMS
#if MK_OS_VMS
const char *vms_command (const char *argv0);
const char *vms_progname (const char *argv0);
@ -823,7 +842,7 @@ extern volatile sig_atomic_t handling_fatal_signal;
#endif
#ifndef initialize_main
# ifdef __EMX__
# if MK_OS_OS2
# define initialize_main(pargc, pargv) \
{ _wildcard(pargc, pargv); _response(pargc, pargv); }
# else
@ -831,7 +850,7 @@ extern volatile sig_atomic_t handling_fatal_signal;
# endif
#endif
#ifdef __EMX__
#if MK_OS_OS2
# if !defined chdir
# define chdir _chdir2
# endif

View File

@ -1,5 +1,5 @@
/* Miscellaneous generic support functions for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -20,15 +20,19 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "os.h"
#include "debug.h"
/* GNU make no longer supports pre-ANSI89 environments. */
#include <assert.h>
#include <stdarg.h>
#ifdef WINDOWS32
#if MK_OS_W32
# include <windows.h>
# include <io.h>
#endif
#if MK_OS_OS2
# define INCL_DOS
# include <os2.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#else
@ -127,7 +131,7 @@ collapse_continuations (char *line)
char *q;
q = strchr(in, '\n');
if (q == 0)
if (!q)
return;
do
@ -158,17 +162,33 @@ collapse_continuations (char *line)
if (i & 1)
{
/* Backslash/newline handling:
In traditional GNU make all trailing whitespace, consecutive
backslash/newlines, and any leading non-newline whitespace on the
next line is reduced to a single space.
In POSIX, each backslash/newline and is replaced by a space. */
unsigned int dollar;
/* Backslash/newline handling: out points to the final "\".
In POSIX, each backslash/newline is replaced by a space.
In GNU Make all trailing whitespace, consecutive backslash +
newlines, and any leading non-newline whitespace on the next line
is reduced to a single space.
As a special case, replace "$\" with the empty string. */
while (ISBLANK (*in))
++in;
if (! posix_pedantic)
{
const char *dp = out;
while (dp > line && dp[-1] == '$')
--dp;
dollar = (out - dp) % 2;
}
if (dollar)
--out;
if (!posix_pedantic)
while (out > line && ISBLANK (out[-1]))
--out;
*out++ = ' ';
if (!dollar)
*out++ = ' ';
}
else
{
@ -331,7 +351,7 @@ xstrndup (const char *str, size_t length)
#else
result = xmalloc (length + 1);
if (length > 0)
strncpy (result, str, length);
memcpy (result, str, length);
result[length] = '\0';
#endif
@ -398,6 +418,50 @@ next_token (const char *s)
return (char *)s;
}
/* This function returns P if P points to EOS, or P+1 if P is NOT an open
paren or brace, or a pointer to the character after the matching close
paren or brace, skipping matched internal parens or braces.
It is typically called when we have seen a '$' in a string and we want to
treat it as a variable reference and find the end of it: in that case P
should point to the character after the '$'. */
char *
skip_reference (const char *p)
{
char openparen = *p;
char closeparen;
int count = 1;
if (openparen == '\0')
return (char*)p;
if (openparen == '(')
closeparen = ')';
else if (openparen == '{')
closeparen = '}';
else
return (char*)(p+1);
while (1)
{
++p;
if (!STOP_SET (*p, MAP_NUL|MAP_VARSEP))
continue;
if (*p == '\0')
break;
if (*p == openparen)
++count;
else if (*p == closeparen && --count == 0)
{
++p;
break;
}
}
return (char*)p;
}
/* Find the next token in PTR; return the address of it, and store the length
of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
of the token, so this function can be called repeatedly in a loop. */
@ -417,6 +481,7 @@ find_next_token (const char **ptr, size_t *lengthptr)
return (char *)p;
}
/* Write a BUFFER of size LEN to file descriptor FD.
Retry short writes from EINTR. Return LEN, or -1 on error. */
ssize_t
@ -430,7 +495,7 @@ writebuf (int fd, const void *buffer, size_t len)
EINTRLOOP (r, write (fd, msg, l));
if (r < 0)
return r;
return -1;
l -= r;
msg += r;
@ -440,8 +505,7 @@ writebuf (int fd, const void *buffer, size_t len)
}
/* Read until we get LEN bytes from file descriptor FD, into BUFFER.
Retry short reads on EINTR. If we get an error, return it.
Return 0 at EOF. */
Retry short reads on EINTR. Return 0 at EOF and -1 on error. */
ssize_t
readbuf (int fd, void *buffer, size_t len)
{
@ -452,7 +516,7 @@ readbuf (int fd, void *buffer, size_t len)
EINTRLOOP (r, read (fd, msg, len));
if (r < 0)
return r;
return -1;
if (r == 0)
break;
@ -464,23 +528,38 @@ readbuf (int fd, void *buffer, size_t len)
}
/* Copy a 'struct dep'. For 2nd expansion deps, dup the name. */
struct dep *
copy_dep (const struct dep *d)
{
struct dep *new = NULL;
if (d)
{
new = xmalloc (sizeof (struct dep));
memcpy (new, d, sizeof (struct dep));
if (new->need_2nd_expansion)
new->name = xstrdup (new->name);
new->next = 0;
}
return new;
}
/* Copy a chain of 'struct dep'. For 2nd expansion deps, dup the name. */
struct dep *
copy_dep_chain (const struct dep *d)
{
struct dep *firstnew = 0;
struct dep *lastnew = 0;
struct dep *firstnew = NULL;
struct dep *lastnew = NULL;
while (d != 0)
{
struct dep *c = xmalloc (sizeof (struct dep));
memcpy (c, d, sizeof (struct dep));
struct dep *c = copy_dep (d);
if (c->need_2nd_expansion)
c->name = xstrdup (c->name);
c->next = 0;
if (firstnew == 0)
firstnew = lastnew = c;
else
@ -498,7 +577,7 @@ copy_dep_chain (const struct dep *d)
void
free_ns_chain (struct nameseq *ns)
{
while (ns != 0)
while (ns != NULL)
{
struct nameseq *t = ns;
ns = ns->next;
@ -521,7 +600,7 @@ spin (const char* type)
{
fprintf (stderr, "SPIN on %s\n", filenm);
do
#ifdef WINDOWS32
#if MK_OS_W32
Sleep (1000);
#else
sleep (1);
@ -530,6 +609,22 @@ spin (const char* type)
}
}
void
dbg (const char *fmt, ...)
{
FILE *fp = fopen ("/tmp/gmkdebug.log", "a+");
va_list args;
char buf[4096];
va_start (args, fmt);
vsprintf (buf, fmt, args);
va_end (args);
fprintf(fp, "%u: %s\n", (unsigned) make_pid (), buf);
fflush (fp);
fclose (fp);
}
#endif
@ -552,8 +647,7 @@ umask (mode_t mask)
}
#endif
#define MAKE_TMPDIR "MAKE_TMPDIR"
#ifdef VMS
#if MK_OS_VMS
# define DEFAULT_TMPFILE "sys$scratch:gnv$make_cmdXXXXXX.com"
#else
# define DEFAULT_TMPFILE "GmXXXXXX"
@ -566,13 +660,36 @@ get_tmpdir ()
if (!tmpdir)
{
if (((tmpdir = getenv (MAKE_TMPDIR)) == NULL || *tmpdir == '\0')
#if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
&& ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0')
&& ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0')
#if MK_OS_DOS || MK_OS_W32 || MK_OS_OS2
# define TMP_EXTRAS "TMP", "TEMP",
#else
# define TMP_EXTRAS
#endif
&& ((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0'))
tmpdir = DEFAULT_TMPDIR;
const char *tlist[] = { "MAKE_TMPDIR", "TMPDIR", TMP_EXTRAS NULL };
const char **tp;
unsigned int found = 0;
for (tp = tlist; *tp; ++tp)
if ((tmpdir = getenv (*tp)) != NULL && *tmpdir != '\0')
{
struct stat st;
int r;
found = 1;
EINTRLOOP(r, stat (tmpdir, &st));
if (r < 0)
OSSS (error, NILF,
_("%s value %s: %s"), *tp, tmpdir, strerror (errno));
else if (! S_ISDIR (st.st_mode))
OSS (error, NILF,
_("%s value %s: not a directory"), *tp, tmpdir);
else
return tmpdir;
}
tmpdir = DEFAULT_TMPDIR;
if (found)
OS (error, NILF, _("using default temporary directory '%s'"), tmpdir);
}
return tmpdir;
@ -588,7 +705,7 @@ get_tmptemplate ()
template = xmalloc (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2);
cp = stpcpy (template, tmpdir);
#if !defined VMS
#if !MK_OS_VMS
/* It's not possible for tmpdir to be empty. */
if (! ISDIRSEP (cp[-1]))
*(cp++) = '/';
@ -612,11 +729,19 @@ get_tmppath ()
# ifdef HAVE_MKTEMP
path = get_tmptemplate ();
if (*mktemp (path) == '\0')
pfatal_with_name ("mktemp");
{
OSS (error, NILF,
_("cannot generate temp path from %s: %s"), path, strerror (errno));
return NULL;
}
# else
path = xmalloc (L_tmpnam + 1);
if (tmpnam (path) == NULL)
pfatal_with_name ("tmpnam");
{
OS (error, NILF,
_("cannot generate temp name: %s"), strerror (errno));
return NULL;
}
# endif
return path;
@ -624,21 +749,30 @@ get_tmppath ()
#endif
/* Generate a temporary file and return an fd for it. If name is NULL then
the temp file is anonymous and will be deleted when the process exits. */
the temp file is anonymous and will be deleted when the process exits. If
name is not null then *name will point to an allocated buffer, or set to
NULL on failure. */
int
get_tmpfd (char **name)
{
int fd = -1;
char *tmpnm;
mode_t mask;
/* If there's an os-specific way to get an anoymous temp file use it. */
if (!name)
if (name)
*name = NULL;
else
{
/* If there's an os-specific way to get an anonymous temp file use it. */
fd = os_anontmp ();
if (fd >= 0)
return fd;
}
/* Preserve the current umask, and set a restrictive one for temp files.
Only really needed for mkstemp() but won't hurt for the open method. */
mask = umask (0077);
#if defined(HAVE_MKSTEMP)
tmpnm = get_tmptemplate ();
@ -646,13 +780,19 @@ get_tmpfd (char **name)
EINTRLOOP (fd, mkstemp (tmpnm));
#else
tmpnm = get_tmppath ();
if (!tmpnm)
return -1;
/* Can't use mkstemp(), but try to guard against a race condition. */
EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
#endif
if (fd < 0)
OSS (fatal, NILF,
_("create temporary file %s: %s"), tmpnm, strerror (errno));
{
OSS (error, NILF,
_("cannot create temporary file %s: %s"), tmpnm, strerror (errno));
free (tmpnm);
return -1;
}
if (name)
*name = tmpnm;
@ -661,17 +801,19 @@ get_tmpfd (char **name)
int r;
EINTRLOOP (r, unlink (tmpnm));
if (r < 0)
OSS (fatal, NILF,
_("unlink temporary file %s: %s"), tmpnm, strerror (errno));
OSS (error, NILF,
_("cannot unlink temporary file %s: %s"), tmpnm, strerror (errno));
free (tmpnm);
}
umask (mask);
return fd;
}
/* Return a FILE* for a temporary file, opened in the safest way possible.
Set name to point to an allocated buffer containing the name of the file.
Note, this cannot be NULL! */
Set name to point to an allocated buffer containing the name of the file,
or NULL on failure. Note, name cannot be NULL! */
FILE *
get_tmpfile (char **name)
{
@ -680,26 +822,37 @@ get_tmpfile (char **name)
FILE *file;
#if defined(HAVE_FDOPEN)
int fd = get_tmpfd (name);
int fd;
assert (name);
fd = get_tmpfd (name);
if (fd < 0)
return NULL;
assert (*name);
ENULLLOOP (file, fdopen (fd, tmpfile_mode));
if (file == NULL)
OSS (fatal, NILF,
OSS (error, NILF,
_("fdopen: temporary file %s: %s"), *name, strerror (errno));
#else
/* Preserve the current umask, and set a restrictive one for temp files. */
mode_t mask = umask (0077);
int err;
assert (name);
*name = get_tmppath ();
if (!*name)
return NULL;
/* Although this fopen is insecure, it is executed only on non-fdopen
platforms, which should be a rarity nowadays. */
ENULLLOOP (file, fopen (*name, tmpfile_mode));
if (file == NULL)
OSS (fatal, NILF,
_("fopen: temporary file %s: %s"), *name, strerror (errno));
{
OSS (error, NILF,
_("fopen: temporary file %s: %s"), *name, strerror (errno));
free (*name);
*name = NULL;
}
umask (mask);
#endif
@ -708,6 +861,40 @@ get_tmpfile (char **name)
}
#if HAVE_TTYNAME && MK_OS_OS2
/* OS/2 kLIBC has a declaration for ttyname(), so configure finds it.
But, it is not implemented! Roll our own. */
char *ttyname (int fd)
{
ULONG type;
ULONG attr;
ULONG rc;
rc = DosQueryHType (fd, &type, &attr);
if (rc)
{
errno = EBADF;
return NULL;
}
if (type == HANDTYPE_DEVICE)
{
if (attr & 3) /* 1 = KBD$, 2 = SCREEN$ */
return (char *) "/dev/con";
if (attr & 4) /* 4 = NUL */
return (char *) "/dev/nul";
if (attr & 8) /* 8 = CLOCK$ */
return (char *) "/dev/clock$";
}
errno = ENOTTY;
return NULL;
}
#endif
#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
for it, define our own version. */
@ -761,25 +948,6 @@ strncasecmp (const char *s1, const char *s2, size_t n)
#endif
#ifdef NEED_GET_PATH_MAX
unsigned int
get_path_max (void)
{
static unsigned int value;
if (value == 0)
{
long int x = pathconf ("/", _PC_PATH_MAX);
if (x > 0)
value = x;
else
return MAXPATHLEN;
}
return value;
}
#endif
#if !HAVE_MEMPCPY
void *
mempcpy (void *dest, const void *src, size_t n)

View File

@ -1,5 +1,5 @@
/* Autoconf values for use on non-POSIX systems.
Copyright (C) 2022 Free Software Foundation, Inc.
Copyright (C) 2022-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

65
src/mkcustom.h Normal file
View File

@ -0,0 +1,65 @@
/* Miscellaneous global declarations and portability cruft for GNU Make.
Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. */
/*
This file is included at the end of config.h
That means it's included _everywhere_ as the first thing,
INCLUDING content imported from gnulib. BE AWARE!!
*/
#undef HAVE_CONFIG_H
#define HAVE_CONFIG_H 1
/* Specify we want GNU source code. This must be defined before any
system headers are included. */
#define _GNU_SOURCE 1
/* AIX requires this to be the first thing in the file. */
#if HAVE_ALLOCA_H
# include <alloca.h>
#else
# ifdef _AIX
#pragma alloca
# else
# if !defined(__GNUC__) && !MK_OS_W32
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
/* Declare function prototypes for src/misc.c functions if needed. */
#include <stddef.h>
#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
int strcasecmp (const char *s1, const char *s2);
#endif
#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI
int strncasecmp (const char *s1, const char *s2, size_t n);
#endif
#if !HAVE_MEMPCPY
void *mempcpy (void *dest, const void *src, size_t n);
#endif
#if !HAVE_STPCPY
char *stpcpy (char *dest, const char *src);
#endif

View File

@ -1,5 +1,5 @@
/* Declarations for operating system interfaces for GNU Make.
Copyright (C) 2016-2022 Free Software Foundation, Inc.
Copyright (C) 2016-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -20,23 +20,28 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#define IO_STDOUT_OK 0x0008
#define IO_STDERR_OK 0x0010
#if defined(VMS) || defined(_AMIGA) || defined(__MSDOS__)
# define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)
# define fd_inherit(_i) (0)
# define fd_noinherit(_i) (0)
# define fd_set_append(_i) (void)(0)
# define os_anontmp() (-1)
#if MK_OS_VMS || MK_OS_DOS
# define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)
# define fd_inherit(_i) (0)
# define fd_noinherit(_i) (0)
# define fd_set_append(_i) (-1)
# define fd_reset_append(_i,_f) (void)(0)
# define os_anontmp() (-1)
#else
/* Determine the state of stdin/stdout/stderr. */
unsigned int check_io_state (void);
/* Set a file descriptor to close/not close in a subprocess. */
void fd_inherit (int);
void fd_noinherit (int);
void fd_inherit (int fd);
void fd_noinherit (int fd);
/* If the file descriptor is for a file put it into append mode. */
void fd_set_append (int);
/* If the file descriptor is for a file put it into append mode.
Return the original flags for the file descriptor, or -1 if not found. */
int fd_set_append (int fd);
/* Reset the append mode to the flags returned by fd_set_append(). */
void fd_reset_append (int fd, int flags);
/* Return a file descriptor for a new anonymous temp file, or -1. */
int os_anontmp (void);
@ -151,8 +156,13 @@ void osync_release (void);
#endif /* NO_OUTPUT_SYNC */
/* Create a "bad" file descriptor for stdin when parallel jobs are run. */
#if defined(VMS) || defined(WINDOWS32) || defined(_AMIGA) || defined(__MSDOS__)
#if MK_OS_VMS || MK_OS_W32 || MK_OS_DOS
# define get_bad_stdin() (-1)
#else
int get_bad_stdin (void);
#endif
#if MK_OS_W32
#include <windows.h> /* Needed for HANDLE */
HANDLE get_handle_for_fd (int);
#endif

View File

@ -1,5 +1,5 @@
/* Output to stdout / stderr for GNU make
Copyright (C) 2013-2022 Free Software Foundation, Inc.
/* Output to stdout / stderr for GNU Make
Copyright (C) 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -18,7 +18,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "os.h"
#include "output.h"
/* GNU make no longer supports pre-ANSI89 environments. */
/* GNU Make no longer supports pre-ANSI89 environments. */
#include <assert.h>
#include <stdio.h>
@ -34,11 +34,11 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
# include <sys/file.h>
#endif
#ifdef WINDOWS32
#if MK_OS_W32
# include <windows.h>
# include <io.h>
# include "sub_proc.h"
#endif /* WINDOWS32 */
#endif
struct output *output_context = NULL;
unsigned int stdio_traced = 0;
@ -51,20 +51,24 @@ unsigned int stdio_traced = 0;
static void
_outputs (struct output *out, int is_err, const char *msg)
{
if (! out || ! out->syncout)
{
FILE *f = is_err ? stderr : stdout;
fputs (msg, f);
fflush (f);
}
else
FILE *f;
if (out && out->syncout)
{
int fd = is_err ? out->err : out->out;
size_t len = strlen (msg);
int r;
EINTRLOOP (r, lseek (fd, 0, SEEK_END));
writebuf (fd, msg, len);
if (fd != OUTPUT_NONE)
{
size_t len = strlen (msg);
int r;
EINTRLOOP (r, lseek (fd, 0, SEEK_END));
writebuf (fd, msg, len);
return;
}
}
f = is_err ? stderr : stdout;
fputs (msg, f);
fflush (f);
}
/* Write a message indicating that we've just entered or
@ -147,7 +151,7 @@ pump_from_tmp (int from, FILE *to)
{
static char buffer[8192];
#ifdef WINDOWS32
#if MK_OS_W32
int prev_mode;
/* "from" is opened by open_tmpfd, which does it in binary mode, so
@ -174,7 +178,7 @@ pump_from_tmp (int from, FILE *to)
fflush (to);
}
#ifdef WINDOWS32
#if MK_OS_W32
/* Switch "to" back to its original mode, so that log messages by
Make have the same EOL format as without --output-sync. */
_setmode (fileno (to), prev_mode);
@ -198,7 +202,16 @@ output_tmpfd (void)
static void
setup_tmpfile (struct output *out)
{
unsigned int io_state = check_io_state ();
static unsigned int in_setup = 0;
unsigned int io_state;
/* If something fails during setup we might recurse back into this function
while writing errors. Make sure we don't do so infinitely. */
if (in_setup)
return;
in_setup = 1;
io_state = check_io_state ();
if (NONE_SET (io_state, IO_STDOUT_OK|IO_STDERR_OK))
{
@ -230,13 +243,18 @@ setup_tmpfile (struct output *out)
}
}
in_setup = 0;
return;
/* If we failed to create a temp file, disable output sync going forward. */
error:
O (error, NILF,
_("cannot open output-sync lock file: suppressing output-sync"));
output_close (out);
output_sync = OUTPUT_SYNC_NONE;
osync_clear ();
in_setup = 0;
}
/* Synchronize the output of jobs in -j mode to keep the results of
@ -262,12 +280,13 @@ output_dump (struct output *out)
if (!osync_acquire ())
{
O (error, NILF,
_("warning: Cannot acquire output lock, disabling output sync."));
_("warning: cannot acquire output lock: disabling output sync"));
osync_clear ();
}
/* Log the working directory for this dump. */
if (print_directory && output_sync != OUTPUT_SYNC_RECURSE)
if (output_sync != OUTPUT_SYNC_RECURSE && should_print_dir ())
traced = log_working_directory (1);
if (outfd_not_empty)
@ -299,6 +318,9 @@ output_dump (struct output *out)
#endif /* NO_OUTPUT_SYNC */
static int stdout_flags = -1;
static int stderr_flags = -1;
void
output_init (struct output *out)
{
@ -311,8 +333,8 @@ output_init (struct output *out)
/* Force stdout/stderr into append mode (if they are files) to ensure
parallel jobs won't lose output due to overlapping writes. */
fd_set_append (fileno (stdout));
fd_set_append (fileno (stderr));
stdout_flags = fd_set_append (fileno (stdout));
stderr_flags = fd_set_append (fileno (stderr));
}
void
@ -322,6 +344,8 @@ output_close (struct output *out)
{
if (stdio_traced)
log_working_directory (0);
fd_reset_append(fileno (stdout), stdout_flags);
fd_reset_append(fileno (stderr), stderr_flags);
return;
}
@ -351,7 +375,7 @@ output_start (void)
/* 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)
if (! stdio_traced && should_print_dir ())
stdio_traced = log_working_directory (1);
}
@ -394,19 +418,16 @@ void
message (int prefix, size_t len, const char *fmt, ...)
{
va_list args;
char *start;
char *p;
len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
p = get_buffer (len);
start = p = get_buffer (len);
if (prefix)
{
if (makelevel == 0)
sprintf (p, "%s: ", program);
else
sprintf (p, "%s[%u]: ", program, makelevel);
p += strlen (p);
}
p += (makelevel == 0
? sprintf (p, "%s: ", program)
: sprintf (p, "%s[%u]: ", program, makelevel));
va_start (args, fmt);
vsprintf (p, fmt, args);
@ -414,8 +435,8 @@ message (int prefix, size_t len, const char *fmt, ...)
strcat (p, "\n");
assert (fmtbuf.buffer[len-1] == '\0');
outputs (0, fmtbuf.buffer);
assert (start[len-1] == '\0');
outputs (0, start);
}
/* Print an error message. */
@ -424,20 +445,19 @@ void
error (const floc *flocp, size_t len, const char *fmt, ...)
{
va_list args;
char *start;
char *p;
len += (strlen (fmt) + strlen (program)
+ (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
+ INTSTR_LENGTH + 4 + 1 + 1);
p = get_buffer (len);
start = p = get_buffer (len);
if (flocp && flocp->filenm)
sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
else if (makelevel == 0)
sprintf (p, "%s: ", program);
else
sprintf (p, "%s[%u]: ", program, makelevel);
p += strlen (p);
p += (flocp && flocp->filenm
? sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset)
: makelevel == 0
? sprintf (p, "%s: ", program)
: sprintf (p, "%s[%u]: ", program, makelevel));
va_start (args, fmt);
vsprintf (p, fmt, args);
@ -445,8 +465,8 @@ error (const floc *flocp, size_t len, const char *fmt, ...)
strcat (p, "\n");
assert (fmtbuf.buffer[len-1] == '\0');
outputs (1, fmtbuf.buffer);
assert (start[len-1] == '\0');
outputs (1, start);
}
/* Print an error message and exit. */
@ -454,22 +474,22 @@ error (const floc *flocp, size_t len, const char *fmt, ...)
void
fatal (const floc *flocp, size_t len, const char *fmt, ...)
{
va_list args;
const char *stop = _(". Stop.\n");
va_list args;
char *start;
char *p;
len += (strlen (fmt) + strlen (program)
+ (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
+ INTSTR_LENGTH + 8 + strlen (stop) + 1);
p = get_buffer (len);
start = p = get_buffer (len);
if (flocp && flocp->filenm)
sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
else if (makelevel == 0)
sprintf (p, "%s: *** ", program);
else
sprintf (p, "%s[%u]: *** ", program, makelevel);
p += strlen (p);
p += (flocp && flocp->filenm
? sprintf (p, "%s:%lu: *** ", flocp->filenm,
flocp->lineno + flocp->offset)
: makelevel == 0
? sprintf (p, "%s: *** ", program)
: sprintf (p, "%s[%u]: *** ", program, makelevel));
va_start (args, fmt);
vsprintf (p, fmt, args);
@ -477,12 +497,35 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
strcat (p, stop);
assert (fmtbuf.buffer[len-1] == '\0');
outputs (1, fmtbuf.buffer);
assert (start[len-1] == '\0');
outputs (1, start);
die (MAKE_FAILURE);
}
/* Format a message and return a pointer to an internal buffer. */
char *
format (const char *prefix, size_t len, const char *fmt, ...)
{
va_list args;
size_t plen = prefix ? strlen (prefix) : 0;
char *start;
char *p;
len += strlen (fmt) + plen + 1;
start = p = get_buffer (len);
if (plen)
p = mempcpy (p, prefix, plen);
va_start (args, fmt);
vsprintf (p, fmt, args);
va_end (args);
return start;
}
/* Print an error message from errno. */
void

View File

@ -1,5 +1,5 @@
/* Output to stdout / stderr for GNU make
Copyright (C) 2013-2022 Free Software Foundation, Inc.
/* Output to stdout / stderr for GNU Make
Copyright (C) 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
/* POSIX-based operating system interface for GNU Make.
Copyright (C) 2016-2022 Free Software Foundation, Inc.
Copyright (C) 2016-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -24,6 +24,10 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#elif defined(HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif
#if MK_OS_ZOS
/* FIXME: HAVE_PSELECT path hangs on z/OS */
#undef HAVE_PSELECT
#endif
#if !defined(FD_OK)
# define FD_OK(_f) 1
@ -118,10 +122,8 @@ make_job_rfd ()
}
static void
set_blocking (int fd, int blocking)
force_blocking (int fd, int blocking)
{
/* If we're not using pselect() don't change the blocking. */
#ifdef HAVE_PSELECT
int flags;
EINTRLOOP (flags, fcntl (fd, F_GETFL));
if (flags >= 0)
@ -132,26 +134,41 @@ set_blocking (int fd, int blocking)
if (r < 0)
pfatal_with_name ("fcntl(O_NONBLOCK)");
}
}
static void
set_blocking (int fd, int blocking)
{
/* If we're not using pselect() don't change the blocking. */
#ifdef HAVE_PSELECT
force_blocking (fd, blocking);
#else
(void) fd;
(void) blocking;
#endif
}
unsigned int
jobserver_setup (int slots, const char *style)
{
int r;
int r, k;
#if HAVE_MKFIFO
if (style == NULL || strcmp (style, "fifo") == 0)
/* This function sets up the root jobserver. */
job_root = 1;
#if JOBSERVER_USE_FIFO
if (!style || strcmp (style, "fifo") == 0)
{
/* Unfortunately glibc warns about uses of mktemp even though we aren't
using it in dangerous way here. So avoid this by generating our own
temporary file name. */
# define FNAME_PREFIX "GMfifo"
temporary file name. The template in misc.c uses 6 X's so be sure this
name cannot conflict with that. */
# define FNAME_PREFIX "GmFIFO"
const char *tmpdir = get_tmpdir ();
fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX)
+ INTSTR_LENGTH + 2);
sprintf (fifo_name, "%s/" FNAME_PREFIX "%" MK_PRI64_PREFIX "d",
sprintf (fifo_name, "%s/" FNAME_PREFIX "%03" MK_PRI64_PREFIX "d",
tmpdir, (long long)make_pid ());
EINTRLOOP (r, mkfifo (fifo_name, 0600));
@ -167,12 +184,12 @@ jobserver_setup (int slots, const char *style)
hang until the write side is open. */
EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY|O_NONBLOCK));
if (job_fds[0] < 0)
OSS (fatal, NILF, _("Cannot open jobserver %s: %s"),
OSS (fatal, NILF, _("cannot open jobserver %s: %s"),
fifo_name, strerror (errno));
EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));
if (job_fds[0] < 0)
OSS (fatal, NILF, _("Cannot open jobserver %s: %s"),
OSS (fatal, NILF, _("cannot open jobserver %s: %s"),
fifo_name, strerror (errno));
js_type = js_fifo;
@ -183,7 +200,7 @@ jobserver_setup (int slots, const char *style)
if (js_type == js_none)
{
if (style && strcmp (style, "pipe") != 0)
OS (fatal, NILF, _("Unknown jobserver auth style '%s'"), style);
OS (fatal, NILF, _("unknown jobserver auth style '%s'"), style);
EINTRLOOP (r, pipe (job_fds));
if (r < 0)
@ -200,18 +217,25 @@ jobserver_setup (int slots, const char *style)
if (make_job_rfd () < 0)
pfatal_with_name (_("duping jobs pipe"));
while (slots--)
/* Set the write side of the pipe to non blocking in case the number of
slots specified by the user exceeds pipe capacity. */
force_blocking (job_fds[1], 0);
for (k = 0; k < slots; ++k)
{
EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1)
pfatal_with_name (_("init jobserver pipe"));
{
if (errno != EAGAIN)
pfatal_with_name (_("init jobserver pipe"));
ONN (fatal, NILF, _("requested job count (%d) is larger than system limit (%d)"), slots+1, k);
}
}
force_blocking (job_fds[1], 1);
/* When using pselect() we want the read to be non-blocking. */
set_blocking (job_fds[0], 0);
job_root = 1;
return 1;
}
@ -229,14 +253,19 @@ jobserver_parse_auth (const char *auth)
EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY));
if (job_fds[0] < 0)
OSS (fatal, NILF,
_("Cannot open jobserver %s: %s"), fifo_name, strerror (errno));
{
OSS (error, NILF,
_("cannot open jobserver %s: %s"), fifo_name, strerror (errno));
return 0;
}
EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));
if (job_fds[0] < 0)
OSS (fatal, NILF,
_("Cannot open jobserver %s: %s"), fifo_name, strerror (errno));
if (job_fds[1] < 0)
{
OSS (error, NILF,
_("cannot open jobserver %s: %s"), fifo_name, strerror (errno));
return 0;
}
js_type = js_fifo;
}
/* If not, it must be a simple pipe. */
@ -545,7 +574,7 @@ set_child_handler_action_flags (int set_handler, int set_alarm)
{
struct sigaction sa;
#ifdef __EMX__
#if MK_OS_OS2
/* The child handler must be turned off here. */
signal (SIGCHLD, SIG_DFL);
#endif
@ -612,7 +641,7 @@ jobserver_acquire (int timeout)
go back and reap_children(), and try again. */
errno = saved_errno;
if (errno != EINTR && errno != EBADF)
if (errno != EINTR && errno != EBADF && errno != EAGAIN)
pfatal_with_name (_("read jobs pipe"));
if (errno == EBADF)
@ -673,6 +702,7 @@ osync_parse_mutex (const char *mutex)
return 0;
}
free (osync_tmpfile);
osync_tmpfile = xstrdup (mutex + CSTRLEN (MUTEX_PREFIX));
EINTRLOOP (osync_handle, open (osync_tmpfile, O_WRONLY));
@ -699,6 +729,7 @@ osync_clear ()
int r;
EINTRLOOP (r, unlink (osync_tmpfile));
free (osync_tmpfile);
osync_tmpfile = NULL;
}
}
@ -816,12 +847,12 @@ fd_noinherit (int fd)
/* Set a file descriptor referring to a regular file to be in O_APPEND mode.
If it fails, just ignore it. */
void
int
fd_set_append (int fd)
{
int flags = -1;
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
struct stat stbuf;
int flags;
if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode))
{
flags = fcntl (fd, F_GETFL, 0);
@ -831,6 +862,22 @@ fd_set_append (int fd)
EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND));
}
}
#endif
return flags;
}
/* Reset a file descriptor referring to a regular file to be in O_APPEND mode.
If it fails, just ignore it. */
void
fd_reset_append (int fd, int flags)
{
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
if (flags >= 0)
{
int r;
EINTRLOOP(r, fcntl (fd, F_SETFL, flags));
}
#endif
}
@ -838,28 +885,42 @@ fd_set_append (int fd)
int
os_anontmp ()
{
const char *tdir = get_tmpdir ();
int fd = -1;
#ifdef O_TMPFILE
EINTRLOOP (fd, open (get_tmpdir (), O_RDWR | O_TMPFILE | O_EXCL, 0600));
if (fd < 0)
pfatal_with_name ("open(O_TMPFILE)");
#elif HAVE_DUP
/* We don't have O_TMPFILE but we can dup: if we are creating temp files in
the default location then try tmpfile() + dup() + fclose() to avoid ever
having a name for a file. */
if (streq (get_tmpdir (), DEFAULT_TMPDIR))
static unsigned int tmpfile_works = 1;
if (tmpfile_works)
{
EINTRLOOP (fd, open (tdir, O_RDWR | O_TMPFILE | O_EXCL, 0600));
if (fd >= 0)
return fd;
DB (DB_BASIC, (_("Cannot open '%s' with O_TMPFILE: %s.\n"),
tdir, strerror (errno)));
tmpfile_works = 0;
}
#endif
#if HAVE_DUP
/* If we can dup and we are creating temp files in the default location then
try tmpfile() + dup() + fclose() to avoid ever having a named file. */
if (streq (tdir, DEFAULT_TMPDIR))
{
mode_t mask = umask (0077);
FILE *tfile;
ENULLLOOP (tfile, tmpfile ());
if (!tfile)
pfatal_with_name ("tmpfile");
{
OS (error, NILF, "tmpfile: %s", strerror (errno));
return -1;
}
umask (mask);
EINTRLOOP (fd, dup (fileno (tfile)));
if (fd < 0)
pfatal_with_name ("dup");
OS (error, NILF, "dup: %s", strerror (errno));
fclose (tfile);
}
#endif

View File

@ -1,5 +1,5 @@
/* Reading and parsing of makefiles for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -18,6 +18,15 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <assert.h>
#if MK_OS_W32
# include <windows.h>
# include "sub_proc.h"
#elif MK_OS_VMS
struct passwd *getpwnam (char *name);
#else
# include <pwd.h>
#endif
#include "filedef.h"
#include "dep.h"
#include "job.h"
@ -27,20 +36,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "rule.h"
#include "debug.h"
#include "hash.h"
#ifdef WINDOWS32
#include <windows.h>
#include "sub_proc.h"
#else /* !WINDOWS32 */
#ifndef _AMIGA
#ifndef VMS
#include <pwd.h>
#else
struct passwd *getpwnam (char *name);
#endif
#endif
#endif /* !WINDOWS32 */
#include "warning.h"
/* A 'struct ebuffer' controls the origin of the makefile we are currently
eval'ing.
@ -72,7 +68,7 @@ struct vmodifiers
enum make_word_type
{
w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon,
w_varassign, w_ampcolon, w_ampdcolon
w_ampcolon, w_ampdcolon
};
@ -100,9 +96,9 @@ static struct conditionals *conditionals = &toplevel_conditionals;
/* Default directories to search for include files in */
static const char *default_include_directories[] =
static const char *const default_include_directories[] =
{
#if defined(WINDOWS32) && !defined(INCLUDEDIR)
#if MK_OS_W32 && !defined(INCLUDEDIR)
/* This completely up to the user when they install MSVC or other packages.
This is defined as a placeholder. */
# define INCLUDEDIR "."
@ -110,12 +106,10 @@ static const char *default_include_directories[] =
#if defined(INCLUDEDIR)
INCLUDEDIR,
#endif
#ifndef _AMIGA
"/usr/gnu/include",
"/usr/local/include",
"/usr/include",
#endif
0
NULL
};
/* List of directories to search for include files in */
@ -192,15 +186,7 @@ read_all_makefiles (const char **makefiles)
char *name, *p;
size_t length;
{
/* Turn off --warn-undefined-variables while we expand MAKEFILES. */
int save = warn_undefined_variables_flag;
warn_undefined_variables_flag = 0;
value = allocated_variable_expand ("$(MAKEFILES)");
warn_undefined_variables_flag = save;
}
value = allocated_expand_variable (STRING_SIZE_TUPLE ("MAKEFILES"));
/* Set NAME to the start of next token and LENGTH to its length.
MAKEFILES is updated for finding remaining tokens. */
@ -236,23 +222,19 @@ read_all_makefiles (const char **makefiles)
if (num_makefiles == 0)
{
static const char *default_makefiles[] =
#ifdef VMS
static const char *const default_makefiles[] =
#if MK_OS_VMS
/* all lower case since readdir() (the vms version) 'lowercasifies' */
/* TODO: Above is not always true, this needs more work */
{ "makefile.vms", "gnumakefile", "makefile", 0 };
#else
#ifdef _AMIGA
{ "GNUmakefile", "Makefile", "SMakefile", 0 };
#else /* !Amiga && !VMS */
#ifdef WINDOWS32
#if MK_OS_W32
{ "GNUmakefile", "makefile", "Makefile", "makefile.mak", 0 };
#else /* !Amiga && !VMS && !WINDOWS32 */
#else /* !MK_OS_VMS && !MK_OS_W32 */
{ "GNUmakefile", "makefile", "Makefile", 0 };
#endif /* !Amiga && !VMS && !WINDOWS32 */
#endif /* AMIGA */
#endif /* VMS */
const char **p = default_makefiles;
#endif /* !MK_OS_VMS && !MK_OS_W32 */
#endif /* MK_OS_VMS */
const char *const *p = default_makefiles;
while (*p != 0 && !file_exists_p (*p))
++p;
@ -373,25 +355,29 @@ eval_makefile (const char *filename, unsigned short flags)
/* If the makefile wasn't found and it's either a makefile from the
'MAKEFILES' variable or an included makefile, search the included
makefile search path for this makefile. */
if (ebuf.fp == NULL && deps->error == ENOENT && (flags & RM_INCLUDED)
&& *filename != '/' && include_directories)
for (const char **dir = include_directories; *dir != NULL; ++dir)
{
const char *included = concat (3, *dir, "/", filename);
if (ebuf.fp == NULL && deps->error == ENOENT && include_directories
&& ANY_SET (flags, RM_INCLUDED)
&& !HAS_DRIVESPEC (filename) && !ISDIRSEP (*filename))
{
const char **dir;
for (dir = include_directories; *dir != NULL; ++dir)
{
const char *included = concat (3, *dir, "/", filename);
ENULLLOOP(ebuf.fp, fopen (included, "r"));
if (ebuf.fp)
{
filename = included;
break;
}
if (errno != ENOENT)
{
filename = included;
deps->error = errno;
break;
}
}
ENULLLOOP(ebuf.fp, fopen (included, "r"));
if (ebuf.fp)
{
filename = included;
break;
}
if (errno != ENOENT)
{
filename = included;
deps->error = errno;
break;
}
}
}
/* Enter the final name for this makefile as a goaldep. */
filename = strcache_add (filename);
@ -400,6 +386,7 @@ eval_makefile (const char *filename, unsigned short flags)
deps->file = enter_file (filename);
filename = deps->file->name;
deps->flags = flags;
deps->file->is_explicit = 1;
free (expanded);
@ -426,7 +413,7 @@ eval_makefile (const char *filename, unsigned short flags)
/* Add this makefile to the list. */
do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file,
f_append_value, 0);
f_append_value, 0, s_global);
/* Evaluate the makefile */
@ -634,6 +621,7 @@ eval (struct ebuffer *ebuf, int set_default)
size_t wlen;
char *p;
char *p2;
unsigned int is_rule;
struct vmodifiers vmod;
/* At the top of this loop, we are starting a brand new line. */
@ -678,16 +666,16 @@ eval (struct ebuffer *ebuf, int set_default)
/* Ignore the commands in a rule with no targets. */
continue;
if (ignoring)
/* Yep, this is a shell command, and we don't care. */
continue;
/* If there is no preceding rule line, don't treat this line
as a command, even though it begins with a recipe prefix.
SunOS 4 make appears to behave this way. */
if (filenames != 0)
{
if (ignoring)
/* Yep, this is a shell command, and we don't care. */
continue;
if (commands_idx == 0)
cmds_started = ebuf->floc.lineno;
@ -745,14 +733,14 @@ eval (struct ebuffer *ebuf, int set_default)
record_waiting_files ();
if (vmod.undefine_v)
{
do_undefine (p, origin, ebuf);
continue;
}
else if (vmod.define_v)
{
do_undefine (p, origin, ebuf);
continue;
}
if (vmod.define_v)
v = do_define (p, origin, ebuf);
else
v = try_variable_definition (fstart, p, origin, 0);
v = try_variable_definition (fstart, p, origin, s_global);
assert (v != NULL);
@ -773,6 +761,8 @@ eval (struct ebuffer *ebuf, int set_default)
wlen = p2 - p;
NEXT_TOKEN (p2);
is_rule = *p2 == ':' || ((*p2 == '&' || *p2 == '|') && p2[1] == ':');
/* If we're in an ignored define, skip this line (but maybe get out). */
if (in_ignored_define)
{
@ -820,7 +810,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Expand the line so we can use indirect and constructed
variable names in an (un)export command. */
cp = ap = allocated_variable_expand (p2);
cp = ap = allocated_expand_string (p2);
for (p = find_next_token (&cp, &l); p != 0;
p = find_next_token (&cp, &l))
@ -846,7 +836,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* vpath ends the previous rule. */
record_waiting_files ();
cp = variable_expand (p2);
cp = expand_string (p2);
p = find_next_token (&cp, &l);
if (p != 0)
{
@ -879,7 +869,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Include ends the previous rule. */
record_waiting_files ();
p = allocated_variable_expand (p2);
p = allocated_expand_string (p2);
/* If no filenames, it's a no-op. */
if (*p == '\0')
@ -923,8 +913,8 @@ eval (struct ebuffer *ebuf, int set_default)
continue;
}
/* Handle the load operations. */
if (word1eq ("load") || word1eq ("-load"))
/* Handle the load operations. Allow targets named "load". */
if ((word1eq ("load") || word1eq ("-load")) && !is_rule)
{
/* A 'load' line specifies a dynamic object to load. */
struct nameseq *files;
@ -933,7 +923,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Load ends the previous rule. */
record_waiting_files ();
p = allocated_variable_expand (p2);
p = allocated_expand_string (p2);
/* If no filenames, it's a no-op. */
if (*p == '\0')
@ -1065,7 +1055,7 @@ eval (struct ebuffer *ebuf, int set_default)
break;
}
p2 = variable_expand_string (NULL, lb_next, wlen);
p2 = expand_string_buf (NULL, lb_next, wlen);
while (1)
{
@ -1093,7 +1083,7 @@ eval (struct ebuffer *ebuf, int set_default)
entirely consistent, since we do an unconditional
expand below once we know we don't have a
target-specific variable. */
variable_expand_string (pend, lb_next, SIZE_MAX);
expand_string_buf (pend, lb_next, SIZE_MAX);
lb_next += strlen (lb_next);
p2 = variable_buffer + p2_off;
cmdleft = variable_buffer + cmd_off + 1;
@ -1129,7 +1119,7 @@ eval (struct ebuffer *ebuf, int set_default)
p2 += strlen (p2);
*(p2++) = ' ';
p2 = variable_expand_string (p2, lb_next, wlen);
p2 = expand_string_buf (p2, lb_next, wlen);
/* We don't need to worry about cmdleft here, because if it was
found in the variable_buffer the entire buffer has already
been expanded... we'll never get here. */
@ -1137,20 +1127,29 @@ eval (struct ebuffer *ebuf, int set_default)
p2 = next_token (variable_buffer);
/* If the word we're looking at is EOL, see if there's _anything_
on the line. If not, a variable expanded to nothing, so ignore
it. If so, we can't parse this line so punt. */
/* If we're at EOL we didn't find a separator so we don't know what
kind of line this is. */
if (wtype == w_eol)
{
/* Ignore an empty line. */
if (*p2 == '\0')
continue;
/* There's no need to be ivory-tower about this: check for
one of the most common bugs found in makefiles... */
/* Check for spaces instead of TAB. */
if (cmd_prefix == '\t' && strneq (line, " ", 8))
O (fatal, fstart, _("missing separator (did you mean TAB instead of 8 spaces?)"));
else
O (fatal, fstart, _("missing separator"));
/* Check for conditionals without whitespace afterward.
We don't check ifdef/ifndef because there's no real way to miss
whitespace there. */
p2 = next_token (line);
if (strneq (p2, "if", 2) &&
((strneq (&p2[2], "neq", 3) && !STOP_SET (p2[5], MAP_BLANK))
|| (strneq (&p2[2], "eq", 2) && !STOP_SET (p2[4], MAP_BLANK))))
O (fatal, fstart, _("missing separator (ifeq/ifneq must be followed by whitespace)"));
/* No idea... */
O (fatal, fstart, _("missing separator"));
}
{
@ -1232,7 +1231,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (*lb_next != '\0')
{
size_t l = p2 - variable_buffer;
variable_expand_string (p2 + plen, lb_next, SIZE_MAX);
expand_string_buf (p2 + plen, lb_next, SIZE_MAX);
p2 = variable_buffer + l;
/* Look for a semicolon in the expanded line. */
@ -1257,22 +1256,6 @@ eval (struct ebuffer *ebuf, int set_default)
else
break;
}
#ifdef _AMIGA
/* Here, the situation is quite complicated. Let's have a look
at a couple of targets:
install: dev:make
dev:make: make
dev:make:: xyz
The rule is that it's only a target, if there are TWO :'s
OR a space around the :.
*/
if (p && !(ISSPACE (p[1]) || !p[1] || ISSPACE (p[-1])))
p = 0;
#endif
#ifdef HAVE_DOS_PATHS
{
int check_again;
@ -1379,7 +1362,7 @@ do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)
char *p, *var;
/* Expand the variable name and find the beginning (NAME) and end. */
var = allocated_variable_expand (name);
var = allocated_expand_string (name);
name = next_token (var);
if (*name == '\0')
O (fatal, &ebuf->floc, _("empty variable name"));
@ -1388,7 +1371,7 @@ do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)
--p;
p[1] = '\0';
undefine_variable_global (name, p - name + 1, origin);
undefine_variable_global (&ebuf->floc, name, p - name + 1, origin);
free (var);
}
@ -1412,8 +1395,11 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
p = parse_variable_definition (name, &var);
if (p == NULL)
/* No assignment token, so assume recursive. */
var.flavor = f_recursive;
{
/* No assignment token, so assume recursive. */
var.flavor = f_recursive;
var.conditional = 0;
}
else
{
if (var.value[0] != '\0')
@ -1424,7 +1410,7 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
}
/* Expand the variable name and find the beginning (NAME) and end. */
n = allocated_variable_expand (name);
n = allocated_expand_string (name);
name = next_token (n);
if (name[0] == '\0')
O (fatal, &defstart, _("empty variable name"));
@ -1497,8 +1483,8 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
else
definition[idx - 1] = '\0';
v = do_variable_definition (&defstart, name,
definition, origin, var.flavor, 0);
v = do_variable_definition (&defstart, name, definition, origin, var.flavor,
var.conditional, s_global);
free (definition);
free (n);
return (v);
@ -1657,7 +1643,7 @@ conditional_line (char *line, size_t len, const floc *flocp)
/* Expand the thing we're looking up, so we can use indirect and
constructed variable names. */
var = allocated_variable_expand (line);
var = allocated_expand_string (line);
/* Make sure there's only one variable name to test. */
p = end_of_token (var);
@ -1686,19 +1672,10 @@ conditional_line (char *line, size_t len, const floc *flocp)
s1 = ++line;
/* Find the end of the first string. */
if (termin == ',')
{
int count = 0;
for (; *line != '\0'; ++line)
if (*line == '(')
++count;
else if (*line == ')')
--count;
else if (*line == ',' && count <= 0)
break;
}
else
while (*line != '\0' && *line != termin)
while (*line != '\0' && *line != termin)
if (*line == '$')
line = skip_reference (line+1);
else
++line;
if (*line == '\0')
@ -1706,7 +1683,7 @@ conditional_line (char *line, size_t len, const floc *flocp)
if (termin == ',')
{
/* Strip blanks after the first string. */
/* Strip blanks before the comma. */
char *p = line++;
while (ISBLANK (p[-1]))
--p;
@ -1715,9 +1692,9 @@ conditional_line (char *line, size_t len, const floc *flocp)
else
*line++ = '\0';
s2 = variable_expand (s1);
s2 = expand_string (s1);
/* We must allocate a new copy of the expanded string because
variable_expand re-uses the same buffer. */
expand_string re-uses the same buffer. */
l = strlen (s2);
s1 = alloca (l + 1);
memcpy (s1, s2, l + 1);
@ -1764,7 +1741,7 @@ conditional_line (char *line, size_t len, const floc *flocp)
if (*line != '\0')
EXTRATEXT ();
s2 = variable_expand (s2);
s2 = expand_string (s2);
conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));
}
@ -1824,7 +1801,7 @@ record_target_var (struct nameseq *filenames, char *defn,
v->origin = origin;
if (v->flavor == f_simple)
v->value = allocated_variable_expand (v->value);
v->value = allocated_expand_string (v->value);
else
v->value = xstrdup (v->value);
}
@ -1845,9 +1822,9 @@ record_target_var (struct nameseq *filenames, char *defn,
initialize_file_variables (f, 1);
current_variable_set_list = f->variables;
v = try_variable_definition (flocp, defn, origin, 1);
v = try_variable_definition (flocp, defn, origin, s_target);
if (!v)
O (fatal, flocp, _("Malformed target-specific variable definition"));
O (fatal, flocp, _("malformed target-specific variable definition"));
current_variable_set_list = global;
}
@ -1915,7 +1892,7 @@ check_specials (struct nameseq *files, int set_default)
continue;
}
#if !defined (__MSDOS__) && !defined (__EMX__)
#if !MK_OS_DOS && !MK_OS_OS2
if (!one_shell && streq (nm, ".ONESHELL"))
{
one_shell = 1;
@ -2133,7 +2110,6 @@ record_files (struct nameseq *filenames, int are_also_makes,
return;
}
/* Walk through each target and create it in the database.
We already set up the first target, above. */
while (1)
@ -2200,11 +2176,6 @@ record_files (struct nameseq *filenames, int are_also_makes,
free_dep_chain (f->deps);
f->deps = 0;
}
/* This file is explicitly mentioned as a target. There is no need
to set is_explicit in the case of double colon below, because an
implicit double colon rule only applies when the prerequisite
exists. A prerequisite which exists is not intermediate anyway. */
f->is_explicit = 1;
}
else
{
@ -2229,6 +2200,8 @@ record_files (struct nameseq *filenames, int are_also_makes,
f->cmds = cmds;
}
/* This file is explicitly mentioned as a target. */
f->is_explicit = 1;
if (are_also_makes)
{
@ -2306,15 +2279,14 @@ record_files (struct nameseq *filenames, int are_also_makes,
}
/* If there are also-makes, then populate a copy of the also-make list into
each one. For the last file, we take our original also_make list instead
wastefully copying it one more time and freeing it. */
each one. Omit the file from its also-make list. */
{
struct dep *i;
for (i = also_make; i != NULL; i = i->next)
{
struct file *f = i->file;
struct dep *cpy = i->next ? copy_dep_chain (also_make) : also_make;
struct dep *dp;
if (f->also_make)
{
@ -2322,11 +2294,20 @@ record_files (struct nameseq *filenames, int are_also_makes,
_("warning: overriding group membership for target '%s'"),
f->name);
free_dep_chain (f->also_make);
f->also_make = NULL;
}
f->also_make = cpy;
for (dp = also_make; dp != NULL; dp = dp->next)
if (dp->file != f)
{
struct dep *cpy = copy_dep (dp);
cpy->next = f->also_make;
f->also_make = cpy;
}
}
}
free_dep_chain (also_make);
}
}
/* Search STRING for an unquoted STOPMAP.
@ -2358,35 +2339,7 @@ find_map_unquote (char *string, int stopmap)
/* If we stopped due to a variable reference, skip over its contents. */
if (*p == '$')
{
char openparen = p[1];
/* Check if '$' is the last character in the string. */
if (openparen == '\0')
break;
p += 2;
/* Skip the contents of a non-quoted, multi-char variable ref. */
if (openparen == '(' || openparen == '{')
{
unsigned int pcount = 1;
char closeparen = (openparen == '(' ? ')' : '}');
while (*p)
{
if (*p == openparen)
++pcount;
else if (*p == closeparen)
if (--pcount == 0)
{
++p;
break;
}
++p;
}
}
/* Skipped the variable reference: look for STOPCHARS again. */
p = skip_reference (p+1);
continue;
}
@ -2693,7 +2646,7 @@ readline (struct ebuffer *ebuf)
/* We got a newline, so add one to the count of lines. */
++nlines;
#if !defined(WINDOWS32) && !defined(__MSDOS__) && !defined(__EMX__)
#if !MK_OS_W32 && !MK_OS_DOS && !MK_OS_OS2
/* Check to see if the line was really ended with CRLF; if so ignore
the CR. */
if ((p - start) > 1 && p[-2] == '\r')
@ -2747,7 +2700,8 @@ readline (struct ebuffer *ebuf)
}
/* Parse the next "makefile word" from the input buffer, and return info
about it.
about it. This function won't be called in any context where we might need
to parse a variable assignment so we don't need to check that.
A "makefile word" is one of:
@ -2760,11 +2714,10 @@ readline (struct ebuffer *ebuf)
w_ampcolon An ampersand-colon (&:) token
w_ampdcolon An ampersand-double-colon (&::) token
w_semicolon A semicolon
w_varassign A variable assignment operator (=, :=, ::=, +=, ?=, or !=)
Note that this function is only used when reading certain parts of the
makefile. Don't use it where special rules hold sway (RHS of a variable,
in a command list, etc.) */
in a recipe, etc.) */
static enum make_word_type
get_next_mword (char *buffer, char **startp, size_t *length)
@ -2791,29 +2744,13 @@ get_next_mword (char *buffer, char **startp, size_t *length)
wtype = w_semicolon;
goto done;
case '=':
wtype = w_varassign;
goto done;
case ':':
if (*p == '=')
wtype = w_colon;
if (*p == ':')
{
++p;
wtype = w_varassign; /* := */
wtype = w_dcolon;
}
else if (*p == ':')
{
++p;
if (p[1] == '=')
{
++p;
wtype = w_varassign; /* ::= */
}
else
wtype = w_dcolon;
}
else
wtype = w_colon;
goto done;
case '&':
@ -2831,43 +2768,26 @@ get_next_mword (char *buffer, char **startp, size_t *length)
}
break;
case '+':
case '?':
case '!':
if (*p == '=')
{
++p;
wtype = w_varassign; /* += or ?= or != */
goto done;
}
break;
default:
break;
}
/* This is some non-operator word. A word consists of the longest
string of characters that doesn't contain whitespace, one of [:=#],
or [?+!]=, or &:. */
/* This is some non-operator word. A word consists of the longest string of
characters that doesn't contain whitespace, one of [:#], or &:. */
/* We start out assuming a static word; if we see a variable we'll
adjust our assumptions then. */
wtype = w_static;
/* We already found the first value of "c", above. */
while (1)
{
char closeparen;
int count;
/* Each time through the loop, "c" has the current character
and "p" points to the next character. */
if (END_OF_TOKEN (c))
goto done_word;
switch (c)
{
case '=':
goto done_word;
case ':':
#ifdef HAVE_DOS_PATHS
/* A word CAN include a colon in its drive spec. The drive
@ -2886,34 +2806,9 @@ get_next_mword (char *buffer, char **startp, size_t *length)
if (c == '\0')
goto done_word;
/* This is a variable reference, so note that it's expandable.
Then read it to the matching close paren. */
/* This is a variable reference: note that then skip it. */
wtype = w_variable;
if (c == '(')
closeparen = ')';
else if (c == '{')
closeparen = '}';
else
/* This is a single-letter variable reference. */
break;
for (count=0; *p != '\0'; ++p)
{
if (*p == c)
++count;
else if (*p == closeparen && --count < 0)
{
++p;
break;
}
}
break;
case '?':
case '+':
if (*p == '=')
goto done_word;
p = skip_reference (p-1);
break;
case '\\':
@ -2947,6 +2842,7 @@ get_next_mword (char *buffer, char **startp, size_t *length)
*startp = beg;
if (length)
*length = p - beg;
return wtype;
}
@ -2967,12 +2863,12 @@ construct_include_path (const char **arg_dirs)
int disable = 0;
/* Compute the number of pointers we need in the table. */
idx = sizeof (default_include_directories) / sizeof (const char *);
idx = ARRAYLEN (default_include_directories);
if (arg_dirs)
for (cpp = arg_dirs; *cpp != 0; ++cpp)
++idx;
#ifdef __MSDOS__
#if MK_OS_DOS
/* Add one for $DJDIR. */
++idx;
#endif
@ -3026,7 +2922,8 @@ construct_include_path (const char **arg_dirs)
/* Now add the standard default dirs at the end. */
if (!disable)
{
#ifdef __MSDOS__
const char *const *ccpp;
#if MK_OS_DOS
/* The environment variable $DJDIR holds the root of the DJGPP directory
tree; add ${DJDIR}/include. */
struct variable *djdir = lookup_variable ("DJDIR", 5);
@ -3043,20 +2940,20 @@ construct_include_path (const char **arg_dirs)
max_incl_len = len;
}
#endif
for (cpp = default_include_directories; *cpp != 0; ++cpp)
for (ccpp = default_include_directories; *ccpp != 0; ++ccpp)
{
int e;
EINTRLOOP (e, stat (*cpp, &stbuf));
EINTRLOOP (e, stat (*ccpp, &stbuf));
if (e == 0 && S_ISDIR (stbuf.st_mode))
{
size_t len = strlen (*cpp);
size_t len = strlen (*ccpp);
/* If dir name is written with trailing slashes, discard them. */
while (len > 1 && (*cpp)[len - 1] == '/')
while (len > 1 && (*ccpp)[len - 1] == '/')
--len;
if (len > max_incl_len)
max_incl_len = len;
dirs[idx++] = strcache_add_len (*cpp, len);
dirs[idx++] = strcache_add_len (*ccpp, len);
}
}
}
@ -3065,10 +2962,11 @@ construct_include_path (const char **arg_dirs)
/* Now add each dir to the .INCLUDE_DIRS variable. */
do_variable_definition (NILF, ".INCLUDE_DIRS", "", o_default, f_simple, 0);
do_variable_definition (NILF, ".INCLUDE_DIRS", "", o_default, f_simple, 0,
s_global);
for (cpp = dirs; *cpp != 0; ++cpp)
do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp,
o_default, f_append, 0);
do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp, o_default, f_append,
0, s_global);
free ((void *) include_directories);
include_directories = dirs;
@ -3080,20 +2978,20 @@ construct_include_path (const char **arg_dirs)
char *
tilde_expand (const char *name)
{
#if !defined(VMS)
#if !MK_OS_VMS
if (name[1] == '/' || name[1] == '\0')
{
char *home_dir;
int is_variable;
{
/* Turn off --warn-undefined-variables while we expand HOME. */
int save = warn_undefined_variables_flag;
warn_undefined_variables_flag = 0;
/* Turn off undefined variables warning while we expand HOME. */
enum warning_action save = warn_get (wt_undefined_var);
warn_set (wt_undefined_var, w_ignore);
home_dir = allocated_variable_expand ("$(HOME)");
home_dir = allocated_expand_variable (STRING_SIZE_TUPLE ("HOME"));
warn_undefined_variables_flag = save;
warn_set (wt_undefined_var, save);
}
is_variable = home_dir[0] != '\0';
@ -3102,7 +3000,7 @@ tilde_expand (const char *name)
free (home_dir);
home_dir = getenv ("HOME");
}
# if !defined(_AMIGA) && !defined(WINDOWS32)
# if !MK_OS_W32
if (home_dir == 0 || home_dir[0] == '\0')
{
char *logname = getlogin ();
@ -3114,7 +3012,7 @@ tilde_expand (const char *name)
home_dir = p->pw_dir;
}
}
# endif /* !AMIGA && !WINDOWS32 */
# endif /* !MK_OS_W32 */
if (home_dir != 0)
{
char *new = xstrdup (concat (2, home_dir, name + 1));
@ -3123,7 +3021,7 @@ tilde_expand (const char *name)
return new;
}
}
# if !defined(_AMIGA) && !defined(WINDOWS32)
# if !MK_OS_W32
else
{
struct passwd *pwent;
@ -3142,8 +3040,8 @@ tilde_expand (const char *name)
else if (userend != 0)
*userend = '/';
}
# endif /* !AMIGA && !WINDOWS32 */
#endif /* !VMS */
# endif /* !MK_OS_W32 */
#endif /* !MK_OS_VMS */
return 0;
}
@ -3254,16 +3152,11 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
s = p;
p = find_map_unquote (p, findmap);
#ifdef VMS
#if MK_OS_VMS
/* convert comma separated list to space separated */
if (p && *p == ',')
*p =' ';
#endif
#ifdef _AMIGA
/* If we stopped due to a device name, skip it. */
if (p && p != s+1 && p[0] == ':')
p = find_map_unquote (p+1, findmap);
#endif
#ifdef HAVE_DOS_PATHS
/* If we stopped due to a drive specifier, skip it.
Tokens separated by spaces are treated as separate paths since make
@ -3286,22 +3179,24 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
/* Strip leading "this directory" references. */
if (NONE_SET (flags, PARSEFS_NOSTRIP))
#ifdef VMS
/* Skip leading '[]'s. should only be one set or bug somewhere else */
if (p - s > 2 && s[0] == '[' && s[1] == ']')
{
#if MK_OS_VMS
/* Skip leading '[]'s. should only be one set or bug somewhere else */
if (p - s > 2 && s[0] == '[' && s[1] == ']')
s += 2;
/* Skip leading '<>'s. should only be one set or bug somewhere else */
if (p - s > 2 && s[0] == '<' && s[1] == '>')
/* Skip leading '<>'s. should only be one set or bug somewhere else */
if (p - s > 2 && s[0] == '<' && s[1] == '>')
s += 2;
#endif
/* Skip leading './'s. */
while (p - s > 2 && s[0] == '.' && s[1] == '/')
{
/* Skip "./" and all following slashes. */
s += 2;
while (*s == '/')
++s;
}
/* Skip leading './'s. */
while (p - s > 2 && s[0] == '.' && s[1] == '/')
{
/* Skip "./" and all following slashes. */
s += 2;
while (*s == '/')
++s;
}
}
/* Extract the filename just found, and skip it.
Set NAME to the string, and NLEN to its length. */
@ -3309,20 +3204,14 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
if (s == p)
{
/* The name was stripped to empty ("./"). */
#if defined(_AMIGA)
/* PDS-- This cannot be right!! */
tp[0] = '\0';
nlen = 0;
#else
tp[0] = '.';
tp[1] = '/';
tp[2] = '\0';
nlen = 2;
#endif
}
else
{
#ifdef VMS
#if MK_OS_VMS
/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
* to remove this '\' before we can use the filename.
* xstrdup called because S may be read-only string constant.

View File

@ -1,5 +1,5 @@
/* Basic dependency engine for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -20,6 +20,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "commands.h"
#include "dep.h"
#include "variable.h"
#include "warning.h"
#include "debug.h"
#include <assert.h>
@ -30,14 +31,15 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <sys/file.h>
#endif
#ifdef VMS
#if MK_OS_VMS
#include <starlet.h>
#endif
#ifdef WINDOWS32
#if MK_OS_W32
#include <windows.h>
#include <io.h>
#include <sys/stat.h>
#if defined(_MSC_VER) && _MSC_VER > 1200
/* VC7 or later supprots _stat64 to access 64-bit file size. */
/* VC7 or later supports _stat64 to access 64-bit file size. */
#define STAT _stat64
#else
#define STAT stat
@ -68,6 +70,13 @@ static struct dep *goal_dep;
All files start with considered == 0. */
static unsigned int considered = 0;
/* During processing we might drop some dependencies, which can't be freed
immediately because they are still in use. Remember them: this is mainly
to satisfy leak detectors. */
static struct dep **dropped_list = NULL;
static size_t dropped_list_len = 0;
#define DROPPED_LIST_INCR 5
static enum update_status update_file (struct file *file, unsigned int depth);
static enum update_status update_file_1 (struct file *file, unsigned int depth);
static enum update_status check_dep (struct file *file, unsigned int depth,
@ -81,19 +90,20 @@ static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr);
static void
check_also_make (const struct file *file)
{
/* If the target was created by an implicit rule, and it exists and was
updated, warn about any of its also_make targets that don't exist. */
if (file->tried_implicit && is_ordinary_mtime (file->last_mtime)
&& file->last_mtime > file->mtime_before_update)
{
struct dep *ad;
struct dep *ad;
FILE_TIMESTAMP mtime = file->last_mtime;
for (ad = file->also_make; ad; ad = ad->next)
if (ad->file->last_mtime == NONEXISTENT_MTIME)
OS (error, file->cmds ? &file->cmds->fileinfo : NILF,
_("warning: pattern recipe did not update peer target '%s'."),
ad->file->name);
}
if (mtime == UNKNOWN_MTIME)
mtime = name_mtime (file->name);
/* If we updated the file, check its also-make files. */
if (is_ordinary_mtime (mtime) && mtime > file->mtime_before_update)
for (ad = file->also_make; ad; ad = ad->next)
if (ad->file->last_mtime == NONEXISTENT_MTIME)
OS (error, file->cmds ? &file->cmds->fileinfo : NILF,
_("warning: pattern recipe did not update peer target '%s'"),
ad->file->name);
}
/* Remake all the goals in the 'struct dep' chain GOALS. Return update_status
@ -107,8 +117,10 @@ check_also_make (const struct file *file)
enum update_status
update_goal_chain (struct goaldep *goaldeps)
{
unsigned long last_cmd_count = 0;
int t = touch_flag, q = question_flag, n = just_print_flag;
enum update_status status = us_none;
const unsigned int depth = rebuilding_makefiles ? 1 : 0;
/* Duplicate the chain so we can remove things from it. */
struct dep *goals_orig = copy_dep_chain ((struct dep *)goaldeps);
@ -127,30 +139,32 @@ update_goal_chain (struct goaldep *goaldeps)
while (goals != 0)
{
struct dep *gu, *g, *lastgoal;
int running = 0, wait = 0;
/* Start jobs that are waiting for the load to go down. */
start_waiting_jobs ();
/* Wait for a child to die. */
/* Check for exited children. If no children have finished since the
last time we looked, then block until one exits. If some have
exited don't block, so we can possibly do more work. */
reap_children (1, 0);
reap_children (last_cmd_count == command_count, 0);
last_cmd_count = command_count;
lastgoal = 0;
gu = goals;
while (gu != 0)
{
/* Iterate over all double-colon entries for this file. */
struct file *file;
int stop = 0, any_not_updated = 0;
struct file *file, *dchead;
int stop = 0, all_updated = 1;
g = gu->shuf ? gu->shuf : gu;
goal_dep = g;
for (file = g->file->double_colon ? g->file->double_colon : g->file;
file != NULL;
file = file->prev)
dchead = g->file->double_colon ? g->file->double_colon : g->file;
for (file = dchead; file != NULL; file = file->prev)
{
unsigned int ocommands_started;
enum update_status fail;
@ -175,8 +189,24 @@ update_goal_chain (struct goaldep *goaldeps)
actually run. */
ocommands_started = commands_started;
fail = update_file (file, rebuilding_makefiles ? 1 : 0);
stop = 0;
/* In the case of double colon rules, only the recipe of the 1st
rule should be blocked by .WAIT. The recipes of all subsequent
rules for the same file will execute sequentially in order
after the 1st. */
wait = file == dchead && g->wait_here && running;
if (wait)
{
DBF (DB_VERBOSE, _(".WAIT is blocking '%s'.\n"));
break;
}
fail = update_file (file, depth);
check_renamed (file);
running |= (file->command_state == cs_running
|| file->command_state == cs_deps_running);
/* Set the goal's 'changed' flag if any commands were started
by calling update_file above. We check this flag below to
@ -184,7 +214,6 @@ update_goal_chain (struct goaldep *goaldeps)
if (commands_started > ocommands_started)
g->changed = 1;
stop = 0;
if ((fail || file->updated) && status < us_question)
{
/* We updated this goal. Update STATUS and decide whether
@ -205,8 +234,6 @@ update_goal_chain (struct goaldep *goaldeps)
FILE_TIMESTAMP mtime = MTIME (file);
check_renamed (file);
check_also_make (file);
if (file->updated && mtime != file->mtime_before_update)
{
/* Updating was done. If this is a makefile and
@ -227,7 +254,7 @@ update_goal_chain (struct goaldep *goaldeps)
/* Keep track if any double-colon entry is not finished.
When they are all finished, the goal is finished. */
any_not_updated |= !file->updated;
all_updated &= file->updated;
file->dontcare = 0;
@ -238,7 +265,10 @@ update_goal_chain (struct goaldep *goaldeps)
/* Reset FILE since it is null at the end of the loop. */
file = g->file;
if (stop || !any_not_updated)
if (wait)
break;
if (stop || all_updated)
{
/* If we have found nothing whatever to do for the goal,
print a message saying nothing needs doing. */
@ -261,21 +291,19 @@ update_goal_chain (struct goaldep *goaldeps)
else
lastgoal->next = gu->next;
gu = lastgoal == 0 ? goals : lastgoal->next;
if (stop)
break;
}
else
{
lastgoal = gu;
gu = gu->next;
}
lastgoal = gu;
gu = gu->next;
}
/* If we reached the end of the dependency graph update CONSIDERED
for the next pass. */
if (gu == 0)
for the next pass. In the case of waiting, increment CONSIDERED to
prevent the same file from getting pruned over and over again. */
if (gu == 0 || wait)
++considered;
}
@ -343,9 +371,15 @@ update_file (struct file *file, unsigned int depth)
{
/* Check for the case where a target has been tried and failed but
the diagnostics haven't been issued. If we need the diagnostics
then we will have to continue. */
then we will have to continue.
In the case of double colon rules, this file cannot be pruned if
this recipe finished (file->command_state == cs_finished) and there
are more double colon rules for this file. Instead the recipe of the
next double colon rule of this file should be run. */
if (!(f->updated && f->update_status > us_none
&& !f->dontcare && f->no_diag))
&& !f->dontcare && f->no_diag)
&& !(file->double_colon && file->command_state == cs_finished &&
f->prev))
{
DBF (DB_VERBOSE, _("Pruning file '%s'.\n"));
return f->command_state == cs_finished ? f->update_status : us_success;
@ -373,7 +407,8 @@ update_file (struct file *file, unsigned int depth)
if (f->command_state == cs_running
|| f->command_state == cs_deps_running)
/* Don't run other :: rules for this target until
this rule is finished. */
this rule is finished. Multiple recipes running in parallel and
updating the same target will corrupt the target. */
return us_success;
if (new > status)
@ -491,8 +526,6 @@ update_file_1 (struct file *file, unsigned int depth)
fail. */
file->no_diag = file->dontcare;
++depth;
/* Notice recursive update of the same file. */
start_updating (file);
@ -500,6 +533,9 @@ update_file_1 (struct file *file, unsigned int depth)
remember this one to turn off updating. */
ofile = file;
/* Increase the depth for reporting how we build the file. */
++depth;
/* Looking at the file's modtime beforehand allows the possibility
that its name may be changed by a VPATH search, and thus it may
not need an implicit rule. If this were not done, the file
@ -510,14 +546,19 @@ update_file_1 (struct file *file, unsigned int depth)
check_renamed (file);
noexist = this_mtime == NONEXISTENT_MTIME;
if (noexist)
DBF (DB_BASIC, _("File '%s' does not exist.\n"));
{
if (file->phony)
DBF (DB_BASIC, _("Target '%s' is phony.\n"));
else
DBF (DB_BASIC, _("File '%s' does not exist.\n"));
}
else if (is_ordinary_mtime (this_mtime) && file->low_resolution_time)
{
/* Avoid spurious rebuilds due to low resolution time stamps. */
int ns = FILE_TIMESTAMP_NS (this_mtime);
if (ns != 0)
OS (error, NILF,
_("*** Warning: .LOW_RESOLUTION_TIME file '%s' has a high resolution time stamp"),
_("*** warning: .LOW_RESOLUTION_TIME file '%s' has a high resolution time stamp"),
file->name);
this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;
}
@ -534,9 +575,14 @@ update_file_1 (struct file *file, unsigned int depth)
if (noexist)
{
check_renamed (adfile);
DBS (DB_BASIC,
(_("Grouped target peer '%s' of file '%s' does not exist.\n"),
adfile->name, file->name));
if (adfile->phony)
DBS (DB_BASIC,
(_("Grouped target peer '%s' of file '%s' is phony.\n"),
adfile->name, file->name));
else
DBS (DB_BASIC,
(_("Grouped target peer '%s' of file '%s' does not exist.\n"),
adfile->name, file->name));
}
else if (fmtime < this_mtime)
this_mtime = fmtime;
@ -600,18 +646,30 @@ update_file_1 (struct file *file, unsigned int depth)
if (is_updating (d->file))
{
OSS (error, NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
/* Avoid macro warning, bacause its output differs from that of
older makes. */
if (warn_error (wt_circular_dep))
OSS (fatal, NILF, _("circular %s <- %s dependency detected"),
file->name, d->file->name);
if (warn_check (wt_circular_dep))
OSS (error, NILF, _("circular %s <- %s dependency 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
check_dep below. */
if (lastd == 0)
file->deps = du->next;
else
lastd->next = du->next;
du = du->next;
/* We cannot free D here because our the caller will still have
a reference to it when we were called recursively via
check_dep below. */
if (dropped_list_len % DROPPED_LIST_INCR == 0)
dropped_list = xrealloc (dropped_list,
sizeof (struct dep *) * (dropped_list_len + DROPPED_LIST_INCR));
dropped_list[dropped_list_len++] = d;
continue;
}
@ -734,16 +792,18 @@ update_file_1 (struct file *file, unsigned int depth)
finish_updating (file);
finish_updating (ofile);
DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n"));
/* We've decided what we need to do to build the file. */
--depth;
if (running)
{
set_command_state (file, cs_deps_running);
--depth;
DBF (DB_VERBOSE, _("The prerequisites of '%s' are being made.\n"));
return us_success;
}
DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n"));
/* If any dependency failed, give up now. */
if (dep_status)
@ -752,8 +812,6 @@ update_file_1 (struct file *file, unsigned int depth)
file->update_status = dep_status == us_none ? us_failed : dep_status;
notice_finished_file (file);
--depth;
DBF (DB_VERBOSE, _("Giving up on target file '%s'.\n"));
if (depth == 0 && keep_going_flag
@ -816,7 +874,12 @@ update_file_1 (struct file *file, unsigned int depth)
else if (d_mtime == NONEXISTENT_MTIME)
{
if (ISDB (DB_BASIC))
fmt = _("Prerequisite '%s' of target '%s' does not exist.\n");
{
if (d->file->phony)
fmt = _("Prerequisite '%s' of target '%s' is phony.\n");
else
fmt = _("Prerequisite '%s' of target '%s' does not exist.\n");
}
}
else if (d->changed)
{
@ -828,16 +891,13 @@ update_file_1 (struct file *file, unsigned int depth)
if (fmt)
{
print_spaces (depth);
print_spaces (depth+1);
printf (fmt, dep_name (d), file->name);
fflush (stdout);
}
}
}
/* Here depth returns to the value it had when we were called. */
depth--;
if (file->double_colon && file->deps == 0)
{
must_make = 1;
@ -871,7 +931,8 @@ update_file_1 (struct file *file, unsigned int depth)
/* Since make has not created this file, make should not remove it,
even if the file is intermediate. */
file->secondary = 1;
if (!file->notintermediate && no_intermediates == 0)
file->secondary = 1;
notice_finished_file (file);
@ -957,7 +1018,7 @@ notice_finished_file (struct file *file)
we don't want to do the touching. */
unsigned int i;
for (i = 0; i < file->cmds->ncommand_lines; ++i)
if (!(file->cmds->lines_flags[i] & COMMANDS_RECURSE))
if (NONE_SET (file->cmds->lines_flags[i], COMMANDS_RECURSE))
goto have_nonrecursing;
}
else
@ -998,7 +1059,7 @@ notice_finished_file (struct file *file)
if ((question_flag || just_print_flag || touch_flag) && file->cmds)
{
for (i = file->cmds->ncommand_lines; i > 0; --i)
if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE))
if (NONE_SET (file->cmds->lines_flags[i-1], COMMANDS_RECURSE))
break;
}
@ -1039,23 +1100,36 @@ notice_finished_file (struct file *file)
}
if (ran && file->update_status != us_none)
/* We actually tried to update FILE, which has
updated its also_make's as well (if it worked).
If it didn't work, it wouldn't work again for them.
So mark them as updated with the same status. */
for (d = file->also_make; d != 0; d = d->next)
{
d->file->command_state = cs_finished;
d->file->updated = 1;
d->file->update_status = file->update_status;
{
/* We actually tried to update FILE, which has
updated its also_make's as well (if it worked).
If it didn't work, it wouldn't work again for them.
So mark them as updated with the same status. */
for (d = file->also_make; d != 0; d = d->next)
{
d->file->command_state = cs_finished;
d->file->updated = 1;
d->file->update_status = file->update_status;
if (ran && !d->file->phony)
/* Fetch the new modification time.
We do this instead of just invalidating the cached time
so that a vpath_search can happen. Otherwise, it would
never be done because the target is already updated. */
f_mtime (d->file, 0);
}
if (ran && !d->file->phony)
{
/* Fetch the new modification time.
We do this instead of just invalidating the cached time
so that a vpath_search can happen. Otherwise, it would
never be done because the target is already updated. */
f_mtime (d->file, 0);
if (just_print_flag)
/* Nothing got updated, but pretend it did. */
d->file->last_mtime = NEW_MTIME;
}
}
/* If the target was created by an implicit rule, and it was updated,
warn about any of its also_make targets that don't exist. */
if (file->tried_implicit && file->also_make)
check_also_make (file);
}
else if (file->update_status == us_none)
/* Nothing was done for FILE, but it needed nothing done.
So mark it now as "succeeded". */
@ -1076,7 +1150,6 @@ check_dep (struct file *file, unsigned int depth,
struct dep *d;
enum update_status dep_status = us_success;
++depth;
start_updating (file);
/* We might change file if we find a different one via vpath;
@ -1094,7 +1167,6 @@ check_dep (struct file *file, unsigned int depth,
check_renamed (file);
if (mtime == NONEXISTENT_MTIME || mtime > this_mtime)
*must_make_ptr = 1;
check_also_make (file);
}
else
{
@ -1156,7 +1228,7 @@ check_dep (struct file *file, unsigned int depth,
if (is_updating (d->file))
{
OSS (error, NILF, _("Circular %s <- %s dependency dropped."),
OSS (error, NILF, _("circular %s <- %s dependency dropped"),
file->name, d->file->name);
if (ld == 0)
{
@ -1175,7 +1247,7 @@ check_dep (struct file *file, unsigned int depth,
d->file->parent = file;
maybe_make = *must_make_ptr;
new = check_dep (d->file, depth, this_mtime, &maybe_make);
new = check_dep (d->file, depth+1, this_mtime, &maybe_make);
if (new > dep_status)
dep_status = new;
@ -1334,7 +1406,7 @@ f_mtime (struct file *file, int search)
if (ar_name (file->name))
{
/* This file is an archive-member reference. */
FILE_TIMESTAMP memmtime;
char *arname, *memname;
struct file *arfile;
time_t member_date;
@ -1342,6 +1414,9 @@ f_mtime (struct file *file, int search)
/* Find the archive's name. */
ar_parse_name (file->name, &arname, &memname);
/* Find the mtime of the member file (it might not exist). */
memmtime = name_mtime (memname);
/* Find the modification time of the archive itself.
Also allow for its name to be changed via VPATH search. */
arfile = lookup_file (arname);
@ -1385,9 +1460,16 @@ f_mtime (struct file *file, int search)
return NONEXISTENT_MTIME;
member_date = ar_member_date (file->hname);
mtime = (member_date == (time_t) -1
? NONEXISTENT_MTIME
: file_timestamp_cons (file->hname, member_date, 0));
if (member_date == (time_t) -1
|| (memmtime != NONEXISTENT_MTIME
&& (time_t) FILE_TIMESTAMP_S (memmtime) > member_date))
/* If the member file exists and is newer than the member in the
archive, pretend it's nonexistent. This means the member file was
updated but not added to the archive yet. */
mtime = NONEXISTENT_MTIME;
else
mtime = file_timestamp_cons (file->hname, member_date, 0);
}
else
#endif
@ -1413,7 +1495,7 @@ f_mtime (struct file *file, int search)
/* If we found it in VPATH, see if it's in GPATH too; if so,
change the name right now; if not, defer until after the
dependencies are updated. */
#ifndef VMS
#if !MK_OS_VMS
name_len = strlen (name) - strlen (file->name) - 1;
#else
name_len = strlen (name) - strlen (file->name);
@ -1451,7 +1533,7 @@ f_mtime (struct file *file, int search)
FILE_TIMESTAMP adjusted_mtime = mtime;
#if defined(WINDOWS32) || defined(__MSDOS__)
#if MK_OS_W32 || MK_OS_DOS
/* Experimentation has shown that FAT filesystems can set file times
up to 3 seconds into the future! Play it safe. */
@ -1460,14 +1542,6 @@ f_mtime (struct file *file, int search)
FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;
if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
adjusted_mtime -= adjustment;
#elif defined(__EMX__)
/* FAT filesystems round time to the nearest even second!
Allow for any file (NTFS or FAT) to perhaps suffer from this
brain damage. */
FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
&& FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS
: 0);
#endif
/* If the file's time appears to be in the future, update our
@ -1490,7 +1564,7 @@ f_mtime (struct file *file, int search)
else
sprintf (from_now_string, "%.2g", from_now);
OSS (error, NILF,
_("Warning: File '%s' has modification time %s s in the future"),
_("warning: file '%s' has modification time %s s in the future"),
file->name, from_now_string);
clock_skew_detected = 1;
}
@ -1537,16 +1611,16 @@ static FILE_TIMESTAMP
name_mtime (const char *name)
{
FILE_TIMESTAMP mtime;
#if defined(WINDOWS32)
#if MK_OS_W32
struct STAT st;
#else
struct stat st;
#endif
int e;
#if defined(WINDOWS32)
#if MK_OS_W32
{
char tem[MAXPATHLEN], *tstart, *tend;
char tem[MAX_PATH+1], *tstart, *tend;
const char *p = name + strlen (name);
/* Remove any trailing slashes and "."/"..". MS-Windows stat
@ -1573,7 +1647,7 @@ name_mtime (const char *name)
tend = &tem[0];
}
#if defined(WINDOWS32)
#if MK_OS_W32
e = STAT (tem, &st);
#else
e = stat (tem, &st);
@ -1677,13 +1751,11 @@ name_mtime (const char *name)
static const char *
library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
{
static const char *dirs[] =
static const char *const dirs[] =
{
#ifndef _AMIGA
"/lib",
"/usr/lib",
#endif
#if defined(WINDOWS32) && !defined(LIBDIR)
#if MK_OS_W32 && !defined(LIBDIR)
/*
* This is completely up to the user at product install time. Just define
* a placeholder.
@ -1707,9 +1779,9 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
/* Information about the earliest (in the vpath sequence) match. */
unsigned int best_vpath = 0, best_path = 0;
const char **dp;
const char *const *dp;
libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
libpatterns = allocated_expand_variable (STRING_SIZE_TUPLE (".LIBPATTERNS"));
/* Skip the '-l'. */
lib += 2;

View File

@ -3,7 +3,7 @@
Please do not send bug reports or questions about it to
the Make maintainers.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
/* Template for the remote job exportation interface to GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
/* Pattern and suffix rule internals for GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -56,10 +56,6 @@ size_t max_pattern_dep_length;
struct file *suffix_file;
/* Maximum length of a suffix. */
static size_t maxsuffix;
/* Return the rule definition: space separated rule targets, followed by
either a colon or two colons in the case of a terminal rule, followed by
space separated rule prerequisites, followed by a pipe, followed by
@ -94,7 +90,7 @@ get_rule_defn (struct rule *r)
if (dep->ignore_mtime == 0)
{
if (dep->wait_here)
p = mempcpy (p, STRING_SIZE_TUPLE (" .WAIT"));
p = mempcpy (p, " .WAIT", CSTRLEN (" .WAIT"));
p = mempcpy (mempcpy (p, " ", 1), dep_name (dep),
strlen (dep_name (dep)));
}
@ -107,7 +103,7 @@ get_rule_defn (struct rule *r)
{
p = mempcpy (p, sep, strlen (sep));
if (ood->wait_here)
p = mempcpy (p, STRING_SIZE_TUPLE (".WAIT "));
p = mempcpy (p, ".WAIT ", CSTRLEN (".WAIT "));
p = mempcpy (p, dep_name (ood), strlen (dep_name (ood)));
}
*p = '\0';
@ -140,6 +136,12 @@ snap_implicit_rules (void)
const char *d = dep_name (dep);
size_t l = strlen (d);
if (second_expansion)
{
if (!dep->name)
dep->name = xstrdup (dep->file->name);
dep->need_2nd_expansion = 1;
}
if (dep->need_2nd_expansion)
/* When pattern_search allocates a buffer, allow 5 bytes per each % to
substitute each % with $(*F) while avoiding realloc. */
@ -171,7 +173,7 @@ snap_implicit_rules (void)
const char *dname = dep_name (dep);
size_t len = strlen (dname);
#ifdef VMS
#if MK_OS_VMS
const char *p = strrchr (dname, ']');
const char *p2;
if (p == 0)
@ -250,7 +252,7 @@ convert_suffix_rule (const char *target, const char *source,
{
/* Special case: TARGET being nil means we are defining a '.X.a' suffix
rule; the target pattern is always '(%.o)'. */
#ifdef VMS
#if MK_OS_VMS
*names = strcache_add_len ("(%.obj)", 7);
#else
*names = strcache_add_len ("(%.o)", 5);
@ -298,7 +300,7 @@ convert_to_pattern (void)
suffixes in the .SUFFIXES target's dependencies and see if it exists.
First find the longest of the suffixes. */
maxsuffix = 0;
size_t maxsuffix = 0;
for (d = suffix_file->deps; d != 0; d = d->next)
{
size_t l = strlen (dep_name (d));
@ -311,6 +313,7 @@ convert_to_pattern (void)
for (d = suffix_file->deps; d != 0; d = d->next)
{
struct file *f;
size_t slen;
/* Make a rule that is just the suffix, with no deps or commands.
@ -321,14 +324,26 @@ convert_to_pattern (void)
/* Record a pattern for this suffix's null-suffix rule. */
convert_suffix_rule ("", dep_name (d), d->file->cmds);
slen = strlen (dep_name (d));
memcpy (rulename, dep_name (d), slen + 1);
f = lookup_file (rulename);
if (f && f->cmds)
{
if (!f->deps)
f->suffix = 1;
else if (!posix_pedantic)
{
O (error, &f->cmds->fileinfo,
_("warning: ignoring prerequisites on suffix rule definition"));
f->suffix = 1;
}
}
/* Add every other suffix to this one and see if it exists as a
two-suffix rule. */
slen = strlen (dep_name (d));
memcpy (rulename, dep_name (d), slen);
for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
{
struct file *f;
size_t s2len;
s2len = strlen (dep_name (d2));
@ -346,17 +361,19 @@ convert_to_pattern (void)
/* POSIX says that suffix rules can't have prerequisites.
In POSIX mode, don't make this a suffix rule. Previous versions
of GNU make did treat this as a suffix rule and ignored the
of GNU Make did treat this as a suffix rule and ignored the
prerequisites, which is bad. In the future we'll do the same as
POSIX, but for now preserve the old behavior and warn about it. */
if (f->deps != 0)
{
if (posix_pedantic)
continue;
error (&f->cmds->fileinfo, 0,
_("warning: ignoring prerequisites on suffix rule definition"));
O (error, &f->cmds->fileinfo,
_("warning: ignoring prerequisites on suffix rule definition"));
}
f->suffix = 1;
if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a')
/* A suffix rule '.X.a:' generates the pattern rule '(%.o): %.X'.
It also generates a normal '%.a: %.X' rule below. */
@ -455,7 +472,7 @@ new_pattern_rule (struct rule *rule, int override)
TERMINAL specifies what the 'terminal' field of the rule should be. */
void
install_pattern_rule (struct pspec *p, int terminal)
install_pattern_rule (const struct pspec *p, int terminal)
{
struct rule *r;
const char *ptr;
@ -616,7 +633,7 @@ print_rule_data_base (void)
/* This can happen if a fatal error was detected while reading the
makefiles and thus count_implicit_rule_limits wasn't called yet. */
if (num_pattern_rules != 0)
ONN (fatal, NILF, _("BUG: num_pattern_rules is wrong! %u != %u"),
ONN (fatal, NILF, "INTERNAL: num_pattern_rules is wrong! %u != %u",
num_pattern_rules, rules);
}
}

View File

@ -1,5 +1,5 @@
/* Definitions for using pattern rules in GNU Make.
Copyright (C) 1988-2022 Free Software Foundation, Inc.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -51,7 +51,7 @@ extern struct file *suffix_file;
void snap_implicit_rules (void);
void convert_to_pattern (void);
void install_pattern_rule (struct pspec *p, int terminal);
void install_pattern_rule (const struct pspec *p, int terminal);
void create_pattern_rule (const char **targets, const char **target_percents,
unsigned short num, int terminal, struct dep *deps,
struct commands *commands, int override);

View File

@ -1,5 +1,5 @@
/* Provide prerequisite shuffle support.
Copyright (C) 2022 Free Software Foundation, Inc.
Copyright (C) 2022-2024 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -104,12 +104,16 @@ static void
random_shuffle_array (void **a, size_t len)
{
size_t i;
for (i = 0; i < len; i++)
if (len <= 1)
return;
for (i = len - 1; i >= 1; i--)
{
void *t;
/* Pick random element and swap. */
unsigned int j = make_rand () % len;
unsigned int j = make_rand () % (i + 1);
if (i == j)
continue;

Some files were not shown because too many files have changed in this diff Show More