mirror of
https://git.savannah.gnu.org/git/make.git
synced 2025-06-23 00:00:31 -04:00
Compare commits
131 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d523661ce2 | ||
|
f12a4fddce | ||
|
186522e480 | ||
|
aa8626ce09 | ||
|
93704dd565 | ||
|
101bf5636f | ||
|
9251546bac | ||
|
7dc23aff30 | ||
|
0267eb64fa | ||
|
bba4427b5d | ||
|
c23a7e6232 | ||
|
4d3bf7838f | ||
|
8c8c7fc226 | ||
|
9fee98f843 | ||
|
f800f8bae3 | ||
|
39a4c81062 | ||
|
d97e048b08 | ||
|
c63a5bc6a2 | ||
|
bc979e4949 | ||
|
6970561de0 | ||
|
f0db5e321f | ||
|
8653c25fcf | ||
|
4d883c414d | ||
|
034f862361 | ||
|
49b955a50d | ||
|
69038e62e0 | ||
|
a9e3eb1eec | ||
|
e3f938caf8 | ||
|
40664fef1f | ||
|
f7985ab827 | ||
|
8339232a2f | ||
|
949952258e | ||
|
479c54f6ed | ||
|
033330e34c | ||
|
61ee4578f5 | ||
|
f289ece6cf | ||
|
d791fb4139 | ||
|
0b91f42f58 | ||
|
882d59c672 | ||
|
5fc62f8295 | ||
|
3d4f3e0627 | ||
|
242603fa46 | ||
|
b8a2a4424b | ||
|
bfbf169b63 | ||
|
21a538ce8f | ||
|
3176b60566 | ||
|
07187db947 | ||
|
a493d9ab6c | ||
|
a382ac6cd1 | ||
|
63b602e74f | ||
|
ec348f51d0 | ||
|
51e56a028e | ||
|
1eff20f6f6 | ||
|
82708b3a3a | ||
|
828906b6dc | ||
|
b936970956 | ||
|
1e43a5d104 | ||
|
25049fef16 | ||
|
31036e648f | ||
|
1ff728bff4 | ||
|
1161779ef8 | ||
|
a80670ad41 | ||
|
d86448fe5f | ||
|
33932663b0 | ||
|
89bea82af3 | ||
|
dd1980426e | ||
|
2ce7e40822 | ||
|
b1e240c554 | ||
|
7fa40eb4fc | ||
|
8817efe46a | ||
|
66adfb7c6f | ||
|
9af3e60f4d | ||
|
8061929963 | ||
|
cd33c9a1e9 | ||
|
c4ecd9d9eb | ||
|
6b7f35cb0b | ||
|
1000374759 | ||
|
8d76fb8778 | ||
|
ee366afbf1 | ||
|
b686980c66 | ||
|
8e5c96c318 | ||
|
363bdaef8c | ||
|
b2bf660abc | ||
|
04f4c2b8d9 | ||
|
347316fdf6 | ||
|
1a03888afa | ||
|
07fcee35f0 | ||
|
c85b71a396 | ||
|
032f784601 | ||
|
78e6a89b19 | ||
|
1748e66414 | ||
|
8e0e6c678f | ||
|
3f28ec2f58 | ||
|
24a84f99bb | ||
|
05c86bfcb2 | ||
|
06c75a35b9 | ||
|
ebe0a1c9f1 | ||
|
0880e5c86a | ||
|
0e06c75889 | ||
|
5340a3d5d1 | ||
|
fec72ea308 | ||
|
6cf6311332 | ||
|
c4329fb953 | ||
|
971b02d58e | ||
|
fdd61fc068 | ||
|
80727d709c | ||
|
cd46baab90 | ||
|
54b3202f8d | ||
|
5111087e12 | ||
|
0552b0abc8 | ||
|
c2792d6129 | ||
|
a0d1e76d60 | ||
|
03ecd94488 | ||
|
2611e1991f | ||
|
9db74434cd | ||
|
23f70b0cb8 | ||
|
78c8c44326 | ||
|
caf1d4c28f | ||
|
f99d083418 | ||
|
a367c0640f | ||
|
3088e3e698 | ||
|
bf7f690202 | ||
|
5d1fe2b16d | ||
|
8285852e55 | ||
|
9b9f3351d1 | ||
|
6f3e9e9b84 | ||
|
6128c3e266 | ||
|
ceb52b5d1b | ||
|
d4692df20d | ||
|
e6bd61d949 | ||
|
fcefae5ec9 |
4
.ccls
4
.ccls
@ -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
14
.clangd
Normal 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
|
@ -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
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -59,6 +59,8 @@ WinDebug/
|
||||
WinRel/
|
||||
GccDebug/
|
||||
GccRel/
|
||||
TccDebug/
|
||||
TccRel/
|
||||
|
||||
# Test artifacts
|
||||
makeerror-*
|
||||
|
9
AUTHORS
9
AUTHORS
@ -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>
|
||||
|
||||
@ -56,6 +53,7 @@ GNU Make porting efforts:
|
||||
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>
|
||||
@ -65,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>
|
||||
@ -97,6 +97,7 @@ 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>
|
||||
@ -111,7 +112,7 @@ With suggestions/comments/bug reports from a cast of ... well ...
|
||||
hundreds, anyway :)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1997-2023 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
|
||||
|
@ -10,7 +10,7 @@
|
||||
#
|
||||
# make.exe -f Basic.mk
|
||||
#
|
||||
# Copyright (C) 2017-2023 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
|
||||
|
43
Makefile.am
43
Makefile.am
@ -1,6 +1,6 @@
|
||||
# This is a -*-Makefile-*-, or close enough
|
||||
#
|
||||
# Copyright (C) 1997-2023 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
|
||||
@ -37,7 +37,7 @@ make_SRCS = src/ar.c src/arscan.c src/commands.c src/commands.h \
|
||||
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
|
||||
|
||||
@ -113,13 +122,12 @@ test_FILES = tests/run_make_tests tests/run_make_tests.bat \
|
||||
|
||||
EXTRA_DIST = ChangeLog INSTALL README build.sh build.cfg.in $(man_MANS) \
|
||||
src/mkconfig.h README.customs README.OS2 README.zOS \
|
||||
README.Amiga SCOPTIONS src/config.ami \
|
||||
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
|
||||
|
||||
@ -155,8 +163,6 @@ 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 =
|
||||
|
||||
@ -180,20 +186,13 @@ 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
|
||||
@rm -f $(testfiles)
|
||||
@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 $$? >.test-result) 2>&1 | tee $(testlog); \
|
||||
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"; \
|
||||
|
96
NEWS
96
NEWS
@ -9,6 +9,96 @@ 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.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)
|
||||
|
||||
@ -925,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
|
||||
@ -1165,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
|
||||
@ -1858,7 +1948,7 @@ Version 3.05
|
||||
(Changes from versions 1 through 3.05 were never recorded. Sorry.)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1988-2023 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
|
||||
|
80
README.Amiga
80
README.Amiga
@ -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-2023 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/>.
|
@ -280,7 +280,7 @@ Bug reports:
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1996-2023 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
|
||||
|
@ -163,7 +163,7 @@ from the make source tree.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2003-2023 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
|
||||
|
@ -347,7 +347,7 @@ Bug reports:
|
||||
is described in the GNU Make manual and the base README.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1996-2023 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
|
||||
|
@ -96,7 +96,7 @@ SunOS 4.1.x:
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1998-2023 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
|
||||
|
27
README.git
27
README.git
@ -1,7 +1,7 @@
|
||||
-*-text-*-
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2002-2023 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
|
||||
@ -147,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.
|
||||
@ -155,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
|
||||
@ -209,6 +210,13 @@ work on non-GNU systems (Windows, MacOS, etc.)
|
||||
|
||||
make clean
|
||||
make -j8 CFLAGS='-ggdb3 -fsanitize=address' LDFLAGS='-ggdb3 -fsanitize=address'
|
||||
|
||||
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
|
||||
@ -335,10 +343,15 @@ When publishing a final release there are extra steps that need to be taken:
|
||||
|
||||
Manage the Savannah project for GNU Make:
|
||||
|
||||
* 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 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 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
|
||||
|
27
README.in
27
README.in
@ -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
|
||||
-----------
|
||||
|
||||
@ -140,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
|
||||
@ -182,8 +177,6 @@ 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.
|
||||
@ -201,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-2023 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
|
||||
|
13
SCOPTIONS
13
SCOPTIONS
@ -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
|
@ -101,7 +101,7 @@ The Rest of the List
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1997-2023 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
|
||||
|
@ -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-2023 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Convenience script for fetching auxiliary files that are omitted from
|
||||
# the version control repository of this package.
|
||||
|
||||
# Copyright (C) 2003-2023 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
scriptlibversion=2022-12-27.16; # UTC
|
||||
|
||||
# Copyright (C) 2003-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
:: Copyright (C) 2018-2023 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Bootstrap configuration. -*-shell-script-*-
|
||||
|
||||
# Copyright (C) 2018-2023 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-202301
|
||||
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
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Configuration for building GNU Make in the absence of any 'make' program.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1993-2023 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
|
||||
|
2
build.sh
2
build.sh
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# Shell script to build GNU Make in the absence of any 'make' program.
|
||||
|
||||
# Copyright (C) 1993-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
:: Copyright (C) 1996-2023 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
|
||||
@ -34,6 +34,7 @@ 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
rem Copyright (C) 1998-2023 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
|
||||
|
15
configure.ac
15
configure.ac
@ -1,6 +1,6 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright (C) 1993-2023 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.4.1],[bug-make@gnu.org])
|
||||
AC_INIT([GNU Make],[4.4.90],[bug-make@gnu.org])
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
@ -67,8 +67,8 @@ AC_HEADER_DIRENT
|
||||
AC_HEADER_STAT
|
||||
|
||||
AC_CHECK_HEADERS([stdlib.h string.h strings.h locale.h unistd.h limits.h \
|
||||
memory.h sys/param.h sys/resource.h sys/timeb.h sys/time.h \
|
||||
sys/select.h sys/file.h fcntl.h spawn.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
|
||||
@ -444,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'],
|
||||
|
1
doc/.gitignore
vendored
1
doc/.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
manual/
|
||||
make.t2d/
|
||||
make.t2p/
|
||||
gendocs_template
|
||||
fdl.texi
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*-Makefile-*-, or close enough
|
||||
# Copyright (C) 2000-2023 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
|
||||
|
62
doc/make.1
62
doc/make.1
@ -270,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
|
||||
@ -364,8 +369,57 @@ 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 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
|
||||
@ -395,7 +449,7 @@ 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-2023 Free Software Foundation, Inc.
|
||||
Copyright \(co 1992\(en1993, 1996\(en2024 Free Software Foundation, Inc.
|
||||
This file is part of
|
||||
.IR "GNU Make" .
|
||||
.LP
|
||||
|
3578
doc/make.texi
3578
doc/make.texi
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
@ -71,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
|
||||
|
||||
@ -115,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
|
||||
@ -146,11 +145,11 @@ extern int errno;
|
||||
# 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. */
|
||||
@ -416,14 +415,14 @@ glob (const char *pattern, int flags,
|
||||
|
||||
/* 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
|
||||
@ -460,7 +459,7 @@ glob (const char *pattern, int flags,
|
||||
{
|
||||
char *newp;
|
||||
dirlen = filename - pattern;
|
||||
#if defined __MSDOS__ || defined WINDOWS32
|
||||
#if MK_OS_DOS || MK_OS_W32
|
||||
if (*filename == ':'
|
||||
|| (filename > pattern + 1 && filename[-1] == ':'))
|
||||
{
|
||||
@ -494,7 +493,7 @@ glob (const char *pattern, int flags,
|
||||
++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] != '/')
|
||||
@ -518,13 +517,13 @@ glob (const char *pattern, int flags,
|
||||
|
||||
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
|
||||
@ -534,11 +533,11 @@ glob (const char *pattern, int flags,
|
||||
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:[]";
|
||||
@ -601,8 +600,8 @@ glob (const char *pattern, int flags,
|
||||
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')
|
||||
@ -622,7 +621,7 @@ glob (const char *pattern, int flags,
|
||||
dirname = newp;
|
||||
}
|
||||
}
|
||||
# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
|
||||
# if !defined _AMIGA && !MK_OS_W32 && !MK_OS_VMS
|
||||
else
|
||||
{
|
||||
char *end_name = strchr (dirname, '/');
|
||||
@ -702,9 +701,9 @@ glob (const char *pattern, int flags,
|
||||
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. */
|
||||
@ -1011,7 +1010,7 @@ prefix_array (const char *dirname, char **array, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
size_t dirlen = strlen (dirname);
|
||||
#if defined __MSDOS__ || defined WINDOWS32
|
||||
#if MK_OS_DOS || MK_OS_W32
|
||||
char sep_char = '/';
|
||||
# define DIRSEP_CHAR sep_char
|
||||
#else
|
||||
@ -1022,7 +1021,7 @@ prefix_array (const char *dirname, char **array, size_t 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] == ':')
|
||||
@ -1124,7 +1123,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|
||||
int meta;
|
||||
int save;
|
||||
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
if (*directory == 0)
|
||||
directory = "[]";
|
||||
#endif
|
||||
|
@ -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/>. */
|
||||
|
||||
#ifndef _GLOB_H
|
||||
#define _GLOB_H 1
|
||||
@ -67,7 +66,7 @@ extern "C" {
|
||||
#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
|
||||
@ -83,7 +82,7 @@ typedef struct
|
||||
struct dirent *(*gl_readdir) (void *);
|
||||
void * (*gl_opendir) (const char *);
|
||||
int (*gl_lstat) (const char *, struct stat *);
|
||||
#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
|
||||
#if MK_OS_VMS && defined(__DECC) && !defined(_POSIX_C_SOURCE)
|
||||
int (*gl_stat) (const char *, struct stat *, ...);
|
||||
#else
|
||||
int (*gl_stat) (const char *, struct stat *);
|
||||
|
@ -1,7 +1,7 @@
|
||||
dnl acinclude.m4 -- Extra macros needed for GNU Make.
|
||||
dnl
|
||||
dnl Automake will incorporate this into its generated aclocal.m4.
|
||||
dnl Copyright (C) 1998-2023 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
|
||||
|
@ -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-2023 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Check for getloadavg.
|
||||
|
||||
# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2023 Free
|
||||
# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2024 Free
|
||||
# Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
|
@ -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' \
|
||||
@ -517,7 +519,7 @@ $(UPLOADS): upload-%: $(DIST_ARCHIVES)
|
||||
# Rebuild Makefile.in if this file is modified.
|
||||
Makefile.in: maintMakefile
|
||||
|
||||
# Copyright (C) 1997-2023 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
|
||||
|
@ -154,7 +154,7 @@ $ exit
|
||||
$ endsubroutine : compileit
|
||||
$!
|
||||
$!-----------------------------------------------------------------------------
|
||||
$!Copyright (C) 1996-2023 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
|
||||
|
45
mk/Amiga.mk
45
mk/Amiga.mk
@ -1,45 +0,0 @@
|
||||
# GNU -*-Makefile-*- to build GNU Make on Amiga
|
||||
#
|
||||
# Amiga overrides for use with Basic.mk.
|
||||
#
|
||||
# Copyright (C) 2017-2023 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,$<,$@)
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# POSIX overrides for use with Basic.mk.
|
||||
#
|
||||
# Copyright (C) 2017-2023 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# VMS overrides for use with Basic.mk.
|
||||
#
|
||||
# Copyright (C) 2017-2023 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# Windows overrides for use with Basic.mk.
|
||||
#
|
||||
# Copyright (C) 2017-2023 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# MS-DOS overrides for use with Basic.mk.
|
||||
#
|
||||
# Copyright (C) 2017-2023 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
|
||||
|
@ -13,6 +13,7 @@ hr
|
||||
id
|
||||
it
|
||||
ja
|
||||
ka
|
||||
ko
|
||||
lt
|
||||
nl
|
||||
|
@ -1,5 +1,5 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Copyright (C) 2000-2023 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2014-2023 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
|
||||
|
113
src/amiga.c
113
src/amiga.c
@ -1,113 +0,0 @@
|
||||
/* Running commands on Amiga
|
||||
Copyright (C) 1995-2023 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;
|
||||
}
|
18
src/amiga.h
18
src/amiga.h
@ -1,18 +0,0 @@
|
||||
/* Definitions for amiga specific things
|
||||
Copyright (C) 1995-2023 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);
|
24
src/ar.c
24
src/ar.c
@ -1,5 +1,5 @@
|
||||
/* Interface to 'ar' archives for GNU Make.
|
||||
Copyright (C) 1988-2023 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Make.
|
||||
|
||||
@ -63,7 +63,7 @@ ar_parse_name (const char *name, char **arname_p, char **memname_p)
|
||||
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);
|
||||
OS (fatal, NILF, "INTERNAL: ar_parse_name: bad name '%s'", *arname_p);
|
||||
*(p++) = '\0';
|
||||
p[strlen (p) - 1] = '\0';
|
||||
*memname_p = p;
|
||||
@ -120,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)
|
||||
{
|
||||
@ -148,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);
|
||||
@ -158,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'. */
|
||||
|
||||
@ -187,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;
|
||||
@ -210,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, ")"));
|
||||
@ -268,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))
|
||||
@ -278,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 */
|
||||
@ -299,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)
|
||||
|
37
src/arscan.c
37
src/arscan.c
@ -1,5 +1,5 @@
|
||||
/* Library function for scanning an archive file.
|
||||
Copyright (C) 1987-2023 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,7 +289,7 @@ 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
|
||||
@ -330,7 +330,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *varg)
|
||||
# define __AR_BIG__
|
||||
#endif
|
||||
|
||||
#ifndef WINDOWS32
|
||||
#if !MK_OS_W32
|
||||
# if !defined (__ANDROID__) && !defined (__BEOS__) && !defined(MK_OS_ZOS)
|
||||
# include <ar.h>
|
||||
# else
|
||||
@ -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))
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Command processing for GNU Make.
|
||||
Copyright (C) 1988-2023 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 ' '
|
||||
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definition of data structures describing shell commands for GNU Make.
|
||||
Copyright (C) 1988-2023 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
|
||||
|
334
src/config.ami
334
src/config.ami
@ -1,334 +0,0 @@
|
||||
/* config.h -- hand-massaged for Amiga -*-C-*-
|
||||
Copyright (C) 1995-2023 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
|
||||
|
||||
/* Include customized declarations. */
|
||||
#include "../src/mkcustom.h"
|
@ -1,6 +1,6 @@
|
||||
/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> -*-C-*-
|
||||
|
||||
Copyright (C) 1996-2023 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. */
|
||||
@ -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 */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*-
|
||||
|
||||
Copyright (C) 1996-2023 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. */
|
||||
@ -390,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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* configh.dos -- hand-massaged config.h file for MS-DOS builds -*-C-*-
|
||||
|
||||
Copyright (C) 1994-2023 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. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Debugging macros and interface.
|
||||
Copyright (C) 1999-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Data base of default implicit rules for GNU Make.
|
||||
Copyright (C) 1988-2023 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
|
||||
@ -536,7 +536,7 @@ static const char *default_variables[] =
|
||||
"CXX", MAKE_CXX,
|
||||
#else
|
||||
# ifdef GCC_IS_NATIVE
|
||||
# ifdef __MSDOS__
|
||||
# ifdef MK_OS_DOS
|
||||
"CXX", "gpp", /* g++ is an invalid name on MSDOS */
|
||||
# else
|
||||
"CXX", "gcc",
|
||||
@ -660,19 +660,17 @@ static const char *default_variables[] =
|
||||
"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
|
||||
@ -709,7 +707,7 @@ set_default_suffixes (void)
|
||||
void
|
||||
install_default_suffix_rules ()
|
||||
{
|
||||
const char **s;
|
||||
const char *const *s;
|
||||
|
||||
if (no_builtin_rules_flag)
|
||||
return;
|
||||
@ -736,7 +734,7 @@ install_default_suffix_rules ()
|
||||
void
|
||||
install_default_implicit_rules (void)
|
||||
{
|
||||
struct pspec *p;
|
||||
const struct pspec *p;
|
||||
|
||||
if (no_builtin_rules_flag)
|
||||
return;
|
||||
@ -751,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;
|
||||
@ -763,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);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions of dependency data structures for GNU Make.
|
||||
Copyright (C) 1988-2023 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);
|
||||
|
132
src/dir.c
132
src/dir.c
@ -1,5 +1,5 @@
|
||||
/* Directory hashing for GNU Make.
|
||||
Copyright (C) 1988-2023 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,7 +23,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#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>
|
||||
|
||||
@ -108,16 +108,12 @@ dosify (const char *filename)
|
||||
*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)
|
||||
@ -141,7 +137,7 @@ downcase (const char *filename)
|
||||
}
|
||||
#endif /* HAVE_CASE_INSENSITIVE_FS */
|
||||
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
|
||||
static char *
|
||||
downcase_inplace(char *filename)
|
||||
@ -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. */
|
||||
@ -295,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]
|
||||
@ -308,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;
|
||||
}
|
||||
|
||||
@ -318,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]
|
||||
@ -331,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;
|
||||
}
|
||||
@ -354,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;
|
||||
@ -362,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;
|
||||
@ -377,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);
|
||||
}
|
||||
@ -475,7 +471,7 @@ find_directory (const char *name)
|
||||
|
||||
struct stat st;
|
||||
int r;
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
char *w32_path;
|
||||
#endif
|
||||
|
||||
@ -503,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));
|
||||
@ -520,7 +516,7 @@ find_directory (const char *name)
|
||||
dir->counter = command_count;
|
||||
|
||||
/* See if the directory exists. */
|
||||
#if defined(WINDOWS32)
|
||||
#if MK_OS_W32
|
||||
{
|
||||
char tem[MAX_PATH+1], *tstart, *tend;
|
||||
size_t len = strlen (name);
|
||||
@ -548,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];
|
||||
@ -566,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;
|
||||
@ -577,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),
|
||||
@ -594,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);
|
||||
}
|
||||
@ -640,7 +636,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
struct dirfile *df;
|
||||
struct dirent *d;
|
||||
struct directory_contents *dc = dir->contents;
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
struct stat st;
|
||||
int rehash = 0;
|
||||
#endif
|
||||
@ -649,7 +645,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
/* The directory could not be stat'd or opened. */
|
||||
return 0;
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#if MK_OS_DOS
|
||||
filename = dosify (filename);
|
||||
#endif
|
||||
|
||||
@ -657,7 +653,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
filename = downcase (filename);
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__
|
||||
#if MK_OS_OS2
|
||||
if (filename != NULL)
|
||||
{
|
||||
size_t len = strlen (filename);
|
||||
@ -688,7 +684,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
|
||||
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
|
||||
@ -738,7 +734,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
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. */
|
||||
@ -755,7 +751,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
dirfile_key.name = d->d_name;
|
||||
dirfile_key.length = len;
|
||||
dirfile_slot = (struct dirfile **) hash_find_slot (&dc->dirfiles, &dirfile_key);
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
/*
|
||||
* If re-reading a directory, don't cache files that have
|
||||
* already been discovered.
|
||||
@ -764,7 +760,7 @@ dir_contents_file_exists_p (struct directory *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
|
||||
@ -801,7 +797,7 @@ dir_contents_file_exists_p (struct directory *dir,
|
||||
int
|
||||
dir_file_exists_p (const char *dirname, const char *filename)
|
||||
{
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
if (filename && dirname && strpbrk (dirname, ":<[") != NULL)
|
||||
filename = vmsify (filename, 0);
|
||||
#endif
|
||||
@ -824,7 +820,7 @@ file_exists_p (const char *name)
|
||||
#endif
|
||||
|
||||
dirend = strrchr (name, '/');
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
if (dirend == NULL)
|
||||
{
|
||||
dirend = strrchr (name, ']');
|
||||
@ -840,7 +836,7 @@ file_exists_p (const char *name)
|
||||
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. */
|
||||
{
|
||||
@ -853,11 +849,7 @@ file_exists_p (const char *name)
|
||||
}
|
||||
#endif /* HAVE_DOS_PATHS */
|
||||
if (dirend == NULL)
|
||||
#ifndef _AMIGA
|
||||
return dir_file_exists_p (".", name);
|
||||
#else /* !AMIGA */
|
||||
return dir_file_exists_p ("", name);
|
||||
#endif /* AMIGA */
|
||||
|
||||
slash = dirend;
|
||||
if (dirend == name)
|
||||
@ -876,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
|
||||
@ -898,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, ']');
|
||||
@ -927,11 +919,7 @@ file_impossible (const char *filename)
|
||||
}
|
||||
#endif /* HAVE_DOS_PATHS */
|
||||
if (dirend == NULL)
|
||||
#ifdef _AMIGA
|
||||
dir = find_directory ("");
|
||||
#else /* !AMIGA */
|
||||
dir = find_directory (".");
|
||||
#endif /* AMIGA */
|
||||
else
|
||||
{
|
||||
const char *dirname;
|
||||
@ -953,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
|
||||
@ -976,7 +964,7 @@ file_impossible (const char *filename)
|
||||
|
||||
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
|
||||
@ -995,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);
|
||||
@ -1023,11 +1011,7 @@ file_impossible_p (const char *filename)
|
||||
}
|
||||
#endif /* HAVE_DOS_PATHS */
|
||||
if (dirend == NULL)
|
||||
#ifdef _AMIGA
|
||||
dir = find_directory ("")->contents;
|
||||
#else /* !AMIGA */
|
||||
dir = find_directory (".")->contents;
|
||||
#endif /* AMIGA */
|
||||
else
|
||||
{
|
||||
const char *dirname;
|
||||
@ -1049,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
|
||||
@ -1063,13 +1047,13 @@ file_impossible_p (const char *filename)
|
||||
/* 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
|
||||
@ -1101,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
|
||||
|
||||
@ -1119,7 +1103,7 @@ print_dir_data_base (void)
|
||||
if (dir->contents == NULL)
|
||||
printf (_("# %s: could not be stat'd.\n"), dir->name);
|
||||
else if (dir->contents->dirfiles.ht_vec == NULL)
|
||||
#ifdef WINDOWS32
|
||||
#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));
|
||||
@ -1152,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));
|
||||
@ -1290,8 +1274,8 @@ read_dirstream (void *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
|
||||
@ -1307,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
|
||||
@ -1330,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
|
||||
@ -1342,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
|
||||
|
403
src/expand.c
403
src/expand.c
@ -1,5 +1,5 @@
|
||||
/* Variable expansion functions for GNU Make.
|
||||
Copyright (C) 1988-2023 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
}
|
||||
|
116
src/file.c
116
src/file.c
@ -1,5 +1,5 @@
|
||||
/* Target file management for GNU Make.
|
||||
Copyright (C) 1988-2023 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,6 +61,14 @@ 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;
|
||||
|
||||
@ -73,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;
|
||||
@ -85,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 != '.')
|
||||
@ -116,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 = "[]";
|
||||
@ -129,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
|
||||
@ -153,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;
|
||||
@ -221,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 ();
|
||||
@ -266,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);
|
||||
}
|
||||
}
|
||||
@ -331,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
|
||||
@ -401,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)
|
||||
@ -421,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;
|
||||
}
|
||||
@ -640,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);
|
||||
@ -692,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)
|
||||
{
|
||||
@ -713,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)
|
||||
@ -732,14 +747,22 @@ snap_file (const void *item, void *arg)
|
||||
|
||||
/* 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. */
|
||||
@ -940,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;
|
||||
@ -1007,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",
|
||||
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 != '.';
|
||||
@ -1032,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;
|
||||
@ -1108,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;
|
||||
@ -1183,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. */
|
||||
|
||||
@ -1190,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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definition of target file data structures for GNU Make.
|
||||
Copyright (C) 1988-2023 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);
|
||||
|
||||
|
275
src/function.c
275
src/function.c
@ -1,5 +1,5 @@
|
||||
/* Builtin function expansion for GNU Make.
|
||||
Copyright (C) 1988-2023 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));
|
||||
@ -2451,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))
|
||||
{
|
||||
@ -2489,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. */
|
||||
@ -2585,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)
|
||||
@ -2613,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))
|
||||
@ -2712,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;
|
||||
@ -2750,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 ();
|
||||
@ -2765,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
|
||||
@ -2778,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;
|
||||
@ -2813,17 +2704,17 @@ 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 = strcache_add (name);
|
||||
@ -2843,9 +2734,9 @@ define_new_function (const floc *flocp, const char *name,
|
||||
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));
|
||||
}
|
||||
|
@ -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-2023 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>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989-2023 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987-1994, 1996-2023 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
;; Contents of the (GNU Make) Guile module
|
||||
;; Copyright (C) 2011-2023 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
|
||||
|
@ -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-2023 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,7 +56,7 @@ 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. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* GNU Guile interface for GNU Make.
|
||||
Copyright (C) 2011-2023 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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Implicit rule searching for GNU Make.
|
||||
Copyright (C) 1988-2023 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 '|':
|
||||
@ -284,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)
|
||||
@ -357,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;
|
||||
@ -706,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. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for managing subprocesses in GNU Make.
|
||||
Copyright (C) 1992-2023 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);
|
||||
|
||||
|
216
src/load.c
216
src/load.c
@ -1,5 +1,5 @@
|
||||
/* Loading dynamic objects for GNU Make.
|
||||
Copyright (C) 2012-2023 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,17 +67,50 @@ 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);
|
||||
if (! symp)
|
||||
/* Find the prefix of the ldname. */
|
||||
fp = strrchr (ldname, '/');
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
if (fp)
|
||||
{
|
||||
struct load_list *new;
|
||||
void *dlp = NULL;
|
||||
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, '\\')
|
||||
@ -93,29 +136,31 @@ load_object (const floc *flocp, int noerror, const char *ldname,
|
||||
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");
|
||||
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);
|
||||
_("loaded object %s is not declared to be GPL compatible"), ldname);
|
||||
|
||||
symp = (load_func_t) dlsym (dlp, symname);
|
||||
symp = (setup_func_t) dlsym (dlp, setupnm);
|
||||
if (! symp)
|
||||
{
|
||||
const char *err = dlerror ();
|
||||
OSSS (fatal, flocp, _("Failed to load symbol %s from %s: %s"),
|
||||
symname, ldname, err);
|
||||
OSSS (fatal, flocp, _("failed to load symbol %s from %s: %s"),
|
||||
setupnm, 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 = 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)
|
||||
/* Unload and remove the entry for this file. */
|
||||
while (*dp != NULL)
|
||||
{
|
||||
struct load_list *d = *dp;
|
||||
|
||||
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);
|
||||
else
|
||||
d->dlp = NULL;
|
||||
break;
|
||||
|
||||
*dp = d->next;
|
||||
free (d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* API for GNU Make dynamic objects.
|
||||
Copyright (C) 2013-2023 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. */
|
||||
|
665
src/main.c
665
src/main.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Miscellaneous global declarations and portability cruft for GNU Make.
|
||||
Copyright (C) 1988-2023 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
|
||||
@ -44,7 +44,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
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"
|
||||
@ -66,11 +66,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#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
|
||||
@ -93,7 +88,12 @@ extern int errno;
|
||||
# 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.
|
||||
*/
|
||||
@ -106,7 +106,7 @@ extern int errno;
|
||||
# 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
|
||||
@ -149,15 +149,8 @@ extern int errno;
|
||||
# endif
|
||||
#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
|
||||
@ -167,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)
|
||||
@ -197,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>
|
||||
@ -366,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)
|
||||
@ -399,7 +396,7 @@ extern int unixy_shell;
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
#endif /* WINDOWS32 */
|
||||
#endif /* MK_OS_W32 */
|
||||
|
||||
/* ALL_SET() evaluates the second argument twice. */
|
||||
#define ANY_SET(_v,_m) (((_v)&(_m)) != 0)
|
||||
@ -426,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
|
||||
@ -443,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
|
||||
@ -497,6 +494,9 @@ 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)
|
||||
|
||||
@ -516,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
|
||||
@ -544,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
|
||||
@ -587,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 *);
|
||||
@ -618,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
|
||||
@ -661,9 +664,9 @@ 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
|
||||
@ -680,14 +683,14 @@ void dbg (const char *fmt, ...);
|
||||
/* 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)
|
||||
# if !MK_OS_VMS && !defined(__DECC)
|
||||
char *getcwd (void);
|
||||
# endif
|
||||
# else
|
||||
@ -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, 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,17 +746,23 @@ 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 and Cygwin so don't use it there. */
|
||||
# if !defined(JOBSERVER_USE_FIFO) && !MK_OS_HURD && !MK_OS_CYGWIN
|
||||
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
|
||||
@ -766,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);
|
||||
|
||||
@ -833,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
|
||||
@ -841,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
|
||||
|
154
src/misc.c
154
src/misc.c
@ -1,5 +1,5 @@
|
||||
/* Miscellaneous generic support functions for GNU Make.
|
||||
Copyright (C) 1988-2023 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,12 +23,12 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__
|
||||
#if MK_OS_OS2
|
||||
# define INCL_DOS
|
||||
# include <os2.h>
|
||||
#endif
|
||||
@ -131,7 +131,7 @@ collapse_continuations (char *line)
|
||||
char *q;
|
||||
|
||||
q = strchr(in, '\n');
|
||||
if (q == 0)
|
||||
if (!q)
|
||||
return;
|
||||
|
||||
do
|
||||
@ -162,16 +162,32 @@ 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;
|
||||
|
||||
if (!dollar)
|
||||
*out++ = ' ';
|
||||
}
|
||||
else
|
||||
@ -335,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
|
||||
|
||||
@ -402,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. */
|
||||
@ -421,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
|
||||
@ -434,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;
|
||||
@ -444,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)
|
||||
{
|
||||
@ -456,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;
|
||||
|
||||
@ -468,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
|
||||
@ -502,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;
|
||||
@ -525,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);
|
||||
@ -572,7 +647,7 @@ umask (mode_t mask)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
# define DEFAULT_TMPFILE "sys$scratch:gnv$make_cmdXXXXXX.com"
|
||||
#else
|
||||
# define DEFAULT_TMPFILE "GmXXXXXX"
|
||||
@ -585,7 +660,7 @@ get_tmpdir ()
|
||||
|
||||
if (!tmpdir)
|
||||
{
|
||||
#if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
|
||||
#if MK_OS_DOS || MK_OS_W32 || MK_OS_OS2
|
||||
# define TMP_EXTRAS "TMP", "TEMP",
|
||||
#else
|
||||
# define TMP_EXTRAS
|
||||
@ -595,7 +670,7 @@ get_tmpdir ()
|
||||
unsigned int found = 0;
|
||||
|
||||
for (tp = tlist; *tp; ++tp)
|
||||
if ((tmpdir = getenv (*tp)) && *tmpdir != '\0')
|
||||
if ((tmpdir = getenv (*tp)) != NULL && *tmpdir != '\0')
|
||||
{
|
||||
struct stat st;
|
||||
int r;
|
||||
@ -630,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++) = '/';
|
||||
@ -786,7 +861,7 @@ get_tmpfile (char **name)
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_TTYNAME && defined(__EMX__)
|
||||
#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)
|
||||
@ -873,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 x = pathconf ("/", _PC_PATH_MAX);
|
||||
if (x > 0)
|
||||
value = (unsigned int) x;
|
||||
else
|
||||
value = PATH_MAX;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_MEMPCPY
|
||||
void *
|
||||
mempcpy (void *dest, const void *src, size_t n)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Autoconf values for use on non-POSIX systems.
|
||||
Copyright (C) 2022-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Miscellaneous global declarations and portability cruft for GNU Make.
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
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
|
||||
@ -36,7 +36,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# if !defined(__GNUC__) && !defined(WINDOWS32)
|
||||
# if !defined(__GNUC__) && !MK_OS_W32
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
|
26
src/os.h
26
src/os.h
@ -1,5 +1,5 @@
|
||||
/* Declarations for operating system interfaces for GNU Make.
|
||||
Copyright (C) 2016-2023 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,11 +20,12 @@ 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__)
|
||||
#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) (void)(0)
|
||||
# define fd_set_append(_i) (-1)
|
||||
# define fd_reset_append(_i,_f) (void)(0)
|
||||
# define os_anontmp() (-1)
|
||||
#else
|
||||
|
||||
@ -32,11 +33,15 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
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
|
||||
|
83
src/output.c
83
src/output.c
@ -1,5 +1,5 @@
|
||||
/* Output to stdout / stderr for GNU Make
|
||||
Copyright (C) 2013-2023 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
|
||||
@ -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;
|
||||
@ -151,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
|
||||
@ -178,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);
|
||||
@ -249,7 +249,7 @@ setup_tmpfile (struct output *out)
|
||||
/* 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."));
|
||||
_("cannot open output-sync lock file: suppressing output-sync"));
|
||||
|
||||
output_close (out);
|
||||
output_sync = OUTPUT_SYNC_NONE;
|
||||
@ -280,7 +280,7 @@ 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 ();
|
||||
}
|
||||
|
||||
@ -318,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)
|
||||
{
|
||||
@ -330,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
|
||||
@ -341,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;
|
||||
}
|
||||
|
||||
@ -420,13 +425,9 @@ message (int prefix, size_t len, const char *fmt, ...)
|
||||
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);
|
||||
@ -452,13 +453,11 @@ error (const floc *flocp, size_t len, const char *fmt, ...)
|
||||
+ INTSTR_LENGTH + 4 + 1 + 1);
|
||||
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);
|
||||
@ -475,8 +474,8 @@ 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;
|
||||
|
||||
@ -485,13 +484,12 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
|
||||
+ INTSTR_LENGTH + 8 + strlen (stop) + 1);
|
||||
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);
|
||||
@ -505,6 +503,29 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
|
||||
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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Output to stdout / stderr for GNU Make
|
||||
Copyright (C) 2013-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* POSIX-based operating system interface for GNU Make.
|
||||
Copyright (C) 2016-2023 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
|
||||
@ -122,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)
|
||||
@ -136,6 +134,14 @@ 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;
|
||||
@ -145,20 +151,24 @@ set_blocking (int fd, int blocking)
|
||||
unsigned int
|
||||
jobserver_setup (int slots, const char *style)
|
||||
{
|
||||
int r;
|
||||
int r, k;
|
||||
|
||||
/* 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));
|
||||
@ -207,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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -557,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
|
||||
@ -830,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);
|
||||
@ -845,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
|
||||
}
|
||||
|
||||
|
355
src/read.c
355
src/read.c
@ -1,5 +1,5 @@
|
||||
/* Reading and parsing of makefiles for GNU Make.
|
||||
Copyright (C) 1988-2023 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,7 +186,7 @@ read_all_makefiles (const char **makefiles)
|
||||
char *name, *p;
|
||||
size_t length;
|
||||
|
||||
value = allocated_variable_expand ("$(MAKEFILES)");
|
||||
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. */
|
||||
@ -228,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;
|
||||
|
||||
@ -423,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 */
|
||||
|
||||
@ -631,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. */
|
||||
@ -675,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;
|
||||
|
||||
@ -746,10 +737,10 @@ eval (struct ebuffer *ebuf, int set_default)
|
||||
do_undefine (p, origin, ebuf);
|
||||
continue;
|
||||
}
|
||||
else if (vmod.define_v)
|
||||
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);
|
||||
|
||||
@ -770,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)
|
||||
{
|
||||
@ -817,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))
|
||||
@ -843,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)
|
||||
{
|
||||
@ -876,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')
|
||||
@ -920,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;
|
||||
@ -930,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')
|
||||
@ -1062,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)
|
||||
{
|
||||
@ -1090,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;
|
||||
@ -1126,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. */
|
||||
@ -1238,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. */
|
||||
@ -1263,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;
|
||||
@ -1385,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"));
|
||||
@ -1394,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);
|
||||
}
|
||||
|
||||
@ -1418,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;
|
||||
var.conditional = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (var.value[0] != '\0')
|
||||
@ -1430,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"));
|
||||
@ -1503,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);
|
||||
@ -1663,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);
|
||||
@ -1692,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)
|
||||
if (*line == '$')
|
||||
line = skip_reference (line+1);
|
||||
else
|
||||
++line;
|
||||
|
||||
if (*line == '\0')
|
||||
@ -1712,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;
|
||||
@ -1721,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);
|
||||
@ -1770,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));
|
||||
}
|
||||
|
||||
@ -1830,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);
|
||||
}
|
||||
@ -1851,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;
|
||||
}
|
||||
|
||||
@ -1921,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;
|
||||
@ -2139,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)
|
||||
@ -2206,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
|
||||
{
|
||||
@ -2235,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)
|
||||
{
|
||||
@ -2312,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)
|
||||
{
|
||||
@ -2328,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;
|
||||
}
|
||||
|
||||
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.
|
||||
@ -2364,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;
|
||||
}
|
||||
|
||||
@ -2699,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')
|
||||
@ -2753,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:
|
||||
|
||||
@ -2766,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)
|
||||
@ -2797,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; /* := */
|
||||
}
|
||||
else if (*p == ':')
|
||||
{
|
||||
++p;
|
||||
if (p[1] == '=')
|
||||
{
|
||||
++p;
|
||||
wtype = w_varassign; /* ::= */
|
||||
}
|
||||
else
|
||||
wtype = w_dcolon;
|
||||
}
|
||||
else
|
||||
wtype = w_colon;
|
||||
goto done;
|
||||
|
||||
case '&':
|
||||
@ -2837,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
|
||||
@ -2892,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 '\\':
|
||||
@ -2953,6 +2842,7 @@ get_next_mword (char *buffer, char **startp, size_t *length)
|
||||
*startp = beg;
|
||||
if (length)
|
||||
*length = p - beg;
|
||||
|
||||
return wtype;
|
||||
}
|
||||
|
||||
@ -2973,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
|
||||
@ -3032,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);
|
||||
@ -3049,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3071,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;
|
||||
@ -3086,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';
|
||||
@ -3108,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 ();
|
||||
@ -3120,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));
|
||||
@ -3129,7 +3021,7 @@ tilde_expand (const char *name)
|
||||
return new;
|
||||
}
|
||||
}
|
||||
# if !defined(_AMIGA) && !defined(WINDOWS32)
|
||||
# if !MK_OS_W32
|
||||
else
|
||||
{
|
||||
struct passwd *pwent;
|
||||
@ -3148,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;
|
||||
}
|
||||
|
||||
@ -3260,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
|
||||
@ -3292,7 +3179,8 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
|
||||
|
||||
/* Strip leading "this directory" references. */
|
||||
if (NONE_SET (flags, PARSEFS_NOSTRIP))
|
||||
#ifdef VMS
|
||||
{
|
||||
#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;
|
||||
@ -3308,6 +3196,7 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
|
||||
while (*s == '/')
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the filename just found, and skip it.
|
||||
Set NAME to the string, and NLEN to its length. */
|
||||
@ -3315,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.
|
||||
|
144
src/remake.c
144
src/remake.c
@ -1,5 +1,5 @@
|
||||
/* Basic dependency engine for GNU Make.
|
||||
Copyright (C) 1988-2023 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,10 +31,10 @@ 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>
|
||||
@ -69,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,
|
||||
@ -94,7 +102,7 @@ check_also_make (const struct file *file)
|
||||
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'."),
|
||||
_("warning: pattern recipe did not update peer target '%s'"),
|
||||
ad->file->name);
|
||||
}
|
||||
|
||||
@ -112,6 +120,7 @@ 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);
|
||||
@ -130,6 +139,7 @@ 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. */
|
||||
|
||||
@ -147,16 +157,14 @@ update_goal_chain (struct goaldep *goaldeps)
|
||||
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;
|
||||
@ -181,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
|
||||
@ -190,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
|
||||
@ -231,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;
|
||||
|
||||
@ -242,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. */
|
||||
@ -265,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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -347,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;
|
||||
@ -377,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)
|
||||
@ -515,14 +546,19 @@ update_file_1 (struct file *file, unsigned int depth)
|
||||
check_renamed (file);
|
||||
noexist = this_mtime == NONEXISTENT_MTIME;
|
||||
if (noexist)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -539,6 +575,11 @@ update_file_1 (struct file *file, unsigned int depth)
|
||||
if (noexist)
|
||||
{
|
||||
check_renamed (adfile);
|
||||
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));
|
||||
@ -605,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."),
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -821,8 +874,13 @@ update_file_1 (struct file *file, unsigned int depth)
|
||||
else if (d_mtime == NONEXISTENT_MTIME)
|
||||
{
|
||||
if (ISDB (DB_BASIC))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (ISDB (DB_BASIC))
|
||||
@ -1054,11 +1112,17 @@ notice_finished_file (struct file *file)
|
||||
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 (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,
|
||||
@ -1164,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)
|
||||
{
|
||||
@ -1431,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);
|
||||
@ -1469,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. */
|
||||
|
||||
@ -1500,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;
|
||||
}
|
||||
@ -1547,14 +1611,14 @@ 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[MAX_PATH+1], *tstart, *tend;
|
||||
const char *p = name + strlen (name);
|
||||
@ -1583,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);
|
||||
@ -1687,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.
|
||||
@ -1717,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;
|
||||
|
@ -3,7 +3,7 @@
|
||||
Please do not send bug reports or questions about it to
|
||||
the Make maintainers.
|
||||
|
||||
Copyright (C) 1988-2023 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Template for the remote job exportation interface to GNU Make.
|
||||
Copyright (C) 1988-2023 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
|
||||
|
47
src/rule.c
47
src/rule.c
@ -1,5 +1,5 @@
|
||||
/* Pattern and suffix rule internals for GNU Make.
|
||||
Copyright (C) 1988-2023 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
|
||||
@ -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));
|
||||
@ -353,10 +368,12 @@ convert_to_pattern (void)
|
||||
{
|
||||
if (posix_pedantic)
|
||||
continue;
|
||||
error (&f->cmds->fileinfo, 0,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for using pattern rules in GNU Make.
|
||||
Copyright (C) 1988-2023 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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Provide prerequisite shuffle support.
|
||||
Copyright (C) 2022-2023 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;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Declarations for target shuffling support.
|
||||
Copyright (C) 2022-2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 2022, 2024-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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert between signal names and numbers.
|
||||
Copyright (C) 1990-2023 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Constant string caching for GNU Make.
|
||||
Copyright (C) 2006-2023 Free Software Foundation, Inc.
|
||||
Copyright (C) 2006-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
|
||||
|
369
src/variable.c
369
src/variable.c
@ -1,5 +1,5 @@
|
||||
/* Internals of variables for GNU Make.
|
||||
Copyright (C) 1988-2023 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,10 +26,11 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#include "variable.h"
|
||||
#include "os.h"
|
||||
#include "rule.h"
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
#include "pathstuff.h"
|
||||
#endif
|
||||
#include "hash.h"
|
||||
#include "warning.h"
|
||||
|
||||
/* Incremented every time we enter target_environment(). */
|
||||
unsigned long long env_recursion = 0;
|
||||
@ -183,6 +184,24 @@ struct variable_set_list *current_variable_set_list = &global_setlist;
|
||||
|
||||
/* Implement variables. */
|
||||
|
||||
static void
|
||||
check_valid_name (const floc* flocp, const char *name, size_t length)
|
||||
{
|
||||
const char *cp, *end;
|
||||
|
||||
if (!warn_check (wt_invalid_var))
|
||||
return;
|
||||
|
||||
for (cp = name, end = name + length; cp < end; ++cp)
|
||||
if (ISSPACE (*cp))
|
||||
break;
|
||||
if (cp == end)
|
||||
return;
|
||||
|
||||
warning (wt_invalid_var, flocp,
|
||||
ONS (format, 0, _("invalid variable name '%.*s'"), (int)length, name));
|
||||
}
|
||||
|
||||
void
|
||||
init_hash_global_variable_set (void)
|
||||
{
|
||||
@ -207,6 +226,8 @@ define_variable_in_set (const char *name, size_t length,
|
||||
struct variable **var_slot;
|
||||
struct variable var_key;
|
||||
|
||||
check_valid_name (flocp, name, length);
|
||||
|
||||
if (set == NULL)
|
||||
set = &global_variable_set;
|
||||
|
||||
@ -215,7 +236,7 @@ define_variable_in_set (const char *name, size_t length,
|
||||
var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);
|
||||
v = *var_slot;
|
||||
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
/* VMS does not populate envp[] with DCL symbols and logical names which
|
||||
historically are mapped to environment variables.
|
||||
If the variable is not yet defined, then we need to check if getenv()
|
||||
@ -329,7 +350,7 @@ free_variable_set (struct variable_set_list *list)
|
||||
}
|
||||
|
||||
void
|
||||
undefine_variable_in_set (const char *name, size_t length,
|
||||
undefine_variable_in_set (const floc *flocp, const char *name, size_t length,
|
||||
enum variable_origin origin,
|
||||
struct variable_set *set)
|
||||
{
|
||||
@ -337,6 +358,8 @@ undefine_variable_in_set (const char *name, size_t length,
|
||||
struct variable **var_slot;
|
||||
struct variable var_key;
|
||||
|
||||
check_valid_name (flocp, name, length);
|
||||
|
||||
if (set == NULL)
|
||||
set = &global_variable_set;
|
||||
|
||||
@ -451,6 +474,25 @@ lookup_special_var (struct variable *var)
|
||||
}
|
||||
|
||||
|
||||
/* Check the variable name for validity. */
|
||||
static void
|
||||
check_variable_reference (const char *name, size_t length)
|
||||
{
|
||||
const char *cp, *end;
|
||||
|
||||
if (!warn_check (wt_invalid_ref))
|
||||
return;
|
||||
|
||||
for (cp = name, end = name + length; cp < end; ++cp)
|
||||
if (ISSPACE (*cp))
|
||||
break;
|
||||
if (cp == end)
|
||||
return;
|
||||
|
||||
warning (wt_invalid_ref, *expanding_var,
|
||||
ONS (format, 0, _("invalid variable reference '%.*s'"), (int)length, name));
|
||||
}
|
||||
|
||||
/* Lookup a variable whose name is a string starting at NAME
|
||||
and with LENGTH chars. NAME need not be null-terminated.
|
||||
Returns address of the 'struct variable' containing all info
|
||||
@ -463,6 +505,8 @@ lookup_variable (const char *name, size_t length)
|
||||
struct variable var_key;
|
||||
int is_parent = 0;
|
||||
|
||||
check_variable_reference (name, length);
|
||||
|
||||
var_key.name = (char *) name;
|
||||
var_key.length = (unsigned int) length;
|
||||
|
||||
@ -479,7 +523,7 @@ lookup_variable (const char *name, size_t length)
|
||||
is_parent |= setlist->next_is_parent;
|
||||
}
|
||||
|
||||
#ifdef VMS
|
||||
#if MK_OS_VMS
|
||||
/* VMS doesn't populate envp[] with DCL symbols and logical names, which
|
||||
historically are mapped to environment variables and returned by
|
||||
getenv(). */
|
||||
@ -520,9 +564,7 @@ lookup_variable (const char *name, size_t length)
|
||||
*nptr++ = '$';
|
||||
}
|
||||
else
|
||||
{
|
||||
*nptr++ = *sptr;
|
||||
}
|
||||
sptr++;
|
||||
}
|
||||
|
||||
@ -534,7 +576,7 @@ lookup_variable (const char *name, size_t length)
|
||||
return define_variable (vname, length, value, o_env, 1);
|
||||
}
|
||||
}
|
||||
#endif /* VMS */
|
||||
#endif /* MK_OS_VMS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -552,12 +594,11 @@ lookup_variable_for_file (const char *name, size_t length, struct file *file)
|
||||
if (file == NULL)
|
||||
return lookup_variable (name, length);
|
||||
|
||||
savev = current_variable_set_list;
|
||||
current_variable_set_list = file->variables;
|
||||
install_file_context (file, &savev, NULL);
|
||||
|
||||
var = lookup_variable (name, length);
|
||||
|
||||
current_variable_set_list = savev;
|
||||
restore_file_context (savev, NULL);
|
||||
|
||||
return var;
|
||||
}
|
||||
@ -573,6 +614,8 @@ lookup_variable_in_set (const char *name, size_t length,
|
||||
{
|
||||
struct variable var_key;
|
||||
|
||||
check_variable_reference (name, length);
|
||||
|
||||
var_key.name = (char *) name;
|
||||
var_key.length = (unsigned int) length;
|
||||
|
||||
@ -659,12 +702,10 @@ initialize_file_variables (struct file *file, int reading)
|
||||
v->flavor = f_simple;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = do_variable_definition (
|
||||
&p->variable.fileinfo, p->variable.name,
|
||||
p->variable.value, p->variable.origin,
|
||||
p->variable.flavor, 1);
|
||||
}
|
||||
&p->variable.fileinfo, p->variable.name, p->variable.value,
|
||||
p->variable.origin, p->variable.flavor,
|
||||
p->variable.conditional, s_pattern);
|
||||
|
||||
/* Also mark it as a per-target and copy export status. */
|
||||
v->per_target = p->variable.per_target;
|
||||
@ -733,7 +774,7 @@ push_new_variable_scope (void)
|
||||
global_setlist.next = current_variable_set_list;
|
||||
current_variable_set_list = &global_setlist;
|
||||
}
|
||||
return (current_variable_set_list);
|
||||
return current_variable_set_list;
|
||||
}
|
||||
|
||||
void
|
||||
@ -770,6 +811,39 @@ pop_variable_scope (void)
|
||||
hash_free (&set->table, 1);
|
||||
free (set);
|
||||
}
|
||||
|
||||
/* Install a new global context for FILE so that errors/warnings are shown
|
||||
in that context. Sets OLDLIST to the previous list, and if not NULL sets
|
||||
OLDFLOC to reading_file and changes reading_file to the current FILE.
|
||||
Use restore_file_context() to undo this. */
|
||||
|
||||
void
|
||||
install_file_context (struct file *file, struct variable_set_list **oldlist, const floc **oldfloc)
|
||||
{
|
||||
*oldlist = current_variable_set_list;
|
||||
current_variable_set_list = file->variables;
|
||||
|
||||
if (oldfloc)
|
||||
{
|
||||
*oldfloc = reading_file;
|
||||
if (file->cmds && file->cmds->fileinfo.filenm)
|
||||
reading_file = &file->cmds->fileinfo;
|
||||
else
|
||||
reading_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore a saved global context from OLDLIST. If OLDFLOC is not NULL,
|
||||
set reading_file back to that value. */
|
||||
|
||||
void
|
||||
restore_file_context (struct variable_set_list *oldlist, const floc *oldfloc)
|
||||
{
|
||||
current_variable_set_list = oldlist;
|
||||
if (oldfloc)
|
||||
reading_file = oldfloc;
|
||||
}
|
||||
|
||||
|
||||
/* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET. */
|
||||
|
||||
@ -871,7 +945,7 @@ define_automatic_variables (void)
|
||||
define_variable_cname ("MAKE_VERSION", buf, o_default, 0);
|
||||
define_variable_cname ("MAKE_HOST", make_host, o_default, 0);
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#if MK_OS_DOS
|
||||
/* Allow to specify a special shell just for Make,
|
||||
and use $COMSPEC as the default $SHELL when appropriate. */
|
||||
{
|
||||
@ -893,7 +967,7 @@ define_automatic_variables (void)
|
||||
(void) define_variable (shell_str, shlen, comp->value, o_env, 0);
|
||||
}
|
||||
}
|
||||
#elif defined(__EMX__)
|
||||
#elif MK_OS_OS2
|
||||
{
|
||||
static char shell_str[] = "SHELL";
|
||||
const int shlen = sizeof (shell_str) - 1;
|
||||
@ -946,7 +1020,7 @@ define_automatic_variables (void)
|
||||
/* This won't override any definition, but it will provide one if there
|
||||
isn't one there. */
|
||||
v = define_variable_cname ("SHELL", default_shell, o_default, 0);
|
||||
#ifdef __MSDOS__
|
||||
#if MK_OS_DOS
|
||||
v->export = v_export; /* Export always SHELL. */
|
||||
#endif
|
||||
|
||||
@ -954,7 +1028,7 @@ define_automatic_variables (void)
|
||||
environment variable on MSDOS, so whoever sets it, does that on purpose.
|
||||
On OS/2 we do not use SHELL from environment but we have already handled
|
||||
that problem above. */
|
||||
#if !defined(__MSDOS__) && !defined(__EMX__)
|
||||
#if !MK_OS_DOS && !MK_OS_OS2
|
||||
/* Don't let SHELL come from the environment. */
|
||||
if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override)
|
||||
{
|
||||
@ -971,7 +1045,7 @@ define_automatic_variables (void)
|
||||
/* Define the magic D and F variables in terms of
|
||||
the automatic variables they are variations of. */
|
||||
|
||||
#if defined(__MSDOS__) || defined(WINDOWS32)
|
||||
#if MK_OS_DOS || MK_OS_W32
|
||||
/* For consistency, remove the trailing backslash as well as slash. */
|
||||
define_variable_cname ("@D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $@)))",
|
||||
o_automatic, 1);
|
||||
@ -987,7 +1061,7 @@ define_automatic_variables (void)
|
||||
o_automatic, 1);
|
||||
define_variable_cname ("+D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $+)))",
|
||||
o_automatic, 1);
|
||||
#else /* not __MSDOS__, not WINDOWS32 */
|
||||
#else /* not MK_OS_DOS, not MK_OS_W32 */
|
||||
define_variable_cname ("@D", "$(patsubst %/,%,$(dir $@))", o_automatic, 1);
|
||||
define_variable_cname ("%D", "$(patsubst %/,%,$(dir $%))", o_automatic, 1);
|
||||
define_variable_cname ("*D", "$(patsubst %/,%,$(dir $*))", o_automatic, 1);
|
||||
@ -1005,7 +1079,6 @@ define_automatic_variables (void)
|
||||
define_variable_cname ("+F", "$(notdir $+)", o_automatic, 1);
|
||||
}
|
||||
|
||||
int export_all_variables;
|
||||
|
||||
static int
|
||||
should_export (const struct variable *v)
|
||||
@ -1210,7 +1283,7 @@ target_environment (struct file *file, int recursive)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
if (streq (v->name, "Path") || streq (v->name, "PATH"))
|
||||
{
|
||||
if (!cp)
|
||||
@ -1252,11 +1325,18 @@ set_special_var (struct variable *var, enum variable_origin origin)
|
||||
reset_makeflags (origin);
|
||||
|
||||
else if (streq (var->name, RECIPEPREFIX_NAME))
|
||||
{
|
||||
/* The user is resetting the command introduction prefix. This has to
|
||||
happen immediately, so that subsequent rules are interpreted
|
||||
properly. */
|
||||
cmd_prefix = var->value[0]=='\0' ? RECIPEPREFIX_DEFAULT : var->value[0];
|
||||
|
||||
else if (streq (var->name, WARNINGS_NAME))
|
||||
{
|
||||
/* It's weird but for .WARNINGS to make sense we need to expand them
|
||||
when they are set, even if it's a recursive variable. */
|
||||
char *actions = allocated_expand_variable (STRING_SIZE_TUPLE (WARNINGS_NAME));
|
||||
decode_warn_actions (actions, &var->fileinfo);
|
||||
free (actions);
|
||||
}
|
||||
|
||||
return var;
|
||||
@ -1272,32 +1352,36 @@ shell_result (const char *p)
|
||||
char *buf;
|
||||
size_t len;
|
||||
char *args[2];
|
||||
char *result;
|
||||
|
||||
install_variable_buffer (&buf, &len);
|
||||
|
||||
args[0] = (char *) p;
|
||||
args[1] = NULL;
|
||||
variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1);
|
||||
result = strdup (variable_buffer);
|
||||
func_shell_base (variable_buffer, args, 0);
|
||||
|
||||
restore_variable_buffer (buf, len);
|
||||
return result;
|
||||
return swap_variable_buffer (buf, len);
|
||||
}
|
||||
|
||||
/* Given a variable, a value, and a flavor, define the variable.
|
||||
See the try_variable_definition() function for details on the parameters. */
|
||||
|
||||
struct variable *
|
||||
do_variable_definition (const floc *flocp, const char *varname,
|
||||
const char *value, enum variable_origin origin,
|
||||
enum variable_flavor flavor, int target_var)
|
||||
do_variable_definition (const floc *flocp, const char *varname, const char *value,
|
||||
enum variable_origin origin, enum variable_flavor flavor,
|
||||
int conditional, enum variable_scope scope)
|
||||
{
|
||||
const char *newval;
|
||||
char *alloc_value = NULL;
|
||||
struct variable *v;
|
||||
int append = 0;
|
||||
int conditional = 0;
|
||||
|
||||
/* Conditional variable definition: only set if the var is not defined. */
|
||||
if (conditional)
|
||||
{
|
||||
v = lookup_variable (varname, strlen (varname));
|
||||
if (v)
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Calculate the variable's new value in VALUE. */
|
||||
|
||||
@ -1308,14 +1392,14 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
We have to allocate memory since otherwise it'll clobber the
|
||||
variable buffer, and we may still need that if we're looking at a
|
||||
target-specific variable. */
|
||||
newval = alloc_value = allocated_variable_expand (value);
|
||||
newval = alloc_value = allocated_expand_string (value);
|
||||
break;
|
||||
case f_expand:
|
||||
{
|
||||
/* A POSIX "var :::= value" assignment. Expand the value, then it
|
||||
becomes a recursive variable. After expansion convert all '$'
|
||||
tokens to '$$' to resolve to '$' when recursively expanded. */
|
||||
char *t = allocated_variable_expand (value);
|
||||
char *t = allocated_expand_string (value);
|
||||
char *np = alloc_value = xmalloc (strlen (t) * 2 + 1);
|
||||
char *op = t;
|
||||
while (op[0] != '\0')
|
||||
@ -1333,23 +1417,13 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
{
|
||||
/* A shell definition "var != value". Expand value, pass it to
|
||||
the shell, and store the result in recursively-expanded var. */
|
||||
char *q = allocated_variable_expand (value);
|
||||
char *q = allocated_expand_string (value);
|
||||
alloc_value = shell_result (q);
|
||||
free (q);
|
||||
flavor = f_recursive;
|
||||
newval = alloc_value;
|
||||
break;
|
||||
}
|
||||
case f_conditional:
|
||||
/* A conditional variable definition "var ?= value".
|
||||
The value is set IFF the variable is not defined yet. */
|
||||
v = lookup_variable (varname, strlen (varname));
|
||||
if (v)
|
||||
goto done;
|
||||
|
||||
conditional = 1;
|
||||
flavor = f_recursive;
|
||||
/* FALLTHROUGH */
|
||||
case f_recursive:
|
||||
/* A recursive variable definition "var = value".
|
||||
The value is used verbatim. */
|
||||
@ -1358,29 +1432,56 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
case f_append:
|
||||
case f_append_value:
|
||||
{
|
||||
/* If we have += but we're in a target variable context, we want to
|
||||
append only with other variables in the context of this target. */
|
||||
if (target_var)
|
||||
int override = 0;
|
||||
if (scope == s_global)
|
||||
v = lookup_variable (varname, strlen (varname));
|
||||
else
|
||||
{
|
||||
/* When appending in a target/pattern variable context, we want to
|
||||
append only with other variables in the context of this
|
||||
target/pattern. */
|
||||
append = 1;
|
||||
v = lookup_variable_in_set (varname, strlen (varname),
|
||||
current_variable_set_list->set);
|
||||
|
||||
/* Don't append from the global set if a previous non-appending
|
||||
target-specific variable definition exists. */
|
||||
if (v && !v->append)
|
||||
append = 0;
|
||||
}
|
||||
else
|
||||
v = lookup_variable (varname, strlen (varname));
|
||||
|
||||
if (v == 0)
|
||||
if (v)
|
||||
{
|
||||
/* There was no old value.
|
||||
This becomes a normal recursive definition. */
|
||||
/* Don't append from the global set if a previous non-appending
|
||||
target/pattern-specific variable definition exists. */
|
||||
if (!v->append)
|
||||
append = 0;
|
||||
|
||||
if (scope == s_pattern &&
|
||||
(v->origin == o_env_override || v->origin == o_command))
|
||||
{
|
||||
/* This is the case of multiple target/pattern specific
|
||||
definitions/appends, e.g.
|
||||
al%: hello := first
|
||||
al%: hello += second
|
||||
in the presence of a command line definition or an
|
||||
env override. Do not merge x->value and value here.
|
||||
For pattern-specific variables the values are merged in
|
||||
recursively_expand_for_file. */
|
||||
override = 1;
|
||||
append = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!v)
|
||||
{
|
||||
/* There was no old value: make this a recursive definition. */
|
||||
newval = value;
|
||||
flavor = f_recursive;
|
||||
}
|
||||
else if (override)
|
||||
{
|
||||
/* Command line definition / env override takes precedence over
|
||||
a pattern/target-specific append. */
|
||||
newval = value;
|
||||
/* Set flavor to f_recursive to recursively expand this variable
|
||||
at build time in recursively_expand_for_file. */
|
||||
flavor = f_recursive;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Paste the old and new values together in VALUE. */
|
||||
@ -1401,7 +1502,7 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
when it was set; and from the expanded new value. Allocate
|
||||
memory for the expansion as we may still need the rest of the
|
||||
buffer if we're looking at a target-specific variable. */
|
||||
val = tp = allocated_variable_expand (val);
|
||||
val = tp = allocated_expand_string (val);
|
||||
|
||||
/* If the new value is empty, nothing to do. */
|
||||
vallen = strlen (val);
|
||||
@ -1419,7 +1520,7 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
{
|
||||
char *s;
|
||||
if (streq (varname, MAKEFLAGS_NAME)
|
||||
&& (s = strstr (v->value, " -- ")))
|
||||
&& (s = strstr (v->value, " -- ")) != NULL)
|
||||
/* We found a separator in MAKEFLAGS. Ignore variable
|
||||
assignments: set_special_var() will reconstruct things. */
|
||||
cp = mempcpy (cp, v->value, s - v->value);
|
||||
@ -1442,7 +1543,7 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
|
||||
assert (newval);
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#if MK_OS_DOS
|
||||
/* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but
|
||||
non-Unix systems don't conform to this default configuration (in
|
||||
fact, most of them don't even have '/bin'). On the other hand,
|
||||
@ -1522,8 +1623,8 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* __MSDOS__ */
|
||||
#ifdef WINDOWS32
|
||||
#endif /* MK_OS_DOS */
|
||||
#if MK_OS_W32
|
||||
if ((origin == o_file || origin == o_override || origin == o_command)
|
||||
&& streq (varname, "SHELL"))
|
||||
{
|
||||
@ -1537,9 +1638,8 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
{
|
||||
v = define_variable_in_set (varname, strlen (varname), default_shell,
|
||||
origin, flavor == f_recursive,
|
||||
(target_var
|
||||
? current_variable_set_list->set
|
||||
: NULL),
|
||||
(scope == s_global ? NULL
|
||||
: current_variable_set_list->set),
|
||||
flocp);
|
||||
no_default_sh_exe = 0;
|
||||
}
|
||||
@ -1547,15 +1647,14 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
{
|
||||
char *tp = alloc_value;
|
||||
|
||||
alloc_value = allocated_variable_expand (newval);
|
||||
alloc_value = allocated_expand_string (newval);
|
||||
|
||||
if (find_and_set_default_shell (alloc_value))
|
||||
{
|
||||
v = define_variable_in_set (varname, strlen (varname), newval,
|
||||
origin, flavor == f_recursive,
|
||||
(target_var
|
||||
? current_variable_set_list->set
|
||||
: NULL),
|
||||
(scope == s_global ? NULL
|
||||
: current_variable_set_list->set),
|
||||
flocp);
|
||||
no_default_sh_exe = 0;
|
||||
}
|
||||
@ -1581,8 +1680,8 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
|
||||
v = define_variable_in_set (varname, strlen (varname), newval, origin,
|
||||
flavor == f_recursive || flavor == f_expand,
|
||||
(target_var
|
||||
? current_variable_set_list->set : NULL),
|
||||
(scope == s_global
|
||||
? NULL : current_variable_set_list->set),
|
||||
flocp);
|
||||
v->append = append;
|
||||
v->conditional = conditional;
|
||||
@ -1603,6 +1702,7 @@ do_variable_definition (const floc *flocp, const char *varname,
|
||||
length : length of the variable name
|
||||
value : value of the variable (nul-terminated)
|
||||
flavor : flavor of the variable
|
||||
conditional : whether it's a conditional assignment
|
||||
Other values in *VAR are unchanged.
|
||||
*/
|
||||
|
||||
@ -1615,11 +1715,13 @@ parse_variable_definition (const char *str, struct variable *var)
|
||||
NEXT_TOKEN (p);
|
||||
var->name = (char *)p;
|
||||
var->length = 0;
|
||||
var->conditional = 0;
|
||||
|
||||
/* Walk through STR until we find a valid assignment operator. Each time
|
||||
through this loop P points to the next character to consider. */
|
||||
while (1)
|
||||
{
|
||||
const char *start;
|
||||
int c = *p++;
|
||||
|
||||
/* If we find a comment or EOS, it's not a variable definition. */
|
||||
@ -1637,26 +1739,36 @@ parse_variable_definition (const char *str, struct variable *var)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This is the start of a token. */
|
||||
start = p - 1;
|
||||
|
||||
/* If we see a ? then it could be a conditional assignment. */
|
||||
if (c == '?')
|
||||
{
|
||||
var->conditional = 1;
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
/* If we found = we're done! */
|
||||
if (c == '=')
|
||||
{
|
||||
if (!end)
|
||||
end = p - 1;
|
||||
var->flavor = f_recursive;
|
||||
end = start;
|
||||
var->flavor = f_recursive; /* = */
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == ':')
|
||||
{
|
||||
if (!end)
|
||||
end = p - 1;
|
||||
end = start;
|
||||
|
||||
/* We need to distinguish :=, ::=, and :::=, and : outside of an
|
||||
/* We need to distinguish :=, ::=, and :::=, versus : outside of an
|
||||
assignment (which means this is not a variable definition). */
|
||||
c = *p++;
|
||||
if (c == '=')
|
||||
{
|
||||
var->flavor = f_simple;
|
||||
var->flavor = f_simple; /* := */
|
||||
break;
|
||||
}
|
||||
if (c == ':')
|
||||
@ -1664,12 +1776,12 @@ parse_variable_definition (const char *str, struct variable *var)
|
||||
c = *p++;
|
||||
if (c == '=')
|
||||
{
|
||||
var->flavor = f_simple;
|
||||
var->flavor = f_simple; /* ::= */
|
||||
break;
|
||||
}
|
||||
if (c == ':' && *p++ == '=')
|
||||
{
|
||||
var->flavor = f_expand;
|
||||
var->flavor = f_expand; /* :::= */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1682,20 +1794,17 @@ parse_variable_definition (const char *str, struct variable *var)
|
||||
switch (c)
|
||||
{
|
||||
case '+':
|
||||
var->flavor = f_append;
|
||||
break;
|
||||
case '?':
|
||||
var->flavor = f_conditional;
|
||||
var->flavor = f_append; /* += */
|
||||
break;
|
||||
case '!':
|
||||
var->flavor = f_shell;
|
||||
var->flavor = f_shell; /* != */
|
||||
break;
|
||||
default:
|
||||
goto other;
|
||||
}
|
||||
|
||||
if (!end)
|
||||
end = p - 1;
|
||||
end = start;
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
@ -1708,47 +1817,16 @@ parse_variable_definition (const char *str, struct variable *var)
|
||||
return NULL;
|
||||
|
||||
if (c == '$')
|
||||
{
|
||||
/* Skip any variable reference, to ensure we don't treat chars
|
||||
inside the reference as assignment operators. */
|
||||
char closeparen;
|
||||
unsigned int count;
|
||||
p = skip_reference (p);
|
||||
|
||||
c = *p++;
|
||||
switch (c)
|
||||
{
|
||||
case '(':
|
||||
closeparen = ')';
|
||||
break;
|
||||
case '{':
|
||||
closeparen = '}';
|
||||
break;
|
||||
case '\0':
|
||||
return NULL;
|
||||
default:
|
||||
/* '$$' or '$X': skip it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* P now points past the opening paren or brace. Count parens or
|
||||
braces until we find the closing paren/brace. */
|
||||
for (count = 1; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == closeparen && --count == 0)
|
||||
{
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
if (*p == c)
|
||||
++count;
|
||||
}
|
||||
}
|
||||
var->conditional = 0;
|
||||
}
|
||||
|
||||
/* We found a valid variable assignment: END points to the char after the
|
||||
end of the variable name and P points to the char after the =. */
|
||||
var->length = (unsigned int) (end - var->name);
|
||||
var->value = next_token (p);
|
||||
|
||||
return (char *)p;
|
||||
}
|
||||
|
||||
@ -1770,7 +1848,7 @@ assign_variable_definition (struct variable *v, const char *line)
|
||||
name = alloca (v->length + 1);
|
||||
memcpy (name, v->name, v->length);
|
||||
name[v->length] = '\0';
|
||||
v->name = allocated_variable_expand (name);
|
||||
v->name = allocated_expand_string (name);
|
||||
|
||||
if (v->name[0] == '\0')
|
||||
O (fatal, &v->fileinfo, _("empty variable name"));
|
||||
@ -1793,7 +1871,7 @@ assign_variable_definition (struct variable *v, const char *line)
|
||||
|
||||
struct variable *
|
||||
try_variable_definition (const floc *flocp, const char *line,
|
||||
enum variable_origin origin, int target_var)
|
||||
enum variable_origin origin, enum variable_scope scope)
|
||||
{
|
||||
struct variable v;
|
||||
struct variable *vp;
|
||||
@ -1806,8 +1884,8 @@ try_variable_definition (const floc *flocp, const char *line,
|
||||
if (!assign_variable_definition (&v, line))
|
||||
return 0;
|
||||
|
||||
vp = do_variable_definition (flocp, v.name, v.value,
|
||||
origin, v.flavor, target_var);
|
||||
vp = do_variable_definition (flocp, v.name, v.value, origin, v.flavor,
|
||||
v.conditional, scope);
|
||||
|
||||
free (v.name);
|
||||
|
||||
@ -1834,23 +1912,43 @@ static const struct defined_vars defined_vars[] = {
|
||||
{ STRING_SIZE_TUPLE ("-*-eval-flags-*-") },
|
||||
{ STRING_SIZE_TUPLE ("VPATH") },
|
||||
{ STRING_SIZE_TUPLE ("GPATH") },
|
||||
{ STRING_SIZE_TUPLE (WARNINGS_NAME) },
|
||||
{ STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
void
|
||||
warn_undefined (const char *name, size_t len)
|
||||
{
|
||||
if (warn_undefined_variables_flag)
|
||||
if (warn_check (wt_undefined_var))
|
||||
{
|
||||
const struct defined_vars *dp;
|
||||
for (dp = defined_vars; dp->name != NULL; ++dp)
|
||||
if (dp->len == len && memcmp (dp->name, name, len) == 0)
|
||||
return;
|
||||
|
||||
error (reading_file, len, _("warning: undefined variable '%.*s'"),
|
||||
(int)len, name);
|
||||
warning (wt_undefined_var, reading_file,
|
||||
ONS (format, 0, _("reference to undefined variable '%.*s'"),
|
||||
(int)len, name));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_env_override (const void *item, void *arg UNUSED)
|
||||
{
|
||||
struct variable *v = (struct variable *)item;
|
||||
enum variable_origin old = env_overrides ? o_env : o_env_override;
|
||||
enum variable_origin new = env_overrides ? o_env_override : o_env;
|
||||
|
||||
if (v->origin == old)
|
||||
v->origin = new;
|
||||
}
|
||||
|
||||
void
|
||||
reset_env_override ()
|
||||
{
|
||||
hash_map_arg (&global_variable_set.table, set_env_override, NULL);
|
||||
}
|
||||
|
||||
/* Print information for variable V, prefixing it with PREFIX. */
|
||||
|
||||
@ -1925,7 +2023,6 @@ print_variable (const void *item, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_auto_variable (const void *item, void *arg)
|
||||
{
|
||||
@ -1935,7 +2032,6 @@ print_auto_variable (const void *item, void *arg)
|
||||
print_variable (item, arg);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_noauto_variable (const void *item, void *arg)
|
||||
{
|
||||
@ -1945,7 +2041,6 @@ print_noauto_variable (const void *item, void *arg)
|
||||
print_variable (item, arg);
|
||||
}
|
||||
|
||||
|
||||
/* Print all the variables in SET. PREFIX is printed before
|
||||
the actual variable definitions (everything else is comments). */
|
||||
|
||||
@ -2017,18 +2112,18 @@ print_target_variables (const struct file *file)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#if MK_OS_W32
|
||||
void
|
||||
sync_Path_environment ()
|
||||
{
|
||||
static char *environ_path = NULL;
|
||||
char *oldpath = environ_path;
|
||||
char *path = allocated_variable_expand ("PATH=$(PATH)");
|
||||
char *path = allocated_expand_string ("PATH=$(PATH)");
|
||||
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
/* Convert the value of PATH into something WINDOWS32 world can grok.
|
||||
/* Convert the value of PATH into something Windows32 world can grok.
|
||||
Note: convert_Path_to_windows32 must see only the value of PATH,
|
||||
and see it from its first character, to do its tricky job. */
|
||||
convert_Path_to_windows32 (path + CSTRLEN ("PATH="), ';');
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user