Compare commits

..

No commits in common. "master" and "4.4.0.91" have entirely different histories.

191 changed files with 4740 additions and 7780 deletions

4
.ccls
View File

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

14
.clangd
View File

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

View File

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

2
.gitignore vendored
View File

@ -59,8 +59,6 @@ WinDebug/
WinRel/ WinRel/
GccDebug/ GccDebug/
GccRel/ GccRel/
TccDebug/
TccRel/
# Test artifacts # Test artifacts
makeerror-* makeerror-*

View File

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

View File

@ -10,7 +10,7 @@
# #
# make.exe -f Basic.mk # make.exe -f Basic.mk
# #
# Copyright (C) 2017-2024 Free Software Foundation, Inc. # Copyright (C) 2017-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # GNU Make is free software; you can redistribute it and/or modify it under
@ -37,6 +37,7 @@ loadavg_SOURCES = %loadavg_SOURCES%
alloca_SOURCES = %alloca_SOURCES% alloca_SOURCES = %alloca_SOURCES%
w32_SOURCES = %w32_SOURCES% w32_SOURCES = %w32_SOURCES%
vms_SOURCES = %vms_SOURCES% vms_SOURCES = %vms_SOURCES%
amiga_SOURCES = %amiga_SOURCES%
remote_SOURCES = $(src)remote-stub.c remote_SOURCES = $(src)remote-stub.c
@ -59,8 +60,6 @@ BUILT_SOURCES =
OBJECTS = $(patsubst %.c,$(OUTDIR)%.$(OBJEXT),$(prog_SOURCES)) OBJECTS = $(patsubst %.c,$(OUTDIR)%.$(OBJEXT),$(prog_SOURCES))
RESOURCE_OBJECTS =
OBJDIRS = $(addsuffix .,$(sort $(dir $(OBJECTS)))) OBJDIRS = $(addsuffix .,$(sort $(dir $(OBJECTS))))
# Use the default value of CC # Use the default value of CC
@ -101,7 +100,7 @@ RM.cmd = rm -f $1
# $(call CP.cmd,<from>,<to>) # $(call CP.cmd,<from>,<to>)
CP.cmd = cp $1 $2 CP.cmd = cp $1 $2
CLEANSPACE = $(call RM.cmd,$(OBJECTS) $(RESOURCE_OBJECTS) $(PROG) $(BUILT_SOURCES)) CLEANSPACE = $(call RM.cmd,$(OBJECTS) $(PROG) $(BUILT_SOURCES))
# Load overrides for the above variables. # Load overrides for the above variables.
include $(firstword $(wildcard $(SRCDIR)/mk/$(lastword $(subst -, ,$(MAKE_HOST)).mk))) include $(firstword $(wildcard $(SRCDIR)/mk/$(lastword $(subst -, ,$(MAKE_HOST)).mk)))
@ -110,7 +109,7 @@ VPATH = $(SRCDIR)
all: $(PROG) all: $(PROG)
$(PROG): $(OBJECTS) $(RESOURCE_OBJECTS) $(PROG): $(OBJECTS)
$(call LINK.cmd,$^) $(call LINK.cmd,$^)
$(OBJECTS): $(OUTDIR)%.$(OBJEXT): %.c $(OBJECTS): $(OUTDIR)%.$(OBJEXT): %.c

View File

@ -1,6 +1,6 @@
# This is a -*-Makefile-*-, or close enough # This is a -*-Makefile-*-, or close enough
# #
# Copyright (C) 1997-2024 Free Software Foundation, Inc. # Copyright (C) 1997-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # 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/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/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/signame.c src/strcache.c src/variable.c src/variable.h \
src/version.c src/vpath.c src/warning.c src/warning.h src/version.c src/vpath.c
w32_SRCS = src/w32/pathstuff.c src/w32/w32os.c src/w32/compat/dirent.c \ 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 \ 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/misc.c src/w32/subproc/proc.h \
src/w32/subproc/sub_proc.c src/w32/subproc/w32err.c 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 \ vms_SRCS = src/vms_exit.c src/vms_export_symbol.c src/vms_progname.c \
src/vmsdir.h src/vmsfunctions.c src/vmsify.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 glob_SRCS = lib/fnmatch.c lib/fnmatch.h lib/glob.c lib/glob.h
alloca_SRCS = lib/alloca.c alloca_SRCS = lib/alloca.c
@ -58,7 +58,7 @@ alloca_SRCS = lib/alloca.c
loadavg_SRCS = lib/getloadavg.c loadavg_SRCS = lib/getloadavg.c
make_SOURCES = $(make_SRCS) make_SOURCES = $(make_SRCS)
EXTRA_make_SOURCES = $(vms_SRCS) EXTRA_make_SOURCES = $(amiga_SRCS) $(vms_SRCS)
if HAVE_GUILE if HAVE_GUILE
_GUILE_CFLAGS = $(GUILE_CFLAGS) _GUILE_CFLAGS = $(GUILE_CFLAGS)
@ -90,15 +90,6 @@ else
make_SOURCES += src/posixos.c make_SOURCES += src/posixos.c
endif endif
UTF8OBJ = src/w32/utf8.$(OBJEXT)
if HAVE_WINDRES
make_LDADD += $(UTF8OBJ)
endif
$(UTF8OBJ) : $(w32_utf8_SRCS)
$(WINDRES) -o $@ -i $<
if USE_CUSTOMS if USE_CUSTOMS
make_SOURCES += src/remote-cstms.c make_SOURCES += src/remote-cstms.c
else else
@ -107,7 +98,7 @@ endif
# Extra stuff to include in the distribution. # Extra stuff to include in the distribution.
mk_FILES = Basic.mk mk/msdosdjgpp.mk mk/VMS.mk mk/Windows32.mk mk_FILES = Basic.mk mk/msdosdjgpp.mk mk/Amiga.mk mk/VMS.mk mk/Windows32.mk
# We don't need this, since the standard automake output will do. # We don't need this, since the standard automake output will do.
#mk/Posix.mk.in #mk/Posix.mk.in
@ -122,12 +113,13 @@ test_FILES = tests/run_make_tests tests/run_make_tests.bat \
EXTRA_DIST = ChangeLog INSTALL README build.sh build.cfg.in $(man_MANS) \ EXTRA_DIST = ChangeLog INSTALL README build.sh build.cfg.in $(man_MANS) \
src/mkconfig.h README.customs README.OS2 README.zOS \ src/mkconfig.h README.customs README.OS2 README.zOS \
README.Amiga SCOPTIONS src/config.ami \
README.DOS builddos.bat src/configh.dos \ README.DOS builddos.bat src/configh.dos \
README.W32 build_w32.bat src/config.h.W32 \ README.W32 build_w32.bat src/config.h.W32 \
README.VMS makefile.com src/config.h-vms src/vmsjobs.c \ README.VMS makefile.com src/config.h-vms src/vmsjobs.c \
vms_export_symbol_test.com \ vms_export_symbol_test.com \
src/gmk-default.scm src/gmk-default.h \ src/gmk-default.scm src/gmk-default.h \
$(mk_FILES) $(m4_FILES) $(test_FILES) $(w32_utf8_SRCS) $(mk_FILES) $(m4_FILES) $(test_FILES)
# --------------- Generate the Guile default module content # --------------- Generate the Guile default module content
@ -163,6 +155,8 @@ check-local: check-regression
# > check-regression # > check-regression
# #
# Look for the make test suite, and run it if found and we can find perl. # 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 = MAKETESTFLAGS =
@ -177,8 +171,7 @@ errorpre = makeerror-$(PACKAGE_VERSION)-$(host_triplet)
testfiles = $(testlog) $(testresult) $(errorfile) testfiles = $(testlog) $(testresult) $(errorfile)
MOSTLYCLEANFILES = $(testfiles) MOSTLYCLEANFILES = $(testfiles)
errordetails = config.status config.log src/config.h src/mkconfig.h \ errordetails = config.status config.log src/config.h $(testlog) tests/work
$(testlog) tests/work
# Create a 4-letter random sequence # Create a 4-letter random sequence
rand_value = c = "abcdefghijklmnopqrstuvwxyz0123456789" rand_value = c = "abcdefghijklmnopqrstuvwxyz0123456789"
@ -186,13 +179,20 @@ rand_char = substr(c,int(rand()*36),1)
rand_string = $(AWK) 'BEGIN{srand(); $(rand_value); print $(rand_char) "" $(rand_char) "" $(rand_char) "" $(rand_char);}' rand_string = $(AWK) 'BEGIN{srand(); $(rand_value); print $(rand_char) "" $(rand_char) "" $(rand_char) "" $(rand_char);}'
check-regression: tests/config-flags.pm check-regression: tests/config-flags.pm
$(AM_V_at) rm -f $(testfiles) @rm -f $(testfiles)
$(AM_V_at) if test -f '$(top_srcdir)/tests/run_make_tests.pl'; then \ @if test -f '$(top_srcdir)/tests/run_make_tests'; then \
ulimit -n 128; \ ulimit -n 128; \
if $(PERL) -v >/dev/null 2>&1; then \ if $(PERL) -v >/dev/null 2>&1; then \
echo "cd tests && $(PERL) $(PERLFLAGS) $(abs_top_srcdir)/tests/run_make_tests.pl -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)"; \ case `cd '$(top_srcdir)'; pwd` in `pwd`) : ;; \
(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); \ *) test -d tests || mkdir tests; \
export TAR_OPTIONS='$(filter-out --sort%,$(TAR_OPTIONS))'; \ 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); \
er=$$(cat $(testresult)); if test "$$er" -ne 0; then \ er=$$(cat $(testresult)); if test "$$er" -ne 0; then \
dirnm="$(errorpre)-$$($(rand_string))"; fnm="$$dirnm.tar.gz"; \ dirnm="$(errorpre)-$$($(rand_string))"; fnm="$$dirnm.tar.gz"; \
rm -rf "$$dirnm"; mkdir "$$dirnm"; \ rm -rf "$$dirnm"; mkdir "$$dirnm"; \

114
NEWS
View File

@ -1,6 +1,6 @@
GNU Make NEWS -*-indented-text-*- GNU Make NEWS -*-indented-text-*-
History of user-visible changes. History of user-visible changes.
26 February 2023 19 February 2023
See the end of this file for copyrights and conditions. See the end of this file for copyrights and conditions.
@ -10,97 +10,7 @@ See the README file and the GNU Make manual for instructions for
reporting bugs. reporting bugs.
Version 4.4.90 (26 Feb 2023) Version 4.4.0.91 (19 Feb 2023)
A complete list of bugs fixed in this version is available here:
https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&set=custom
* WARNING: Removed AmigaOS support!
This version of GNU Make no longer supports AmigaOS. If you need support
for AmigaOS please use one of the older versions of GNU Make.
* WARNING: Loaded Object ABI incompatibility!
This release changes the loaded object feature from "technology preview" to
fully-supported feature. However, it introduces an ABI incompatibility with
previous releases: the setup function now takes an ABI version as its first
argument. At compile time you can test the GMK_ABI_VERSION constant to
detect which ABI should be used. At runtime your initialization function
can check the provided ABI version to verify it's being loaded correctly.
* WARNING: Backward-incompatibility!
Parsing of the first argument in ifeq/ifneq with () has been cleaned up.
When locating the separating "," any variable reference (single char as well
as using $() or ${}) is skipped. However parentheses that are not part of
or contained in variable references will not be counted. This means that
things like "ifeq ((foo,bar),)" are now syntax errors. Use a variable to
hide the comma if needed: "COMMA = ," / "ifeq ((foo$(COMMA)bar),)".
See https://savannah.gnu.org/bugs/index.php?64402
* WARNING: Backward-incompatibility!
If -e is given all environment variables will now have an origin of
"environment override" even if they are not otherwise set in the makefile.
See https://savannah.gnu.org/bugs/index.php?64803
* WARNING: Backward-incompatibility!
The behavior of appending to pattern-specific variables has been clarified
when combined with command-line settings or -e overrides.
See https://savannah.gnu.org/bugs/index.php?64822
* NOTE: Deprecated behavior.
The check in GNU Make 4.3 for suffix rules with prerequisites didn't check
single-suffix rules, only double-suffix rules. Add the missing check.
* New feature: Any assignment operator can be made conditional
GNU Make has long supported the conditional operator "?=" which creates a
recursive variable set to a value if and only if the variable is not already
defined. In this release, the "?" can precede any assignment operator to
make it conditional. For example, "?:=" creates a simply-expanded variable
and expands the right-hand side if and only if the variable is not already
defined. The constructs "?::=", "?:::=", and "?!=" also behave as expected.
* New feature: Unload function for loaded objects
When a loaded object needs to be unloaded by GNU Make, it will invoke an
unload function (if one is defined) beforehand that allows the object to
perform cleanup operations.
Original idea and implementation: Dmitry Goncharov <dgoncharov@users.sf.net>
* New feature: Makefile warning reporting control
A new option "--warn" controls reporting of warnings for makefiles. Actions
can be set to "ignore", "warn", or "error". Two new warnings are reported:
assigning to invalid variable names, and referencing invalid variable names
(both set to "warn" by default), in addition to the existing warning for
undefined variables (defaults to "ignore"). "--warn-undefined-variables" is
deprecated, and is translated to "--warn=undefined-vars" internally.
* New feature: Control warnings with the .WARNINGS variable
In addition to --warn from the command line, which takes effect for make
invoked recursively, warnings can be controlled only for the current
instance of make using the .WARNINGS variable.
* New feature: Printing targets defined by the makefile
A new option "--print-targets" will print all explicit, non-special targets
defined in the makefiles, one per line, then exit with success. No recipes
are invoked and no makefiles are re-built.
* Warnings for detecting circular dependencies are controllable via warning
reporting, with the name "circular-dep".
* 'make --print-data-base' (or 'make -p') now outputs time of day
using the same form as for file timestamps, e.g., "2023-05-10
10:43:57.570558743". Previously it used the form "Wed May 10
10:43:57 2023", which has less detail and is harder to compare.
* Conditional statements starting with the recipe prefix were sometimes
interpreted in previous versions. As per the documentation, lines starting
with the recipe prefix are now never considered conditional statements.
* Tests in the regression test suite now are run in their own directory to
avoid cross-contamination and allow cleanup if the tests are interrupted.
More information is printed about failing tests.
Version 4.4.1 (26 Feb 2023)
This release is primarily a bug-fix release. This release is primarily a bug-fix release.
A complete list of bugs fixed in this version is available here: A complete list of bugs fixed in this version is available here:
@ -122,21 +32,21 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=110&se
builds with archive creation. See the "Dangers When Using Archives" section builds with archive creation. See the "Dangers When Using Archives" section
of the GNU Make manual, and https://savannah.gnu.org/bugs/index.php?14927 of the GNU Make manual, and https://savannah.gnu.org/bugs/index.php?14927
* New platform: GNU Make is supported on z/OS
Thanks to Igor Todorovski <itodorov@ca.ibm.com> for the patches and testing
assistance.
* Previously target-specific variables would inherit their "export" capability * Previously target-specific variables would inherit their "export" capability
from parent target-specific variables even if they were marked private. Now from parent target-specific variables even if they were marked private. Now
private parent target-specific variables have no affect. For more details private parent target-specific variables have no affect. For more details
see https://savannah.gnu.org/bugs/index.php?61463 see https://savannah.gnu.org/bugs/index.php?61463
* Disable FIFO jobserver on GNU/Hurd and Cygwin
Experimentation shows that the new FIFO-based jobserver doesn't work well on
GNU/Hurd or Cygwin: revert these systems to use the pipe-based jobserver.
* Updates to allow building on OS/2 * Updates to allow building on OS/2
Provided by KO Myung-Hun <komh78@gmail.com> Provided by KO Myung-Hun <komh78@gmail.com>
* New platform: GNU Make is supported on z/OS * Disable FIFO jobserver on GNU/Hurd and Cygwin
Thanks to Igor Todorovski <itodorov@ca.ibm.com> for the patches and testing Experimentation shows that the new FIFO-based jobserver doesn't work well on
assistance. GNU/Hurd or Cygwin: revert these systems to use the pipe-based jobserver.
Version 4.4 (31 Oct 2022) Version 4.4 (31 Oct 2022)
@ -1015,7 +925,7 @@ Version 3.80 (03 Oct 2002)
* This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com. * 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 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. GNU Make 3.60 by Mike Moretti.
It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and
@ -1255,7 +1165,7 @@ Version 3.77 (28 Jul 1998)
* This is the VMS port of GNU Make. * This is the VMS port of GNU Make.
It is based on the VMS port of GNU Make 3.60 by Mike Moretti. 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. * There is first-level support available from proGIS Software, Germany.
Visit their web-site at https://www.progis.de to get information Visit their web-site at https://www.progis.de to get information
@ -1948,7 +1858,7 @@ Version 3.05
(Changes from versions 1 through 3.05 were never recorded. Sorry.) (Changes from versions 1 through 3.05 were never recorded. Sorry.)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the

80
README.Amiga Normal file
View File

@ -0,0 +1,80 @@
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/>.

View File

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

View File

@ -163,7 +163,7 @@ from the make source tree.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2003-2024 Free Software Foundation, Inc. Copyright (C) 2003-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the

View File

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

View File

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

View File

@ -1,7 +1,7 @@
-*-text-*- -*-text-*-
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2002-2024 Free Software Foundation, Inc. Copyright (C) 2002-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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. to build and test GNU Make.
NOTE! This method builds GNU Make in "maintainer mode". Make programs built NOTE! This method builds GNU Make in "maintainer mode". Make programs built
in this mode will be slower, possibly MUCH slower: there are various in this mode it will be slower, possibly MUCH slower: there are various
sanity checks enabled. Further this mode assumes a modern GCC, GNU sanity checks enabled. Further this mode assumes a modern GCC, GNU
libc, and well-formed system headers and enables a high level of libc, and well-formed system headers and enables a high level of
warnings AND enables -Werror to turn warnings into failures. warnings AND enables -Werror to turn warnings into failures.
@ -155,8 +155,7 @@ NOTE! This method builds GNU Make in "maintainer mode". Make programs built
If you want to build from Git with "maintainer mode" disabled, add 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 "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 off the extra warning flags, add "MAKE_CFLAGS=" to the make command
line. If you want to keep the warnings but not fail, add line.
"EXTRA_CFLAGS=-Wno-error" to the make command line.
For example: For example:
$ ./configure $ ./configure
@ -210,13 +209,6 @@ work on non-GNU systems (Windows, MacOS, etc.)
make clean make clean
make -j8 CFLAGS='-ggdb3 -fsanitize=address' LDFLAGS='-ggdb3 -fsanitize=address' 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 make check
Note that ASAN is reporting many more errors than valgrind. I don't know Note that ASAN is reporting many more errors than valgrind. I don't know
@ -259,7 +251,6 @@ consistent (that's why we don't finalize the Git tag, etc. until the end).
* Update the configure.ac file with the new release number. * Update the configure.ac file with the new release number.
* Update the EDITION value in the doc/make.texi file. * Update the EDITION value in the doc/make.texi file.
* Update the doc/make.1 file with the release date.
* Update the NEWS file with the release number and date. * Update the NEWS file with the release number and date.
* Ensure the Savannah bug list URL in the NEWS file uses the correct * Ensure the Savannah bug list URL in the NEWS file uses the correct
"Fixed Release" ID number. "Fixed Release" ID number.
@ -343,15 +334,10 @@ When publishing a final release there are extra steps that need to be taken:
Manage the Savannah project for GNU Make: Manage the Savannah project for GNU Make:
* In Savannah edit the "Component Version" field and choose the "SCM" entry. * In Savannah modify the "Value", "Rank", and "Description" values for the
Modify the "Value", "Rank", and "Description" values for the to refer to current "SCM" entry in both "Component Version" and "Fix Release" fields
the new release. The "Rank" field should be 10 less than the previous to refer to the new release. The "Rank" field should be 10 less than the
release so it orders properly. 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: * In Savannah create a new entry for the "Component Version" field:
- Value: SCM - Value: SCM

View File

@ -3,15 +3,11 @@ This directory contains the @PACKAGE_VERSION@ release of @PACKAGE_NAME@.
See the file NEWS for the user-visible changes from previous releases. See the file NEWS for the user-visible changes from previous releases.
In addition, there have been bugs fixed. 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 Please check the system-specific notes below for any caveats related to your
operating system. operating system.
This README assumes you are building on a POSIX-based operating system. If you are trying to build GNU Make from a Git clone rather than a downloaded
For ports to other operating systems please see the system-specific README source distribution, see the README.git file for instructions.
files, as described in the "Ports" section below.
For source distribution building and installation instructions, see the file For source distribution building and installation instructions, see the file
INSTALL. INSTALL.
@ -33,7 +29,6 @@ GNU Make is copyright by the Free Software Foundation. Copyright notices
condense sequential years into a range; e.g. "1987-1994" means all years condense sequential years into a range; e.g. "1987-1994" means all years
from 1987 to 1994 inclusive. from 1987 to 1994 inclusive.
Downloading Downloading
----------- -----------
@ -145,6 +140,16 @@ known to be broken to be checked in. Use at your own risk.
System-specific Notes 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 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 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 debug this code, you can do 'make check-loadavg' to see if it works
@ -177,6 +182,8 @@ Ports
- See README.VMS for details about GNU Make on OpenVMS. - 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.zOS for details about GNU Make on z/OS.
- See README.W32 for details about GNU Make on Windows NT, 95, or 98. - See README.W32 for details about GNU Make on Windows NT, 95, or 98.
@ -194,13 +201,13 @@ Ports
it you should start by asking on those mailing lists and forums. it you should start by asking on those mailing lists and forums.
Please note there are two _separate_ ports of GNU Make for Microsoft Please note there are two _separate_ ports of GNU Make for Microsoft
systems: a native Windows port built with (for example) MSVC or MinGW, systems: a native Windows tool built with (for example) MSVC or Cygwin,
and a DOS-based port built with DJGPP. Please be sure you are looking and a DOS-based tool built with DJGPP. Please be sure you are looking
at the right README! at the right README!
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the

13
SCOPTIONS Normal file
View File

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

View File

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

View File

@ -4,7 +4,7 @@
# also regenerates all aclocal.m4, config.h.in, Makefile.in, configure files # also regenerates all aclocal.m4, config.h.in, Makefile.in, configure files
# with new versions of autoconf or automake. # with new versions of autoconf or automake.
# Copyright (C) 2003-2024 Free Software Foundation, Inc. # Copyright (C) 2003-2023 Free Software Foundation, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
# Convenience script for fetching auxiliary files that are omitted from # Convenience script for fetching auxiliary files that are omitted from
# the version control repository of this package. # the version control repository of this package.
# Copyright (C) 2003-2024 Free Software Foundation, Inc. # Copyright (C) 2003-2023 Free Software Foundation, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
scriptlibversion=2022-12-27.16; # UTC scriptlibversion=2022-12-27.16; # UTC
# Copyright (C) 2003-2024 Free Software Foundation, Inc. # Copyright (C) 2003-2023 Free Software Foundation, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
@echo off @echo off
:: Copyright (C) 2018-2024 Free Software Foundation, Inc. :: Copyright (C) 2018-2023 Free Software Foundation, Inc.
:: This file is part of GNU Make. :: This file is part of GNU Make.
:: ::
:: GNU Make is free software; you can redistribute it and/or modify it under :: GNU Make is free software; you can redistribute it and/or modify it under

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# Shell script to build GNU Make in the absence of any 'make' program. # Shell script to build GNU Make in the absence of any 'make' program.
# Copyright (C) 1993-2024 Free Software Foundation, Inc. # Copyright (C) 1993-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # GNU Make is free software; you can redistribute it and/or modify it under

View File

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

View File

@ -1,5 +1,5 @@
@echo off @echo off
rem Copyright (C) 1998-2024 Free Software Foundation, Inc. rem Copyright (C) 1998-2023 Free Software Foundation, Inc.
rem This file is part of GNU Make. rem This file is part of GNU Make.
rem rem
rem GNU Make is free software; you can redistribute it and/or modify it under rem GNU Make is free software; you can redistribute it and/or modify it under
@ -56,7 +56,6 @@ 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/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/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/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/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/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 gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/vpath.c -o vpath.o
@ -75,7 +74,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 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 off
echo commands.o > respf.$$$ echo commands.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 (job output dir file misc main read remake rule implicit default variable 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 (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.$$$ 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 gcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/guile.c -o guile.o

View File

@ -1,6 +1,6 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
# #
# Copyright (C) 1993-2024 Free Software Foundation, Inc. # Copyright (C) 1993-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # 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 # You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>. # this program. If not, see <https://www.gnu.org/licenses/>.
AC_INIT([GNU Make],[4.4.90],[bug-make@gnu.org]) AC_INIT([GNU Make],[4.4.0.91],[bug-make@gnu.org])
AC_PREREQ([2.69]) AC_PREREQ([2.69])
@ -67,8 +67,8 @@ AC_HEADER_DIRENT
AC_HEADER_STAT AC_HEADER_STAT
AC_CHECK_HEADERS([stdlib.h string.h strings.h locale.h unistd.h limits.h \ AC_CHECK_HEADERS([stdlib.h string.h strings.h locale.h unistd.h limits.h \
memory.h sys/param.h sys/resource.h sys/time.h sys/select.h \ memory.h sys/param.h sys/resource.h sys/timeb.h sys/time.h \
sys/file.h fcntl.h spawn.h]) sys/select.h sys/file.h fcntl.h spawn.h])
AM_PROG_CC_C_O AM_PROG_CC_C_O
AC_C_CONST AC_C_CONST
@ -353,14 +353,14 @@ AS_CASE([/$make_cv_load/$user_load/],
# For example passing -rdynamic to the SunPRO linker gives a warning # For example passing -rdynamic to the SunPRO linker gives a warning
# but succeeds and creates a shared object, not an executable! # but succeeds and creates a shared object, not an executable!
AS_IF([test "$make_cv_load" = yes], [ AS_IF([test "$make_cv_load" = yes], [
AC_MSG_CHECKING([if the linker accepts -Wl,--export-dynamic]) AC_MSG_CHECKING([If the linker accepts -Wl,--export-dynamic])
old_LDFLAGS="$LDFLAGS" old_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,--export-dynamic" LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])], AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])],
[AC_MSG_RESULT([yes]) [AC_MSG_RESULT([yes])
AC_SUBST([AM_LDFLAGS], [-Wl,--export-dynamic])], AC_SUBST([AM_LDFLAGS], [-Wl,--export-dynamic])],
[AC_MSG_RESULT([no]) [AC_MSG_RESULT([no])
AC_MSG_CHECKING([if the linker accepts -rdynamic]) AC_MSG_CHECKING([If the linker accepts -rdynamic])
LDFLAGS="$old_LDFLAGS -rdynamic" LDFLAGS="$old_LDFLAGS -rdynamic"
AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])], AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])],
[AC_MSG_RESULT([yes]) [AC_MSG_RESULT([yes])
@ -444,18 +444,13 @@ AC_SUBST([MAKE_HOST])
w32_target_env=no w32_target_env=no
AM_CONDITIONAL([WINDOWSENV], [false]) AM_CONDITIONAL([WINDOWSENV], [false])
AM_CONDITIONAL([HAVE_WINDRES], [false])
AS_CASE([$host], AS_CASE([$host],
[*-*-mingw32], [*-*-mingw32],
[AM_CONDITIONAL([WINDOWSENV], [true]) [AM_CONDITIONAL([WINDOWSENV], [true])
w32_target_env=yes w32_target_env=yes
AC_DEFINE([MK_OS_W32], [1], [Build for the Windows32 API.]) AC_DEFINE([WINDOWS32], [1], [Build for the WINDOWS32 API.])
AC_DEFINE([HAVE_DOS_PATHS], [1], [Support DOS-style pathnames.]) 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'], AC_DEFINE_UNQUOTED([PATH_SEPARATOR_CHAR],['$PATH_SEPARATOR'],

1
doc/.gitignore vendored
View File

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

View File

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

View File

@ -1,4 +1,4 @@
.TH MAKE 1 "26 May 2023" "GNU" "User Commands" .TH MAKE 1 "31 May 2022" "GNU" "User Commands"
.SH NAME .SH NAME
make \- GNU Make utility to maintain groups of programs make \- GNU Make utility to maintain groups of programs
.SH SYNOPSIS .SH SYNOPSIS
@ -76,8 +76,9 @@ listing, right near other important files such as
The first name checked, The first name checked,
.IR GNUmakefile , .IR GNUmakefile ,
is not recommended for most makefiles. You should use this name if you have a is not recommended for most makefiles. You should use this name if you have a
makefile that is specific to GNU Make, and will not be understood by other makefile that is specific to GNU
versions of .BR make ,
and will not be understood by other versions of
.BR make . .BR make .
If If
.I makefile .I makefile
@ -270,15 +271,10 @@ reading the makefiles; then execute as usual or as otherwise
specified. specified.
This also prints the version information given by the This also prints the version information given by the
.B \-v .B \-v
switch (see below). To print the built-in data base only, use switch (see below).
To print the data base without trying to remake any files, use
.IR "make \-p \-f/dev/null" . .IR "make \-p \-f/dev/null" .
.TP 0.5i .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 \fB\-q\fR, \fB\-\-question\fR
``Question mode''. ``Question mode''.
Do not run any commands, or print anything; just return an exit status Do not run any commands, or print anything; just return an exit status
@ -369,59 +365,12 @@ command on the given file before running
except that the modification time is changed only in the imagination of except that the modification time is changed only in the imagination of
.BR make . .BR make .
.TP 0.5i .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 .B \-\-warn\-undefined\-variables
A deprecated alternative for Warn when an undefined variable is referenced.
.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" .SH "EXIT STATUS"
GNU Make exits with a status of zero if all makefiles were successfully parsed GNU
.B 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 and no targets that were built failed. A status of one will be returned
if the if the
.B \-q .B \-q
@ -449,7 +398,7 @@ This manual page contributed by Dennis Morse of Stanford University.
Further updates contributed by Mike Frysinger. It has been reworked by Roland Further updates contributed by Mike Frysinger. It has been reworked by Roland
McGrath. Maintained by Paul Smith. McGrath. Maintained by Paul Smith.
.SH "COPYRIGHT" .SH "COPYRIGHT"
Copyright \(co 1992\(en1993, 1996\(en2024 Free Software Foundation, Inc. Copyright \(co 1992-1993, 1996-2023 Free Software Foundation, Inc.
This file is part of This file is part of
.IR "GNU Make" . .IR "GNU Make" .
.LP .LP

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public License You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. along with this library; see the file COPYING.LIB. If not, write to the Free
If not, see <https://www.gnu.org/licenses/>. */ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
# include <config.h> # include <config.h>

View File

@ -13,8 +13,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public License You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. along with this library; see the file COPYING.LIB. If not, write to the Free
If not, see <https://www.gnu.org/licenses/>. */ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
#ifndef _FNMATCH_H #ifndef _FNMATCH_H
#define _FNMATCH_H 1 #define _FNMATCH_H 1

View File

@ -12,8 +12,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public License You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. along with this library; see the file COPYING.LIB. If not, write to the Free
If not, see <https://www.gnu.org/licenses/>. */ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
/* AIX requires this to be the first thing in the file. */ /* AIX requires this to be the first thing in the file. */
#if defined _AIX && !defined __GNUC__ #if defined _AIX && !defined __GNUC__
@ -70,7 +71,7 @@ If not, see <https://www.gnu.org/licenses/>. */
# endif # endif
#endif #endif
#if !defined _AMIGA && !MK_OS_VMS && !MK_OS_W32 #if !defined _AMIGA && !defined VMS && !defined WINDOWS32
# include <pwd.h> # include <pwd.h>
#endif #endif
@ -114,7 +115,7 @@ extern int errno;
#endif #endif
#if (defined POSIX || MK_OS_W32) && !defined __GNU_LIBRARY__ #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
/* Posix does not require that the d_ino field be present, and some /* Posix does not require that the d_ino field be present, and some
systems do not provide it. */ systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1 # define REAL_DIR_ENTRY(dp) 1
@ -145,11 +146,11 @@ extern int errno;
# include <alloca.h> # include <alloca.h>
# else /* Not HAVE_ALLOCA_H. */ # else /* Not HAVE_ALLOCA_H. */
# ifndef _AIX # ifndef _AIX
# if MK_OS_W32 # ifdef WINDOWS32
# include <malloc.h> # include <malloc.h>
# else # else
extern char *alloca (); extern char *alloca ();
# endif /* MK_OS_W32 */ # endif /* WINDOWS32 */
# endif /* Not _AIX. */ # endif /* Not _AIX. */
# endif /* sparc or HAVE_ALLOCA_H. */ # endif /* sparc or HAVE_ALLOCA_H. */
# endif /* GCC. */ # endif /* GCC. */
@ -415,14 +416,14 @@ glob (const char *pattern, int flags,
/* Find the filename. */ /* Find the filename. */
filename = strrchr (pattern, '/'); filename = strrchr (pattern, '/');
#if MK_OS_DOS || MK_OS_W32 #if defined __MSDOS__ || defined WINDOWS32
/* The case of "d:pattern". Since `:' is not allowed in /* The case of "d:pattern". Since `:' is not allowed in
file names, we can safely assume that wherever it file names, we can safely assume that wherever it
happens in pattern, it signals the filename part. This happens in pattern, it signals the filename part. This
is so we could some day support patterns like "[a-z]:foo". */ is so we could some day support patterns like "[a-z]:foo". */
if (filename == NULL) if (filename == NULL)
filename = strchr (pattern, ':'); filename = strchr (pattern, ':');
#endif /* MK_OS_DOS || MK_OS_W32 */ #endif /* __MSDOS__ || WINDOWS32 */
if (filename == NULL) if (filename == NULL)
{ {
/* This can mean two things: a simple name or "~name". The later /* This can mean two things: a simple name or "~name". The later
@ -459,7 +460,7 @@ glob (const char *pattern, int flags,
{ {
char *newp; char *newp;
dirlen = filename - pattern; dirlen = filename - pattern;
#if MK_OS_DOS || MK_OS_W32 #if defined __MSDOS__ || defined WINDOWS32
if (*filename == ':' if (*filename == ':'
|| (filename > pattern + 1 && filename[-1] == ':')) || (filename > pattern + 1 && filename[-1] == ':'))
{ {
@ -493,7 +494,7 @@ glob (const char *pattern, int flags,
++filename; ++filename;
if (filename[0] == '\0' if (filename[0] == '\0'
#if MK_OS_DOS || MK_OS_W32 #if defined __MSDOS__ || defined WINDOWS32
&& dirname[dirlen - 1] != ':' && dirname[dirlen - 1] != ':'
&& (dirlen < 3 || dirname[dirlen - 2] != ':' && (dirlen < 3 || dirname[dirlen - 2] != ':'
|| dirname[dirlen - 1] != '/') || dirname[dirlen - 1] != '/')
@ -517,13 +518,13 @@ glob (const char *pattern, int flags,
oldcount = pglob->gl_pathc; oldcount = pglob->gl_pathc;
#if !MK_OS_VMS #ifndef VMS
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
{ {
if (dirname[1] == '\0' || dirname[1] == '/') if (dirname[1] == '\0' || dirname[1] == '/')
{ {
/* Look up home directory. */ /* Look up home directory. */
#if MK_OS_VMS #ifdef VMS
/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */ /* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
const char *home_dir = getenv ("SYS$LOGIN"); const char *home_dir = getenv ("SYS$LOGIN");
#else #else
@ -533,11 +534,11 @@ glob (const char *pattern, int flags,
if (home_dir == NULL || home_dir[0] == '\0') if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS:"; home_dir = "SYS:";
# else # else
# if MK_OS_W32 # ifdef WINDOWS32
if (home_dir == NULL || home_dir[0] == '\0') if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "c:/users/default"; /* poor default */ home_dir = "c:/users/default"; /* poor default */
# else # else
# if MK_OS_VMS # ifdef VMS
/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */ /* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
if (home_dir == NULL || home_dir[0] == '\0') if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS$DISK:[]"; home_dir = "SYS$DISK:[]";
@ -600,8 +601,8 @@ glob (const char *pattern, int flags,
else else
home_dir = "~"; /* No luck. */ home_dir = "~"; /* No luck. */
} }
# endif /* MK_OS_VMS */ # endif /* VMS */
# endif /* MK_OS_W32 */ # endif /* WINDOWS32 */
# endif # endif
/* Now construct the full directory. */ /* Now construct the full directory. */
if (dirname[1] == '\0') if (dirname[1] == '\0')
@ -621,7 +622,7 @@ glob (const char *pattern, int flags,
dirname = newp; dirname = newp;
} }
} }
# if !defined _AMIGA && !MK_OS_W32 && !MK_OS_VMS # if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
else else
{ {
char *end_name = strchr (dirname, '/'); char *end_name = strchr (dirname, '/');
@ -701,9 +702,9 @@ glob (const char *pattern, int flags,
home directory. */ home directory. */
return GLOB_NOMATCH; return GLOB_NOMATCH;
} }
# endif /* Not Amiga && not MK_OS_W32 && not MK_OS_VMS. */ # endif /* Not Amiga && not WINDOWS32 && not VMS. */
} }
#endif /* Not MK_OS_VMS. */ #endif /* Not VMS. */
/* Now test whether we looked for "~" or "~NAME". In this case we /* Now test whether we looked for "~" or "~NAME". In this case we
can give the answer now. */ can give the answer now. */
@ -1010,7 +1011,7 @@ prefix_array (const char *dirname, char **array, size_t n)
{ {
size_t i; size_t i;
size_t dirlen = strlen (dirname); size_t dirlen = strlen (dirname);
#if MK_OS_DOS || MK_OS_W32 #if defined __MSDOS__ || defined WINDOWS32
char sep_char = '/'; char sep_char = '/';
# define DIRSEP_CHAR sep_char # define DIRSEP_CHAR sep_char
#else #else
@ -1021,7 +1022,7 @@ prefix_array (const char *dirname, char **array, size_t n)
/* DIRNAME is just "/", so normal prepending would get us "//foo". /* DIRNAME is just "/", so normal prepending would get us "//foo".
We want "/foo" instead, so don't prepend any chars from DIRNAME. */ We want "/foo" instead, so don't prepend any chars from DIRNAME. */
dirlen = 0; dirlen = 0;
#if MK_OS_DOS || MK_OS_W32 #if defined __MSDOS__ || defined WINDOWS32
else if (dirlen > 1) else if (dirlen > 1)
{ {
if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
@ -1123,7 +1124,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
int meta; int meta;
int save; int save;
#if MK_OS_VMS #ifdef VMS
if (*directory == 0) if (*directory == 0)
directory = "[]"; directory = "[]";
#endif #endif

View File

@ -12,8 +12,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public License You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. along with this library; see the file COPYING.LIB. If not, write to the Free
If not, see <https://www.gnu.org/licenses/>. */ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA. */
#ifndef _GLOB_H #ifndef _GLOB_H
#define _GLOB_H 1 #define _GLOB_H 1
@ -66,7 +67,7 @@ extern "C" {
#endif #endif
/* Structure describing a globbing run. */ /* Structure describing a globbing run. */
#if !defined _AMIGA && !MK_OS_VMS /* Buggy compiler. */ #if !defined _AMIGA && !defined VMS /* Buggy compiler. */
struct stat; struct stat;
#endif #endif
typedef struct typedef struct
@ -82,7 +83,7 @@ typedef struct
struct dirent *(*gl_readdir) (void *); struct dirent *(*gl_readdir) (void *);
void * (*gl_opendir) (const char *); void * (*gl_opendir) (const char *);
int (*gl_lstat) (const char *, struct stat *); int (*gl_lstat) (const char *, struct stat *);
#if MK_OS_VMS && defined(__DECC) && !defined(_POSIX_C_SOURCE) #if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
int (*gl_stat) (const char *, struct stat *, ...); int (*gl_stat) (const char *, struct stat *, ...);
#else #else
int (*gl_stat) (const char *, struct stat *); int (*gl_stat) (const char *, struct stat *);

View File

@ -1,7 +1,7 @@
dnl acinclude.m4 -- Extra macros needed for GNU Make. dnl acinclude.m4 -- Extra macros needed for GNU Make.
dnl dnl
dnl Automake will incorporate this into its generated aclocal.m4. dnl Automake will incorporate this into its generated aclocal.m4.
dnl Copyright (C) 1998-2024 Free Software Foundation, Inc. dnl Copyright (C) 1998-2023 Free Software Foundation, Inc.
dnl This file is part of GNU Make. dnl This file is part of GNU Make.
dnl dnl
dnl GNU Make is free software; you can redistribute it and/or modify it under dnl GNU Make is free software; you can redistribute it and/or modify it under

View File

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

View File

@ -1,6 +1,6 @@
# Check for getloadavg. # Check for getloadavg.
# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2024 Free # Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2023 Free
# Software Foundation, Inc. # Software Foundation, Inc.
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation

View File

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

View File

@ -34,10 +34,7 @@ MAKE_CFLAGS := -C -Wall -Wextra -Werror -Wwrite-strings -Wshadow \
-Wtype-limits -Wunused-but-set-parameter -Wlogical-op -Wpointer-arith \ -Wtype-limits -Wunused-but-set-parameter -Wlogical-op -Wpointer-arith \
-Wignored-qualifiers -Wformat-signedness -Wduplicated-cond -Wignored-qualifiers -Wformat-signedness -Wduplicated-cond
# Allow extra options without overriding MAKE_CFLAGS AM_CFLAGS += $(MAKE_CFLAGS)
EXTRA_CFLAGS :=
AM_CFLAGS += $(MAKE_CFLAGS) $(EXTRA_CFLAGS)
# Unfortunately the Guile headers are sometimes broken. Convince GCC # Unfortunately the Guile headers are sometimes broken. Convince GCC
# to treat them as system headers so warnings are ignored. # to treat them as system headers so warnings are ignored.
@ -70,6 +67,7 @@ Basic.mk: Basic.mk.template .dep_segment Makefile
sed -e 's@%make_SOURCES%@$(call cvt,src,$(make_SRCS))@g' \ sed -e 's@%make_SOURCES%@$(call cvt,src,$(make_SRCS))@g' \
-e 's@%w32_SOURCES%@$(call cvt,src,$(w32_SRCS))@g' \ -e 's@%w32_SOURCES%@$(call cvt,src,$(w32_SRCS))@g' \
-e 's@%vms_SOURCES%@$(call cvt,src,$(vms_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@%loadavg_SOURCES%@$(call cvt,lib,$(loadavg_SRCS))@g' \
-e 's@%alloca_SOURCES%@$(call cvt,lib,$(alloca_SRCS))@g' \ -e 's@%alloca_SOURCES%@$(call cvt,lib,$(alloca_SRCS))@g' \
-e 's@%glob_SOURCES%@$(call cvt,lib,$(glob_SRCS))@g' \ -e 's@%glob_SOURCES%@$(call cvt,lib,$(glob_SRCS))@g' \
@ -519,7 +517,7 @@ $(UPLOADS): upload-%: $(DIST_ARCHIVES)
# Rebuild Makefile.in if this file is modified. # Rebuild Makefile.in if this file is modified.
Makefile.in: maintMakefile Makefile.in: maintMakefile
# Copyright (C) 1997-2024 Free Software Foundation, Inc. # Copyright (C) 1997-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # GNU Make is free software; you can redistribute it and/or modify it under

View File

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

45
mk/Amiga.mk Normal file
View File

@ -0,0 +1,45 @@
# 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,$<,$@)

View File

@ -2,7 +2,7 @@
# #
# POSIX overrides for use with Basic.mk. # POSIX overrides for use with Basic.mk.
# #
# Copyright (C) 2017-2024 Free Software Foundation, Inc. # Copyright (C) 2017-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -2,7 +2,7 @@
# #
# VMS overrides for use with Basic.mk. # VMS overrides for use with Basic.mk.
# #
# Copyright (C) 2017-2024 Free Software Foundation, Inc. # Copyright (C) 2017-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # GNU Make is free software; you can redistribute it and/or modify it under

View File

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

View File

@ -2,7 +2,7 @@
# #
# MS-DOS overrides for use with Basic.mk. # MS-DOS overrides for use with Basic.mk.
# #
# Copyright (C) 2017-2024 Free Software Foundation, Inc. # Copyright (C) 2017-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# GNU Make is free software; you can redistribute it and/or modify it under # GNU Make is free software; you can redistribute it and/or modify it under

View File

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

View File

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

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2014-2024 Free Software Foundation, Inc. # Copyright (C) 2014-2023 Free Software Foundation, Inc.
# This file is part of GNU Make. # This file is part of GNU Make.
# #
# Update GNU Make copyrights using gnulib update-copyright # Update GNU Make copyrights using gnulib update-copyright

113
src/amiga.c Normal file
View File

@ -0,0 +1,113 @@
/* 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 Normal file
View File

@ -0,0 +1,18 @@
/* 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);

View File

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

View File

@ -1,5 +1,5 @@
/* Library function for scanning an archive file. /* Library function for scanning an archive file.
Copyright (C) 1987-2024 Free Software Foundation, Inc. Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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 #ifndef NO_ARCHIVES
#if MK_OS_VMS #ifdef VMS
#include <lbrdef.h> #include <lbrdef.h>
#include <mhddef.h> #include <mhddef.h>
#include <credef.h> #include <credef.h>
@ -289,7 +289,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *varg)
return -2; return -2;
} }
#else /* !MK_OS_VMS */ #else /* !VMS */
/* SCO Unix's compiler defines both of these. */ /* SCO Unix's compiler defines both of these. */
#ifdef M_UNIX #ifdef M_UNIX
@ -330,7 +330,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *varg)
# define __AR_BIG__ # define __AR_BIG__
#endif #endif
#if !MK_OS_W32 #ifndef WINDOWS32
# if !defined (__ANDROID__) && !defined (__BEOS__) && !defined(MK_OS_ZOS) # if !defined (__ANDROID__) && !defined (__BEOS__) && !defined(MK_OS_ZOS)
# include <ar.h> # include <ar.h>
# else # else
@ -395,12 +395,16 @@ parse_int (const char *ptr, const size_t len, const int base, uintmax_t max,
while (ptr < ep && *ptr != ' ') while (ptr < ep && *ptr != ' ')
{ {
if (*ptr < '0' || *ptr > maxchar uintmax_t nv;
|| INT_MULTIPLY_WRAPV (val, base, &val)
|| INT_ADD_WRAPV (val, *ptr - '0', &val) if (*ptr < '0' || *ptr > maxchar)
|| val > max)
OSSS (fatal, NILF, OSSS (fatal, NILF,
_("invalid %s for archive %s member %s"), type, archive, name); _("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;
++ptr; ++ptr;
} }
@ -837,7 +841,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
close (desc); close (desc);
return -2; return -2;
} }
#endif /* !MK_OS_VMS */ #endif /* !VMS */
/* Return nonzero iff NAME matches MEM. /* Return nonzero iff NAME matches MEM.
If TRUNCATED is nonzero, MEM may be truncated to If TRUNCATED is nonzero, MEM may be truncated to
@ -848,16 +852,11 @@ ar_name_equal (const char *name, const char *mem, int truncated)
{ {
const char *p; 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, '/'); p = strrchr (name, '/');
if (p != 0) if (p != 0)
name = p + 1; name = p + 1;
#if !MK_OS_VMS #ifndef VMS
if (truncated) if (truncated)
{ {
#ifdef AIAMAG #ifdef AIAMAG
@ -897,10 +896,10 @@ ar_name_equal (const char *name, const char *mem, int truncated)
match = !strcasecmp (name, mem); match = !strcasecmp (name, mem);
return match; return match;
} }
#endif /* !MK_OS_VMS */ #endif /* !VMS */
} }
#if !MK_OS_VMS #ifndef VMS
/* ARGSUSED */ /* ARGSUSED */
static intmax_t static intmax_t
ar_member_pos (int desc UNUSED, const char *mem, int truncated, ar_member_pos (int desc UNUSED, const char *mem, int truncated,
@ -954,7 +953,7 @@ ar_member_touch (const char *arname, const char *memname)
if (r < 0) if (r < 0)
goto lose; goto lose;
/* Advance member's time to that time */ /* Advance member's time to that time */
#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || MK_OS_W32 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
datelen = snprintf (TOCHAR (ar_hdr.ar_date), sizeof ar_hdr.ar_date, datelen = snprintf (TOCHAR (ar_hdr.ar_date), sizeof ar_hdr.ar_date,
"%" PRIdMAX, (intmax_t) statbuf.st_mtime); "%" PRIdMAX, (intmax_t) statbuf.st_mtime);
if (! (0 <= datelen && datelen < (int) sizeof ar_hdr.ar_date)) if (! (0 <= datelen && datelen < (int) sizeof ar_hdr.ar_date))

View File

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

View File

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

334
src/config.ami Normal file
View File

@ -0,0 +1,334 @@
/* 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"

View File

@ -1,6 +1,6 @@
/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> -*-C-*- /* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> -*-C-*-
Copyright (C) 1996-2024 Free Software Foundation, Inc. Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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" #include "mkconfig.h"
#define MK_OS_VMS 1 #define MK_VMS 1
/* Pull in types.h here to get __CRTL_VER defined for old versions of the /* Pull in types.h here to get __CRTL_VER defined for old versions of the
compiler which don't define it. */ compiler which don't define it. */
@ -339,6 +339,11 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 1 if you have the <sys/param.h> header file. */ /* Define to 1 if you have the <sys/param.h> header file. */
/* #undef HAVE_SYS_PARAM_H */ /* #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. */ /* Define to 1 if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H */ /* #undef HAVE_SYS_WAIT_H */

View File

@ -1,6 +1,6 @@
/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*- /* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*-
Copyright (C) 1996-2024 Free Software Foundation, Inc. Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -17,8 +17,10 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "mkconfig.h" #include "mkconfig.h"
/* Build for the Windows32 API. */ #define MK_W32 1
#define MK_OS_W32 1
/* Build for the WINDOWS32 API. */
#define WINDOWS32 1
/* Suppress some Visual C++ warnings. /* Suppress some Visual C++ warnings.
Maybe after the code cleanup for ISO C we can remove some/all of these. */ Maybe after the code cleanup for ISO C we can remove some/all of these. */
@ -388,6 +390,9 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 1 if you have the <sys/stat.h> header file. */ /* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1 #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. */ /* Define to 1 if you have the <sys/time.h> header file. */
#ifdef __MINGW32__ #ifdef __MINGW32__
#define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TIME_H 1

View File

@ -1,6 +1,6 @@
/* configh.dos -- hand-massaged config.h file for MS-DOS builds -*-C-*- /* configh.dos -- hand-massaged config.h file for MS-DOS builds -*-C-*-
Copyright (C) 1994-2024 Free Software Foundation, Inc. Copyright (C) 1994-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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" #include "mkconfig.h"
#define MK_OS_DOS 1 #define MK_DJGPP 1
/* Include this header to make __DJGPP_MINOR__ available because DJGPP ports /* Include this header to make __DJGPP_MINOR__ available because DJGPP ports
of GCC 4.3.0 and later no longer do it automatically. */ of GCC 4.3.0 and later no longer do it automatically. */

View File

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

View File

@ -1,5 +1,5 @@
/* Data base of default implicit rules for GNU Make. /* Data base of default implicit rules for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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 /* Define GCC_IS_NATIVE if gcc is the native development environment on
your system (gcc/bison/flex vs cc/yacc/lex). */ your system (gcc/bison/flex vs cc/yacc/lex). */
#if MK_OS_DOS || MK_OS_OS2 #if defined(__MSDOS__) || defined(__EMX__)
# define GCC_IS_NATIVE # define GCC_IS_NATIVE
#endif #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 '.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. */ a '.c' or '.p' or ... file rather than from a .s file. */
static const char default_suffixes[] static char default_suffixes[]
#if MK_OS_VMS #ifdef VMS
/* VMS should include all UNIX/POSIX + some VMS extensions */ /* 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 \ = ".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 \ .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 \ .tex .texinfo .texi .txinfo .mem .hlp .brn .rnh .rno .rnt .rnx .w .ch .cweb \
.web .com .sh .elc .el"; .web .com .sh .elc .el";
#elif MK_OS_OS2 #elif defined(__EMX__)
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \ = ".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 \ .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .web .sh .elc .el .obj .exe .dll .lib"; .w .ch .web .sh .elc .el .obj .exe .dll .lib";
@ -53,9 +53,9 @@ static const char default_suffixes[]
.w .ch .web .sh .elc .el"; .w .ch .web .sh .elc .el";
#endif #endif
static const struct pspec default_pattern_rules[] = static struct pspec default_pattern_rules[] =
{ {
#if MK_OS_VMS #ifdef VMS
{ "(%)", "%", { "(%)", "%",
"@if f$$search(\"$@\") .eqs. \"\" then $(LIBRARY)/CREATE/" "@if f$$search(\"$@\") .eqs. \"\" then $(LIBRARY)/CREATE/"
"$(or " "$(or "
@ -76,7 +76,7 @@ static const struct pspec default_pattern_rules[] =
/* The X.out rules are only in BSD's default set because /* The X.out rules are only in BSD's default set because
BSD Make has no null-suffix rules, so 'foo.out' and BSD Make has no null-suffix rules, so 'foo.out' and
'foo' are the same thing. */ 'foo' are the same thing. */
#if MK_OS_VMS #ifdef VMS
{ "%.exe", "%", { "%.exe", "%",
"$(CP) $< $@" }, "$(CP) $< $@" },
@ -93,9 +93,9 @@ static const struct pspec default_pattern_rules[] =
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static const struct pspec default_terminal_rules[] = static struct pspec default_terminal_rules[] =
{ {
#if MK_OS_VMS #ifdef VMS
/* RCS. */ /* RCS. */
{ "%", "%$$5lv", /* Multinet style */ { "%", "%$$5lv", /* Multinet style */
@ -124,13 +124,13 @@ static const struct pspec default_terminal_rules[] =
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" }, "$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
{ "%", "SCCS/s.%", { "%", "SCCS/s.%",
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" }, "$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
#endif /* !MK_OS_VMS */ #endif /* !VMS */
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static const char *const default_suffix_rules[] = static const char *default_suffix_rules[] =
{ {
#if MK_OS_VMS #ifdef VMS
".o", ".o",
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@", "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@",
".obj", ".obj",
@ -263,7 +263,7 @@ static const char *const default_suffix_rules[] =
".l.ln", ".l.ln",
"@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c", "@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
#else /* ! MK_OS_VMS */ #else /* ! VMS */
".o", ".o",
"$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@", "$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@",
@ -326,19 +326,19 @@ static const char *const default_suffix_rules[] =
".c.ln", ".c.ln",
"$(LINT.c) -C$* $<", "$(LINT.c) -C$* $<",
".y.ln", ".y.ln",
#if MK_OS_DOS #ifndef __MSDOS__
"$(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", "$(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 #endif
".l.ln", ".l.ln",
"@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c", "@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
".y.c", ".y.c",
#if MK_OS_DOS #ifndef __MSDOS__
"$(YACC.y) $< \n mv -f y_tab.c $@",
#else
"$(YACC.y) $< \n mv -f y.tab.c $@", "$(YACC.y) $< \n mv -f y.tab.c $@",
#else
"$(YACC.y) $< \n mv -f y_tab.c $@",
#endif #endif
".l.c", ".l.c",
"@$(RM) $@ \n $(LEX.l) $< > $@", "@$(RM) $@ \n $(LEX.l) $< > $@",
@ -393,14 +393,14 @@ static const char *const default_suffix_rules[] =
".web.tex", ".web.tex",
"$(WEAVE) $<", "$(WEAVE) $<",
#endif /* !MK_OS_VMS */ #endif /* !VMS */
0, 0, 0, 0,
}; };
static const char *const default_variables[] = static const char *default_variables[] =
{ {
#if MK_OS_VMS #ifdef VMS
#ifdef __ALPHA #ifdef __ALPHA
"ARCH", "ALPHA", "ARCH", "ALPHA",
#endif #endif
@ -515,7 +515,7 @@ static const char *const default_variables[] =
"CP", "copy", "CP", "copy",
".LIBPATTERNS", "%.olb lib%.a", ".LIBPATTERNS", "%.olb lib%.a",
#else /* !MK_OS_VMS */ #else /* !VMS */
"AR", "ar", "AR", "ar",
#ifdef _AIX #ifdef _AIX
@ -536,7 +536,7 @@ static const char *const default_variables[] =
"CXX", MAKE_CXX, "CXX", MAKE_CXX,
#else #else
# ifdef GCC_IS_NATIVE # ifdef GCC_IS_NATIVE
# ifdef MK_OS_DOS # ifdef __MSDOS__
"CXX", "gpp", /* g++ is an invalid name on MSDOS */ "CXX", "gpp", /* g++ is an invalid name on MSDOS */
# else # else
"CXX", "gcc", "CXX", "gcc",
@ -660,17 +660,19 @@ static const char *const default_variables[] =
"SCCS_OUTPUT_OPTION", "-G$@", "SCCS_OUTPUT_OPTION", "-G$@",
#endif #endif
#if MK_OS_DOS #if defined(_AMIGA)
".LIBPATTERNS", "%.lib",
#elif defined(__MSDOS__)
".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a", ".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a",
#elif defined(__APPLE__) #elif defined(__APPLE__)
".LIBPATTERNS", "lib%.dylib lib%.a", ".LIBPATTERNS", "lib%.dylib lib%.a",
#elif defined(__CYGWIN__) || MK_OS_W32 #elif defined(__CYGWIN__) || defined(WINDOWS32)
".LIBPATTERNS", "lib%.dll.a %.dll.a lib%.a %.lib lib%.dll %.dll", ".LIBPATTERNS", "lib%.dll.a %.dll.a lib%.a %.lib lib%.dll %.dll",
#else #else
".LIBPATTERNS", "lib%.so lib%.a", ".LIBPATTERNS", "lib%.so lib%.a",
#endif #endif
#endif /* !MK_OS_VMS */ #endif /* !VMS */
/* Make this assignment to avoid undefined variable warnings. */ /* Make this assignment to avoid undefined variable warnings. */
GNUMAKEFLAGS_NAME, "", GNUMAKEFLAGS_NAME, "",
0, 0 0, 0
@ -705,9 +707,9 @@ set_default_suffixes (void)
installed after. */ installed after. */
void void
install_default_suffix_rules () install_default_suffix_rules (void)
{ {
const char *const *s; const char **s;
if (no_builtin_rules_flag) if (no_builtin_rules_flag)
return; return;
@ -715,17 +717,15 @@ install_default_suffix_rules ()
for (s = default_suffix_rules; *s != 0; s += 2) for (s = default_suffix_rules; *s != 0; s += 2)
{ {
struct file *f = enter_file (strcache_add (s[0])); struct file *f = enter_file (strcache_add (s[0]));
/* Install the default rule only if there is no user defined rule. */ /* This function should run before any makefile is parsed. */
if (!f->cmds) assert (f->cmds == 0);
{
f->cmds = xmalloc (sizeof (struct commands)); f->cmds = xmalloc (sizeof (struct commands));
f->cmds->fileinfo.filenm = NULL; f->cmds->fileinfo.filenm = 0;
f->cmds->commands = xstrdup (s[1]); f->cmds->commands = xstrdup (s[1]);
f->cmds->command_lines = NULL; f->cmds->command_lines = 0;
f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT; f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
f->builtin = 1; f->builtin = 1;
} }
}
} }
@ -734,7 +734,7 @@ install_default_suffix_rules ()
void void
install_default_implicit_rules (void) install_default_implicit_rules (void)
{ {
const struct pspec *p; struct pspec *p;
if (no_builtin_rules_flag) if (no_builtin_rules_flag)
return; return;
@ -749,7 +749,7 @@ install_default_implicit_rules (void)
void void
define_default_variables (void) define_default_variables (void)
{ {
const char *const *s; const char **s;
if (no_builtin_variables_flag) if (no_builtin_variables_flag)
return; return;
@ -761,8 +761,8 @@ define_default_variables (void)
void void
undefine_default_variables (void) undefine_default_variables (void)
{ {
const char *const *s; const char **s;
for (s = default_variables; *s != 0; s += 2) for (s = default_variables; *s != 0; s += 2)
undefine_variable_global (NILF, s[0], strlen (s[0]), o_default); undefine_variable_global (s[0], strlen (s[0]), o_default);
} }

View File

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

132
src/dir.c
View File

@ -1,5 +1,5 @@
/* Directory hashing for GNU Make. /* Directory hashing for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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 #ifdef HAVE_DIRENT_H
# include <dirent.h> # include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name) # define NAMLEN(dirent) strlen((dirent)->d_name)
# if MK_OS_VMS # ifdef VMS
/* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */ /* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */
const char *vmsify (const char *name, int type); const char *vmsify (const char *name, int type);
# endif # endif
@ -50,7 +50,7 @@ const char *vmsify (const char *name, int type);
# define NAMLEN(d) _D_NAMLEN(d) # define NAMLEN(d) _D_NAMLEN(d)
#endif #endif
#if (defined (POSIX) || MK_OS_VMS || MK_OS_W32) && !defined (__GNU_LIBRARY__) #if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
/* Posix does not require that the d_ino field be present, and some /* Posix does not require that the d_ino field be present, and some
systems do not provide it. */ systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1 # 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) # define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
#endif /* POSIX */ #endif /* POSIX */
#if MK_OS_DOS #ifdef __MSDOS__
#include <ctype.h> #include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
@ -108,12 +108,16 @@ dosify (const char *filename)
*df = '\0'; *df = '\0';
return dos_filename; return dos_filename;
} }
#endif /* MK_OS_DOS */ #endif /* __MSDOS__ */
#if MK_OS_W32 #ifdef WINDOWS32
#include "pathstuff.h" #include "pathstuff.h"
#endif #endif
#ifdef _AMIGA
#include <ctype.h>
#endif
#ifdef HAVE_CASE_INSENSITIVE_FS #ifdef HAVE_CASE_INSENSITIVE_FS
static const char * static const char *
downcase (const char *filename) downcase (const char *filename)
@ -137,7 +141,7 @@ downcase (const char *filename)
} }
#endif /* HAVE_CASE_INSENSITIVE_FS */ #endif /* HAVE_CASE_INSENSITIVE_FS */
#if MK_OS_VMS #ifdef VMS
static char * static char *
downcase_inplace(char *filename) downcase_inplace(char *filename)
@ -227,7 +231,7 @@ vmsstat_dir (const char *name, struct stat *st)
# define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf) # define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)
#endif /* _USE_STD_STAT */ #endif /* _USE_STD_STAT */
#endif /* MK_OS_VMS */ #endif /* VMS */
/* Never have more than this many directories open at once. */ /* Never have more than this many directories open at once. */
@ -244,8 +248,8 @@ static unsigned int open_directories = 0;
struct directory_contents struct directory_contents
{ {
dev_t dev; /* Device and inode numbers of this dir. */ dev_t dev; /* Device and inode numbers of this dir. */
#if MK_OS_W32 #ifdef WINDOWS32
/* Inode means nothing on Windows32. Even file key information is /* Inode means nothing on WINDOWS32. Even file key information is
* unreliable because it is random per file open and undefined for remote * 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 * filesystems. The most unique attribute I can come up with is the fully
* qualified name of the directory. Beware though, this is also * qualified name of the directory. Beware though, this is also
@ -258,12 +262,12 @@ struct directory_contents
# define FS_NTFS 0x2 # define FS_NTFS 0x2
# define FS_UNKNOWN 0x4 # define FS_UNKNOWN 0x4
#else #else
# if MK_OS_VMS_INO_T # ifdef VMS_INO_T
ino_t ino[3]; ino_t ino[3];
# else # else
ino_t ino; ino_t ino;
# endif # endif
#endif /* MK_OS_W32 */ #endif /* WINDOWS32 */
struct hash_table dirfiles; /* Files in this directory. */ struct hash_table dirfiles; /* Files in this directory. */
unsigned long counter; /* command_count value when last read. */ unsigned long counter; /* command_count value when last read. */
DIR *dirstream; /* Stream reading this directory. */ DIR *dirstream; /* Stream reading this directory. */
@ -291,12 +295,12 @@ directory_contents_hash_1 (const void *key_0)
const struct directory_contents *key = key_0; const struct directory_contents *key = key_0;
unsigned long hash; unsigned long hash;
#if MK_OS_W32 #ifdef WINDOWS32
hash = 0; hash = 0;
ISTRING_HASH_1 (key->path_key, hash); ISTRING_HASH_1 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime; hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
#else #else
# if MK_OS_VMS_INO_T # ifdef VMS_INO_T
hash = (((unsigned int) key->dev << 4) hash = (((unsigned int) key->dev << 4)
^ ((unsigned int) key->ino[0] ^ ((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1] + (unsigned int) key->ino[1]
@ -304,7 +308,7 @@ directory_contents_hash_1 (const void *key_0)
# else # else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino; hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
# endif # endif
#endif /* MK_OS_W32 */ #endif /* WINDOWS32 */
return hash; return hash;
} }
@ -314,12 +318,12 @@ directory_contents_hash_2 (const void *key_0)
const struct directory_contents *key = key_0; const struct directory_contents *key = key_0;
unsigned long hash; unsigned long hash;
#if MK_OS_W32 #ifdef WINDOWS32
hash = 0; hash = 0;
ISTRING_HASH_2 (key->path_key, hash); ISTRING_HASH_2 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime; hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
#else #else
# if MK_OS_VMS_INO_T # ifdef VMS_INO_T
hash = (((unsigned int) key->dev << 4) hash = (((unsigned int) key->dev << 4)
^ ~((unsigned int) key->ino[0] ^ ~((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1] + (unsigned int) key->ino[1]
@ -327,7 +331,7 @@ directory_contents_hash_2 (const void *key_0)
# else # else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino; hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
# endif # endif
#endif /* MK_OS_W32 */ #endif /* WINDOWS32 */
return hash; return hash;
} }
@ -350,7 +354,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
const struct directory_contents *y = yv; const struct directory_contents *y = yv;
int result; int result;
#if MK_OS_W32 #ifdef WINDOWS32
ISTRING_COMPARE (x->path_key, y->path_key, result); ISTRING_COMPARE (x->path_key, y->path_key, result);
if (result) if (result)
return result; return result;
@ -358,7 +362,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
if (result) if (result)
return result; return result;
#else #else
# if MK_OS_VMS_INO_T # ifdef VMS_INO_T
result = MAKECMP(x->ino[0], y->ino[0]); result = MAKECMP(x->ino[0], y->ino[0]);
if (result) if (result)
return result; return result;
@ -373,7 +377,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
if (result) if (result)
return result; return result;
# endif # endif
#endif /* MK_OS_W32 */ #endif /* WINDOWS32 */
return MAKECMP(x->dev, y->dev); return MAKECMP(x->dev, y->dev);
} }
@ -471,7 +475,7 @@ find_directory (const char *name)
struct stat st; struct stat st;
int r; int r;
#if MK_OS_W32 #ifdef WINDOWS32
char *w32_path; char *w32_path;
#endif #endif
@ -499,7 +503,7 @@ find_directory (const char *name)
size_t len = strlen (name); size_t len = strlen (name);
dir = xmalloc (sizeof (struct directory)); dir = xmalloc (sizeof (struct directory));
#if defined(HAVE_CASE_INSENSITIVE_FS) && MK_OS_VMS #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
/* Todo: Why is this only needed on VMS? */ /* Todo: Why is this only needed on VMS? */
{ {
char *lname = downcase_inplace (xstrdup (name)); char *lname = downcase_inplace (xstrdup (name));
@ -516,7 +520,7 @@ find_directory (const char *name)
dir->counter = command_count; dir->counter = command_count;
/* See if the directory exists. */ /* See if the directory exists. */
#if MK_OS_W32 #if defined(WINDOWS32)
{ {
char tem[MAX_PATH+1], *tstart, *tend; char tem[MAX_PATH+1], *tstart, *tend;
size_t len = strlen (name); size_t len = strlen (name);
@ -544,11 +548,11 @@ find_directory (const char *name)
memset (&dc_key, '\0', sizeof (dc_key)); memset (&dc_key, '\0', sizeof (dc_key));
dc_key.dev = st.st_dev; dc_key.dev = st.st_dev;
#if MK_OS_W32 #ifdef WINDOWS32
dc_key.path_key = w32_path = w32ify (name, 1); dc_key.path_key = w32_path = w32ify (name, 1);
dc_key.ctime = st.st_ctime; dc_key.ctime = st.st_ctime;
#else #else
# if MK_OS_VMS_INO_T # ifdef VMS_INO_T
dc_key.ino[0] = st.st_ino[0]; dc_key.ino[0] = st.st_ino[0];
dc_key.ino[1] = st.st_ino[1]; dc_key.ino[1] = st.st_ino[1];
dc_key.ino[2] = st.st_ino[2]; dc_key.ino[2] = st.st_ino[2];
@ -562,7 +566,7 @@ find_directory (const char *name)
if (HASH_VACANT (dc)) if (HASH_VACANT (dc))
{ {
/* Nope; this really is a directory we haven't seen before. */ /* Nope; this really is a directory we haven't seen before. */
#if MK_OS_W32 #ifdef WINDOWS32
char fs_label[BUFSIZ]; char fs_label[BUFSIZ];
char fs_type[BUFSIZ]; char fs_type[BUFSIZ];
unsigned long fs_serno; unsigned long fs_serno;
@ -573,11 +577,11 @@ find_directory (const char *name)
dc = xcalloc (sizeof (struct directory_contents)); dc = xcalloc (sizeof (struct directory_contents));
*dc = dc_key; *dc = dc_key;
#if MK_OS_W32 #ifdef WINDOWS32
dc->path_key = xstrdup (w32_path); dc->path_key = xstrdup (w32_path);
dc->mtime = st.st_mtime; 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. */ directory when files are added/deleted from a directory. */
w32_path[3] = '\0'; w32_path[3] = '\0';
if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label), if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label),
@ -590,7 +594,7 @@ find_directory (const char *name)
dc->fs_flags = FS_NTFS; dc->fs_flags = FS_NTFS;
else else
dc->fs_flags = FS_UNKNOWN; dc->fs_flags = FS_UNKNOWN;
#endif /* MK_OS_W32 */ #endif /* WINDOWS32 */
hash_insert_at (&directory_contents, dc, dc_slot); hash_insert_at (&directory_contents, dc, dc_slot);
} }
@ -636,7 +640,7 @@ dir_contents_file_exists_p (struct directory *dir,
struct dirfile *df; struct dirfile *df;
struct dirent *d; struct dirent *d;
struct directory_contents *dc = dir->contents; struct directory_contents *dc = dir->contents;
#if MK_OS_W32 #ifdef WINDOWS32
struct stat st; struct stat st;
int rehash = 0; int rehash = 0;
#endif #endif
@ -645,7 +649,7 @@ dir_contents_file_exists_p (struct directory *dir,
/* The directory could not be stat'd or opened. */ /* The directory could not be stat'd or opened. */
return 0; return 0;
#if MK_OS_DOS #ifdef __MSDOS__
filename = dosify (filename); filename = dosify (filename);
#endif #endif
@ -653,7 +657,7 @@ dir_contents_file_exists_p (struct directory *dir,
filename = downcase (filename); filename = downcase (filename);
#endif #endif
#if MK_OS_OS2 #ifdef __EMX__
if (filename != NULL) if (filename != NULL)
{ {
size_t len = strlen (filename); size_t len = strlen (filename);
@ -684,7 +688,7 @@ dir_contents_file_exists_p (struct directory *dir,
if (dc->dirstream == NULL) if (dc->dirstream == NULL)
{ {
#if MK_OS_W32 #ifdef WINDOWS32
/* /*
* Check to see if directory has changed since last read. FAT * Check to see if directory has changed since last read. FAT
* filesystems force a rehash always as mtime does not change * filesystems force a rehash always as mtime does not change
@ -734,7 +738,7 @@ dir_contents_file_exists_p (struct directory *dir,
break; break;
} }
#if MK_OS_VMS && defined(HAVE_DIRENT_H) #if defined(VMS) && defined(HAVE_DIRENT_H)
/* In VMS we get file versions too, which have to be stripped off. /* In VMS we get file versions too, which have to be stripped off.
Some versions of VMS return versions on Unix files even when Some versions of VMS return versions on Unix files even when
the feature option to strip them is set. */ the feature option to strip them is set. */
@ -751,7 +755,7 @@ dir_contents_file_exists_p (struct directory *dir,
dirfile_key.name = d->d_name; dirfile_key.name = d->d_name;
dirfile_key.length = len; dirfile_key.length = len;
dirfile_slot = (struct dirfile **) hash_find_slot (&dc->dirfiles, &dirfile_key); dirfile_slot = (struct dirfile **) hash_find_slot (&dc->dirfiles, &dirfile_key);
#if MK_OS_W32 #ifdef WINDOWS32
/* /*
* If re-reading a directory, don't cache files that have * If re-reading a directory, don't cache files that have
* already been discovered. * already been discovered.
@ -760,7 +764,7 @@ dir_contents_file_exists_p (struct directory *dir,
#endif #endif
{ {
df = xmalloc (sizeof (struct dirfile)); df = xmalloc (sizeof (struct dirfile));
#if MK_OS_VMS && defined(HAVE_CASE_INSENSITIVE_FS) #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
/* TODO: Why is this only needed on VMS? */ /* TODO: Why is this only needed on VMS? */
df->name = strcache_add_len (downcase_inplace (d->d_name), len); df->name = strcache_add_len (downcase_inplace (d->d_name), len);
#else #else
@ -797,7 +801,7 @@ dir_contents_file_exists_p (struct directory *dir,
int int
dir_file_exists_p (const char *dirname, const char *filename) dir_file_exists_p (const char *dirname, const char *filename)
{ {
#if MK_OS_VMS #ifdef VMS
if (filename && dirname && strpbrk (dirname, ":<[") != NULL) if (filename && dirname && strpbrk (dirname, ":<[") != NULL)
filename = vmsify (filename, 0); filename = vmsify (filename, 0);
#endif #endif
@ -820,7 +824,7 @@ file_exists_p (const char *name)
#endif #endif
dirend = strrchr (name, '/'); dirend = strrchr (name, '/');
#if MK_OS_VMS #ifdef VMS
if (dirend == NULL) if (dirend == NULL)
{ {
dirend = strrchr (name, ']'); dirend = strrchr (name, ']');
@ -836,7 +840,7 @@ file_exists_p (const char *name)
dirend = strrchr (name, ':'); dirend = strrchr (name, ':');
dirend == NULL ? dirend : dirend++; dirend == NULL ? dirend : dirend++;
} }
#endif /* MK_OS_VMS */ #endif /* VMS */
#ifdef HAVE_DOS_PATHS #ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */ /* Forward and backslashes might be mixed. We need the rightmost one. */
{ {
@ -849,7 +853,11 @@ file_exists_p (const char *name)
} }
#endif /* HAVE_DOS_PATHS */ #endif /* HAVE_DOS_PATHS */
if (dirend == NULL) if (dirend == NULL)
#ifndef _AMIGA
return dir_file_exists_p (".", name); return dir_file_exists_p (".", name);
#else /* !AMIGA */
return dir_file_exists_p ("", name);
#endif /* AMIGA */
slash = dirend; slash = dirend;
if (dirend == name) if (dirend == name)
@ -868,7 +876,7 @@ file_exists_p (const char *name)
p[dirend - name] = '\0'; p[dirend - name] = '\0';
dirname = p; dirname = p;
} }
#if MK_OS_VMS #ifdef VMS
if (*slash == '/') if (*slash == '/')
slash++; slash++;
#else #else
@ -890,7 +898,7 @@ file_impossible (const char *filename)
struct dirfile *new; struct dirfile *new;
dirend = strrchr (p, '/'); dirend = strrchr (p, '/');
#if MK_OS_VMS #ifdef VMS
if (dirend == NULL) if (dirend == NULL)
{ {
dirend = strrchr (p, ']'); dirend = strrchr (p, ']');
@ -919,7 +927,11 @@ file_impossible (const char *filename)
} }
#endif /* HAVE_DOS_PATHS */ #endif /* HAVE_DOS_PATHS */
if (dirend == NULL) if (dirend == NULL)
#ifdef _AMIGA
dir = find_directory ("");
#else /* !AMIGA */
dir = find_directory ("."); dir = find_directory (".");
#endif /* AMIGA */
else else
{ {
const char *dirname; const char *dirname;
@ -941,7 +953,7 @@ file_impossible (const char *filename)
dirname = cp; dirname = cp;
} }
dir = find_directory (dirname); dir = find_directory (dirname);
#if MK_OS_VMS #ifdef VMS
if (*slash == '/') if (*slash == '/')
filename = p = slash + 1; filename = p = slash + 1;
else else
@ -964,7 +976,7 @@ file_impossible (const char *filename)
new = xmalloc (sizeof (struct dirfile)); new = xmalloc (sizeof (struct dirfile));
new->length = strlen (filename); new->length = strlen (filename);
#if defined(HAVE_CASE_INSENSITIVE_FS) && MK_OS_VMS #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
/* todo: Why is this only needed on VMS? */ /* todo: Why is this only needed on VMS? */
new->name = strcache_add_len (downcase (filename), new->length); new->name = strcache_add_len (downcase (filename), new->length);
#else #else
@ -983,12 +995,12 @@ file_impossible_p (const char *filename)
struct directory_contents *dir; struct directory_contents *dir;
struct dirfile *dirfile; struct dirfile *dirfile;
struct dirfile dirfile_key; struct dirfile dirfile_key;
#if MK_OS_VMS #ifdef VMS
int want_vmsify = 0; int want_vmsify = 0;
#endif #endif
dirend = strrchr (filename, '/'); dirend = strrchr (filename, '/');
#if MK_OS_VMS #ifdef VMS
if (dirend == NULL) if (dirend == NULL)
{ {
want_vmsify = (strpbrk (filename, "]>:^") != NULL); want_vmsify = (strpbrk (filename, "]>:^") != NULL);
@ -1011,7 +1023,11 @@ file_impossible_p (const char *filename)
} }
#endif /* HAVE_DOS_PATHS */ #endif /* HAVE_DOS_PATHS */
if (dirend == NULL) if (dirend == NULL)
#ifdef _AMIGA
dir = find_directory ("")->contents;
#else /* !AMIGA */
dir = find_directory (".")->contents; dir = find_directory (".")->contents;
#endif /* AMIGA */
else else
{ {
const char *dirname; const char *dirname;
@ -1033,7 +1049,7 @@ file_impossible_p (const char *filename)
dirname = cp; dirname = cp;
} }
dir = find_directory (dirname)->contents; dir = find_directory (dirname)->contents;
#if MK_OS_VMS #ifdef VMS
if (*slash == '/') if (*slash == '/')
filename = slash + 1; filename = slash + 1;
else else
@ -1047,13 +1063,13 @@ file_impossible_p (const char *filename)
/* There are no files entered for this directory. */ /* There are no files entered for this directory. */
return 0; return 0;
#if MK_OS_DOS #ifdef __MSDOS__
filename = dosify (filename); filename = dosify (filename);
#endif #endif
#ifdef HAVE_CASE_INSENSITIVE_FS #ifdef HAVE_CASE_INSENSITIVE_FS
filename = downcase (filename); filename = downcase (filename);
#endif #endif
#if MK_OS_VMS #ifdef VMS
if (want_vmsify) if (want_vmsify)
filename = vmsify (filename, 1); filename = vmsify (filename, 1);
#endif #endif
@ -1085,7 +1101,7 @@ print_dir_data_base (void)
unsigned int impossible; unsigned int impossible;
struct directory **dir_slot; struct directory **dir_slot;
struct directory **dir_end; struct directory **dir_end;
#if MK_OS_W32 #ifdef WINDOWS32
char buf[INTSTR_LENGTH + 1]; char buf[INTSTR_LENGTH + 1];
#endif #endif
@ -1103,7 +1119,7 @@ print_dir_data_base (void)
if (dir->contents == NULL) if (dir->contents == NULL)
printf (_("# %s: could not be stat'd.\n"), dir->name); printf (_("# %s: could not be stat'd.\n"), dir->name);
else if (dir->contents->dirfiles.ht_vec == NULL) else if (dir->contents->dirfiles.ht_vec == NULL)
#if MK_OS_W32 #ifdef WINDOWS32
printf (_("# %s (key %s, mtime %s): could not be opened.\n"), printf (_("# %s (key %s, mtime %s): could not be opened.\n"),
dir->name, dir->contents->path_key, dir->name, dir->contents->path_key,
make_ulltoa ((unsigned long long)dir->contents->mtime, buf)); make_ulltoa ((unsigned long long)dir->contents->mtime, buf));
@ -1136,7 +1152,7 @@ print_dir_data_base (void)
++f; ++f;
} }
} }
#if MK_OS_W32 #ifdef WINDOWS32
printf (_("# %s (key %s, mtime %s): "), printf (_("# %s (key %s, mtime %s): "),
dir->name, dir->contents->path_key, dir->name, dir->contents->path_key,
make_ulltoa ((unsigned long long)dir->contents->mtime, buf)); make_ulltoa ((unsigned long long)dir->contents->mtime, buf));
@ -1274,8 +1290,8 @@ read_dirstream (void *stream)
* On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
* regular file; fix that here. * regular file; fix that here.
*/ */
#if !defined(stat) && !MK_OS_W32 || MK_OS_VMS #if !defined(stat) && !defined(WINDOWS32) || defined(VMS)
# if !MK_OS_VMS # ifndef VMS
# ifndef HAVE_SYS_STAT_H # ifndef HAVE_SYS_STAT_H
int stat (const char *path, struct stat *sbuf); int stat (const char *path, struct stat *sbuf);
# endif # endif
@ -1291,7 +1307,7 @@ static int
local_stat (const char *path, struct stat *buf) local_stat (const char *path, struct stat *buf)
{ {
int e; int e;
#if MK_OS_W32 #ifdef WINDOWS32
size_t plen = strlen (path); size_t plen = strlen (path);
/* Make sure the parent of "." exists and is a directory, not a /* Make sure the parent of "." exists and is a directory, not a
@ -1314,8 +1330,8 @@ local_stat (const char *path, struct stat *buf)
#endif #endif
/* Similarly for lstat. */ /* Similarly for lstat. */
#if !defined(lstat) && !MK_OS_W32 || MK_OS_VMS #if !defined(lstat) && !defined(WINDOWS32) || defined(VMS)
# if !MK_OS_VMS # ifndef VMS
# ifndef HAVE_SYS_STAT_H # ifndef HAVE_SYS_STAT_H
int lstat (const char *path, struct stat *sbuf); int lstat (const char *path, struct stat *sbuf);
# endif # endif
@ -1326,7 +1342,7 @@ int lstat (const char *path, struct stat *sbuf);
# endif # endif
# endif # endif
# define local_lstat lstat # define local_lstat lstat
#elif MK_OS_W32 #elif defined(WINDOWS32)
/* Windows doesn't support lstat(). */ /* Windows doesn't support lstat(). */
# define local_lstat local_stat # define local_lstat local_stat
#else #else

View File

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

View File

@ -1,5 +1,5 @@
/* Target file management for GNU Make. /* Target file management for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -26,7 +26,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "debug.h" #include "debug.h"
#include "hash.h" #include "hash.h"
#include "shuffle.h" #include "shuffle.h"
#include "rule.h"
/* Remember whether snap_deps has been invoked: we need this to be sure we /* Remember whether snap_deps has been invoked: we need this to be sure we
@ -61,14 +60,6 @@ file_hash_cmp (const void *x, const void *y)
static struct hash_table files; 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. */ /* Whether or not .SECONDARY with no prerequisites was given. */
static int all_secondary = 0; static int all_secondary = 0;
@ -82,7 +73,7 @@ lookup_file (const char *name)
{ {
struct file *f; struct file *f;
struct file file_key; struct file file_key;
#if MK_OS_VMS #ifdef VMS
int want_vmsify; int want_vmsify;
#ifndef WANT_CASE_SENSITIVE_TARGETS #ifndef WANT_CASE_SENSITIVE_TARGETS
char *lname; char *lname;
@ -94,7 +85,7 @@ lookup_file (const char *name)
/* This is also done in parse_file_seq, so this is redundant /* This is also done in parse_file_seq, so this is redundant
for names read from makefiles. It is here for names passed for names read from makefiles. It is here for names passed
on the command line. */ on the command line. */
#if MK_OS_VMS #ifdef VMS
want_vmsify = (strpbrk (name, "]>:^") != NULL); want_vmsify = (strpbrk (name, "]>:^") != NULL);
# ifndef WANT_CASE_SENSITIVE_TARGETS # ifndef WANT_CASE_SENSITIVE_TARGETS
if (*name != '.') if (*name != '.')
@ -125,8 +116,12 @@ lookup_file (const char *name)
if (*name == '\0') if (*name == '\0')
{ {
/* It was all slashes after a dot. */ /* It was all slashes after a dot. */
#if defined(_AMIGA)
name = "";
#else
name = "./"; name = "./";
#if MK_OS_VMS #endif
#if defined(VMS)
/* TODO - This section is probably not needed. */ /* TODO - This section is probably not needed. */
if (want_vmsify) if (want_vmsify)
name = "[]"; name = "[]";
@ -134,7 +129,7 @@ lookup_file (const char *name)
} }
file_key.hname = name; file_key.hname = name;
f = hash_find_item (&files, &file_key); f = hash_find_item (&files, &file_key);
#if MK_OS_VMS && !defined(WANT_CASE_SENSITIVE_TARGETS) #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
if (*name != '.') if (*name != '.')
free (lname); free (lname);
#endif #endif
@ -158,7 +153,7 @@ enter_file (const char *name)
assert (*name != '\0'); assert (*name != '\0');
assert (! verify_flag || strcache_iscached (name)); assert (! verify_flag || strcache_iscached (name));
#if MK_OS_VMS && !defined(WANT_CASE_SENSITIVE_TARGETS) #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
if (*name != '.') if (*name != '.')
{ {
const char *n; const char *n;
@ -226,7 +221,8 @@ rehash_file (struct file *from_file, const char *to_hname)
/* Find the end of the renamed list for the "from" file. */ /* Find the end of the renamed list for the "from" file. */
file_key.hname = from_file->hname; file_key.hname = from_file->hname;
check_renamed (from_file); while (from_file->renamed != 0)
from_file = from_file->renamed;
if (file_hash_cmp (from_file, &file_key)) if (file_hash_cmp (from_file, &file_key))
/* hname changed unexpectedly!! */ /* hname changed unexpectedly!! */
abort (); abort ();
@ -270,19 +266,19 @@ rehash_file (struct file *from_file, const char *to_hname)
if (to_file->cmds->fileinfo.filenm != 0) if (to_file->cmds->fileinfo.filenm != 0)
error (&from_file->cmds->fileinfo, error (&from_file->cmds->fileinfo,
l + strlen (to_file->cmds->fileinfo.filenm) + INTSTR_LENGTH, 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->name, from_file->cmds->fileinfo.filenm,
from_file->cmds->fileinfo.lineno); from_file->cmds->fileinfo.lineno);
else else
error (&from_file->cmds->fileinfo, l, 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); from_file->name);
l += strlen (to_hname); l += strlen (to_hname);
error (&from_file->cmds->fileinfo, l, 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); from_file->name, to_hname);
error (&from_file->cmds->fileinfo, l, 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); from_file->name, to_hname);
} }
} }
@ -335,17 +331,10 @@ rehash_file (struct file *from_file, const char *to_hname)
MERGE (notintermediate); MERGE (notintermediate);
MERGE (ignore_vpath); MERGE (ignore_vpath);
MERGE (snapped); MERGE (snapped);
MERGE (suffix);
#undef MERGE #undef MERGE
to_file->builtin = 0; to_file->builtin = 0;
from_file->renamed = to_file; 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 /* Rename FILE to NAME. This is not as simple as resetting
@ -412,7 +401,7 @@ remove_intermediates (int sig)
{ {
if (sig) if (sig)
OS (error, NILF, OS (error, NILF,
_("*** deleting intermediate file '%s'"), f->name); _("*** Deleting intermediate file '%s'"), f->name);
else else
{ {
if (! doneany) if (! doneany)
@ -432,10 +421,7 @@ remove_intermediates (int sig)
} }
if (status < 0) if (status < 0)
{ {
if (doneany) perror_with_name ("\nunlink: ", f->name);
fputs ("\n", stdout);
fflush (stdout);
perror_with_name ("unlink: ", f->name);
/* Start printing over. */ /* Start printing over. */
doneany = 0; doneany = 0;
} }
@ -654,7 +640,7 @@ expand_deps (struct file *f)
set_file_variables (f, d->stem ? d->stem : f->stem); set_file_variables (f, d->stem ? d->stem : f->stem);
/* Perform second expansion. */ /* Perform second expansion. */
p = expand_string_for_file (d->name, f); p = variable_expand_for_file (d->name, f);
/* Free the un-expanded name. */ /* Free the un-expanded name. */
free ((char*)d->name); free ((char*)d->name);
@ -706,7 +692,7 @@ struct dep *
expand_extra_prereqs (const struct variable *extra) expand_extra_prereqs (const struct variable *extra)
{ {
struct dep *d; struct dep *d;
struct dep *prereqs = extra ? split_prereqs (expand_string (extra->value)) : NULL; struct dep *prereqs = extra ? split_prereqs (variable_expand (extra->value)) : NULL;
for (d = prereqs; d; d = d->next) for (d = prereqs; d; d = d->next)
{ {
@ -727,7 +713,6 @@ snap_file (const void *item, void *arg)
{ {
struct file *f = (struct file*)item; struct file *f = (struct file*)item;
struct dep *prereqs = NULL; struct dep *prereqs = NULL;
struct dep *d;
/* If we're not doing second expansion then reset updating. */ /* If we're not doing second expansion then reset updating. */
if (!second_expansion) if (!second_expansion)
@ -747,22 +732,14 @@ snap_file (const void *item, void *arg)
/* If .EXTRA_PREREQS is set, add them as ignored by automatic variables. */ /* If .EXTRA_PREREQS is set, add them as ignored by automatic variables. */
if (f->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) else if (f->is_target)
prereqs = copy_dep_chain (arg); prereqs = copy_dep_chain (arg);
if (prereqs) if (prereqs)
{ {
struct dep *d;
for (d = prereqs; d; d = d->next) for (d = prereqs; d; d = d->next)
if (streq (f->name, dep_name (d))) if (streq (f->name, dep_name (d)))
/* Skip circular dependencies. */ /* Skip circular dependencies. */
@ -963,7 +940,7 @@ file_timestamp_cons (const char *fname, time_t stamp, long int ns)
ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX; ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
file_timestamp_sprintf (buf, ts); file_timestamp_sprintf (buf, ts);
OSS (error, NILF, OSS (error, NILF,
_("%s: timestamp out of range: substituting %s"), f, buf); _("%s: Timestamp out of range; substituting %s"), f, buf);
} }
return ts; return ts;
@ -1030,20 +1007,22 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
if (tm) if (tm)
{ {
intmax_t year = tm->tm_year; intmax_t year = tm->tm_year;
p += sprintf (p, "%04" PRIdMAX "-%02d-%02d %02d:%02d:%02d", sprintf (p, "%04" PRIdMAX "-%02d-%02d %02d:%02d:%02d",
year + 1900, tm->tm_mon + 1, tm->tm_mday, year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
} }
else if (t < 0) else if (t < 0)
p += sprintf (p, "%" PRIdMAX, (intmax_t) t); sprintf (p, "%" PRIdMAX, (intmax_t) t);
else else
p += sprintf (p, "%" PRIuMAX, (uintmax_t) t); sprintf (p, "%" PRIuMAX, (uintmax_t) t);
p += strlen (p);
/* Append nanoseconds as a fraction, but remove trailing zeros. We don't /* Append nanoseconds as a fraction, but remove trailing zeros. We don't
know the actual timestamp resolution, since clock_getres applies only to know the actual timestamp resolution, since clock_getres applies only to
local times, whereas this timestamp might come from a remote filesystem. local times, whereas this timestamp might come from a remote filesystem.
So removing trailing zeros is the best guess that we can do. */ So removing trailing zeros is the best guess that we can do. */
p += sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts)) - 1; sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
p += strlen (p) - 1;
while (*p == '0') while (*p == '0')
p--; p--;
p += *p != '.'; p += *p != '.';
@ -1053,7 +1032,7 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
/* Print the data base of files. */ /* Print the data base of files. */
static void void
print_prereqs (const struct dep *deps) print_prereqs (const struct dep *deps)
{ {
const struct dep *ood = 0; const struct dep *ood = 0;
@ -1129,9 +1108,6 @@ print_file (const void *item)
puts (_("# File is a prerequisite of .NOTINTERMEDIATE.")); puts (_("# File is a prerequisite of .NOTINTERMEDIATE."));
if (f->secondary) if (f->secondary)
puts (_("# File is secondary (prerequisite of .SECONDARY).")); puts (_("# File is secondary (prerequisite of .SECONDARY)."));
if (f->is_explicit)
puts (_("# File is explicitly mentioned."));
if (f->also_make != 0) if (f->also_make != 0)
{ {
const struct dep *d; const struct dep *d;
@ -1207,34 +1183,6 @@ print_file_data_base (void)
fputs (_("\n# files hash-table stats:\n# "), stdout); fputs (_("\n# files hash-table stats:\n# "), stdout);
hash_print_stats (&files, 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. */ /* Verify the integrity of the data base of files. */
@ -1242,7 +1190,7 @@ print_targets (void)
do{ \ do{ \
if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \ if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \
error (NULL, strlen (_p->name) + CSTRLEN (# _n) + strlen (_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) }while(0)
static void static void

View File

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

View File

@ -1,5 +1,5 @@
/* Builtin function expansion for GNU Make. /* Builtin function expansion for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -23,6 +23,10 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "commands.h" #include "commands.h"
#include "debug.h" #include "debug.h"
#ifdef _AMIGA
#include "amiga.h"
#endif
struct function_table_entry struct function_table_entry
{ {
@ -520,7 +524,7 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
int is_suffix = funcname[0] == 's'; int is_suffix = funcname[0] == 's';
int is_notdir = !is_suffix; int is_notdir = !is_suffix;
int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0); int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0);
#if MK_OS_VMS #ifdef VMS
/* For VMS list_iterator points to a comma separated list. To use the common /* 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 [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 spaces. Obviously, there is a problem if there is a ',' in the VMS filename
@ -565,7 +569,7 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
if (is_notdir || p >= p2) if (is_notdir || p >= p2)
{ {
#if MK_OS_VMS #ifdef VMS
if (vms_comma_separator) if (vms_comma_separator)
o = variable_buffer_output (o, ",", 1); o = variable_buffer_output (o, ",", 1);
else else
@ -596,7 +600,7 @@ func_basename_dir (char *o, char **argv, const char *funcname)
int is_basename = funcname[0] == 'b'; int is_basename = funcname[0] == 'b';
int is_dir = !is_basename; int is_dir = !is_basename;
int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL; int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;
#if MK_OS_VMS #ifdef VMS
/* As in func_notdir_suffix ... */ /* As in func_notdir_suffix ... */
char *vms_p3 = alloca (strlen(p3) + 1); char *vms_p3 = alloca (strlen(p3) + 1);
int i; int i;
@ -625,7 +629,7 @@ func_basename_dir (char *o, char **argv, const char *funcname)
o = variable_buffer_output (o, p2, 2); o = variable_buffer_output (o, p2, 2);
#endif #endif
else if (is_dir) else if (is_dir)
#if MK_OS_VMS #ifdef VMS
{ {
extern int vms_report_unix_paths; extern int vms_report_unix_paths;
if (vms_report_unix_paths) if (vms_report_unix_paths)
@ -634,13 +638,17 @@ func_basename_dir (char *o, char **argv, const char *funcname)
o = variable_buffer_output (o, "[]", 2); o = variable_buffer_output (o, "[]", 2);
} }
#else #else
#ifndef _AMIGA
o = variable_buffer_output (o, "./", 2); o = variable_buffer_output (o, "./", 2);
#endif /* !MK_OS_VMS */ #else
; /* Just a nop... */
#endif /* AMIGA */
#endif /* !VMS */
else else
/* The entire name is the basename. */ /* The entire name is the basename. */
o = variable_buffer_output (o, p2, len); o = variable_buffer_output (o, p2, len);
#if MK_OS_VMS #ifdef VMS
if (vms_comma_separator) if (vms_comma_separator)
o = variable_buffer_output (o, ",", 1); o = variable_buffer_output (o, ",", 1);
else else
@ -737,7 +745,8 @@ func_words (char *o, char **argv, const char *funcname UNUSED)
while (find_next_token (&word_iterator, NULL) != 0) while (find_next_token (&word_iterator, NULL) != 0)
++i; ++i;
o = variable_buffer_output (o, buf, sprintf (buf, "%u", i)); sprintf (buf, "%u", i);
o = variable_buffer_output (o, buf, strlen (buf));
return o; return o;
} }
@ -884,7 +893,7 @@ func_foreach (char *o, char **argv, const char *funcname UNUSED)
free (var->value); free (var->value);
var->value = xstrndup (p, len); var->value = xstrndup (p, len);
result = allocated_expand_string (body); result = allocated_variable_expand (body);
o = variable_buffer_output (o, result, strlen (result)); o = variable_buffer_output (o, result, strlen (result));
o = variable_buffer_output (o, " ", 1); o = variable_buffer_output (o, " ", 1);
@ -914,6 +923,8 @@ func_let (char *o, char **argv, const char *funcname UNUSED)
const char *vp; const char *vp;
const char *vp_next = varnames; const char *vp_next = varnames;
const char *list_iterator = list; const char *list_iterator = list;
char *p;
size_t len;
size_t vlen; size_t vlen;
push_new_variable_scope (); push_new_variable_scope ();
@ -923,9 +934,8 @@ func_let (char *o, char **argv, const char *funcname UNUSED)
NEXT_TOKEN (vp_next); NEXT_TOKEN (vp_next);
while (*vp_next != '\0') while (*vp_next != '\0')
{ {
size_t len; p = find_next_token (&list_iterator, &len);
char *p = find_next_token (&list_iterator, &len); if (*list_iterator != '\0')
if (p && *list_iterator != '\0')
{ {
++list_iterator; ++list_iterator;
p[len] = '\0'; p[len] = '\0';
@ -943,7 +953,7 @@ func_let (char *o, char **argv, const char *funcname UNUSED)
/* Expand the body in the context of the arguments, adding the result to /* Expand the body in the context of the arguments, adding the result to
the variable buffer. */ the variable buffer. */
o = expand_string_buf (o, body, SIZE_MAX); o = variable_expand_string (o, body, SIZE_MAX);
pop_variable_scope (); pop_variable_scope ();
free (varnames); free (varnames);
@ -1173,17 +1183,16 @@ func_error (char *o, char **argv, const char *funcname)
case 'i': case 'i':
{ {
size_t len = strlen (argv[0]); size_t len = strlen (argv[0]);
char *msg = xmalloc (len + 2); char *msg = alloca (len + 2);
memcpy (msg, argv[0], len); memcpy (msg, argv[0], len);
msg[len] = '\n'; msg[len] = '\n';
msg[len + 1] = '\0'; msg[len + 1] = '\0';
outputs (0, msg); outputs (0, msg);
free (msg);
break; break;
} }
default: default:
OS (fatal, *expanding_var, "INTERNAL: func_error: '%s'", funcname); OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname);
} }
/* The warning function expands to the empty string. */ /* The warning function expands to the empty string. */
@ -1327,8 +1336,6 @@ func_intcmp (char *o, char **argv, const char *funcname UNUSED)
cmp = (llen > rlen) - (llen < rlen); cmp = (llen > rlen) - (llen < rlen);
if (cmp == 0) if (cmp == 0)
cmp = memcmp (lnum, rnum, llen); cmp = memcmp (lnum, rnum, llen);
if (lsign < 0)
cmp *= -1;
} }
argv += 2; argv += 2;
@ -1521,8 +1528,12 @@ func_and (char *o, char **argv, const char *funcname UNUSED)
static char * static char *
func_wildcard (char *o, char **argv, const char *funcname UNUSED) 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]); char *p = string_glob (argv[0]);
o = variable_buffer_output (o, p, strlen (p)); o = variable_buffer_output (o, p, strlen (p));
#endif
return o; return o;
} }
@ -1619,7 +1630,7 @@ shell_completed (int exit_code, int exit_sig)
define_variable_cname (".SHELLSTATUS", buf, o_override, 0); define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
} }
#if MK_OS_W32 #ifdef WINDOWS32
/*untested*/ /*untested*/
#include <windows.h> #include <windows.h>
@ -1670,11 +1681,11 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
if (hIn == INVALID_HANDLE_VALUE) if (hIn == INVALID_HANDLE_VALUE)
{ {
ON (error, NILF, ON (error, NILF,
_("windows32_openpipe: DuplicateHandle(In) failed (e=%lu)"), e); _("windows32_openpipe: DuplicateHandle(In) failed (e=%lu)\n"), e);
return -1; return -1;
} }
} }
tmpErr = get_handle_for_fd (errfd); tmpErr = (HANDLE)_get_osfhandle (errfd);
if (DuplicateHandle (GetCurrentProcess (), tmpErr, if (DuplicateHandle (GetCurrentProcess (), tmpErr,
GetCurrentProcess (), &hErr, GetCurrentProcess (), &hErr,
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
@ -1694,14 +1705,14 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
if (hErr == INVALID_HANDLE_VALUE) if (hErr == INVALID_HANDLE_VALUE)
{ {
ON (error, NILF, ON (error, NILF,
_("windows32_openpipe: DuplicateHandle(Err) failed (e=%lu)"), e); _("windows32_openpipe: DuplicateHandle(Err) failed (e=%lu)\n"), e);
return -1; return -1;
} }
} }
if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0)) if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0))
{ {
ON (error, NILF, _("CreatePipe() failed (e=%lu)"), GetLastError()); ON (error, NILF, _("CreatePipe() failed (e=%lu)\n"), GetLastError());
return -1; return -1;
} }
@ -1709,7 +1720,7 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
if (!hProcess) if (!hProcess)
{ {
O (error, NILF, _("windows32_openpipe(): process_init_fd() failed")); O (error, NILF, _("windows32_openpipe(): process_init_fd() failed\n"));
return -1; return -1;
} }
@ -1749,7 +1760,7 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv,
#endif #endif
#if MK_OS_DOS #ifdef __MSDOS__
FILE * FILE *
msdos_openpipe (int* pipedes, int *pidp, char *text) msdos_openpipe (int* pipedes, int *pidp, char *text)
{ {
@ -1808,7 +1819,7 @@ msdos_openpipe (int* pipedes, int *pidp, char *text)
Do shell spawning, with the naughty bits for different OSes. Do shell spawning, with the naughty bits for different OSes.
*/ */
#if MK_OS_VMS #ifdef VMS
/* VMS can't do $(shell ...) */ /* VMS can't do $(shell ...) */
@ -1823,21 +1834,22 @@ func_shell_base (char *o, char **argv, int trim_newlines)
#define func_shell 0 #define func_shell 0
#else #else
#ifndef _AMIGA
char * char *
func_shell_base (char *o, char **argv, int trim_newlines) func_shell_base (char *o, char **argv, int trim_newlines)
{ {
struct childbase child = {0}; struct childbase child = {0};
char *batch_filename = NULL; char *batch_filename = NULL;
int errfd; int errfd;
#if MK_OS_DOS #ifdef __MSDOS__
FILE *fpipe; FILE *fpipe;
#endif #endif
char **command_argv = NULL; char **command_argv = NULL;
int pipedes[2]; int pipedes[2];
pid_t pid; pid_t pid;
#if !MK_OS_DOS #ifndef __MSDOS__
#if MK_OS_W32 #ifdef WINDOWS32
/* Reset just_print_flag. This is needed on Windows when batch files /* Reset just_print_flag. This is needed on Windows when batch files
are used to run the commands, because we normally refrain from are used to run the commands, because we normally refrain from
creating batch files under -n. */ creating batch files under -n. */
@ -1850,12 +1862,12 @@ func_shell_base (char *o, char **argv, int trim_newlines)
&batch_filename); &batch_filename);
if (command_argv == 0) if (command_argv == 0)
{ {
#if MK_OS_W32 #ifdef WINDOWS32
just_print_flag = j_p_f; just_print_flag = j_p_f;
#endif #endif
return o; return o;
} }
#endif /* !MK_OS_DOS */ #endif /* !__MSDOS__ */
/* Set up the output in case the shell writes something. */ /* Set up the output in case the shell writes something. */
output_start (); output_start ();
@ -1865,7 +1877,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
child.environment = target_environment (NULL, 0); child.environment = target_environment (NULL, 0);
#if MK_OS_DOS #if defined(__MSDOS__)
fpipe = msdos_openpipe (pipedes, &pid, argv[0]); fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
if (pipedes[0] < 0) if (pipedes[0] < 0)
{ {
@ -1874,7 +1886,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
goto done; goto done;
} }
#elif MK_OS_W32 #elif defined(WINDOWS32)
windows32_openpipe (pipedes, errfd, &pid, command_argv, child.environment); windows32_openpipe (pipedes, errfd, &pid, command_argv, child.environment);
/* Restore the value of just_print_flag. */ /* Restore the value of just_print_flag. */
just_print_flag = j_p_f; just_print_flag = j_p_f;
@ -1920,7 +1932,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
/* Record the PID for reap_children. */ /* Record the PID for reap_children. */
shell_function_pid = pid; shell_function_pid = pid;
#if !MK_OS_DOS #ifndef __MSDOS__
shell_function_completed = 0; shell_function_completed = 0;
/* Close the write side of the pipe. We test for -1, since /* Close the write side of the pipe. We test for -1, since
@ -1951,7 +1963,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
buffer[i] = '\0'; buffer[i] = '\0';
/* Close the read side of the pipe. */ /* Close the read side of the pipe. */
#if MK_OS_DOS #ifdef __MSDOS__
if (fpipe) if (fpipe)
{ {
int st = pclose (fpipe); int st = pclose (fpipe);
@ -1996,12 +2008,100 @@ func_shell_base (char *o, char **argv, int trim_newlines)
return o; 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 * static char *
func_shell (char *o, char **argv, const char *funcname UNUSED) func_shell (char *o, char **argv, const char *funcname UNUSED)
{ {
return func_shell_base (o, argv, 1); return func_shell_base (o, argv, 1);
} }
#endif /* !MK_OS_VMS */ #endif /* !VMS */
#ifdef EXPERIMENTAL #ifdef EXPERIMENTAL
@ -2012,8 +2112,7 @@ static char *
func_eq (char *o, char **argv, char *funcname UNUSED) func_eq (char *o, char **argv, char *funcname UNUSED)
{ {
int result = ! strcmp (argv[0], argv[1]); int result = ! strcmp (argv[0], argv[1]);
if (result) o = variable_buffer_output (o, result ? "1" : "", result);
o = variable_buffer_output (o, "1", 1);
return o; return o;
} }
@ -2028,8 +2127,7 @@ func_not (char *o, char **argv, char *funcname UNUSED)
int result = 0; int result = 0;
NEXT_TOKEN (s); NEXT_TOKEN (s);
result = ! (*s); result = ! (*s);
if (result) o = variable_buffer_output (o, result ? "1" : "", result);
o = variable_buffer_output (o, "1", 1);
return o; return o;
} }
#endif #endif
@ -2109,7 +2207,7 @@ abspath (const char *name, char *apath)
apath[3] = '/'; apath[3] = '/';
dest++; dest++;
root_len++; root_len++;
/* memcpy above copied one character too many. */ /* strncpy above copied one character too many. */
name--; name--;
} }
else else
@ -2119,7 +2217,7 @@ abspath (const char *name, char *apath)
for (start = end = name; *start != '\0'; start = end) for (start = end = name; *start != '\0'; start = end)
{ {
ptrdiff_t len; size_t len;
/* Skip sequence of multiple path-separators. */ /* Skip sequence of multiple path-separators. */
while (ISDIRSEP (*start)) while (ISDIRSEP (*start))
@ -2147,7 +2245,7 @@ abspath (const char *name, char *apath)
if (! ISDIRSEP (dest[-1])) if (! ISDIRSEP (dest[-1]))
*dest++ = '/'; *dest++ = '/';
if (apath_limit - dest <= len) if (dest + len >= apath_limit)
return NULL; return NULL;
dest = mempcpy (dest, start, len); dest = mempcpy (dest, start, len);
@ -2178,13 +2276,13 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED)
{ {
if (len < GET_PATH_MAX) if (len < GET_PATH_MAX)
{ {
char *rp, *inend; char *rp;
struct stat st; struct stat st;
PATH_VAR (in); PATH_VAR (in);
PATH_VAR (out); PATH_VAR (out);
inend = mempcpy (in, path, len); strncpy (in, path, len);
*inend = '\0'; in[len] = '\0';
#ifdef HAVE_REALPATH #ifdef HAVE_REALPATH
ENULLLOOP (rp, realpath (in, out)); ENULLLOOP (rp, realpath (in, out));
@ -2353,9 +2451,9 @@ func_abspath (char *o, char **argv, const char *funcname UNUSED)
{ {
PATH_VAR (in); PATH_VAR (in);
PATH_VAR (out); PATH_VAR (out);
char *inend = mempcpy (in, path, len);
*inend = '\0'; strncpy (in, path, len);
in[len] = '\0';
if (abspath (in, out)) if (abspath (in, out))
{ {
@ -2391,52 +2489,54 @@ static char *func_call (char *o, char **argv, const char *funcname);
#define FT_ENTRY(_name, _min, _max, _exp, _func) \ #define FT_ENTRY(_name, _min, _max, _exp, _func) \
{ { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0, 0 } { { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0, 0 }
static const struct function_table_entry function_table_init[] = static struct function_table_entry function_table_init[] =
{ {
/* Name MIN MAX EXP? Function */ /* Name MIN MAX EXP? Function */
FT_ENTRY ("abspath", 0, 1, 1, func_abspath), FT_ENTRY ("abspath", 0, 1, 1, func_abspath),
FT_ENTRY ("addprefix", 2, 2, 1, func_addsuffix_addprefix), FT_ENTRY ("addprefix", 2, 2, 1, func_addsuffix_addprefix),
FT_ENTRY ("addsuffix", 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 ("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 ("dir", 0, 1, 1, func_basename_dir),
FT_ENTRY ("error", 0, 1, 1, func_error), FT_ENTRY ("notdir", 0, 1, 1, func_notdir_suffix),
FT_ENTRY ("eval", 0, 1, 1, func_eval), FT_ENTRY ("subst", 3, 3, 1, func_subst),
FT_ENTRY ("file", 1, 2, 1, func_file), FT_ENTRY ("suffix", 0, 1, 1, func_notdir_suffix),
FT_ENTRY ("filter", 2, 2, 1, func_filter_filterout), FT_ENTRY ("filter", 2, 2, 1, func_filter_filterout),
FT_ENTRY ("filter-out", 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 ("findstring", 2, 2, 1, func_findstring),
FT_ENTRY ("firstword", 0, 1, 1, func_firstword), FT_ENTRY ("firstword", 0, 1, 1, func_firstword),
FT_ENTRY ("flavor", 0, 1, 1, func_flavor), 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 ("join", 2, 2, 1, func_join),
FT_ENTRY ("lastword", 0, 1, 1, func_lastword), 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 ("patsubst", 3, 3, 1, func_patsubst),
FT_ENTRY ("realpath", 0, 1, 1, func_realpath), FT_ENTRY ("realpath", 0, 1, 1, func_realpath),
FT_ENTRY ("shell", 0, 1, 1, func_shell), FT_ENTRY ("shell", 0, 1, 1, func_shell),
FT_ENTRY ("sort", 0, 1, 1, func_sort), FT_ENTRY ("sort", 0, 1, 1, func_sort),
FT_ENTRY ("strip", 0, 1, 1, func_strip), 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 ("wildcard", 0, 1, 1, func_wildcard),
FT_ENTRY ("word", 2, 2, 1, func_word), FT_ENTRY ("word", 2, 2, 1, func_word),
FT_ENTRY ("wordlist", 3, 3, 1, func_wordlist), FT_ENTRY ("wordlist", 3, 3, 1, func_wordlist),
FT_ENTRY ("words", 0, 1, 1, func_words), 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 #ifdef EXPERIMENTAL
FT_ENTRY ("eq", 2, 2, 1, func_eq), FT_ENTRY ("eq", 2, 2, 1, func_eq),
FT_ENTRY ("not", 0, 1, 1, func_not), FT_ENTRY ("not", 0, 1, 1, func_not),
#endif #endif
}; };
#define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
/* These must come after the definition of function_table. */ /* These must come after the definition of function_table. */
@ -2485,8 +2585,7 @@ expand_builtin_function (char *o, unsigned int argc, char **argv,
/* Check for a function invocation in *STRINGP. *STRINGP points at the /* Check for a function invocation in *STRINGP. *STRINGP points at the
opening ( or { and is not null-terminated. If a function invocation opening ( or { and is not null-terminated. If a function invocation
is found, expand it into the buffer at *OP, updating *OP, incrementing is found, expand it into the buffer at *OP, updating *OP, incrementing
*STRINGP past the reference, and return nonzero. *STRINGP past the reference and returning nonzero. If not, return zero. */
If no function is found, return zero and don't change *OP or *STRINGP. */
int int
handle_function (char **op, const char **stringp) handle_function (char **op, const char **stringp)
@ -2514,10 +2613,10 @@ handle_function (char **op, const char **stringp)
beg += entry_p->len; beg += entry_p->len;
NEXT_TOKEN (beg); NEXT_TOKEN (beg);
/* Find the end of the function invocation, counting nested use of whichever /* Find the end of the function invocation, counting nested use of
kind of parens we use. Don't use skip_reference so we can count commas 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 to get a rough estimate of how many arguments we might have. The
might be high, but it'll never be low. */ count might be high, but it'll never be low. */
for (nargs=1, end=beg; *end != '\0'; ++end) for (nargs=1, end=beg; *end != '\0'; ++end)
if (!STOP_SET (*end, MAP_VARSEP|MAP_COMMA)) if (!STOP_SET (*end, MAP_VARSEP|MAP_COMMA))
@ -2613,6 +2712,7 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{ {
static unsigned int max_args = 0; static unsigned int max_args = 0;
char *fname; char *fname;
char *body;
size_t flen; size_t flen;
unsigned int i; unsigned int i;
int saved_args; int saved_args;
@ -2650,6 +2750,13 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
if (v == 0 || *v->value == '\0') if (v == 0 || *v->value == '\0')
return o; 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. */ /* Set up arguments $(1) .. $(N). $(0) is the function name. */
push_new_variable_scope (); push_new_variable_scope ();
@ -2658,7 +2765,8 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{ {
char num[INTSTR_LENGTH]; char num[INTSTR_LENGTH];
define_variable (num, sprintf (num, "%u", i), *argv, o_automatic, 0); sprintf (num, "%u", i);
define_variable (num, strlen (num), *argv, o_automatic, 0);
} }
/* If the number of arguments we have is < max_args, it means we're inside /* If the number of arguments we have is < max_args, it means we're inside
@ -2670,17 +2778,18 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
{ {
char num[INTSTR_LENGTH]; char num[INTSTR_LENGTH];
define_variable (num, sprintf (num, "%u", i), "", o_automatic, 0); sprintf (num, "%u", i);
define_variable (num, strlen (num), "", o_automatic, 0);
} }
/* Expand the function in the context of the arguments, adding the result to /* Expand the body in the context of the arguments, adding the result to
the variable buffer. */ the variable buffer. */
v->exp_count = EXP_COUNT_MAX; v->exp_count = EXP_COUNT_MAX;
saved_args = max_args; saved_args = max_args;
max_args = i; max_args = i;
o = expand_variable_output (o, fname, flen); o = variable_expand_string (o, body, flen+3);
max_args = saved_args; max_args = saved_args;
v->exp_count = 0; v->exp_count = 0;
@ -2704,17 +2813,17 @@ define_new_function (const floc *flocp, const char *name,
len = e - name; len = e - name;
if (len == 0) if (len == 0)
O (fatal, flocp, _("empty function name")); O (fatal, flocp, _("Empty function name"));
if (*name == '.' || *e != '\0') if (*name == '.' || *e != '\0')
OS (fatal, flocp, _("invalid function name: %s"), name); OS (fatal, flocp, _("Invalid function name: %s"), name);
if (len > 255) if (len > 255)
OS (fatal, flocp, _("function name too long: %s"), name); OS (fatal, flocp, _("Function name too long: %s"), name);
if (min > 255) if (min > 255)
ONS (fatal, flocp, 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)) if (max > 255 || (max && max < min))
ONS (fatal, flocp, 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 = xmalloc (sizeof (struct function_table_entry));
ent->name = strcache_add (name); ent->name = strcache_add (name);
@ -2734,9 +2843,9 @@ define_new_function (const floc *flocp, const char *name,
void void
hash_init_function_table (void) hash_init_function_table (void)
{ {
hash_init (&function_table, ARRAYLEN (function_table_init) * 2, hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
function_table_entry_hash_1, function_table_entry_hash_2, function_table_entry_hash_1, function_table_entry_hash_2,
function_table_entry_hash_cmp); function_table_entry_hash_cmp);
hash_load (&function_table, function_table_init, hash_load (&function_table, function_table_init,
ARRAYLEN (function_table_init), sizeof (struct function_table_entry)); FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
} }

View File

@ -3,7 +3,7 @@ NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org "Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it! before changing it!
Copyright (C) 1987-2024 Free Software Foundation, Inc. Copyright (C) 1987-2023 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library. NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@gnu.org. 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> # include <unistd.h>
#endif /* GNU C library. */ #endif /* GNU C library. */
#if MK_OS_VMS #ifdef VMS
# include <unixlib.h> # include <unixlib.h>
# if HAVE_STRING_H - 0 # if HAVE_STRING_H - 0
# include <string.h> # include <string.h>

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
;; Contents of the (GNU Make) Guile module ;; Contents of the (GNU Make) Guile module
;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
;; This file is part of GNU Make. ;; This file is part of GNU Make.
;; ;;
;; GNU Make is free software; you can redistribute it and/or modify it under ;; GNU Make is free software; you can redistribute it and/or modify it under

View File

@ -1,6 +1,7 @@
/* External interfaces usable by dynamic objects loaded into GNU Make. /* 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-2024 Free Software Foundation, Inc. Copyright (C) 2013-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -18,8 +19,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GNUMAKE_H_ #ifndef _GNUMAKE_H_
#define _GNUMAKE_H_ #define _GNUMAKE_H_
#define GMK_ABI_VERSION 1
/* Specify the location of elements read from makefiles. */ /* Specify the location of elements read from makefiles. */
typedef struct typedef struct
{ {
@ -29,23 +28,6 @@ typedef struct
typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv); 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 _WIN32
# ifdef GMK_BUILDING_MAKE # ifdef GMK_BUILDING_MAKE
# define GMK_EXPORT __declspec(dllexport) # define GMK_EXPORT __declspec(dllexport)
@ -56,7 +38,7 @@ typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);
# define GMK_EXPORT # define GMK_EXPORT
#endif #endif
/* Free memory returned by the gmk_expand() and gmk_free() functions. */ /* Free memory returned by the gmk_expand() function. */
GMK_EXPORT void gmk_free (char *str); GMK_EXPORT void gmk_free (char *str);
/* Allocate memory in GNU Make's context. */ /* Allocate memory in GNU Make's context. */

View File

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

View File

@ -33,7 +33,7 @@ static unsigned long round_up_2 __P((unsigned long rough));
potentially hit every slot in the table during collision potentially hit every slot in the table during collision
resolution. */ resolution. */
const void *hash_deleted_item = &hash_deleted_item; void *hash_deleted_item = &hash_deleted_item;
/* Force the table size to be a power of two, possibly rounding up the /* Force the table size to be a power of two, possibly rounding up the
given size. */ given size. */
@ -65,10 +65,10 @@ hash_init (struct hash_table *ht, unsigned long size,
/* Load an array of items into 'ht'. */ /* Load an array of items into 'ht'. */
void void
hash_load (struct hash_table *ht, const void *item_table, hash_load (struct hash_table *ht, void *item_table,
unsigned long cardinality, unsigned long size) unsigned long cardinality, unsigned long size)
{ {
const char *items = (const char *) item_table; char *items = (char *) item_table;
while (cardinality--) while (cardinality--)
{ {
hash_insert (ht, items); hash_insert (ht, items);

View File

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

View File

@ -1,5 +1,5 @@
/* Implicit rule searching for GNU Make. /* Implicit rule searching for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -87,10 +87,12 @@ get_next_word (const char *buffer, size_t *length)
return 0; return 0;
/* We already found the first value of "c", above. */
while (1) while (1)
{ {
/* Each time through the loop, "c" has the current char char closeparen;
and "p" points to the next char. */ int count;
switch (c) switch (c)
{ {
case '\0': case '\0':
@ -99,8 +101,31 @@ get_next_word (const char *buffer, size_t *length)
goto done_word; goto done_word;
case '$': case '$':
/* This is a variable reference, so skip it. */ c = *(p++);
p = skip_reference (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;
}
}
break; break;
case '|': case '|':
@ -259,7 +284,7 @@ pattern_search (struct file *file, int archive,
but not counting any slash at the end. (foo/bar/ counts as but not counting any slash at the end. (foo/bar/ counts as
bar/ in directory foo/, not empty in directory foo/bar/.) */ bar/ in directory foo/, not empty in directory foo/bar/.) */
lastslash = memrchr (filename, '/', namelen - 1); lastslash = memrchr (filename, '/', namelen - 1);
#if MK_OS_VMS #ifdef VMS
if (lastslash == NULL) if (lastslash == NULL)
lastslash = strrchr (filename, ']'); lastslash = strrchr (filename, ']');
if (lastslash == NULL) if (lastslash == NULL)
@ -332,7 +357,7 @@ pattern_search (struct file *file, int archive,
check_lastslash = 0; check_lastslash = 0;
if (lastslash) if (lastslash)
{ {
#if MK_OS_VMS #ifdef VMS
check_lastslash = strpbrk (target, "/]>:") == NULL; check_lastslash = strpbrk (target, "/]>:") == NULL;
#else #else
check_lastslash = strchr (target, '/') == 0; check_lastslash = strchr (target, '/') == 0;
@ -681,7 +706,7 @@ pattern_search (struct file *file, int archive,
} }
/* Perform the 2nd expansion. */ /* Perform the 2nd expansion. */
p = expand_string_for_file (depname, file); p = variable_expand_for_file (depname, file);
dptr = &dl; dptr = &dl;
/* Parse the results into a deps list. */ /* Parse the results into a deps list. */

494
src/job.c

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Miscellaneous global declarations and portability cruft for GNU Make. /* Miscellaneous global declarations and portability cruft for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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. Be sure to use the local one, and not one installed on the system.
Define GMK_BUILDING_MAKE for proper selection of dllexport/dllimport Define GMK_BUILDING_MAKE for proper selection of dllexport/dllimport
declarations for MS-Windows. */ declarations for MS-Windows. */
#if MK_OS_W32 #ifdef WINDOWS32
# define GMK_BUILDING_MAKE # define GMK_BUILDING_MAKE
#endif #endif
#include "gnumake.h" #include "gnumake.h"
@ -66,6 +66,11 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <stdio.h> #include <stdio.h>
#include <ctype.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 #if HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
#endif #endif
@ -88,12 +93,7 @@ extern int errno;
# define MK_OS_ZOS 1 # define MK_OS_ZOS 1
#endif #endif
#if defined(__EMX__)
# define MK_OS_OS2 1
#endif
#ifdef __VMS #ifdef __VMS
# define MK_OS_VMS 1
/* In strict ANSI mode, VMS compilers should not be defining the /* 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. VMS macro. Define it here instead of a bulk edit for the correct code.
*/ */
@ -106,7 +106,7 @@ extern int errno;
# include <unistd.h> # include <unistd.h>
/* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get /* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get
POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself! */ POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself! */
# if defined (_POSIX_VERSION) && !defined (ultrix) && !MK_OS_VMS # if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS)
# define POSIX 1 # define POSIX 1
# endif # endif
#endif #endif
@ -149,8 +149,15 @@ extern int errno;
# endif # endif
#endif #endif
#define GET_PATH_MAX PATH_MAX #ifdef PATH_MAX
#define PATH_VAR(var) char var[PATH_MAX+1] # 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
#ifndef CHAR_BIT #ifndef CHAR_BIT
# define CHAR_BIT 8 # define CHAR_BIT 8
@ -160,10 +167,6 @@ extern int errno;
# define USHRT_MAX 65535 # define USHRT_MAX 65535
#endif #endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)~(size_t)0)
#endif
/* Nonzero if the integer type T is signed. /* Nonzero if the integer type T is signed.
Use <= to avoid GCC warnings about always-false expressions. */ Use <= to avoid GCC warnings about always-false expressions. */
#define INTEGER_TYPE_SIGNED(t) ((t) -1 <= 0) #define INTEGER_TYPE_SIGNED(t) ((t) -1 <= 0)
@ -194,7 +197,7 @@ extern int errno;
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif #endif
#if MK_OS_VMS #ifdef VMS
# include <fcntl.h> # include <fcntl.h>
# include <types.h> # include <types.h>
# include <unixlib.h> # include <unixlib.h>
@ -363,7 +366,7 @@ extern mode_t umask (mode_t);
# include <direct.h> # include <direct.h>
#endif #endif
#if MK_OS_W32 #ifdef WINDOWS32
# include <fcntl.h> # include <fcntl.h>
# include <malloc.h> # include <malloc.h>
# define pipe(_p) _pipe((_p), 512, O_BINARY) # define pipe(_p) _pipe((_p), 512, O_BINARY)
@ -396,7 +399,7 @@ extern int unixy_shell;
# ifndef WIN32_LEAN_AND_MEAN # ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
# endif # endif
#endif /* MK_OS_W32 */ #endif /* WINDOWS32 */
/* ALL_SET() evaluates the second argument twice. */ /* ALL_SET() evaluates the second argument twice. */
#define ANY_SET(_v,_m) (((_v)&(_m)) != 0) #define ANY_SET(_v,_m) (((_v)&(_m)) != 0)
@ -423,7 +426,7 @@ extern int unixy_shell;
/* The set of characters which are directory separators is OS-specific. */ /* The set of characters which are directory separators is OS-specific. */
#define MAP_DIRSEP 0x8000 #define MAP_DIRSEP 0x8000
#if MK_OS_VMS #ifdef VMS
# define MAP_VMSCOMMA MAP_COMMA # define MAP_VMSCOMMA MAP_COMMA
#else #else
# define MAP_VMSCOMMA 0x0000 # define MAP_VMSCOMMA 0x0000
@ -440,7 +443,7 @@ extern int unixy_shell;
# define PATH_SEPARATOR_CHAR ';' # define PATH_SEPARATOR_CHAR ';'
# define MAP_PATHSEP MAP_SEMI # define MAP_PATHSEP MAP_SEMI
#elif !defined(PATH_SEPARATOR_CHAR) #elif !defined(PATH_SEPARATOR_CHAR)
# if MK_OS_VMS # if defined (VMS)
# define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':') # define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':')
# define MAP_PATHSEP (vms_comma_separator ? MAP_COMMA : MAP_SEMI) # define MAP_PATHSEP (vms_comma_separator ? MAP_COMMA : MAP_SEMI)
# else # else
@ -494,9 +497,6 @@ extern struct rlimit stack_limit;
#define NILF ((floc *)0) #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. */ /* Number of characters in a string constant. Does NOT include the \0 byte. */
#define CSTRLEN(_s) (sizeof (_s)-1) #define CSTRLEN(_s) (sizeof (_s)-1)
@ -516,7 +516,7 @@ extern struct rlimit stack_limit;
# define TTYNAME(_f) DEFAULT_TTYNAME # define TTYNAME(_f) DEFAULT_TTYNAME
#endif #endif
#if MK_OS_VMS #ifdef VMS
# define DEFAULT_TMPDIR "/sys$scratch/" # define DEFAULT_TMPDIR "/sys$scratch/"
#elif defined(P_tmpdir) #elif defined(P_tmpdir)
# define DEFAULT_TMPDIR P_tmpdir # define DEFAULT_TMPDIR P_tmpdir
@ -544,8 +544,6 @@ void error (const floc *flocp, size_t length, const char *fmt, ...)
ATTRIBUTE ((__format__ (__printf__, 3, 4))); ATTRIBUTE ((__format__ (__printf__, 3, 4)));
void fatal (const floc *flocp, size_t length, const char *fmt, ...) void fatal (const floc *flocp, size_t length, const char *fmt, ...)
ATTRIBUTE ((noreturn, __format__ (__printf__, 3, 4))); 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; void out_of_memory (void) NORETURN;
/* When adding macros to this list be sure to update the value of /* When adding macros to this list be sure to update the value of
@ -589,7 +587,6 @@ char *xstrndup (const char *, size_t);
char *find_next_token (const char **, size_t *); char *find_next_token (const char **, size_t *);
char *next_token (const char *); char *next_token (const char *);
char *end_of_token (const char *); char *end_of_token (const char *);
char *skip_reference (const char *);
void collapse_continuations (char *); void collapse_continuations (char *);
char *lindex (const char *, const char *, int); char *lindex (const char *, const char *, int);
int alpha_compare (const void *, const void *); int alpha_compare (const void *, const void *);
@ -621,7 +618,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, intmax_t ar_scan (const char *archive, ar_member_func_t function,
const void *arg); const void *arg);
int ar_name_equal (const char *name, const char *mem, int truncated); int ar_name_equal (const char *name, const char *mem, int truncated);
#if !MK_OS_VMS #ifndef VMS
int ar_member_touch (const char *arname, const char *memname); int ar_member_touch (const char *arname, const char *memname);
#endif #endif
#endif #endif
@ -664,9 +661,9 @@ const char *strcache_add_len (const char *str, size_t len);
int guile_gmake_setup (const floc *flocp); int guile_gmake_setup (const floc *flocp);
/* Loadable object support. Sets to the strcached name of the loaded file. */ /* 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 load_file (const floc *flocp, struct file *file, int noerror);
int unload_file (const char *name); int unload_file (const char *name);
void unload_all (void);
/* Maintainer mode support */ /* Maintainer mode support */
#ifdef MAKE_MAINTAINER_MODE #ifdef MAKE_MAINTAINER_MODE
@ -683,14 +680,14 @@ void dbg (const char *fmt, ...);
/* We omit these declarations on non-POSIX systems which define _POSIX_VERSION, /* We omit these declarations on non-POSIX systems which define _POSIX_VERSION,
because such systems often declare them in header files anyway. */ because such systems often declare them in header files anyway. */
#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !MK_OS_W32 #if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32)
# if !MK_OS_VMS # ifndef VMS
long int lseek (); long int lseek ();
# endif # endif
# ifdef HAVE_GETCWD # ifdef HAVE_GETCWD
# if !MK_OS_VMS && !defined(__DECC) # if !defined(VMS) && !defined(__DECC)
char *getcwd (void); char *getcwd (void);
# endif # endif
# else # else
@ -732,10 +729,10 @@ extern unsigned short stopchar_map[];
extern int just_print_flag, run_silent, ignore_errors_flag, keep_going_flag; 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 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 env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
extern int print_version_flag, check_symlink_flag, posix_pedantic; extern int print_version_flag, check_symlink_flag;
extern int warn_undefined_variables_flag, posix_pedantic;
extern int not_parallel, second_expansion, clock_skew_detected; extern int not_parallel, second_expansion, clock_skew_detected;
extern int rebuilding_makefiles, one_shell, output_sync, verify_flag; extern int rebuilding_makefiles, one_shell, output_sync, verify_flag;
extern int export_all_variables;
extern unsigned long command_count; extern unsigned long command_count;
extern const char *default_shell; extern const char *default_shell;
@ -746,23 +743,17 @@ extern int batch_mode_shell;
#define GNUMAKEFLAGS_NAME "GNUMAKEFLAGS" #define GNUMAKEFLAGS_NAME "GNUMAKEFLAGS"
#define MAKEFLAGS_NAME "MAKEFLAGS" #define MAKEFLAGS_NAME "MAKEFLAGS"
#define MAKELEVEL_NAME "MAKELEVEL"
#define MAKELEVEL_LENGTH (CSTRLEN (MAKELEVEL_NAME))
/* Resetting the command script introduction prefix character. */ /* Resetting the command script introduction prefix character. */
#define RECIPEPREFIX_NAME ".RECIPEPREFIX" #define RECIPEPREFIX_NAME ".RECIPEPREFIX"
#define RECIPEPREFIX_DEFAULT '\t' #define RECIPEPREFIX_DEFAULT '\t'
extern char cmd_prefix; extern char cmd_prefix;
/* Setting warning actions. */
#define WARNINGS_NAME ".WARNINGS"
extern unsigned int no_intermediates; extern unsigned int no_intermediates;
#if HAVE_MKFIFO #if HAVE_MKFIFO
/* It seems that mkfifo() is not working correctly, or at least not the way /* It seems that mkfifo() is not working correctly, or at least not the way
GNU make wants it to work, on: GNU/Hurd, Cygwin, OS2; don't use it there. */ 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 && !MK_OS_OS2 # if !defined(JOBSERVER_USE_FIFO) && !MK_OS_HURD && !MK_OS_CYGWIN
# define JOBSERVER_USE_FIFO 1 # define JOBSERVER_USE_FIFO 1
# endif # endif
#endif #endif
@ -775,7 +766,7 @@ extern double max_load_average;
extern const char *program; extern const char *program;
#if MK_OS_VMS #ifdef VMS
const char *vms_command (const char *argv0); const char *vms_command (const char *argv0);
const char *vms_progname (const char *argv0); const char *vms_progname (const char *argv0);
@ -842,7 +833,7 @@ extern volatile sig_atomic_t handling_fatal_signal;
#endif #endif
#ifndef initialize_main #ifndef initialize_main
# if MK_OS_OS2 # ifdef __EMX__
# define initialize_main(pargc, pargv) \ # define initialize_main(pargc, pargv) \
{ _wildcard(pargc, pargv); _response(pargc, pargv); } { _wildcard(pargc, pargv); _response(pargc, pargv); }
# else # else
@ -850,7 +841,7 @@ extern volatile sig_atomic_t handling_fatal_signal;
# endif # endif
#endif #endif
#if MK_OS_OS2 #ifdef __EMX__
# if !defined chdir # if !defined chdir
# define chdir _chdir2 # define chdir _chdir2
# endif # endif

View File

@ -1,5 +1,5 @@
/* Miscellaneous generic support functions for GNU Make. /* Miscellaneous generic support functions for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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 <assert.h>
#include <stdarg.h> #include <stdarg.h>
#if MK_OS_W32 #ifdef WINDOWS32
# include <windows.h> # include <windows.h>
# include <io.h> # include <io.h>
#endif #endif
#if MK_OS_OS2 #ifdef __EMX__
# define INCL_DOS # define INCL_DOS
# include <os2.h> # include <os2.h>
#endif #endif
@ -131,7 +131,7 @@ collapse_continuations (char *line)
char *q; char *q;
q = strchr(in, '\n'); q = strchr(in, '\n');
if (!q) if (q == 0)
return; return;
do do
@ -162,32 +162,16 @@ collapse_continuations (char *line)
if (i & 1) if (i & 1)
{ {
unsigned int dollar; /* Backslash/newline handling:
In traditional GNU Make all trailing whitespace, consecutive
/* Backslash/newline handling: out points to the final "\". backslash/newlines, and any leading non-newline whitespace on the
In POSIX, each backslash/newline is replaced by a space. next line is reduced to a single space.
In GNU Make all trailing whitespace, consecutive backslash + In POSIX, each backslash/newline and is replaced by a space. */
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)) while (ISBLANK (*in))
++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])) while (out > line && ISBLANK (out[-1]))
--out; --out;
if (!dollar)
*out++ = ' '; *out++ = ' ';
} }
else else
@ -351,7 +335,7 @@ xstrndup (const char *str, size_t length)
#else #else
result = xmalloc (length + 1); result = xmalloc (length + 1);
if (length > 0) if (length > 0)
memcpy (result, str, length); strncpy (result, str, length);
result[length] = '\0'; result[length] = '\0';
#endif #endif
@ -418,50 +402,6 @@ next_token (const char *s)
return (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 /* 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 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. */ of the token, so this function can be called repeatedly in a loop. */
@ -481,7 +421,6 @@ find_next_token (const char **ptr, size_t *lengthptr)
return (char *)p; return (char *)p;
} }
/* Write a BUFFER of size LEN to file descriptor FD. /* Write a BUFFER of size LEN to file descriptor FD.
Retry short writes from EINTR. Return LEN, or -1 on error. */ Retry short writes from EINTR. Return LEN, or -1 on error. */
ssize_t ssize_t
@ -495,7 +434,7 @@ writebuf (int fd, const void *buffer, size_t len)
EINTRLOOP (r, write (fd, msg, l)); EINTRLOOP (r, write (fd, msg, l));
if (r < 0) if (r < 0)
return -1; return r;
l -= r; l -= r;
msg += r; msg += r;
@ -505,7 +444,8 @@ writebuf (int fd, const void *buffer, size_t len)
} }
/* Read until we get LEN bytes from file descriptor FD, into BUFFER. /* Read until we get LEN bytes from file descriptor FD, into BUFFER.
Retry short reads on EINTR. Return 0 at EOF and -1 on error. */ Retry short reads on EINTR. If we get an error, return it.
Return 0 at EOF. */
ssize_t ssize_t
readbuf (int fd, void *buffer, size_t len) readbuf (int fd, void *buffer, size_t len)
{ {
@ -516,7 +456,7 @@ readbuf (int fd, void *buffer, size_t len)
EINTRLOOP (r, read (fd, msg, len)); EINTRLOOP (r, read (fd, msg, len));
if (r < 0) if (r < 0)
return -1; return r;
if (r == 0) if (r == 0)
break; break;
@ -528,38 +468,23 @@ 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. */ /* Copy a chain of 'struct dep'. For 2nd expansion deps, dup the name. */
struct dep * struct dep *
copy_dep_chain (const struct dep *d) copy_dep_chain (const struct dep *d)
{ {
struct dep *firstnew = NULL; struct dep *firstnew = 0;
struct dep *lastnew = NULL; struct dep *lastnew = 0;
while (d != 0) while (d != 0)
{ {
struct dep *c = copy_dep (d); struct dep *c = xmalloc (sizeof (struct dep));
memcpy (c, d, sizeof (struct dep));
if (c->need_2nd_expansion)
c->name = xstrdup (c->name);
c->next = 0;
if (firstnew == 0) if (firstnew == 0)
firstnew = lastnew = c; firstnew = lastnew = c;
else else
@ -577,7 +502,7 @@ copy_dep_chain (const struct dep *d)
void void
free_ns_chain (struct nameseq *ns) free_ns_chain (struct nameseq *ns)
{ {
while (ns != NULL) while (ns != 0)
{ {
struct nameseq *t = ns; struct nameseq *t = ns;
ns = ns->next; ns = ns->next;
@ -600,7 +525,7 @@ spin (const char* type)
{ {
fprintf (stderr, "SPIN on %s\n", filenm); fprintf (stderr, "SPIN on %s\n", filenm);
do do
#if MK_OS_W32 #ifdef WINDOWS32
Sleep (1000); Sleep (1000);
#else #else
sleep (1); sleep (1);
@ -647,7 +572,7 @@ umask (mode_t mask)
} }
#endif #endif
#if MK_OS_VMS #ifdef VMS
# define DEFAULT_TMPFILE "sys$scratch:gnv$make_cmdXXXXXX.com" # define DEFAULT_TMPFILE "sys$scratch:gnv$make_cmdXXXXXX.com"
#else #else
# define DEFAULT_TMPFILE "GmXXXXXX" # define DEFAULT_TMPFILE "GmXXXXXX"
@ -660,7 +585,7 @@ get_tmpdir ()
if (!tmpdir) if (!tmpdir)
{ {
#if MK_OS_DOS || MK_OS_W32 || MK_OS_OS2 #if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
# define TMP_EXTRAS "TMP", "TEMP", # define TMP_EXTRAS "TMP", "TEMP",
#else #else
# define TMP_EXTRAS # define TMP_EXTRAS
@ -670,7 +595,7 @@ get_tmpdir ()
unsigned int found = 0; unsigned int found = 0;
for (tp = tlist; *tp; ++tp) for (tp = tlist; *tp; ++tp)
if ((tmpdir = getenv (*tp)) != NULL && *tmpdir != '\0') if ((tmpdir = getenv (*tp)) && *tmpdir != '\0')
{ {
struct stat st; struct stat st;
int r; int r;
@ -705,7 +630,7 @@ get_tmptemplate ()
template = xmalloc (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2); template = xmalloc (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2);
cp = stpcpy (template, tmpdir); cp = stpcpy (template, tmpdir);
#if !MK_OS_VMS #if !defined VMS
/* It's not possible for tmpdir to be empty. */ /* It's not possible for tmpdir to be empty. */
if (! ISDIRSEP (cp[-1])) if (! ISDIRSEP (cp[-1]))
*(cp++) = '/'; *(cp++) = '/';
@ -861,7 +786,7 @@ get_tmpfile (char **name)
} }
#if HAVE_TTYNAME && MK_OS_OS2 #if HAVE_TTYNAME && defined(__EMX__)
/* OS/2 kLIBC has a declaration for ttyname(), so configure finds it. /* OS/2 kLIBC has a declaration for ttyname(), so configure finds it.
But, it is not implemented! Roll our own. */ But, it is not implemented! Roll our own. */
char *ttyname (int fd) char *ttyname (int fd)
@ -948,6 +873,25 @@ strncasecmp (const char *s1, const char *s2, size_t n)
#endif #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 #if !HAVE_MEMPCPY
void * void *
mempcpy (void *dest, const void *src, size_t n) mempcpy (void *dest, const void *src, size_t n)

View File

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

View File

@ -1,5 +1,5 @@
/* Miscellaneous global declarations and portability cruft for GNU Make. /* Miscellaneous global declarations and portability cruft for GNU Make.
Copyright (C) 2023-2024 Free Software Foundation, Inc. Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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 # ifdef _AIX
#pragma alloca #pragma alloca
# else # else
# if !defined(__GNUC__) && !MK_OS_W32 # if !defined(__GNUC__) && !defined(WINDOWS32)
# ifndef alloca /* predefined by HP cc +Olibcalls */ # ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca (); char *alloca ();
# endif # endif

View File

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

View File

@ -1,5 +1,5 @@
/* Output to stdout / stderr for GNU Make /* Output to stdout / stderr for GNU Make
Copyright (C) 2013-2024 Free Software Foundation, Inc. Copyright (C) 2013-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the 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> # include <sys/file.h>
#endif #endif
#if MK_OS_W32 #ifdef WINDOWS32
# include <windows.h> # include <windows.h>
# include <io.h> # include <io.h>
# include "sub_proc.h" # include "sub_proc.h"
#endif #endif /* WINDOWS32 */
struct output *output_context = NULL; struct output *output_context = NULL;
unsigned int stdio_traced = 0; unsigned int stdio_traced = 0;
@ -151,7 +151,7 @@ pump_from_tmp (int from, FILE *to)
{ {
static char buffer[8192]; static char buffer[8192];
#if MK_OS_W32 #ifdef WINDOWS32
int prev_mode; int prev_mode;
/* "from" is opened by open_tmpfd, which does it in binary mode, so /* "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); fflush (to);
} }
#if MK_OS_W32 #ifdef WINDOWS32
/* Switch "to" back to its original mode, so that log messages by /* Switch "to" back to its original mode, so that log messages by
Make have the same EOL format as without --output-sync. */ Make have the same EOL format as without --output-sync. */
_setmode (fileno (to), prev_mode); _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. */ /* If we failed to create a temp file, disable output sync going forward. */
error: error:
O (error, NILF, 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_close (out);
output_sync = OUTPUT_SYNC_NONE; output_sync = OUTPUT_SYNC_NONE;
@ -280,7 +280,7 @@ output_dump (struct output *out)
if (!osync_acquire ()) if (!osync_acquire ())
{ {
O (error, NILF, O (error, NILF,
_("warning: cannot acquire output lock: disabling output sync")); _("warning: Cannot acquire output lock, disabling output sync."));
osync_clear (); osync_clear ();
} }
@ -318,9 +318,6 @@ output_dump (struct output *out)
#endif /* NO_OUTPUT_SYNC */ #endif /* NO_OUTPUT_SYNC */
static int stdout_flags = -1;
static int stderr_flags = -1;
void void
output_init (struct output *out) output_init (struct output *out)
{ {
@ -333,8 +330,8 @@ output_init (struct output *out)
/* Force stdout/stderr into append mode (if they are files) to ensure /* Force stdout/stderr into append mode (if they are files) to ensure
parallel jobs won't lose output due to overlapping writes. */ parallel jobs won't lose output due to overlapping writes. */
stdout_flags = fd_set_append (fileno (stdout)); fd_set_append (fileno (stdout));
stderr_flags = fd_set_append (fileno (stderr)); fd_set_append (fileno (stderr));
} }
void void
@ -344,8 +341,6 @@ output_close (struct output *out)
{ {
if (stdio_traced) if (stdio_traced)
log_working_directory (0); log_working_directory (0);
fd_reset_append(fileno (stdout), stdout_flags);
fd_reset_append(fileno (stderr), stderr_flags);
return; return;
} }
@ -425,9 +420,13 @@ message (int prefix, size_t len, const char *fmt, ...)
start = p = get_buffer (len); start = p = get_buffer (len);
if (prefix) if (prefix)
p += (makelevel == 0 {
? sprintf (p, "%s: ", program) if (makelevel == 0)
: sprintf (p, "%s[%u]: ", program, makelevel)); sprintf (p, "%s: ", program);
else
sprintf (p, "%s[%u]: ", program, makelevel);
p += strlen (p);
}
va_start (args, fmt); va_start (args, fmt);
vsprintf (p, fmt, args); vsprintf (p, fmt, args);
@ -453,11 +452,13 @@ error (const floc *flocp, size_t len, const char *fmt, ...)
+ INTSTR_LENGTH + 4 + 1 + 1); + INTSTR_LENGTH + 4 + 1 + 1);
start = p = get_buffer (len); start = p = get_buffer (len);
p += (flocp && flocp->filenm if (flocp && flocp->filenm)
? sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset) sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
: makelevel == 0 else if (makelevel == 0)
? sprintf (p, "%s: ", program) sprintf (p, "%s: ", program);
: sprintf (p, "%s[%u]: ", program, makelevel)); else
sprintf (p, "%s[%u]: ", program, makelevel);
p += strlen (p);
va_start (args, fmt); va_start (args, fmt);
vsprintf (p, fmt, args); vsprintf (p, fmt, args);
@ -474,8 +475,8 @@ error (const floc *flocp, size_t len, const char *fmt, ...)
void void
fatal (const floc *flocp, size_t len, const char *fmt, ...) fatal (const floc *flocp, size_t len, const char *fmt, ...)
{ {
const char *stop = _(". Stop.\n");
va_list args; va_list args;
const char *stop = _(". Stop.\n");
char *start; char *start;
char *p; char *p;
@ -484,12 +485,13 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
+ INTSTR_LENGTH + 8 + strlen (stop) + 1); + INTSTR_LENGTH + 8 + strlen (stop) + 1);
start = p = get_buffer (len); start = p = get_buffer (len);
p += (flocp && flocp->filenm if (flocp && flocp->filenm)
? sprintf (p, "%s:%lu: *** ", flocp->filenm, sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
flocp->lineno + flocp->offset) else if (makelevel == 0)
: makelevel == 0 sprintf (p, "%s: *** ", program);
? sprintf (p, "%s: *** ", program) else
: sprintf (p, "%s[%u]: *** ", program, makelevel)); sprintf (p, "%s[%u]: *** ", program, makelevel);
p += strlen (p);
va_start (args, fmt); va_start (args, fmt);
vsprintf (p, fmt, args); vsprintf (p, fmt, args);
@ -503,29 +505,6 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
die (MAKE_FAILURE); 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. */ /* Print an error message from errno. */
void void

View File

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

View File

@ -1,5 +1,5 @@
/* POSIX-based operating system interface for GNU Make. /* POSIX-based operating system interface for GNU Make.
Copyright (C) 2016-2024 Free Software Foundation, Inc. Copyright (C) 2016-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -122,8 +122,10 @@ make_job_rfd ()
} }
static void static void
force_blocking (int fd, int blocking) set_blocking (int fd, int blocking)
{ {
/* If we're not using pselect() don't change the blocking. */
#ifdef HAVE_PSELECT
int flags; int flags;
EINTRLOOP (flags, fcntl (fd, F_GETFL)); EINTRLOOP (flags, fcntl (fd, F_GETFL));
if (flags >= 0) if (flags >= 0)
@ -134,14 +136,6 @@ force_blocking (int fd, int blocking)
if (r < 0) if (r < 0)
pfatal_with_name ("fcntl(O_NONBLOCK)"); 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 #else
(void) fd; (void) fd;
(void) blocking; (void) blocking;
@ -151,24 +145,20 @@ set_blocking (int fd, int blocking)
unsigned int unsigned int
jobserver_setup (int slots, const char *style) jobserver_setup (int slots, const char *style)
{ {
int r, k; int r;
/* This function sets up the root jobserver. */
job_root = 1;
#if JOBSERVER_USE_FIFO #if JOBSERVER_USE_FIFO
if (!style || strcmp (style, "fifo") == 0) if (!style || strcmp (style, "fifo") == 0)
{ {
/* Unfortunately glibc warns about uses of mktemp even though we aren't /* 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 using it in dangerous way here. So avoid this by generating our own
temporary file name. The template in misc.c uses 6 X's so be sure this temporary file name. */
name cannot conflict with that. */ # define FNAME_PREFIX "GMfifo"
# define FNAME_PREFIX "GmFIFO"
const char *tmpdir = get_tmpdir (); const char *tmpdir = get_tmpdir ();
fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX) fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX)
+ INTSTR_LENGTH + 2); + INTSTR_LENGTH + 2);
sprintf (fifo_name, "%s/" FNAME_PREFIX "%03" MK_PRI64_PREFIX "d", sprintf (fifo_name, "%s/" FNAME_PREFIX "%" MK_PRI64_PREFIX "d",
tmpdir, (long long)make_pid ()); tmpdir, (long long)make_pid ());
EINTRLOOP (r, mkfifo (fifo_name, 0600)); EINTRLOOP (r, mkfifo (fifo_name, 0600));
@ -217,25 +207,18 @@ jobserver_setup (int slots, const char *style)
if (make_job_rfd () < 0) if (make_job_rfd () < 0)
pfatal_with_name (_("duping jobs pipe")); pfatal_with_name (_("duping jobs pipe"));
/* Set the write side of the pipe to non blocking in case the number of while (slots--)
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)); EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1) if (r != 1)
{
if (errno != EAGAIN)
pfatal_with_name (_("init jobserver pipe")); 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. */ /* When using pselect() we want the read to be non-blocking. */
set_blocking (job_fds[0], 0); set_blocking (job_fds[0], 0);
job_root = 1;
return 1; return 1;
} }
@ -574,7 +557,7 @@ set_child_handler_action_flags (int set_handler, int set_alarm)
{ {
struct sigaction sa; struct sigaction sa;
#if MK_OS_OS2 #ifdef __EMX__
/* The child handler must be turned off here. */ /* The child handler must be turned off here. */
signal (SIGCHLD, SIG_DFL); signal (SIGCHLD, SIG_DFL);
#endif #endif
@ -847,12 +830,12 @@ fd_noinherit (int fd)
/* Set a file descriptor referring to a regular file to be in O_APPEND mode. /* Set a file descriptor referring to a regular file to be in O_APPEND mode.
If it fails, just ignore it. */ If it fails, just ignore it. */
int void
fd_set_append (int fd) fd_set_append (int fd)
{ {
int flags = -1;
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND) #if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
struct stat stbuf; struct stat stbuf;
int flags;
if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode)) if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode))
{ {
flags = fcntl (fd, F_GETFL, 0); flags = fcntl (fd, F_GETFL, 0);
@ -862,22 +845,6 @@ fd_set_append (int fd)
EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND)); 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 #endif
} }

View File

@ -1,5 +1,5 @@
/* Reading and parsing of makefiles for GNU Make. /* Reading and parsing of makefiles for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -18,15 +18,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <assert.h> #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 "filedef.h"
#include "dep.h" #include "dep.h"
#include "job.h" #include "job.h"
@ -36,7 +27,20 @@ struct passwd *getpwnam (char *name);
#include "rule.h" #include "rule.h"
#include "debug.h" #include "debug.h"
#include "hash.h" #include "hash.h"
#include "warning.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 */
/* A 'struct ebuffer' controls the origin of the makefile we are currently /* A 'struct ebuffer' controls the origin of the makefile we are currently
eval'ing. eval'ing.
@ -68,7 +72,7 @@ struct vmodifiers
enum make_word_type enum make_word_type
{ {
w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon, w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon,
w_ampcolon, w_ampdcolon w_varassign, w_ampcolon, w_ampdcolon
}; };
@ -96,9 +100,9 @@ static struct conditionals *conditionals = &toplevel_conditionals;
/* Default directories to search for include files in */ /* Default directories to search for include files in */
static const char *const default_include_directories[] = static const char *default_include_directories[] =
{ {
#if MK_OS_W32 && !defined(INCLUDEDIR) #if defined(WINDOWS32) && !defined(INCLUDEDIR)
/* This completely up to the user when they install MSVC or other packages. /* This completely up to the user when they install MSVC or other packages.
This is defined as a placeholder. */ This is defined as a placeholder. */
# define INCLUDEDIR "." # define INCLUDEDIR "."
@ -106,10 +110,12 @@ static const char *const default_include_directories[] =
#if defined(INCLUDEDIR) #if defined(INCLUDEDIR)
INCLUDEDIR, INCLUDEDIR,
#endif #endif
#ifndef _AMIGA
"/usr/gnu/include", "/usr/gnu/include",
"/usr/local/include", "/usr/local/include",
"/usr/include", "/usr/include",
NULL #endif
0
}; };
/* List of directories to search for include files in */ /* List of directories to search for include files in */
@ -186,7 +192,7 @@ read_all_makefiles (const char **makefiles)
char *name, *p; char *name, *p;
size_t length; size_t length;
value = allocated_expand_variable (STRING_SIZE_TUPLE ("MAKEFILES")); value = allocated_variable_expand ("$(MAKEFILES)");
/* Set NAME to the start of next token and LENGTH to its length. /* Set NAME to the start of next token and LENGTH to its length.
MAKEFILES is updated for finding remaining tokens. */ MAKEFILES is updated for finding remaining tokens. */
@ -222,19 +228,23 @@ read_all_makefiles (const char **makefiles)
if (num_makefiles == 0) if (num_makefiles == 0)
{ {
static const char *const default_makefiles[] = static const char *default_makefiles[] =
#if MK_OS_VMS #ifdef VMS
/* all lower case since readdir() (the vms version) 'lowercasifies' */ /* all lower case since readdir() (the vms version) 'lowercasifies' */
/* TODO: Above is not always true, this needs more work */ /* TODO: Above is not always true, this needs more work */
{ "makefile.vms", "gnumakefile", "makefile", 0 }; { "makefile.vms", "gnumakefile", "makefile", 0 };
#else #else
#if MK_OS_W32 #ifdef _AMIGA
{ "GNUmakefile", "Makefile", "SMakefile", 0 };
#else /* !Amiga && !VMS */
#ifdef WINDOWS32
{ "GNUmakefile", "makefile", "Makefile", "makefile.mak", 0 }; { "GNUmakefile", "makefile", "Makefile", "makefile.mak", 0 };
#else /* !MK_OS_VMS && !MK_OS_W32 */ #else /* !Amiga && !VMS && !WINDOWS32 */
{ "GNUmakefile", "makefile", "Makefile", 0 }; { "GNUmakefile", "makefile", "Makefile", 0 };
#endif /* !MK_OS_VMS && !MK_OS_W32 */ #endif /* !Amiga && !VMS && !WINDOWS32 */
#endif /* MK_OS_VMS */ #endif /* AMIGA */
const char *const *p = default_makefiles; #endif /* VMS */
const char **p = default_makefiles;
while (*p != 0 && !file_exists_p (*p)) while (*p != 0 && !file_exists_p (*p))
++p; ++p;
@ -413,7 +423,7 @@ eval_makefile (const char *filename, unsigned short flags)
/* Add this makefile to the list. */ /* Add this makefile to the list. */
do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file, do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file,
f_append_value, 0, s_global); f_append_value, 0);
/* Evaluate the makefile */ /* Evaluate the makefile */
@ -621,7 +631,6 @@ eval (struct ebuffer *ebuf, int set_default)
size_t wlen; size_t wlen;
char *p; char *p;
char *p2; char *p2;
unsigned int is_rule;
struct vmodifiers vmod; struct vmodifiers vmod;
/* At the top of this loop, we are starting a brand new line. */ /* At the top of this loop, we are starting a brand new line. */
@ -666,16 +675,16 @@ eval (struct ebuffer *ebuf, int set_default)
/* Ignore the commands in a rule with no targets. */ /* Ignore the commands in a rule with no targets. */
continue; 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 /* If there is no preceding rule line, don't treat this line
as a command, even though it begins with a recipe prefix. as a command, even though it begins with a recipe prefix.
SunOS 4 make appears to behave this way. */ SunOS 4 make appears to behave this way. */
if (filenames != 0) if (filenames != 0)
{ {
if (ignoring)
/* Yep, this is a shell command, and we don't care. */
continue;
if (commands_idx == 0) if (commands_idx == 0)
cmds_started = ebuf->floc.lineno; cmds_started = ebuf->floc.lineno;
@ -737,10 +746,10 @@ eval (struct ebuffer *ebuf, int set_default)
do_undefine (p, origin, ebuf); do_undefine (p, origin, ebuf);
continue; continue;
} }
if (vmod.define_v) else if (vmod.define_v)
v = do_define (p, origin, ebuf); v = do_define (p, origin, ebuf);
else else
v = try_variable_definition (fstart, p, origin, s_global); v = try_variable_definition (fstart, p, origin, 0);
assert (v != NULL); assert (v != NULL);
@ -761,8 +770,6 @@ eval (struct ebuffer *ebuf, int set_default)
wlen = p2 - p; wlen = p2 - p;
NEXT_TOKEN (p2); 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 we're in an ignored define, skip this line (but maybe get out). */
if (in_ignored_define) if (in_ignored_define)
{ {
@ -810,7 +817,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Expand the line so we can use indirect and constructed /* Expand the line so we can use indirect and constructed
variable names in an (un)export command. */ variable names in an (un)export command. */
cp = ap = allocated_expand_string (p2); cp = ap = allocated_variable_expand (p2);
for (p = find_next_token (&cp, &l); p != 0; for (p = find_next_token (&cp, &l); p != 0;
p = find_next_token (&cp, &l)) p = find_next_token (&cp, &l))
@ -836,7 +843,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* vpath ends the previous rule. */ /* vpath ends the previous rule. */
record_waiting_files (); record_waiting_files ();
cp = expand_string (p2); cp = variable_expand (p2);
p = find_next_token (&cp, &l); p = find_next_token (&cp, &l);
if (p != 0) if (p != 0)
{ {
@ -869,7 +876,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Include ends the previous rule. */ /* Include ends the previous rule. */
record_waiting_files (); record_waiting_files ();
p = allocated_expand_string (p2); p = allocated_variable_expand (p2);
/* If no filenames, it's a no-op. */ /* If no filenames, it's a no-op. */
if (*p == '\0') if (*p == '\0')
@ -913,8 +920,8 @@ eval (struct ebuffer *ebuf, int set_default)
continue; continue;
} }
/* Handle the load operations. Allow targets named "load". */ /* Handle the load operations. */
if ((word1eq ("load") || word1eq ("-load")) && !is_rule) if (word1eq ("load") || word1eq ("-load"))
{ {
/* A 'load' line specifies a dynamic object to load. */ /* A 'load' line specifies a dynamic object to load. */
struct nameseq *files; struct nameseq *files;
@ -923,7 +930,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Load ends the previous rule. */ /* Load ends the previous rule. */
record_waiting_files (); record_waiting_files ();
p = allocated_expand_string (p2); p = allocated_variable_expand (p2);
/* If no filenames, it's a no-op. */ /* If no filenames, it's a no-op. */
if (*p == '\0') if (*p == '\0')
@ -1055,7 +1062,7 @@ eval (struct ebuffer *ebuf, int set_default)
break; break;
} }
p2 = expand_string_buf (NULL, lb_next, wlen); p2 = variable_expand_string (NULL, lb_next, wlen);
while (1) while (1)
{ {
@ -1083,7 +1090,7 @@ eval (struct ebuffer *ebuf, int set_default)
entirely consistent, since we do an unconditional entirely consistent, since we do an unconditional
expand below once we know we don't have a expand below once we know we don't have a
target-specific variable. */ target-specific variable. */
expand_string_buf (pend, lb_next, SIZE_MAX); variable_expand_string (pend, lb_next, SIZE_MAX);
lb_next += strlen (lb_next); lb_next += strlen (lb_next);
p2 = variable_buffer + p2_off; p2 = variable_buffer + p2_off;
cmdleft = variable_buffer + cmd_off + 1; cmdleft = variable_buffer + cmd_off + 1;
@ -1119,7 +1126,7 @@ eval (struct ebuffer *ebuf, int set_default)
p2 += strlen (p2); p2 += strlen (p2);
*(p2++) = ' '; *(p2++) = ' ';
p2 = expand_string_buf (p2, lb_next, wlen); p2 = variable_expand_string (p2, lb_next, wlen);
/* We don't need to worry about cmdleft here, because if it was /* We don't need to worry about cmdleft here, because if it was
found in the variable_buffer the entire buffer has already found in the variable_buffer the entire buffer has already
been expanded... we'll never get here. */ been expanded... we'll never get here. */
@ -1231,7 +1238,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (*lb_next != '\0') if (*lb_next != '\0')
{ {
size_t l = p2 - variable_buffer; size_t l = p2 - variable_buffer;
expand_string_buf (p2 + plen, lb_next, SIZE_MAX); variable_expand_string (p2 + plen, lb_next, SIZE_MAX);
p2 = variable_buffer + l; p2 = variable_buffer + l;
/* Look for a semicolon in the expanded line. */ /* Look for a semicolon in the expanded line. */
@ -1256,6 +1263,22 @@ eval (struct ebuffer *ebuf, int set_default)
else else
break; 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 #ifdef HAVE_DOS_PATHS
{ {
int check_again; int check_again;
@ -1362,7 +1385,7 @@ do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)
char *p, *var; char *p, *var;
/* Expand the variable name and find the beginning (NAME) and end. */ /* Expand the variable name and find the beginning (NAME) and end. */
var = allocated_expand_string (name); var = allocated_variable_expand (name);
name = next_token (var); name = next_token (var);
if (*name == '\0') if (*name == '\0')
O (fatal, &ebuf->floc, _("empty variable name")); O (fatal, &ebuf->floc, _("empty variable name"));
@ -1371,7 +1394,7 @@ do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)
--p; --p;
p[1] = '\0'; p[1] = '\0';
undefine_variable_global (&ebuf->floc, name, p - name + 1, origin); undefine_variable_global (name, p - name + 1, origin);
free (var); free (var);
} }
@ -1395,11 +1418,8 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
p = parse_variable_definition (name, &var); p = parse_variable_definition (name, &var);
if (p == NULL) if (p == NULL)
{
/* No assignment token, so assume recursive. */ /* No assignment token, so assume recursive. */
var.flavor = f_recursive; var.flavor = f_recursive;
var.conditional = 0;
}
else else
{ {
if (var.value[0] != '\0') if (var.value[0] != '\0')
@ -1410,7 +1430,7 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
} }
/* Expand the variable name and find the beginning (NAME) and end. */ /* Expand the variable name and find the beginning (NAME) and end. */
n = allocated_expand_string (name); n = allocated_variable_expand (name);
name = next_token (n); name = next_token (n);
if (name[0] == '\0') if (name[0] == '\0')
O (fatal, &defstart, _("empty variable name")); O (fatal, &defstart, _("empty variable name"));
@ -1483,8 +1503,8 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
else else
definition[idx - 1] = '\0'; definition[idx - 1] = '\0';
v = do_variable_definition (&defstart, name, definition, origin, var.flavor, v = do_variable_definition (&defstart, name,
var.conditional, s_global); definition, origin, var.flavor, 0);
free (definition); free (definition);
free (n); free (n);
return (v); return (v);
@ -1643,7 +1663,7 @@ conditional_line (char *line, size_t len, const floc *flocp)
/* Expand the thing we're looking up, so we can use indirect and /* Expand the thing we're looking up, so we can use indirect and
constructed variable names. */ constructed variable names. */
var = allocated_expand_string (line); var = allocated_variable_expand (line);
/* Make sure there's only one variable name to test. */ /* Make sure there's only one variable name to test. */
p = end_of_token (var); p = end_of_token (var);
@ -1672,10 +1692,19 @@ conditional_line (char *line, size_t len, const floc *flocp)
s1 = ++line; s1 = ++line;
/* Find the end of the first string. */ /* Find the end of the first string. */
while (*line != '\0' && *line != termin) if (termin == ',')
if (*line == '$') {
line = skip_reference (line+1); int count = 0;
for (; *line != '\0'; ++line)
if (*line == '(')
++count;
else if (*line == ')')
--count;
else if (*line == ',' && count <= 0)
break;
}
else else
while (*line != '\0' && *line != termin)
++line; ++line;
if (*line == '\0') if (*line == '\0')
@ -1683,7 +1712,7 @@ conditional_line (char *line, size_t len, const floc *flocp)
if (termin == ',') if (termin == ',')
{ {
/* Strip blanks before the comma. */ /* Strip blanks after the first string. */
char *p = line++; char *p = line++;
while (ISBLANK (p[-1])) while (ISBLANK (p[-1]))
--p; --p;
@ -1692,9 +1721,9 @@ conditional_line (char *line, size_t len, const floc *flocp)
else else
*line++ = '\0'; *line++ = '\0';
s2 = expand_string (s1); s2 = variable_expand (s1);
/* We must allocate a new copy of the expanded string because /* We must allocate a new copy of the expanded string because
expand_string re-uses the same buffer. */ variable_expand re-uses the same buffer. */
l = strlen (s2); l = strlen (s2);
s1 = alloca (l + 1); s1 = alloca (l + 1);
memcpy (s1, s2, l + 1); memcpy (s1, s2, l + 1);
@ -1741,7 +1770,7 @@ conditional_line (char *line, size_t len, const floc *flocp)
if (*line != '\0') if (*line != '\0')
EXTRATEXT (); EXTRATEXT ();
s2 = expand_string (s2); s2 = variable_expand (s2);
conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq)); conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));
} }
@ -1801,7 +1830,7 @@ record_target_var (struct nameseq *filenames, char *defn,
v->origin = origin; v->origin = origin;
if (v->flavor == f_simple) if (v->flavor == f_simple)
v->value = allocated_expand_string (v->value); v->value = allocated_variable_expand (v->value);
else else
v->value = xstrdup (v->value); v->value = xstrdup (v->value);
} }
@ -1822,9 +1851,9 @@ record_target_var (struct nameseq *filenames, char *defn,
initialize_file_variables (f, 1); initialize_file_variables (f, 1);
current_variable_set_list = f->variables; current_variable_set_list = f->variables;
v = try_variable_definition (flocp, defn, origin, s_target); v = try_variable_definition (flocp, defn, origin, 1);
if (!v) if (!v)
O (fatal, flocp, _("malformed target-specific variable definition")); O (fatal, flocp, _("Malformed target-specific variable definition"));
current_variable_set_list = global; current_variable_set_list = global;
} }
@ -1892,7 +1921,7 @@ check_specials (struct nameseq *files, int set_default)
continue; continue;
} }
#if !MK_OS_DOS && !MK_OS_OS2 #if !defined (__MSDOS__) && !defined (__EMX__)
if (!one_shell && streq (nm, ".ONESHELL")) if (!one_shell && streq (nm, ".ONESHELL"))
{ {
one_shell = 1; one_shell = 1;
@ -2110,6 +2139,7 @@ record_files (struct nameseq *filenames, int are_also_makes,
return; return;
} }
/* Walk through each target and create it in the database. /* Walk through each target and create it in the database.
We already set up the first target, above. */ We already set up the first target, above. */
while (1) while (1)
@ -2176,6 +2206,11 @@ record_files (struct nameseq *filenames, int are_also_makes,
free_dep_chain (f->deps); free_dep_chain (f->deps);
f->deps = 0; 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 else
{ {
@ -2200,8 +2235,6 @@ record_files (struct nameseq *filenames, int are_also_makes,
f->cmds = cmds; f->cmds = cmds;
} }
/* This file is explicitly mentioned as a target. */
f->is_explicit = 1;
if (are_also_makes) if (are_also_makes)
{ {
@ -2279,14 +2312,15 @@ record_files (struct nameseq *filenames, int are_also_makes,
} }
/* If there are also-makes, then populate a copy of the also-make list into /* If there are also-makes, then populate a copy of the also-make list into
each one. Omit the file from its also-make list. */ each one. For the last file, we take our original also_make list instead
wastefully copying it one more time and freeing it. */
{ {
struct dep *i; struct dep *i;
for (i = also_make; i != NULL; i = i->next) for (i = also_make; i != NULL; i = i->next)
{ {
struct file *f = i->file; struct file *f = i->file;
struct dep *dp; struct dep *cpy = i->next ? copy_dep_chain (also_make) : also_make;
if (f->also_make) if (f->also_make)
{ {
@ -2294,20 +2328,11 @@ record_files (struct nameseq *filenames, int are_also_makes,
_("warning: overriding group membership for target '%s'"), _("warning: overriding group membership for target '%s'"),
f->name); f->name);
free_dep_chain (f->also_make); 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; f->also_make = cpy;
} }
} }
free_dep_chain (also_make);
}
} }
/* Search STRING for an unquoted STOPMAP. /* Search STRING for an unquoted STOPMAP.
@ -2339,7 +2364,35 @@ find_map_unquote (char *string, int stopmap)
/* If we stopped due to a variable reference, skip over its contents. */ /* If we stopped due to a variable reference, skip over its contents. */
if (*p == '$') if (*p == '$')
{ {
p = skip_reference (p+1); 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. */
continue; continue;
} }
@ -2646,7 +2699,7 @@ readline (struct ebuffer *ebuf)
/* We got a newline, so add one to the count of lines. */ /* We got a newline, so add one to the count of lines. */
++nlines; ++nlines;
#if !MK_OS_W32 && !MK_OS_DOS && !MK_OS_OS2 #if !defined(WINDOWS32) && !defined(__MSDOS__) && !defined(__EMX__)
/* Check to see if the line was really ended with CRLF; if so ignore /* Check to see if the line was really ended with CRLF; if so ignore
the CR. */ the CR. */
if ((p - start) > 1 && p[-2] == '\r') if ((p - start) > 1 && p[-2] == '\r')
@ -2700,8 +2753,7 @@ readline (struct ebuffer *ebuf)
} }
/* Parse the next "makefile word" from the input buffer, and return info /* Parse the next "makefile word" from the input buffer, and return info
about it. This function won't be called in any context where we might need about it.
to parse a variable assignment so we don't need to check that.
A "makefile word" is one of: A "makefile word" is one of:
@ -2714,10 +2766,11 @@ readline (struct ebuffer *ebuf)
w_ampcolon An ampersand-colon (&:) token w_ampcolon An ampersand-colon (&:) token
w_ampdcolon An ampersand-double-colon (&::) token w_ampdcolon An ampersand-double-colon (&::) token
w_semicolon A semicolon w_semicolon A semicolon
w_varassign A variable assignment operator (=, :=, ::=, +=, ?=, or !=)
Note that this function is only used when reading certain parts of the 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, makefile. Don't use it where special rules hold sway (RHS of a variable,
in a recipe, etc.) */ in a command list, etc.) */
static enum make_word_type static enum make_word_type
get_next_mword (char *buffer, char **startp, size_t *length) get_next_mword (char *buffer, char **startp, size_t *length)
@ -2744,13 +2797,29 @@ get_next_mword (char *buffer, char **startp, size_t *length)
wtype = w_semicolon; wtype = w_semicolon;
goto done; goto done;
case '=':
wtype = w_varassign;
goto done;
case ':': case ':':
wtype = w_colon; if (*p == '=')
if (*p == ':')
{ {
++p; ++p;
wtype = w_varassign; /* := */
}
else if (*p == ':')
{
++p;
if (p[1] == '=')
{
++p;
wtype = w_varassign; /* ::= */
}
else
wtype = w_dcolon; wtype = w_dcolon;
} }
else
wtype = w_colon;
goto done; goto done;
case '&': case '&':
@ -2768,26 +2837,43 @@ get_next_mword (char *buffer, char **startp, size_t *length)
} }
break; break;
case '+':
case '?':
case '!':
if (*p == '=')
{
++p;
wtype = w_varassign; /* += or ?= or != */
goto done;
}
break;
default: default:
break; break;
} }
/* This is some non-operator word. A word consists of the longest string of /* This is some non-operator word. A word consists of the longest
characters that doesn't contain whitespace, one of [:#], or &:. */ string of characters that doesn't contain whitespace, one of [:=#],
or [?+!]=, or &:. */
/* We start out assuming a static word; if we see a variable we'll /* We start out assuming a static word; if we see a variable we'll
adjust our assumptions then. */ adjust our assumptions then. */
wtype = w_static; wtype = w_static;
/* We already found the first value of "c", above. */
while (1) while (1)
{ {
/* Each time through the loop, "c" has the current character char closeparen;
and "p" points to the next character. */ int count;
if (END_OF_TOKEN (c)) if (END_OF_TOKEN (c))
goto done_word; goto done_word;
switch (c) switch (c)
{ {
case '=':
goto done_word;
case ':': case ':':
#ifdef HAVE_DOS_PATHS #ifdef HAVE_DOS_PATHS
/* A word CAN include a colon in its drive spec. The drive /* A word CAN include a colon in its drive spec. The drive
@ -2806,9 +2892,34 @@ get_next_mword (char *buffer, char **startp, size_t *length)
if (c == '\0') if (c == '\0')
goto done_word; goto done_word;
/* This is a variable reference: note that then skip it. */ /* This is a variable reference, so note that it's expandable.
Then read it to the matching close paren. */
wtype = w_variable; wtype = w_variable;
p = skip_reference (p-1);
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;
break; break;
case '\\': case '\\':
@ -2842,7 +2953,6 @@ get_next_mword (char *buffer, char **startp, size_t *length)
*startp = beg; *startp = beg;
if (length) if (length)
*length = p - beg; *length = p - beg;
return wtype; return wtype;
} }
@ -2863,12 +2973,12 @@ construct_include_path (const char **arg_dirs)
int disable = 0; int disable = 0;
/* Compute the number of pointers we need in the table. */ /* Compute the number of pointers we need in the table. */
idx = ARRAYLEN (default_include_directories); idx = sizeof (default_include_directories) / sizeof (const char *);
if (arg_dirs) if (arg_dirs)
for (cpp = arg_dirs; *cpp != 0; ++cpp) for (cpp = arg_dirs; *cpp != 0; ++cpp)
++idx; ++idx;
#if MK_OS_DOS #ifdef __MSDOS__
/* Add one for $DJDIR. */ /* Add one for $DJDIR. */
++idx; ++idx;
#endif #endif
@ -2922,8 +3032,7 @@ construct_include_path (const char **arg_dirs)
/* Now add the standard default dirs at the end. */ /* Now add the standard default dirs at the end. */
if (!disable) if (!disable)
{ {
const char *const *ccpp; #ifdef __MSDOS__
#if MK_OS_DOS
/* The environment variable $DJDIR holds the root of the DJGPP directory /* The environment variable $DJDIR holds the root of the DJGPP directory
tree; add ${DJDIR}/include. */ tree; add ${DJDIR}/include. */
struct variable *djdir = lookup_variable ("DJDIR", 5); struct variable *djdir = lookup_variable ("DJDIR", 5);
@ -2940,20 +3049,20 @@ construct_include_path (const char **arg_dirs)
max_incl_len = len; max_incl_len = len;
} }
#endif #endif
for (ccpp = default_include_directories; *ccpp != 0; ++ccpp) for (cpp = default_include_directories; *cpp != 0; ++cpp)
{ {
int e; int e;
EINTRLOOP (e, stat (*ccpp, &stbuf)); EINTRLOOP (e, stat (*cpp, &stbuf));
if (e == 0 && S_ISDIR (stbuf.st_mode)) if (e == 0 && S_ISDIR (stbuf.st_mode))
{ {
size_t len = strlen (*ccpp); size_t len = strlen (*cpp);
/* If dir name is written with trailing slashes, discard them. */ /* If dir name is written with trailing slashes, discard them. */
while (len > 1 && (*ccpp)[len - 1] == '/') while (len > 1 && (*cpp)[len - 1] == '/')
--len; --len;
if (len > max_incl_len) if (len > max_incl_len)
max_incl_len = len; max_incl_len = len;
dirs[idx++] = strcache_add_len (*ccpp, len); dirs[idx++] = strcache_add_len (*cpp, len);
} }
} }
} }
@ -2962,11 +3071,10 @@ construct_include_path (const char **arg_dirs)
/* Now add each dir to the .INCLUDE_DIRS variable. */ /* 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) for (cpp = dirs; *cpp != 0; ++cpp)
do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp, o_default, f_append, do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp,
0, s_global); o_default, f_append, 0);
free ((void *) include_directories); free ((void *) include_directories);
include_directories = dirs; include_directories = dirs;
@ -2978,20 +3086,20 @@ construct_include_path (const char **arg_dirs)
char * char *
tilde_expand (const char *name) tilde_expand (const char *name)
{ {
#if !MK_OS_VMS #if !defined(VMS)
if (name[1] == '/' || name[1] == '\0') if (name[1] == '/' || name[1] == '\0')
{ {
char *home_dir; char *home_dir;
int is_variable; int is_variable;
{ {
/* Turn off undefined variables warning while we expand HOME. */ /* Turn off --warn-undefined-variables while we expand HOME. */
enum warning_action save = warn_get (wt_undefined_var); int save = warn_undefined_variables_flag;
warn_set (wt_undefined_var, w_ignore); warn_undefined_variables_flag = 0;
home_dir = allocated_expand_variable (STRING_SIZE_TUPLE ("HOME")); home_dir = allocated_variable_expand ("$(HOME)");
warn_set (wt_undefined_var, save); warn_undefined_variables_flag = save;
} }
is_variable = home_dir[0] != '\0'; is_variable = home_dir[0] != '\0';
@ -3000,7 +3108,7 @@ tilde_expand (const char *name)
free (home_dir); free (home_dir);
home_dir = getenv ("HOME"); home_dir = getenv ("HOME");
} }
# if !MK_OS_W32 # if !defined(_AMIGA) && !defined(WINDOWS32)
if (home_dir == 0 || home_dir[0] == '\0') if (home_dir == 0 || home_dir[0] == '\0')
{ {
char *logname = getlogin (); char *logname = getlogin ();
@ -3012,7 +3120,7 @@ tilde_expand (const char *name)
home_dir = p->pw_dir; home_dir = p->pw_dir;
} }
} }
# endif /* !MK_OS_W32 */ # endif /* !AMIGA && !WINDOWS32 */
if (home_dir != 0) if (home_dir != 0)
{ {
char *new = xstrdup (concat (2, home_dir, name + 1)); char *new = xstrdup (concat (2, home_dir, name + 1));
@ -3021,7 +3129,7 @@ tilde_expand (const char *name)
return new; return new;
} }
} }
# if !MK_OS_W32 # if !defined(_AMIGA) && !defined(WINDOWS32)
else else
{ {
struct passwd *pwent; struct passwd *pwent;
@ -3040,8 +3148,8 @@ tilde_expand (const char *name)
else if (userend != 0) else if (userend != 0)
*userend = '/'; *userend = '/';
} }
# endif /* !MK_OS_W32 */ # endif /* !AMIGA && !WINDOWS32 */
#endif /* !MK_OS_VMS */ #endif /* !VMS */
return 0; return 0;
} }
@ -3152,11 +3260,16 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
s = p; s = p;
p = find_map_unquote (p, findmap); p = find_map_unquote (p, findmap);
#if MK_OS_VMS #ifdef VMS
/* convert comma separated list to space separated */ /* convert comma separated list to space separated */
if (p && *p == ',') if (p && *p == ',')
*p =' '; *p =' ';
#endif #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 #ifdef HAVE_DOS_PATHS
/* If we stopped due to a drive specifier, skip it. /* If we stopped due to a drive specifier, skip it.
Tokens separated by spaces are treated as separate paths since make Tokens separated by spaces are treated as separate paths since make
@ -3179,8 +3292,7 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
/* Strip leading "this directory" references. */ /* Strip leading "this directory" references. */
if (NONE_SET (flags, PARSEFS_NOSTRIP)) if (NONE_SET (flags, PARSEFS_NOSTRIP))
{ #ifdef VMS
#if MK_OS_VMS
/* Skip leading '[]'s. should only be one set or bug somewhere else */ /* Skip leading '[]'s. should only be one set or bug somewhere else */
if (p - s > 2 && s[0] == '[' && s[1] == ']') if (p - s > 2 && s[0] == '[' && s[1] == ']')
s += 2; s += 2;
@ -3196,7 +3308,6 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
while (*s == '/') while (*s == '/')
++s; ++s;
} }
}
/* Extract the filename just found, and skip it. /* Extract the filename just found, and skip it.
Set NAME to the string, and NLEN to its length. */ Set NAME to the string, and NLEN to its length. */
@ -3204,14 +3315,20 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
if (s == p) if (s == p)
{ {
/* The name was stripped to empty ("./"). */ /* The name was stripped to empty ("./"). */
#if defined(_AMIGA)
/* PDS-- This cannot be right!! */
tp[0] = '\0';
nlen = 0;
#else
tp[0] = '.'; tp[0] = '.';
tp[1] = '/'; tp[1] = '/';
tp[2] = '\0'; tp[2] = '\0';
nlen = 2; nlen = 2;
#endif
} }
else else
{ {
#if MK_OS_VMS #ifdef VMS
/* VMS filenames can have a ':' in them but they have to be '\'ed but we need /* 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. * to remove this '\' before we can use the filename.
* xstrdup called because S may be read-only string constant. * xstrdup called because S may be read-only string constant.

View File

@ -1,5 +1,5 @@
/* Basic dependency engine for GNU Make. /* Basic dependency engine for GNU Make.
Copyright (C) 1988-2024 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the
@ -20,7 +20,6 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "commands.h" #include "commands.h"
#include "dep.h" #include "dep.h"
#include "variable.h" #include "variable.h"
#include "warning.h"
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
@ -31,10 +30,10 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include <sys/file.h> #include <sys/file.h>
#endif #endif
#if MK_OS_VMS #ifdef VMS
#include <starlet.h> #include <starlet.h>
#endif #endif
#if MK_OS_W32 #ifdef WINDOWS32
#include <windows.h> #include <windows.h>
#include <io.h> #include <io.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -70,13 +69,6 @@ static struct dep *goal_dep;
All files start with considered == 0. */ All files start with considered == 0. */
static unsigned int 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 (struct file *file, unsigned int depth);
static enum update_status update_file_1 (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, static enum update_status check_dep (struct file *file, unsigned int depth,
@ -102,7 +94,7 @@ check_also_make (const struct file *file)
for (ad = file->also_make; ad; ad = ad->next) for (ad = file->also_make; ad; ad = ad->next)
if (ad->file->last_mtime == NONEXISTENT_MTIME) if (ad->file->last_mtime == NONEXISTENT_MTIME)
OS (error, file->cmds ? &file->cmds->fileinfo : NILF, 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); ad->file->name);
} }
@ -120,7 +112,6 @@ update_goal_chain (struct goaldep *goaldeps)
unsigned long last_cmd_count = 0; unsigned long last_cmd_count = 0;
int t = touch_flag, q = question_flag, n = just_print_flag; int t = touch_flag, q = question_flag, n = just_print_flag;
enum update_status status = us_none; enum update_status status = us_none;
const unsigned int depth = rebuilding_makefiles ? 1 : 0;
/* Duplicate the chain so we can remove things from it. */ /* Duplicate the chain so we can remove things from it. */
struct dep *goals_orig = copy_dep_chain ((struct dep *)goaldeps); struct dep *goals_orig = copy_dep_chain ((struct dep *)goaldeps);
@ -139,7 +130,6 @@ update_goal_chain (struct goaldep *goaldeps)
while (goals != 0) while (goals != 0)
{ {
struct dep *gu, *g, *lastgoal; struct dep *gu, *g, *lastgoal;
int running = 0, wait = 0;
/* Start jobs that are waiting for the load to go down. */ /* Start jobs that are waiting for the load to go down. */
@ -157,14 +147,16 @@ update_goal_chain (struct goaldep *goaldeps)
while (gu != 0) while (gu != 0)
{ {
/* Iterate over all double-colon entries for this file. */ /* Iterate over all double-colon entries for this file. */
struct file *file, *dchead; struct file *file;
int stop = 0, all_updated = 1; int stop = 0, any_not_updated = 0;
g = gu->shuf ? gu->shuf : gu; g = gu->shuf ? gu->shuf : gu;
goal_dep = g; goal_dep = g;
dchead = g->file->double_colon ? g->file->double_colon : g->file;
for (file = dchead; file != NULL; file = file->prev) for (file = g->file->double_colon ? g->file->double_colon : g->file;
file != NULL;
file = file->prev)
{ {
unsigned int ocommands_started; unsigned int ocommands_started;
enum update_status fail; enum update_status fail;
@ -189,24 +181,8 @@ update_goal_chain (struct goaldep *goaldeps)
actually run. */ actually run. */
ocommands_started = commands_started; ocommands_started = commands_started;
stop = 0; fail = update_file (file, rebuilding_makefiles ? 1 : 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); 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 /* Set the goal's 'changed' flag if any commands were started
by calling update_file above. We check this flag below to by calling update_file above. We check this flag below to
@ -214,6 +190,7 @@ update_goal_chain (struct goaldep *goaldeps)
if (commands_started > ocommands_started) if (commands_started > ocommands_started)
g->changed = 1; g->changed = 1;
stop = 0;
if ((fail || file->updated) && status < us_question) if ((fail || file->updated) && status < us_question)
{ {
/* We updated this goal. Update STATUS and decide whether /* We updated this goal. Update STATUS and decide whether
@ -254,7 +231,7 @@ update_goal_chain (struct goaldep *goaldeps)
/* Keep track if any double-colon entry is not finished. /* Keep track if any double-colon entry is not finished.
When they are all finished, the goal is finished. */ When they are all finished, the goal is finished. */
all_updated &= file->updated; any_not_updated |= !file->updated;
file->dontcare = 0; file->dontcare = 0;
@ -265,10 +242,7 @@ update_goal_chain (struct goaldep *goaldeps)
/* Reset FILE since it is null at the end of the loop. */ /* Reset FILE since it is null at the end of the loop. */
file = g->file; file = g->file;
if (wait) if (stop || !any_not_updated)
break;
if (stop || all_updated)
{ {
/* If we have found nothing whatever to do for the goal, /* If we have found nothing whatever to do for the goal,
print a message saying nothing needs doing. */ print a message saying nothing needs doing. */
@ -291,19 +265,21 @@ update_goal_chain (struct goaldep *goaldeps)
else else
lastgoal->next = gu->next; lastgoal->next = gu->next;
gu = lastgoal == 0 ? goals : lastgoal->next;
if (stop) if (stop)
break; break;
} }
else else
{
lastgoal = gu; lastgoal = gu;
gu = gu->next; gu = gu->next;
} }
}
/* If we reached the end of the dependency graph update CONSIDERED /* If we reached the end of the dependency graph update CONSIDERED
for the next pass. In the case of waiting, increment CONSIDERED to for the next pass. */
prevent the same file from getting pruned over and over again. */ if (gu == 0)
if (gu == 0 || wait)
++considered; ++considered;
} }
@ -371,15 +347,9 @@ update_file (struct file *file, unsigned int depth)
{ {
/* Check for the case where a target has been tried and failed but /* Check for the case where a target has been tried and failed but
the diagnostics haven't been issued. If we need the diagnostics 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 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")); DBF (DB_VERBOSE, _("Pruning file '%s'.\n"));
return f->command_state == cs_finished ? f->update_status : us_success; return f->command_state == cs_finished ? f->update_status : us_success;
@ -407,8 +377,7 @@ update_file (struct file *file, unsigned int depth)
if (f->command_state == cs_running if (f->command_state == cs_running
|| f->command_state == cs_deps_running) || f->command_state == cs_deps_running)
/* Don't run other :: rules for this target until /* Don't run other :: rules for this target until
this rule is finished. Multiple recipes running in parallel and this rule is finished. */
updating the same target will corrupt the target. */
return us_success; return us_success;
if (new > status) if (new > status)
@ -546,19 +515,14 @@ update_file_1 (struct file *file, unsigned int depth)
check_renamed (file); check_renamed (file);
noexist = this_mtime == NONEXISTENT_MTIME; noexist = this_mtime == NONEXISTENT_MTIME;
if (noexist) if (noexist)
{
if (file->phony)
DBF (DB_BASIC, _("Target '%s' is phony.\n"));
else
DBF (DB_BASIC, _("File '%s' does not exist.\n")); DBF (DB_BASIC, _("File '%s' does not exist.\n"));
}
else if (is_ordinary_mtime (this_mtime) && file->low_resolution_time) else if (is_ordinary_mtime (this_mtime) && file->low_resolution_time)
{ {
/* Avoid spurious rebuilds due to low resolution time stamps. */ /* Avoid spurious rebuilds due to low resolution time stamps. */
int ns = FILE_TIMESTAMP_NS (this_mtime); int ns = FILE_TIMESTAMP_NS (this_mtime);
if (ns != 0) if (ns != 0)
OS (error, NILF, 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); file->name);
this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns; this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;
} }
@ -575,11 +539,6 @@ update_file_1 (struct file *file, unsigned int depth)
if (noexist) if (noexist)
{ {
check_renamed (adfile); 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, DBS (DB_BASIC,
(_("Grouped target peer '%s' of file '%s' does not exist.\n"), (_("Grouped target peer '%s' of file '%s' does not exist.\n"),
adfile->name, file->name)); adfile->name, file->name));
@ -646,30 +605,18 @@ update_file_1 (struct file *file, unsigned int depth)
if (is_updating (d->file)) if (is_updating (d->file))
{ {
/* Avoid macro warning, bacause its output differs from that of OSS (error, NILF, _("Circular %s <- %s dependency dropped."),
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); 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) if (lastd == 0)
file->deps = du->next; file->deps = du->next;
else else
lastd->next = du->next; lastd->next = du->next;
du = 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; continue;
} }
@ -874,13 +821,8 @@ update_file_1 (struct file *file, unsigned int depth)
else if (d_mtime == NONEXISTENT_MTIME) else if (d_mtime == NONEXISTENT_MTIME)
{ {
if (ISDB (DB_BASIC)) 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"); fmt = _("Prerequisite '%s' of target '%s' does not exist.\n");
} }
}
else if (d->changed) else if (d->changed)
{ {
if (ISDB (DB_BASIC)) if (ISDB (DB_BASIC))
@ -1112,17 +1054,11 @@ notice_finished_file (struct file *file)
d->file->update_status = file->update_status; d->file->update_status = file->update_status;
if (ran && !d->file->phony) if (ran && !d->file->phony)
{
/* Fetch the new modification time. /* Fetch the new modification time.
We do this instead of just invalidating the cached time We do this instead of just invalidating the cached time
so that a vpath_search can happen. Otherwise, it would so that a vpath_search can happen. Otherwise, it would
never be done because the target is already updated. */ never be done because the target is already updated. */
f_mtime (d->file, 0); 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, /* If the target was created by an implicit rule, and it was updated,
@ -1228,7 +1164,7 @@ check_dep (struct file *file, unsigned int depth,
if (is_updating (d->file)) 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); file->name, d->file->name);
if (ld == 0) if (ld == 0)
{ {
@ -1495,7 +1431,7 @@ f_mtime (struct file *file, int search)
/* If we found it in VPATH, see if it's in GPATH too; if so, /* 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 change the name right now; if not, defer until after the
dependencies are updated. */ dependencies are updated. */
#if !MK_OS_VMS #ifndef VMS
name_len = strlen (name) - strlen (file->name) - 1; name_len = strlen (name) - strlen (file->name) - 1;
#else #else
name_len = strlen (name) - strlen (file->name); name_len = strlen (name) - strlen (file->name);
@ -1533,7 +1469,7 @@ f_mtime (struct file *file, int search)
FILE_TIMESTAMP adjusted_mtime = mtime; FILE_TIMESTAMP adjusted_mtime = mtime;
#if MK_OS_W32 || MK_OS_DOS #if defined(WINDOWS32) || defined(__MSDOS__)
/* Experimentation has shown that FAT filesystems can set file times /* Experimentation has shown that FAT filesystems can set file times
up to 3 seconds into the future! Play it safe. */ up to 3 seconds into the future! Play it safe. */
@ -1564,7 +1500,7 @@ f_mtime (struct file *file, int search)
else else
sprintf (from_now_string, "%.2g", from_now); sprintf (from_now_string, "%.2g", from_now);
OSS (error, NILF, 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); file->name, from_now_string);
clock_skew_detected = 1; clock_skew_detected = 1;
} }
@ -1611,14 +1547,14 @@ static FILE_TIMESTAMP
name_mtime (const char *name) name_mtime (const char *name)
{ {
FILE_TIMESTAMP mtime; FILE_TIMESTAMP mtime;
#if MK_OS_W32 #if defined(WINDOWS32)
struct STAT st; struct STAT st;
#else #else
struct stat st; struct stat st;
#endif #endif
int e; int e;
#if MK_OS_W32 #if defined(WINDOWS32)
{ {
char tem[MAX_PATH+1], *tstart, *tend; char tem[MAX_PATH+1], *tstart, *tend;
const char *p = name + strlen (name); const char *p = name + strlen (name);
@ -1647,7 +1583,7 @@ name_mtime (const char *name)
tend = &tem[0]; tend = &tem[0];
} }
#if MK_OS_W32 #if defined(WINDOWS32)
e = STAT (tem, &st); e = STAT (tem, &st);
#else #else
e = stat (tem, &st); e = stat (tem, &st);
@ -1751,11 +1687,13 @@ name_mtime (const char *name)
static const char * static const char *
library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
{ {
static const char *const dirs[] = static const char *dirs[] =
{ {
#ifndef _AMIGA
"/lib", "/lib",
"/usr/lib", "/usr/lib",
#if MK_OS_W32 && !defined(LIBDIR) #endif
#if defined(WINDOWS32) && !defined(LIBDIR)
/* /*
* This is completely up to the user at product install time. Just define * This is completely up to the user at product install time. Just define
* a placeholder. * a placeholder.
@ -1779,9 +1717,9 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
/* Information about the earliest (in the vpath sequence) match. */ /* Information about the earliest (in the vpath sequence) match. */
unsigned int best_vpath = 0, best_path = 0; unsigned int best_vpath = 0, best_path = 0;
const char *const *dp; const char **dp;
libpatterns = allocated_expand_variable (STRING_SIZE_TUPLE (".LIBPATTERNS")); libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
/* Skip the '-l'. */ /* Skip the '-l'. */
lib += 2; lib += 2;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* Convert between signal names and numbers. /* Convert between signal names and numbers.
Copyright (C) 1990-2024 Free Software Foundation, Inc. Copyright (C) 1990-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
/* Constant string caching for GNU Make. /* Constant string caching for GNU Make.
Copyright (C) 2006-2024 Free Software Foundation, Inc. Copyright (C) 2006-2023 Free Software Foundation, Inc.
This file is part of GNU Make. This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the GNU Make is free software; you can redistribute it and/or modify it under the

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