mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Import GNU Make 4.4.1
Landlock Make hasn't been working well on AARCH64 systems. Let's do this over the right way, using our new build tools.
This commit is contained in:
parent
9315ebbfd9
commit
14bf57180f
88 changed files with 13931 additions and 16191 deletions
|
@ -98,7 +98,7 @@ errno_t ttyname_r(int fd, char *buf, size_t size) {
|
|||
}
|
||||
}
|
||||
errno = e;
|
||||
STRACE("ttyname_r(%d, %#.*hhs) → %s", fd, (int)size, buf,
|
||||
STRACE("ttyname_r(%d, %#.*hhs) → %s", fd, (int)strnlen(buf, size), buf,
|
||||
!res ? "0" : _strerrno(res));
|
||||
return res;
|
||||
}
|
||||
|
|
90
third_party/make/AUTHORS
vendored
90
third_party/make/AUTHORS
vendored
|
@ -1,90 +0,0 @@
|
|||
-----------------------------------
|
||||
|
||||
GNU make development up to version 3.75 by:
|
||||
Roland McGrath <roland@gnu.org>
|
||||
|
||||
|
||||
Development starting with GNU make 3.76 by:
|
||||
Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
Additional development starting with GNU make 3.81 by:
|
||||
Boris Kolpackov <boris@kolpackov.net>
|
||||
|
||||
|
||||
GNU Make User's Manual
|
||||
Written by:
|
||||
Richard M. Stallman <rms@gnu.org>
|
||||
|
||||
Edited by:
|
||||
Roland McGrath <roland@gnu.org>
|
||||
Bob Chassell <bob@gnu.org>
|
||||
Melissa Weisshaus <melissa@gnu.org>
|
||||
Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
-----------------------------------
|
||||
GNU make porting efforts:
|
||||
|
||||
Port to VMS by:
|
||||
Klaus Kaempf <kkaempf@progis.de>
|
||||
Hartmut Becker <Hartmut.Becker@hp.com>
|
||||
Archive support/Bug fixes by:
|
||||
John W. Eaton <jwe@bevo.che.wisc.edu>
|
||||
Martin Zinser <zinser@decus.decus.de>
|
||||
|
||||
Port to Amiga by:
|
||||
Aaron Digulla <digulla@fh-konstanz.de>
|
||||
|
||||
Port to MS-DOS (DJGPP), OS/2, and MS-Windows (native/MinGW) by:
|
||||
DJ Delorie <dj@delorie.com>
|
||||
Rob Tulloh <rob_tulloh@tivoli.com>
|
||||
Eli Zaretskii <eliz@gnu.org>
|
||||
Jonathan Grant <jg@jguk.org>
|
||||
Andreas Beuning <andreas.buening@nexgo.de>
|
||||
Earnie Boyd <earnie@uses.sf.net>
|
||||
Troy Runkel <Troy.Runkel@mathworks.com>
|
||||
|
||||
-----------------------------------
|
||||
Other contributors:
|
||||
|
||||
Janet Carson <janet_carson@tivoli.com>
|
||||
Howard Chu <hyc@highlandsun.com>
|
||||
Ludovic Courtès <ludo@gnu.org>
|
||||
Paul Eggert <eggert@twinsun.com>
|
||||
Ramon Garcia Fernandez <ramon.garcia.f@gmail.com>
|
||||
Klaus Heinz <kamar@ease.rhein-main.de>
|
||||
Michael Joosten
|
||||
Jim Kelton <jim_kelton@tivoli.com>
|
||||
David Lubbren <uhay@rz.uni-karlsruhe.de>
|
||||
Tim Magill <tim.magill@telops.gte.com>
|
||||
Markus Mauhart <qwe123@chello.at>
|
||||
Greg McGary <greg@mcgary.org>
|
||||
Thien-Thi Nguyen <ttn@gnuvola.org>
|
||||
Thomas Riedl <thomas.riedl@siemens.com>
|
||||
Han-Wen Nienhuys <hanwen@cs.uu.nl>
|
||||
Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
|
||||
Carl Staelin (Princeton University)
|
||||
Ian Stewartson (Data Logic Limited)
|
||||
David A. Wheeler <dwheeler@dwheeler.com>
|
||||
David Boyce <dsb@boyski.com>
|
||||
Frank Heckenbach <f.heckenbach@fh-soft.de>
|
||||
Kaz Kylheku <kaz@kylheku.com>
|
||||
Christof Warlich <cwarlich@gmx.de>
|
||||
|
||||
With suggestions/comments/bug reports from a cast of ... well ...
|
||||
hundreds, anyway :)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 1997-2020 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 <http://www.gnu.org/licenses/>.
|
85
third_party/make/BUILD.mk
vendored
85
third_party/make/BUILD.mk
vendored
|
@ -14,67 +14,42 @@ THIRD_PARTY_MAKE_A = \
|
|||
o/$(MODE)/third_party/make/make.a
|
||||
|
||||
THIRD_PARTY_MAKE_HDRS = \
|
||||
third_party/make/filename.h \
|
||||
third_party/make/dirname.h \
|
||||
third_party/make/stddef.h \
|
||||
third_party/make/error.h \
|
||||
third_party/make/gnumake.h \
|
||||
third_party/make/gettext.h \
|
||||
third_party/make/stdlib.h \
|
||||
third_party/make/xalloc.h \
|
||||
third_party/make/xalloc-oversized.h \
|
||||
third_party/make/os.h \
|
||||
third_party/make/stdint.h \
|
||||
third_party/make/fd-hook.h \
|
||||
third_party/make/job.h \
|
||||
third_party/make/unistd.h \
|
||||
third_party/make/getprogname.h \
|
||||
third_party/make/config.h \
|
||||
third_party/make/concat-filename.h \
|
||||
third_party/make/findprog.h \
|
||||
third_party/make/intprops.h \
|
||||
third_party/make/exitfail.h \
|
||||
third_party/make/alloca.h \
|
||||
third_party/make/hash.h \
|
||||
third_party/make/rule.h \
|
||||
third_party/make/filedef.h \
|
||||
third_party/make/fcntl.h \
|
||||
third_party/make/stdio.h \
|
||||
third_party/make/variable.h \
|
||||
third_party/make/commands.h \
|
||||
third_party/make/glob.h \
|
||||
third_party/make/config.h \
|
||||
third_party/make/debug.h \
|
||||
third_party/make/output.h \
|
||||
third_party/make/getopt.h \
|
||||
third_party/make/dep.h \
|
||||
third_party/make/commands.h
|
||||
|
||||
third_party/make/findprog.h \
|
||||
third_party/make/filedef.h \
|
||||
third_party/make/filename.h \
|
||||
third_party/make/getopt.h \
|
||||
third_party/make/gettext.h \
|
||||
third_party/make/gnumake.h \
|
||||
third_party/make/hash.h \
|
||||
third_party/make/job.h \
|
||||
third_party/make/makeint.h \
|
||||
third_party/make/mkconfig.h \
|
||||
third_party/make/mkcustom.h \
|
||||
third_party/make/os.h \
|
||||
third_party/make/output.h \
|
||||
third_party/make/rule.h \
|
||||
third_party/make/shuffle.h \
|
||||
third_party/make/variable.h
|
||||
|
||||
THIRD_PARTY_MAKE_INCS = \
|
||||
third_party/make/makeint.inc
|
||||
third_party/make/makeint.h
|
||||
|
||||
THIRD_PARTY_MAKE_CHECKS = \
|
||||
$(THIRD_PARTY_MAKE_A).pkg
|
||||
|
||||
# libgnu.a recipe
|
||||
THIRD_PARTY_MAKE_SRCS_LIB = \
|
||||
third_party/make/basename-lgpl.c \
|
||||
third_party/make/concat-filename.c \
|
||||
third_party/make/dirname-lgpl.c \
|
||||
third_party/make/error.c \
|
||||
third_party/make/exitfail.c \
|
||||
third_party/make/fcntl.c \
|
||||
third_party/make/fd-hook.c \
|
||||
third_party/make/findprog-in.c \
|
||||
third_party/make/getprogname.c \
|
||||
third_party/make/stripslash.c \
|
||||
third_party/make/unistd.c \
|
||||
third_party/make/xalloc-die.c \
|
||||
third_party/make/xconcat-filename.c \
|
||||
third_party/make/xmalloc.c
|
||||
|
||||
THIRD_PARTY_MAKE_SRCS_BASE = \
|
||||
THIRD_PARTY_MAKE_SRCS = \
|
||||
third_party/make/glob.c \
|
||||
third_party/make/commands.c \
|
||||
third_party/make/default.c \
|
||||
third_party/make/dir.c \
|
||||
third_party/make/concat-filename.c \
|
||||
third_party/make/findprog-in.c \
|
||||
third_party/make/expand.c \
|
||||
third_party/make/file.c \
|
||||
third_party/make/function.c \
|
||||
|
@ -97,12 +72,9 @@ THIRD_PARTY_MAKE_SRCS_BASE = \
|
|||
third_party/make/strcache.c \
|
||||
third_party/make/variable.c \
|
||||
third_party/make/version.c \
|
||||
third_party/make/shuffle.c \
|
||||
third_party/make/vpath.c
|
||||
|
||||
THIRD_PARTY_MAKE_SRCS = \
|
||||
$(THIRD_PARTY_MAKE_SRCS_BASE) \
|
||||
$(THIRD_PARTY_MAKE_SRCS_LIB)
|
||||
|
||||
THIRD_PARTY_MAKE_OBJS = \
|
||||
$(THIRD_PARTY_MAKE_SRCS:%.c=o/$(MODE)/%.o)
|
||||
|
||||
|
@ -170,12 +142,9 @@ o/$(MODE)/third_party/make/hash.o: private \
|
|||
|
||||
$(THIRD_PARTY_MAKE_OBJS): private \
|
||||
CFLAGS += \
|
||||
-fportcosmo \
|
||||
-DNO_ARCHIVES \
|
||||
-DHAVE_CONFIG_H \
|
||||
-DSTACK_FRAME_UNLIMITED \
|
||||
-DINCLUDEDIR=\".\" \
|
||||
-DLIBDIR=\".\" \
|
||||
-DLOCALEDIR=\".\"
|
||||
-DHAVE_CONFIG_H
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/make
|
||||
o/$(MODE)/third_party/make: \
|
||||
|
|
674
third_party/make/COPYING
vendored
674
third_party/make/COPYING
vendored
|
@ -1,674 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
5
third_party/make/README.cosmo
vendored
5
third_party/make/README.cosmo
vendored
|
@ -5,8 +5,8 @@ DESCRIPTION
|
|||
|
||||
ORIGIN
|
||||
|
||||
GNU Make 4.3
|
||||
http://ftp.gnu.org/gnu/make/make-4.3.tar.gz
|
||||
GNU Make 4.4.1
|
||||
http://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz
|
||||
|
||||
LICENSE
|
||||
|
||||
|
@ -30,4 +30,3 @@ LOCAL CHANGES
|
|||
- .MAXCORE variable to set upper limit on core dumps
|
||||
- Do automatic setup and teardown of TMPDIR per rule
|
||||
- Remove code that forces slow path if not using /bin/sh
|
||||
- Remove 200,000 lines of VAX/OS2/DOS/AMIGA/etc. code
|
||||
|
|
68
third_party/make/alloca.h
vendored
68
third_party/make/alloca.h
vendored
|
@ -1,68 +0,0 @@
|
|||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Memory allocation on the stack.
|
||||
|
||||
Copyright (C) 1995, 1999, 2001-2004, 2006-2020 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program 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/>.
|
||||
*/
|
||||
|
||||
/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
|
||||
means there is a real alloca function. */
|
||||
#ifndef _GL_ALLOCA_H
|
||||
#define _GL_ALLOCA_H
|
||||
|
||||
/* alloca (N) returns a pointer to N bytes of memory
|
||||
allocated on the stack, which will last until the function returns.
|
||||
Use of alloca should be avoided:
|
||||
- inside arguments of function calls - undefined behaviour,
|
||||
- in inline functions - the allocation may actually last until the
|
||||
calling function returns,
|
||||
- for huge N (say, N >= 65536) - you never know how large (or small)
|
||||
the stack is, and when the stack cannot fulfill the memory allocation
|
||||
request, the program just crashes.
|
||||
*/
|
||||
|
||||
#ifndef alloca
|
||||
# ifdef __GNUC__
|
||||
/* Some version of mingw have an <alloca.h> that causes trouble when
|
||||
included after 'alloca' gets defined as a macro. As a workaround, include
|
||||
this <alloca.h> first and define 'alloca' as a macro afterwards. */
|
||||
# if (defined _WIN32 && ! defined __CYGWIN__) && 1
|
||||
# endif
|
||||
# define alloca __builtin_alloca
|
||||
# elif defined _AIX
|
||||
# define alloca __alloca
|
||||
# elif defined _MSC_VER
|
||||
# define alloca _alloca
|
||||
# elif defined __DECC && defined __VMS
|
||||
# define alloca __ALLOCA
|
||||
# elif defined __TANDEM && defined _TNS_E_TARGET
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
void *_alloca (unsigned short);
|
||||
# pragma intrinsic (_alloca)
|
||||
# define alloca _alloca
|
||||
# elif defined __MVS__
|
||||
# else
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
void *alloca (size_t);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _GL_ALLOCA_H */
|
90
third_party/make/ar.c
vendored
90
third_party/make/ar.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Interface to 'ar' archives for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Make.
|
||||
|
||||
|
@ -13,13 +13,16 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "libc/mem/alg.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/musl/fnmatch.h"
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "makeint.h"
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
#include <fnmatch.h>
|
||||
#include <intprops.h>
|
||||
|
||||
/* Return nonzero if NAME is an archive-member reference, zero if not. An
|
||||
archive-member reference is a name like 'lib(member)' where member is a
|
||||
|
@ -33,7 +36,7 @@ ar_name (const char *name)
|
|||
const char *p = strchr (name, '(');
|
||||
const char *end;
|
||||
|
||||
if (p == 0 || p == name)
|
||||
if (p == NULL || p == name)
|
||||
return 0;
|
||||
|
||||
end = p + strlen (p) - 1;
|
||||
|
@ -58,6 +61,9 @@ ar_parse_name (const char *name, char **arname_p, char **memname_p)
|
|||
|
||||
*arname_p = xstrdup (name);
|
||||
p = strchr (*arname_p, '(');
|
||||
/* This is never called unless ar_name() is true so p cannot be NULL. */
|
||||
if (!p)
|
||||
OS (fatal, NILF, "Internal: ar_parse_name: bad name '%s'", *arname_p);
|
||||
*(p++) = '\0';
|
||||
p[strlen (p) - 1] = '\0';
|
||||
*memname_p = p;
|
||||
|
@ -67,10 +73,10 @@ ar_parse_name (const char *name, char **arname_p, char **memname_p)
|
|||
/* This function is called by 'ar_scan' to find which member to look at. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static long int
|
||||
static intmax_t
|
||||
ar_member_date_1 (int desc UNUSED, const char *mem, int truncated,
|
||||
long int hdrpos UNUSED, long int datapos UNUSED,
|
||||
long int size UNUSED, long int date,
|
||||
long int size UNUSED, intmax_t date,
|
||||
int uid UNUSED, int gid UNUSED, unsigned int mode UNUSED,
|
||||
const void *name)
|
||||
{
|
||||
|
@ -84,7 +90,7 @@ ar_member_date (const char *name)
|
|||
{
|
||||
char *arname;
|
||||
char *memname;
|
||||
long int val;
|
||||
intmax_t val;
|
||||
|
||||
ar_parse_name (name, &arname, &memname);
|
||||
|
||||
|
@ -109,11 +115,19 @@ ar_member_date (const char *name)
|
|||
|
||||
free (arname);
|
||||
|
||||
return (val <= 0 ? (time_t) -1 : (time_t) val);
|
||||
return 0 < val && val <= TYPE_MAXIMUM (time_t) ? val : -1;
|
||||
}
|
||||
|
||||
/* Set the archive-member NAME's modtime to now. */
|
||||
|
||||
#ifdef VMS
|
||||
int
|
||||
ar_touch (const char *name)
|
||||
{
|
||||
O (error, NILF, _("touch archive member is not available on VMS"));
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int
|
||||
ar_touch (const char *name)
|
||||
{
|
||||
|
@ -158,7 +172,7 @@ ar_touch (const char *name)
|
|||
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* !VMS */
|
||||
|
||||
/* State of an 'ar_glob' run, passed to 'ar_glob_match'. */
|
||||
|
||||
|
@ -173,6 +187,9 @@ struct ar_glob_state
|
|||
{
|
||||
const char *arname;
|
||||
const char *pattern;
|
||||
#ifdef VMS
|
||||
char *suffix;
|
||||
#endif
|
||||
size_t size;
|
||||
struct nameseq *chain;
|
||||
unsigned int n;
|
||||
|
@ -181,10 +198,10 @@ struct ar_glob_state
|
|||
/* This function is called by 'ar_scan' to match one archive
|
||||
element against the pattern in STATE. */
|
||||
|
||||
static long int
|
||||
static intmax_t
|
||||
ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
|
||||
long int hdrpos UNUSED, long int datapos UNUSED,
|
||||
long int size UNUSED, long int date UNUSED, int uid UNUSED,
|
||||
long int size UNUSED, intmax_t date UNUSED, int uid UNUSED,
|
||||
int gid UNUSED, unsigned int mode UNUSED, const void *arg)
|
||||
{
|
||||
struct ar_glob_state *state = (struct ar_glob_state *)arg;
|
||||
|
@ -192,14 +209,20 @@ ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
|
|||
if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
|
||||
{
|
||||
/* We have a match. Add it to the chain. */
|
||||
struct nameseq *new = xcalloc (1, state->size);
|
||||
struct nameseq *new = xcalloc (state->size);
|
||||
#ifdef VMS
|
||||
if (state->suffix)
|
||||
new->name = strcache_add(
|
||||
concat(5, state->arname, "(", mem, state->suffix, ")"));
|
||||
else
|
||||
#endif
|
||||
new->name = strcache_add(concat(4, state->arname, "(", mem, ")"));
|
||||
new->next = state->chain;
|
||||
state->chain = new;
|
||||
++state->n;
|
||||
}
|
||||
|
||||
return 0L;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if PATTERN contains any metacharacters.
|
||||
|
@ -245,7 +268,9 @@ ar_glob (const char *arname, const char *member_pattern, size_t size)
|
|||
struct nameseq *n;
|
||||
const char **names;
|
||||
unsigned int i;
|
||||
|
||||
#ifdef VMS
|
||||
char *vms_member_pattern;
|
||||
#endif
|
||||
if (! ar_glob_pattern_p (member_pattern, 1))
|
||||
return 0;
|
||||
|
||||
|
@ -253,11 +278,36 @@ ar_glob (const char *arname, const char *member_pattern, size_t size)
|
|||
ar_glob_match will accumulate them in STATE.chain. */
|
||||
state.arname = arname;
|
||||
state.pattern = member_pattern;
|
||||
#ifdef VMS
|
||||
{
|
||||
/* In a copy of the pattern, find the suffix, save it and remove it from
|
||||
the pattern */
|
||||
char *lastdot;
|
||||
vms_member_pattern = xstrdup(member_pattern);
|
||||
lastdot = strrchr(vms_member_pattern, '.');
|
||||
state.suffix = lastdot;
|
||||
if (lastdot)
|
||||
{
|
||||
state.suffix = xstrdup(lastdot);
|
||||
*lastdot = 0;
|
||||
}
|
||||
state.pattern = vms_member_pattern;
|
||||
}
|
||||
#endif
|
||||
state.size = size;
|
||||
state.chain = 0;
|
||||
state.n = 0;
|
||||
ar_scan (arname, ar_glob_match, &state);
|
||||
|
||||
#ifdef VMS
|
||||
/* Deallocate any duplicated string */
|
||||
free(vms_member_pattern);
|
||||
if (state.suffix)
|
||||
{
|
||||
free(state.suffix);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state.chain == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -278,3 +328,5 @@ ar_glob (const char *arname, const char *member_pattern, size_t size)
|
|||
|
||||
return state.chain;
|
||||
}
|
||||
|
||||
#endif /* Not NO_ARCHIVES. */
|
||||
|
|
407
third_party/make/arscan.c
vendored
407
third_party/make/arscan.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Library function for scanning an archive file.
|
||||
Copyright (C) 1987-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-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
|
||||
|
@ -12,16 +12,290 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "makeint.h"
|
||||
|
||||
#ifdef TEST
|
||||
/* Hack, the real error() routine eventually pulls in die from main.c */
|
||||
#define error(a, b, c, d)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
|
||||
#ifdef VMS
|
||||
#include <lbrdef.h>
|
||||
#include <mhddef.h>
|
||||
#include <credef.h>
|
||||
#include <descrip.h>
|
||||
#include <ctype.h>
|
||||
#include <ssdef.h>
|
||||
#include <stsdef.h>
|
||||
#include <rmsdef.h>
|
||||
|
||||
/* This symbol should be present in lbrdef.h. */
|
||||
#if !defined LBR$_HDRTRUNC
|
||||
#pragma extern_model save
|
||||
#pragma extern_model globalvalue
|
||||
extern unsigned int LBR$_HDRTRUNC;
|
||||
#pragma extern_model restore
|
||||
#endif
|
||||
|
||||
#include <unixlib.h>
|
||||
#include <lbr$routines.h>
|
||||
|
||||
const char *
|
||||
vmsify (const char *name, int type);
|
||||
|
||||
/* Time conversion from VMS to Unix
|
||||
Conversion from local time (stored in library) to GMT (needed for gmake)
|
||||
Note: The tm_gmtoff element is a VMS extension to the ANSI standard. */
|
||||
static time_t
|
||||
vms_time_to_unix(void *vms_time)
|
||||
{
|
||||
struct tm *tmp;
|
||||
time_t unix_time;
|
||||
|
||||
unix_time = decc$fix_time(vms_time);
|
||||
tmp = localtime(&unix_time);
|
||||
unix_time -= tmp->tm_gmtoff;
|
||||
|
||||
return unix_time;
|
||||
}
|
||||
|
||||
|
||||
/* VMS library routines need static variables for callback */
|
||||
static void *VMS_lib_idx;
|
||||
|
||||
static const void *VMS_saved_arg;
|
||||
|
||||
static intmax_t (*VMS_function) ();
|
||||
|
||||
static intmax_t VMS_function_ret;
|
||||
|
||||
|
||||
/* This is a callback procedure for lib$get_index */
|
||||
static int
|
||||
VMS_get_member_info(struct dsc$descriptor_s *module, unsigned long *rfa)
|
||||
{
|
||||
int status, i;
|
||||
const int truncated = 0; /* Member name may be truncated */
|
||||
time_t member_date; /* Member date */
|
||||
char *filename;
|
||||
unsigned int buffer_length; /* Actual buffer length */
|
||||
|
||||
/* Unused constants - Make does not actually use most of these */
|
||||
const int file_desc = -1; /* archive file descriptor for reading the data */
|
||||
const int header_position = 0; /* Header position */
|
||||
const int data_position = 0; /* Data position in file */
|
||||
const int data_size = 0; /* Data size */
|
||||
const int uid = 0; /* member gid */
|
||||
const int gid = 0; /* member gid */
|
||||
const int mode = 0; /* member protection mode */
|
||||
/* End of unused constants */
|
||||
|
||||
static struct dsc$descriptor_s bufdesc =
|
||||
{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
|
||||
|
||||
/* Only need the module definition */
|
||||
struct mhddef *mhd;
|
||||
|
||||
/* If a previous callback is non-zero, just return that status */
|
||||
if (VMS_function_ret)
|
||||
{
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
/* lbr_set_module returns more than just the module header. So allocate
|
||||
a buffer which is big enough: the maximum LBR$C_MAXHDRSIZ. That's at
|
||||
least bigger than the size of struct mhddef.
|
||||
If the request is too small, a buffer truncated warning is issued so
|
||||
it can be reissued with a larger buffer.
|
||||
We do not care if the buffer is truncated, so that is still a success. */
|
||||
mhd = xmalloc(LBR$C_MAXHDRSIZ);
|
||||
bufdesc.dsc$a_pointer = (char *) mhd;
|
||||
bufdesc.dsc$w_length = LBR$C_MAXHDRSIZ;
|
||||
|
||||
status = lbr$set_module(&VMS_lib_idx, rfa, &bufdesc, &buffer_length, 0);
|
||||
|
||||
if ((status != LBR$_HDRTRUNC) && !$VMS_STATUS_SUCCESS(status))
|
||||
{
|
||||
ON(error, NILF,
|
||||
_("lbr$set_module() failed to extract module info, status = %d"),
|
||||
status);
|
||||
|
||||
lbr$close(&VMS_lib_idx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
/* When testing this code, it is useful to know the length returned */
|
||||
printf ("Input length = %d, actual = %u\n",
|
||||
bufdesc.dsc$w_length, buffer_length);
|
||||
#endif
|
||||
|
||||
/* Conversion from VMS time to C time.
|
||||
VMS defectlet - mhddef is sub-optimal, for the time, it has a 32 bit
|
||||
longword, mhd$l_datim, and a 32 bit fill instead of two longwords, or
|
||||
equivalent. */
|
||||
member_date = vms_time_to_unix(&mhd->mhd$l_datim);
|
||||
free(mhd);
|
||||
|
||||
/* Here we have a problem. The module name on VMS does not have
|
||||
a file type, but the filename pattern in the "VMS_saved_arg"
|
||||
may have one.
|
||||
But only the method being called knows how to interpret the
|
||||
filename pattern.
|
||||
There are currently two different formats being used.
|
||||
This means that we need a VMS specific code in those methods
|
||||
to handle it. */
|
||||
filename = xmalloc(module->dsc$w_length + 1);
|
||||
|
||||
/* TODO: We may need an option to preserve the case of the module
|
||||
For now force the module name to lower case */
|
||||
for (i = 0; i < module->dsc$w_length; i++)
|
||||
filename[i] = _tolower((unsigned char )module->dsc$a_pointer[i]);
|
||||
|
||||
filename[i] = '\0';
|
||||
|
||||
VMS_function_ret = (*VMS_function)(file_desc, filename, truncated,
|
||||
header_position, data_position, data_size, member_date, uid, gid, mode,
|
||||
VMS_saved_arg);
|
||||
|
||||
free(filename);
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
/* Takes three arguments ARCHIVE, FUNCTION and ARG.
|
||||
|
||||
Open the archive named ARCHIVE, find its members one by one,
|
||||
and for each one call FUNCTION with the following arguments:
|
||||
archive file descriptor for reading the data,
|
||||
member name,
|
||||
member name might be truncated flag,
|
||||
member header position in file,
|
||||
member data position in file,
|
||||
member data size,
|
||||
member date,
|
||||
member uid,
|
||||
member gid,
|
||||
member protection mode,
|
||||
ARG.
|
||||
|
||||
NOTE: on VMS systems, only name, date, and arg are meaningful!
|
||||
|
||||
The descriptor is poised to read the data of the member
|
||||
when FUNCTION is called. It does not matter how much
|
||||
data FUNCTION reads.
|
||||
|
||||
If FUNCTION returns nonzero, we immediately return
|
||||
what FUNCTION returned.
|
||||
|
||||
Returns -1 if archive does not exist,
|
||||
Returns -2 if archive has invalid format.
|
||||
Returns 0 if have scanned successfully. */
|
||||
|
||||
intmax_t
|
||||
ar_scan (const char *archive, ar_member_func_t function, const void *varg)
|
||||
{
|
||||
char *vms_archive;
|
||||
|
||||
static struct dsc$descriptor_s libdesc =
|
||||
{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
|
||||
|
||||
const unsigned long func = LBR$C_READ;
|
||||
const unsigned long type = LBR$C_TYP_UNK;
|
||||
const unsigned long index = 1;
|
||||
unsigned long lib_idx;
|
||||
int status;
|
||||
|
||||
VMS_saved_arg = varg;
|
||||
|
||||
/* Null archive string can show up in test and cause an access violation */
|
||||
if (archive == NULL)
|
||||
{
|
||||
/* Null filenames do not exist */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* archive path name must be in VMS format */
|
||||
vms_archive = (char *) vmsify(archive, 0);
|
||||
|
||||
status = lbr$ini_control(&VMS_lib_idx, &func, &type, 0);
|
||||
|
||||
if (!$VMS_STATUS_SUCCESS(status))
|
||||
{
|
||||
ON(error, NILF, _("lbr$ini_control() failed with status = %d"), status);
|
||||
return -2;
|
||||
}
|
||||
|
||||
libdesc.dsc$a_pointer = vms_archive;
|
||||
libdesc.dsc$w_length = strlen(vms_archive);
|
||||
|
||||
status = lbr$open(&VMS_lib_idx, &libdesc, 0, NULL, 0, NULL, 0);
|
||||
|
||||
if (!$VMS_STATUS_SUCCESS(status))
|
||||
{
|
||||
|
||||
/* TODO: A library format failure could mean that this is a file
|
||||
generated by the GNU AR utility and in that case, we need to
|
||||
take the UNIX codepath. This will also take a change to the
|
||||
GNV AR wrapper program. */
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case RMS$_FNF:
|
||||
/* Archive does not exist */
|
||||
return -1;
|
||||
default:
|
||||
#ifndef TEST
|
||||
OSN(error, NILF,
|
||||
_("unable to open library '%s' to lookup member status %d"),
|
||||
archive, status);
|
||||
#endif
|
||||
/* For library format errors, specification says to return -2 */
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
VMS_function = function;
|
||||
|
||||
/* Clear the return status, as we are supposed to stop calling the
|
||||
callback function if it becomes non-zero, and this is a static
|
||||
variable. */
|
||||
VMS_function_ret = 0;
|
||||
|
||||
status = lbr$get_index(&VMS_lib_idx, &index, VMS_get_member_info, NULL, 0);
|
||||
|
||||
lbr$close(&VMS_lib_idx);
|
||||
|
||||
/* Unless a failure occurred in the lbr$ routines, return the
|
||||
the status from the 'function' routine. */
|
||||
if ($VMS_STATUS_SUCCESS(status))
|
||||
{
|
||||
return VMS_function_ret;
|
||||
}
|
||||
|
||||
/* This must be something wrong with the library and an error
|
||||
message should already have been printed. */
|
||||
return -2;
|
||||
}
|
||||
|
||||
#else /* !VMS */
|
||||
|
||||
/* SCO Unix's compiler defines both of these. */
|
||||
#ifdef M_UNIX
|
||||
#undef M_XENIX
|
||||
#endif
|
||||
|
||||
/* On the sun386i and in System V rel 3, ar.h defines two different archive
|
||||
formats depending upon whether you have defined PORTAR (normal) or PORT5AR
|
||||
(System V Release 1). There is no default, one or the other must be defined
|
||||
|
@ -57,7 +331,8 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#endif
|
||||
|
||||
#ifndef WINDOWS32
|
||||
# if 0 && !defined (__ANDROID__) && !defined (__BEOS__)
|
||||
# if !defined (__ANDROID__) && !defined (__BEOS__) && !defined(MK_OS_ZOS)
|
||||
# include <ar.h>
|
||||
# else
|
||||
/* These platforms don't have <ar.h> but have archives in the same format
|
||||
* as many other Unices. This was taken from GNU binutils for BeOS.
|
||||
|
@ -80,6 +355,9 @@ struct ar_hdr
|
|||
/* These should allow us to read Windows (VC++) libraries (according to Frank
|
||||
* Libbrecht <frankl@abzx.belgium.hp.com>)
|
||||
*/
|
||||
# include <windows.h>
|
||||
# include <windef.h>
|
||||
# include <io.h>
|
||||
# define ARMAG IMAGE_ARCHIVE_START
|
||||
# define SARMAG IMAGE_ARCHIVE_START_SIZE
|
||||
# define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
|
||||
|
@ -98,8 +376,41 @@ struct ar_hdr
|
|||
# define AR_HDR_SIZE (sizeof (struct ar_hdr))
|
||||
#endif
|
||||
|
||||
#include "third_party/make/output.h"
|
||||
#include "intprops.h"
|
||||
|
||||
#include "output.h"
|
||||
|
||||
|
||||
static uintmax_t
|
||||
parse_int (const char *ptr, const size_t len, const int base, uintmax_t max,
|
||||
const char *type, const char *archive, const char *name)
|
||||
{
|
||||
const char *const ep = ptr + len;
|
||||
const int maxchar = '0' + base - 1;
|
||||
uintmax_t val = 0;
|
||||
|
||||
/* In all the versions I know of the spaces come last, but be safe. */
|
||||
while (ptr < ep && *ptr == ' ')
|
||||
++ptr;
|
||||
|
||||
while (ptr < ep && *ptr != ' ')
|
||||
{
|
||||
uintmax_t nv;
|
||||
|
||||
if (*ptr < '0' || *ptr > maxchar)
|
||||
OSSS (fatal, NILF,
|
||||
_("Invalid %s for archive %s member %s"), type, archive, name);
|
||||
nv = (val * base) + (*ptr - '0');
|
||||
if (nv < val || nv > max)
|
||||
OSSS (fatal, NILF,
|
||||
_("Invalid %s for archive %s member %s"), type, archive, name);
|
||||
val = nv;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Takes three arguments ARCHIVE, FUNCTION and ARG.
|
||||
|
||||
Open the archive named ARCHIVE, find its members one by one,
|
||||
|
@ -127,7 +438,7 @@ struct ar_hdr
|
|||
Returns -2 if archive has invalid format.
|
||||
Returns 0 if have scanned successfully. */
|
||||
|
||||
long int
|
||||
intmax_t
|
||||
ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
||||
{
|
||||
#ifdef AIAMAG
|
||||
|
@ -138,7 +449,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
# endif
|
||||
#endif
|
||||
char *namemap = 0;
|
||||
int namemap_size = 0;
|
||||
unsigned int namemap_size = 0;
|
||||
int desc = open (archive, O_RDONLY, 0);
|
||||
if (desc < 0)
|
||||
return -1;
|
||||
|
@ -238,7 +549,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
|
||||
while (1)
|
||||
{
|
||||
int nread;
|
||||
ssize_t nread;
|
||||
struct ar_hdr member_header;
|
||||
#ifdef AIAMAGBIG
|
||||
struct ar_hdr_big member_header_big;
|
||||
|
@ -247,7 +558,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
# define ARNAME_MAX 255
|
||||
char name[ARNAME_MAX + 1];
|
||||
int name_len;
|
||||
long int dateval;
|
||||
intmax_t dateval;
|
||||
int uidval, gidval;
|
||||
long int data_offset;
|
||||
#else
|
||||
|
@ -259,9 +570,13 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
#endif
|
||||
long int eltsize;
|
||||
unsigned int eltmode;
|
||||
long int fnval;
|
||||
intmax_t eltdate;
|
||||
int eltuid, eltgid;
|
||||
intmax_t fnval;
|
||||
off_t o;
|
||||
|
||||
memset(&member_header, '\0', sizeof (member_header));
|
||||
|
||||
EINTRLOOP (o, lseek (desc, member_offset, 0));
|
||||
if (o < 0)
|
||||
goto invalid;
|
||||
|
@ -288,7 +603,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
|
||||
name[name_len] = '\0';
|
||||
|
||||
sscanf (member_header_big.ar_date, "%12ld", &dateval);
|
||||
sscanf (member_header_big.ar_date, "%12" SCNdMAX, &dateval);
|
||||
sscanf (member_header_big.ar_uid, "%12d", &uidval);
|
||||
sscanf (member_header_big.ar_gid, "%12d", &gidval);
|
||||
sscanf (member_header_big.ar_mode, "%12o", &eltmode);
|
||||
|
@ -316,7 +631,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
|
||||
name[name_len] = '\0';
|
||||
|
||||
sscanf (member_header.ar_date, "%12ld", &dateval);
|
||||
sscanf (member_header.ar_date, "%12" SCNdMAX, &dateval);
|
||||
sscanf (member_header.ar_uid, "%12d", &uidval);
|
||||
sscanf (member_header.ar_gid, "%12d", &gidval);
|
||||
sscanf (member_header.ar_mode, "%12o", &eltmode);
|
||||
|
@ -391,10 +706,11 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
&& (name[0] == ' ' || name[0] == '/')
|
||||
&& namemap != 0)
|
||||
{
|
||||
int name_off = atoi (name + 1);
|
||||
int name_len;
|
||||
const char* err;
|
||||
unsigned int name_off = make_toui (name + 1, &err);
|
||||
size_t name_len;
|
||||
|
||||
if (name_off < 0 || name_off >= namemap_size)
|
||||
if (err|| name_off >= namemap_size)
|
||||
goto invalid;
|
||||
|
||||
name = namemap + name_off;
|
||||
|
@ -407,14 +723,15 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
&& name[1] == '1'
|
||||
&& name[2] == '/')
|
||||
{
|
||||
int name_len = atoi (name + 3);
|
||||
const char* err;
|
||||
unsigned int name_len = make_toui (name + 3, &err);
|
||||
|
||||
if (name_len < 1)
|
||||
if (err || name_len == 0 || name_len >= MIN (PATH_MAX, INT_MAX))
|
||||
goto invalid;
|
||||
|
||||
name = alloca (name_len + 1);
|
||||
nread = readbuf (desc, name, name_len);
|
||||
if (nread != name_len)
|
||||
if (nread < 0 || (unsigned int) nread != name_len)
|
||||
goto invalid;
|
||||
|
||||
name[name_len] = '\0';
|
||||
|
@ -425,8 +742,16 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
}
|
||||
|
||||
#ifndef M_XENIX
|
||||
sscanf (TOCHAR (member_header.ar_mode), "%8o", &eltmode);
|
||||
eltsize = atol (TOCHAR (member_header.ar_size));
|
||||
#define PARSE_INT(_m, _t, _b, _n) \
|
||||
(_t) parse_int (TOCHAR (member_header._m), sizeof (member_header._m), \
|
||||
_b, TYPE_MAXIMUM (_t), _n, archive, name)
|
||||
|
||||
eltmode = PARSE_INT (ar_mode, unsigned int, 8, "mode");
|
||||
eltsize = PARSE_INT (ar_size, long, 10, "size");
|
||||
eltdate = PARSE_INT (ar_date, intmax_t, 10, "date");
|
||||
eltuid = PARSE_INT (ar_uid, int, 10, "uid");
|
||||
eltgid = PARSE_INT (ar_gid, int, 10, "gid");
|
||||
#undef PARSE_INT
|
||||
#else /* Xenix. */
|
||||
eltmode = (unsigned short int) member_header.ar_mode;
|
||||
eltsize = member_header.ar_size;
|
||||
|
@ -436,9 +761,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
(*function) (desc, name, ! long_name, member_offset,
|
||||
member_offset + AR_HDR_SIZE, eltsize,
|
||||
#ifndef M_XENIX
|
||||
atol (TOCHAR (member_header.ar_date)),
|
||||
atoi (TOCHAR (member_header.ar_uid)),
|
||||
atoi (TOCHAR (member_header.ar_gid)),
|
||||
eltdate, eltuid, eltgid,
|
||||
#else /* Xenix. */
|
||||
member_header.ar_date,
|
||||
member_header.ar_uid,
|
||||
|
@ -518,7 +841,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
|
|||
close (desc);
|
||||
return -2;
|
||||
}
|
||||
|
||||
#endif /* !VMS */
|
||||
|
||||
/* Return nonzero iff NAME matches MEM.
|
||||
If TRUNCATED is nonzero, MEM may be truncated to
|
||||
|
@ -578,10 +901,10 @@ ar_name_equal (const char *name, const char *mem, int truncated)
|
|||
|
||||
#ifndef VMS
|
||||
/* ARGSUSED */
|
||||
static long int
|
||||
static intmax_t
|
||||
ar_member_pos (int desc UNUSED, const char *mem, int truncated,
|
||||
long int hdrpos, long int datapos UNUSED, long int size UNUSED,
|
||||
long int date UNUSED, int uid UNUSED, int gid UNUSED,
|
||||
intmax_t date UNUSED, int uid UNUSED, int gid UNUSED,
|
||||
unsigned int mode UNUSED, const void *name)
|
||||
{
|
||||
if (!ar_name_equal (name, mem, truncated))
|
||||
|
@ -599,12 +922,13 @@ ar_member_pos (int desc UNUSED, const char *mem, int truncated,
|
|||
int
|
||||
ar_member_touch (const char *arname, const char *memname)
|
||||
{
|
||||
long int pos = ar_scan (arname, ar_member_pos, memname);
|
||||
intmax_t pos = ar_scan (arname, ar_member_pos, memname);
|
||||
off_t opos;
|
||||
int fd;
|
||||
struct ar_hdr ar_hdr;
|
||||
off_t o;
|
||||
int r;
|
||||
unsigned int ui;
|
||||
int datelen;
|
||||
struct stat statbuf;
|
||||
|
||||
if (pos < 0)
|
||||
|
@ -612,11 +936,13 @@ ar_member_touch (const char *arname, const char *memname)
|
|||
if (!pos)
|
||||
return 1;
|
||||
|
||||
opos = (off_t) pos;
|
||||
|
||||
EINTRLOOP (fd, open (arname, O_RDWR, 0666));
|
||||
if (fd < 0)
|
||||
return -3;
|
||||
/* Read in this member's header */
|
||||
EINTRLOOP (o, lseek (fd, pos, 0));
|
||||
EINTRLOOP (o, lseek (fd, opos, 0));
|
||||
if (o < 0)
|
||||
goto lose;
|
||||
r = readbuf (fd, &ar_hdr, AR_HDR_SIZE);
|
||||
|
@ -628,15 +954,16 @@ ar_member_touch (const char *arname, const char *memname)
|
|||
goto lose;
|
||||
/* Advance member's time to that time */
|
||||
#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
|
||||
for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
|
||||
ar_hdr.ar_date[ui] = ' ';
|
||||
sprintf (TOCHAR (ar_hdr.ar_date), "%lu", (long unsigned) statbuf.st_mtime);
|
||||
ar_hdr.ar_date[strlen ((char *) ar_hdr.ar_date)] = ' ';
|
||||
datelen = snprintf (TOCHAR (ar_hdr.ar_date), sizeof ar_hdr.ar_date,
|
||||
"%" PRIdMAX, (intmax_t) statbuf.st_mtime);
|
||||
if (! (0 <= datelen && datelen < (int) sizeof ar_hdr.ar_date))
|
||||
goto lose;
|
||||
memset (ar_hdr.ar_date + datelen, ' ', sizeof ar_hdr.ar_date - datelen);
|
||||
#else
|
||||
ar_hdr.ar_date = statbuf.st_mtime;
|
||||
#endif
|
||||
/* Write back this member's header */
|
||||
EINTRLOOP (o, lseek (fd, pos, 0));
|
||||
EINTRLOOP (o, lseek (fd, opos, 0));
|
||||
if (o < 0)
|
||||
goto lose;
|
||||
r = writebuf (fd, &ar_hdr, AR_HDR_SIZE);
|
||||
|
@ -655,18 +982,21 @@ ar_member_touch (const char *arname, const char *memname)
|
|||
|
||||
#ifdef TEST
|
||||
|
||||
long int
|
||||
intmax_t
|
||||
describe_member (int desc, const char *name, int truncated,
|
||||
long int hdrpos, long int datapos, long int size,
|
||||
long int date, int uid, int gid, unsigned int mode,
|
||||
intmax_t date, int uid, int gid, unsigned int mode,
|
||||
const void *arg)
|
||||
{
|
||||
extern char *ctime ();
|
||||
time_t d = date;
|
||||
char const *ds;
|
||||
|
||||
printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"),
|
||||
name, truncated ? _(" (name might be truncated)") : "",
|
||||
size, hdrpos, datapos);
|
||||
printf (_(" Date %s"), ctime (&date));
|
||||
ds = ctime (&d);
|
||||
printf (_(" Date %s"), ds ? ds : "?");
|
||||
printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
|
||||
|
||||
return 0;
|
||||
|
@ -680,3 +1010,4 @@ main (int argc, char **argv)
|
|||
}
|
||||
|
||||
#endif /* TEST. */
|
||||
#endif /* NO_ARCHIVES. */
|
||||
|
|
74
third_party/make/basename-lgpl.c
vendored
74
third_party/make/basename-lgpl.c
vendored
|
@ -1,74 +0,0 @@
|
|||
/* basename.c -- return the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2020 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "third_party/make/config.h"
|
||||
/**/
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/make/dirname.h"
|
||||
|
||||
/* Return the address of the last file name component of NAME. If
|
||||
NAME has no relative file name components because it is a file
|
||||
system root, return the empty string. */
|
||||
|
||||
char *
|
||||
last_component (char const *name)
|
||||
{
|
||||
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
|
||||
char const *p;
|
||||
bool saw_slash = false;
|
||||
|
||||
while (ISSLASH (*base))
|
||||
base++;
|
||||
|
||||
for (p = base; *p; p++)
|
||||
{
|
||||
if (ISSLASH (*p))
|
||||
saw_slash = true;
|
||||
else if (saw_slash)
|
||||
{
|
||||
base = p;
|
||||
saw_slash = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *) base;
|
||||
}
|
||||
|
||||
/* Return the length of the basename NAME. Typically NAME is the
|
||||
value returned by base_name or last_component. Act like strlen
|
||||
(NAME), except omit all trailing slashes. */
|
||||
|
||||
size_t
|
||||
base_len (char const *name)
|
||||
{
|
||||
size_t len;
|
||||
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
|
||||
|
||||
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
|
||||
continue;
|
||||
|
||||
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
|
||||
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
|
||||
return 2;
|
||||
|
||||
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
|
||||
&& len == prefix_len && ISSLASH (name[prefix_len]))
|
||||
return prefix_len + 1;
|
||||
|
||||
return len;
|
||||
}
|
183
third_party/make/commands.c
vendored
183
third_party/make/commands.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Command processing for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,20 +12,22 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/variable.h"
|
||||
/**/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "os.h"
|
||||
#include "dep.h"
|
||||
#include "variable.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
|
||||
#define FILE_LIST_SEPARATOR ' '
|
||||
#if VMS
|
||||
# define FILE_LIST_SEPARATOR (vms_comma_separator ? ',' : ' ')
|
||||
#else
|
||||
# define FILE_LIST_SEPARATOR ' '
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned long
|
||||
dep_hash_1 (const void *key)
|
||||
|
@ -49,10 +51,13 @@ dep_hash_cmp (const void *x, const void *y)
|
|||
return strcmp (dep_name (dx), dep_name (dy));
|
||||
}
|
||||
|
||||
/* Set FILE's automatic variables up. */
|
||||
/* Set FILE's automatic variables up.
|
||||
* Use STEM to set $*.
|
||||
* If STEM is 0, then set FILE->STEM and $* to the target name with any
|
||||
* suffix in the .SUFFIXES list stripped off. */
|
||||
|
||||
void
|
||||
set_file_variables (struct file *file)
|
||||
set_file_variables (struct file *file, const char *stem)
|
||||
{
|
||||
struct dep *d;
|
||||
const char *at, *percent, *star, *less;
|
||||
|
@ -86,7 +91,7 @@ set_file_variables (struct file *file)
|
|||
}
|
||||
|
||||
/* $* is the stem from an implicit or static pattern rule. */
|
||||
if (file->stem == 0)
|
||||
if (stem == 0)
|
||||
{
|
||||
/* In Unix make, $* is set to the target name with
|
||||
any suffix in the .SUFFIXES list stripped off for
|
||||
|
@ -109,24 +114,24 @@ set_file_variables (struct file *file)
|
|||
|
||||
for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
|
||||
{
|
||||
size_t slen = strlen (dep_name (d));
|
||||
if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
|
||||
const char *dn = dep_name (d);
|
||||
size_t slen = strlen (dn);
|
||||
if (len > slen && memcmp (dn, name + (len - slen), slen) == 0)
|
||||
{
|
||||
file->stem = strcache_add_len (name, len - slen);
|
||||
file->stem = stem = strcache_add_len (name, len - slen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d == 0)
|
||||
file->stem = "";
|
||||
file->stem = stem = "";
|
||||
}
|
||||
star = file->stem;
|
||||
star = stem;
|
||||
|
||||
/* $< is the first not order-only dependency. */
|
||||
less = "";
|
||||
for (d = file->deps; d != 0; d = d->next)
|
||||
if (!d->ignore_mtime && !d->ignore_automatic_vars)
|
||||
if (!d->ignore_mtime && !d->ignore_automatic_vars && !d->need_2nd_expansion)
|
||||
{
|
||||
if (!d->need_2nd_expansion)
|
||||
less = dep_name (d);
|
||||
break;
|
||||
}
|
||||
|
@ -205,8 +210,7 @@ set_file_variables (struct file *file)
|
|||
#endif
|
||||
len = strlen (c);
|
||||
|
||||
memcpy (cp, c, len);
|
||||
cp += len;
|
||||
cp = mempcpy (cp, c, len);
|
||||
*cp++ = FILE_LIST_SEPARATOR;
|
||||
if (! (d->changed || always_make_flag))
|
||||
qmark_len -= len + 1; /* Don't space in $? for this one. */
|
||||
|
@ -276,19 +280,16 @@ set_file_variables (struct file *file)
|
|||
|
||||
if (d->ignore_mtime)
|
||||
{
|
||||
memcpy (bp, c, len);
|
||||
bp += len;
|
||||
bp = mempcpy (bp, c, len);
|
||||
*bp++ = FILE_LIST_SEPARATOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (cp, c, len);
|
||||
cp += len;
|
||||
cp = mempcpy (cp, c, len);
|
||||
*cp++ = FILE_LIST_SEPARATOR;
|
||||
if (d->changed || always_make_flag)
|
||||
{
|
||||
memcpy (qp, c, len);
|
||||
qp += len;
|
||||
qp = mempcpy (qp, c, len);
|
||||
*qp++ = FILE_LIST_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
@ -317,14 +318,12 @@ set_file_variables (struct file *file)
|
|||
void
|
||||
chop_commands (struct commands *cmds)
|
||||
{
|
||||
unsigned int nlines;
|
||||
unsigned short idx;
|
||||
unsigned short nlines;
|
||||
unsigned short i;
|
||||
char **lines;
|
||||
|
||||
/* If we don't have any commands,
|
||||
or we already parsed them, never mind. */
|
||||
|
||||
if (!cmds || cmds->command_lines != 0)
|
||||
/* If we don't have any commands, or we already parsed them, never mind. */
|
||||
if (!cmds || cmds->command_lines != NULL)
|
||||
return;
|
||||
|
||||
/* Chop CMDS->commands up into lines in CMDS->command_lines. */
|
||||
|
@ -343,25 +342,27 @@ chop_commands (struct commands *cmds)
|
|||
}
|
||||
else
|
||||
{
|
||||
const char *p;
|
||||
const char *p = cmds->commands;
|
||||
size_t max = 5;
|
||||
|
||||
nlines = 5;
|
||||
lines = xmalloc (nlines * sizeof (char *));
|
||||
idx = 0;
|
||||
p = cmds->commands;
|
||||
nlines = 0;
|
||||
lines = xmalloc (max * sizeof (char *));
|
||||
while (*p != '\0')
|
||||
{
|
||||
const char *end = p;
|
||||
find_end:;
|
||||
end = strchr (end, '\n');
|
||||
if (end == 0)
|
||||
if (end == NULL)
|
||||
end = p + strlen (p);
|
||||
else if (end > p && end[-1] == '\\')
|
||||
{
|
||||
int backslash = 1;
|
||||
if (end > p + 1)
|
||||
{
|
||||
const char *b;
|
||||
for (b = end - 2; b >= p && *b == '\\'; --b)
|
||||
backslash = !backslash;
|
||||
}
|
||||
if (backslash)
|
||||
{
|
||||
++end;
|
||||
|
@ -369,40 +370,36 @@ chop_commands (struct commands *cmds)
|
|||
}
|
||||
}
|
||||
|
||||
if (idx == nlines)
|
||||
if (nlines == USHRT_MAX)
|
||||
ON (fatal, &cmds->fileinfo,
|
||||
_("Recipe has too many lines (limit %hu)"), nlines);
|
||||
|
||||
if (nlines == max)
|
||||
{
|
||||
nlines += 2;
|
||||
lines = xrealloc (lines, nlines * sizeof (char *));
|
||||
max += 2;
|
||||
lines = xrealloc (lines, max * sizeof (char *));
|
||||
}
|
||||
lines[idx++] = xstrndup (p, (size_t) (end - p));
|
||||
|
||||
lines[nlines++] = xstrndup (p, (size_t) (end - p));
|
||||
p = end;
|
||||
if (*p != '\0')
|
||||
++p;
|
||||
}
|
||||
|
||||
if (idx != nlines)
|
||||
{
|
||||
nlines = idx;
|
||||
lines = xrealloc (lines, nlines * sizeof (char *));
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, set the corresponding CMDS->lines_flags elements and the
|
||||
CMDS->any_recurse flag. */
|
||||
|
||||
if (nlines > USHRT_MAX)
|
||||
ON (fatal, &cmds->fileinfo, _("Recipe has too many lines (%ud)"), nlines);
|
||||
|
||||
cmds->ncommand_lines = (unsigned short)nlines;
|
||||
cmds->ncommand_lines = nlines;
|
||||
cmds->command_lines = lines;
|
||||
|
||||
cmds->any_recurse = 0;
|
||||
cmds->lines_flags = xmalloc (nlines);
|
||||
|
||||
for (idx = 0; idx < nlines; ++idx)
|
||||
for (i = 0; i < nlines; ++i)
|
||||
{
|
||||
unsigned char flags = 0;
|
||||
const char *p = lines[idx];
|
||||
const char *p = lines[i];
|
||||
|
||||
while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
|
||||
switch (*(p++))
|
||||
|
@ -419,12 +416,12 @@ chop_commands (struct commands *cmds)
|
|||
}
|
||||
|
||||
/* If no explicit '+' was given, look for MAKE variable references. */
|
||||
if (!(flags & COMMANDS_RECURSE)
|
||||
if (! ANY_SET (flags, COMMANDS_RECURSE)
|
||||
&& (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
|
||||
flags |= COMMANDS_RECURSE;
|
||||
|
||||
cmds->lines_flags[idx] = flags;
|
||||
cmds->any_recurse |= flags & COMMANDS_RECURSE ? 1 : 0;
|
||||
cmds->lines_flags[i] = flags;
|
||||
cmds->any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,12 +453,17 @@ execute_file_commands (struct file *file)
|
|||
|
||||
initialize_file_variables (file, 0);
|
||||
|
||||
set_file_variables (file);
|
||||
set_file_variables (file, file->stem);
|
||||
|
||||
/* If this is a loaded dynamic object, unload it before remaking.
|
||||
Some systems don't support overwriting a loaded object. */
|
||||
if (file->loaded)
|
||||
unload_file (file->name);
|
||||
/* Some systems don't support overwriting a loaded object so if this one
|
||||
unload it before remaking. Keep its name in .LOADED: it will be rebuilt
|
||||
and loaded again. If rebuilding or loading again fail, then we'll exit
|
||||
anyway and it won't matter. */
|
||||
if (file->loaded && unload_file (file->name) == 0)
|
||||
{
|
||||
file->loaded = 0;
|
||||
file->unloaded = 1;
|
||||
}
|
||||
|
||||
/* Start the commands running. */
|
||||
new_job (file);
|
||||
|
@ -470,17 +472,36 @@ execute_file_commands (struct file *file)
|
|||
/* This is set while we are inside fatal_error_signal,
|
||||
so things can avoid nonreentrant operations. */
|
||||
|
||||
int handling_fatal_signal = 0;
|
||||
volatile sig_atomic_t handling_fatal_signal = 0;
|
||||
|
||||
/* Handle fatal signals. */
|
||||
|
||||
RETSIGTYPE
|
||||
void
|
||||
fatal_error_signal (int sig)
|
||||
{
|
||||
#ifdef __MSDOS__
|
||||
extern int dos_status, dos_command_running;
|
||||
|
||||
if (dos_command_running)
|
||||
{
|
||||
/* That was the child who got the signal, not us. */
|
||||
dos_status |= (sig << 8);
|
||||
return;
|
||||
}
|
||||
remove_intermediates (1);
|
||||
exit (EXIT_FAILURE);
|
||||
#else /* not __MSDOS__ */
|
||||
#ifdef _AMIGA
|
||||
remove_intermediates (1);
|
||||
if (sig == SIGINT)
|
||||
fputs (_("*** Break.\n"), stderr);
|
||||
|
||||
exit (10);
|
||||
#else /* not Amiga */
|
||||
#ifdef WINDOWS32
|
||||
extern HANDLE main_thread;
|
||||
|
||||
/* Windows creates a sperate thread for handling Ctrl+C, so we need
|
||||
/* Windows creates a separate thread for handling Ctrl+C, so we need
|
||||
to suspend the main thread, or else we will have race conditions
|
||||
when both threads call reap_children. */
|
||||
if (main_thread)
|
||||
|
@ -488,12 +509,12 @@ fatal_error_signal (int sig)
|
|||
DWORD susp_count = SuspendThread (main_thread);
|
||||
|
||||
if (susp_count != 0)
|
||||
fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count);
|
||||
fprintf (stderr, "SuspendThread: suspend count = %lu\n", susp_count);
|
||||
else if (susp_count == (DWORD)-1)
|
||||
{
|
||||
DWORD ierr = GetLastError ();
|
||||
|
||||
fprintf (stderr, "SuspendThread: error %ld: %s\n",
|
||||
fprintf (stderr, "SuspendThread: error %lu: %s\n",
|
||||
ierr, map_windows32_error_to_string (ierr));
|
||||
}
|
||||
}
|
||||
|
@ -504,6 +525,10 @@ fatal_error_signal (int sig)
|
|||
It is blocked now while we run this handler. */
|
||||
signal (sig, SIG_DFL);
|
||||
|
||||
temp_stdin_unlink ();
|
||||
osync_clear ();
|
||||
jobserver_clear ();
|
||||
|
||||
/* A termination signal won't be sent to the entire
|
||||
process group, but it means we want to kill the children. */
|
||||
|
||||
|
@ -519,9 +544,12 @@ fatal_error_signal (int sig)
|
|||
wanted to kill make, remove pending targets. */
|
||||
|
||||
if (sig == SIGTERM || sig == SIGINT
|
||||
#ifdef SIGHUP
|
||||
|| sig == SIGHUP
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
|| sig == SIGQUIT
|
||||
|| sig == SIGPIPE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct child *c;
|
||||
|
@ -533,10 +561,7 @@ fatal_error_signal (int sig)
|
|||
(void) remote_kill (c->pid, sig);
|
||||
|
||||
for (c = children; c != 0; c = c->next)
|
||||
{
|
||||
delete_child_targets (c);
|
||||
delete_tmpdir (c);
|
||||
}
|
||||
|
||||
/* Clean up the children. We don't just use the call below because
|
||||
we don't want to print the "Waiting for children" message. */
|
||||
|
@ -552,10 +577,12 @@ fatal_error_signal (int sig)
|
|||
|
||||
remove_intermediates (1);
|
||||
|
||||
#ifdef SIGQUIT
|
||||
if (sig == SIGQUIT)
|
||||
/* We don't want to send ourselves SIGQUIT, because it will
|
||||
cause a core dump. Just exit instead. */
|
||||
exit (MAKE_TROUBLE);
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if (main_thread)
|
||||
|
@ -566,9 +593,11 @@ fatal_error_signal (int sig)
|
|||
#else
|
||||
/* Signal the same code; this time it will really be fatal. The signal
|
||||
will be unblocked when we return and arrive then to kill us. */
|
||||
if (kill (getpid (), sig) < 0)
|
||||
if (kill (make_pid (), sig) < 0)
|
||||
pfatal_with_name ("kill");
|
||||
#endif /* not WINDOWS32 */
|
||||
#endif /* not Amiga */
|
||||
#endif /* not __MSDOS__ */
|
||||
}
|
||||
|
||||
/* Delete FILE unless it's precious or not actually a file (phony),
|
||||
|
|
11
third_party/make/commands.h
vendored
11
third_party/make/commands.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Definition of data structures describing shell commands for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,7 +12,7 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Structure that gives the commands to make a file
|
||||
and information about where these commands came from. */
|
||||
|
@ -34,9 +34,12 @@ struct commands
|
|||
#define COMMANDS_SILENT 2 /* Silent: @. */
|
||||
#define COMMANDS_NOERROR 4 /* No errors: -. */
|
||||
|
||||
RETSIGTYPE fatal_error_signal (int sig);
|
||||
struct file;
|
||||
struct child;
|
||||
|
||||
void fatal_error_signal (int sig);
|
||||
void execute_file_commands (struct file *file);
|
||||
void print_commands (const struct commands *cmds);
|
||||
void delete_child_targets (struct child *child);
|
||||
void chop_commands (struct commands *cmds);
|
||||
void set_file_variables (struct file *file);
|
||||
void set_file_variables (struct file *file, const char *stem);
|
||||
|
|
31
third_party/make/concat-filename.c
vendored
31
third_party/make/concat-filename.c
vendored
|
@ -1,26 +1,31 @@
|
|||
/* Construct a full filename from a directory and a relative filename.
|
||||
Copyright (C) 2001-2004, 2006-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3 of the License, or any
|
||||
later version.
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This file 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.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Bruno Haible <haible@clisp.cons.org>. */
|
||||
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/make/concat-filename.h"
|
||||
#include "third_party/make/filename.h"
|
||||
#include "third_party/make/config.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Specification. */
|
||||
#include "concat-filename.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "filename.h"
|
||||
|
||||
/* Concatenate a directory filename, a relative filename and an optional
|
||||
suffix. The directory may end with the directory separator. The second
|
||||
|
|
25
third_party/make/concat-filename.h
vendored
25
third_party/make/concat-filename.h
vendored
|
@ -1,22 +1,24 @@
|
|||
/* Construct a full filename from a directory and a relative filename.
|
||||
Copyright (C) 2001-2004, 2007-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001-2004, 2007-2023 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This file 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.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _CONCAT_FILENAME_H
|
||||
#define _CONCAT_FILENAME_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -26,12 +28,15 @@ extern "C" {
|
|||
suffix. Return a freshly allocated filename. Return NULL and set errno
|
||||
upon memory allocation failure. */
|
||||
extern char *concatenated_filename (const char *directory,
|
||||
const char *filename, const char *suffix);
|
||||
const char *filename, const char *suffix)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
|
||||
|
||||
/* Concatenate a directory filename, a relative filename and an optional
|
||||
suffix. Return a freshly allocated filename. */
|
||||
extern char *xconcatenated_filename (const char *directory,
|
||||
const char *filename, const char *suffix);
|
||||
const char *filename, const char *suffix)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
|
||||
_GL_ATTRIBUTE_RETURNS_NONNULL;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
1285
third_party/make/config.h
vendored
1285
third_party/make/config.h
vendored
File diff suppressed because it is too large
Load diff
10
third_party/make/debug.h
vendored
10
third_party/make/debug.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Debugging macros and interface.
|
||||
Copyright (C) 1999-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-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
|
||||
|
@ -12,22 +12,22 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libc/intrin/likely.h"
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define DB_NONE (0x000)
|
||||
#define DB_BASIC (0x001)
|
||||
#define DB_VERBOSE (0x002)
|
||||
#define DB_JOBS (0x004)
|
||||
#define DB_IMPLICIT (0x008)
|
||||
#define DB_PRINT (0x010)
|
||||
#define DB_WHY (0x020)
|
||||
#define DB_MAKEFILES (0x100)
|
||||
|
||||
#define DB_ALL (0xfff)
|
||||
|
||||
extern int db_level;
|
||||
|
||||
#define ISDB(_l) UNLIKELY((_l)&db_level)
|
||||
#define ISDB(_l) ((_l)&db_level)
|
||||
|
||||
/* When adding macros to this list be sure to update the value of
|
||||
XGETTEXT_OPTIONS in the po/Makevars file. */
|
||||
|
|
421
third_party/make/default.c
vendored
421
third_party/make/default.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Data base of default implicit rules for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,37 +12,74 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "makeint.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "filedef.h"
|
||||
#include "variable.h"
|
||||
#include "rule.h"
|
||||
#include "dep.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
|
||||
/* Define GCC_IS_NATIVE if gcc is the native development environment on
|
||||
your system (gcc/bison/flex vs cc/yacc/lex). */
|
||||
#if defined(__MSDOS__) || defined(__EMX__)
|
||||
# define GCC_IS_NATIVE
|
||||
#endif
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "third_party/make/rule.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "libc/assert.h"
|
||||
#include "third_party/make/commands.h"
|
||||
|
||||
/* This is the default list of suffixes for suffix rules.
|
||||
'.s' must come last, so that a '.o' file will be made from
|
||||
a '.c' or '.p' or ... file rather than from a .s file. */
|
||||
|
||||
static char default_suffixes[]
|
||||
#ifdef VMS
|
||||
/* VMS should include all UNIX/POSIX + some VMS extensions */
|
||||
= ".out .exe .a .olb .hlb .tlb .mlb .ln .o .obj .c .cxx .cc .cpp .pas .p \
|
||||
.for .f .r .y .l .ym .yl .mar .s .ss .i .ii .mod .sym .def .h .info .dvi \
|
||||
.tex .texinfo .texi .txinfo .mem .hlp .brn .rnh .rno .rnt .rnx .w .ch .cweb \
|
||||
.web .com .sh .elc .el";
|
||||
#elif defined(__EMX__)
|
||||
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \
|
||||
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
|
||||
.w .ch .web .sh .elc .el .obj .exe .dll .lib";
|
||||
#else
|
||||
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \
|
||||
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
|
||||
.w .ch .web .sh .elc .el";
|
||||
#endif
|
||||
|
||||
static struct pspec default_pattern_rules[] =
|
||||
{
|
||||
#ifdef VMS
|
||||
{ "(%)", "%",
|
||||
"@if f$$search(\"$@\") .eqs. \"\" then $(LIBRARY)/CREATE/"
|
||||
"$(or "
|
||||
"$(patsubst %,TEXT,$(filter %.tlb %.TLB,$@)),"
|
||||
"$(patsubst %,HELP,$(filter %.hlb %.HLB,$@)),"
|
||||
"$(patsubst %,MACRO,$(filter %.mlb %.MLB,$@)),"
|
||||
"$(and "
|
||||
"$(patsubst %,SHARE,$(filter %.olb %.OLB,$@)),"
|
||||
"$(patsubst %,SHARE,$(filter %.exe %.EXE,$<))),"
|
||||
"OBJECT)"
|
||||
" $@\n"
|
||||
"$(AR) $(ARFLAGS) $@ $<" },
|
||||
|
||||
#else
|
||||
{ "(%)", "%",
|
||||
"$(AR) $(ARFLAGS) $@ $<" },
|
||||
#endif
|
||||
/* The X.out rules are only in BSD's default set because
|
||||
BSD Make has no null-suffix rules, so 'foo.out' and
|
||||
'foo' are the same thing. */
|
||||
#ifdef __COSMOPOLITAN__
|
||||
#ifdef VMS
|
||||
{ "%.exe", "%",
|
||||
"$(CP) $< $@" },
|
||||
|
||||
#endif
|
||||
{ "%.out", "%",
|
||||
"@rm -f $@ \n cp $< $@" },
|
||||
|
@ -58,6 +95,22 @@ static struct pspec default_pattern_rules[] =
|
|||
|
||||
static struct pspec default_terminal_rules[] =
|
||||
{
|
||||
#ifdef VMS
|
||||
|
||||
/* RCS. */
|
||||
{ "%", "%$$5lv", /* Multinet style */
|
||||
"if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" },
|
||||
{ "%", "[.$$rcs]%$$5lv", /* Multinet style */
|
||||
"if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" },
|
||||
{ "%", "%_v", /* Normal style */
|
||||
"if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" },
|
||||
{ "%", "[.rcs]%_v", /* Normal style */
|
||||
"if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" },
|
||||
|
||||
/* SCCS. */
|
||||
/* ain't no SCCS on vms */
|
||||
|
||||
#else
|
||||
/* RCS. */
|
||||
{ "%", "%,v",
|
||||
"$(CHECKOUT,v)" },
|
||||
|
@ -71,12 +124,147 @@ static struct pspec default_terminal_rules[] =
|
|||
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
|
||||
{ "%", "SCCS/s.%",
|
||||
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
|
||||
|
||||
#endif /* !VMS */
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const char *default_suffix_rules[] =
|
||||
{
|
||||
#ifdef VMS
|
||||
".o",
|
||||
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".obj",
|
||||
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".s",
|
||||
"$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".S",
|
||||
"$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".c",
|
||||
"$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".cc",
|
||||
"$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".C",
|
||||
"$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".cpp",
|
||||
"$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".f",
|
||||
"$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".m",
|
||||
"$(LINK.m) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".p",
|
||||
"$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".F",
|
||||
"$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".r",
|
||||
"$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".mod",
|
||||
"$(COMPILE.mod) -o $@ -e $@ $^",
|
||||
|
||||
".def.sym",
|
||||
"$(COMPILE.def) -o $@ $<",
|
||||
|
||||
".sh",
|
||||
"copy $< >$@",
|
||||
|
||||
".obj.exe",
|
||||
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
|
||||
".mar.exe",
|
||||
"$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
|
||||
".s.o",
|
||||
"$(COMPILE.s) -o $@ $<",
|
||||
".s.exe",
|
||||
"$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
|
||||
".c.exe",
|
||||
"$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
|
||||
".cc.exe",
|
||||
#ifdef GCC_IS_NATIVE
|
||||
"$(COMPILE.cc) $^ \n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
|
||||
#else
|
||||
"$(COMPILE.cc) $^ \n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
|
||||
".cxx.exe",
|
||||
"$(COMPILE.cxx) $^ \n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
|
||||
#endif
|
||||
".for.exe",
|
||||
"$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
|
||||
".pas.exe",
|
||||
"$(COMPILE.pas) $^ \n $(LINK.obj) $(subst .pas,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
|
||||
|
||||
".com",
|
||||
"copy $< >$@",
|
||||
|
||||
".mar.obj",
|
||||
"$(COMPILE.mar) /obj=$@ $<",
|
||||
".s.obj",
|
||||
"$(COMPILE.s) /obj=$@ $<",
|
||||
".ss.obj",
|
||||
"$(COMPILE.s) /obj=$@ $<",
|
||||
".c.i",
|
||||
"$(COMPILE.c)/prep /list=$@ $<",
|
||||
".c.s",
|
||||
"$(COMPILE.c)/noobj/machine /list=$@ $<",
|
||||
".i.s",
|
||||
"$(COMPILE.c)/noprep/noobj/machine /list=$@ $<",
|
||||
".c.obj",
|
||||
"$(COMPILE.c) /obj=$@ $<",
|
||||
".c.o",
|
||||
"$(COMPILE.c) /obj=$@ $<",
|
||||
".cc.ii",
|
||||
"$(COMPILE.cc)/prep /list=$@ $<",
|
||||
".cc.ss",
|
||||
"$(COMPILE.cc)/noobj/machine /list=$@ $<",
|
||||
".ii.ss",
|
||||
"$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<",
|
||||
".cc.obj",
|
||||
"$(COMPILE.cc) /obj=$@ $<",
|
||||
".cc.o",
|
||||
"$(COMPILE.cc) /obj=$@ $<",
|
||||
".cxx.obj",
|
||||
"$(COMPILE.cxx) /obj=$@ $<",
|
||||
".cxx.o",
|
||||
"$(COMPILE.cxx) /obj=$@ $<",
|
||||
".for.obj",
|
||||
"$(COMPILE.for) /obj=$@ $<",
|
||||
".for.o",
|
||||
"$(COMPILE.for) /obj=$@ $<",
|
||||
".pas.obj",
|
||||
"$(COMPILE.pas) /obj=$@ $<",
|
||||
".pas.o",
|
||||
"$(COMPILE.pas) /obj=$@ $<",
|
||||
|
||||
".y.c",
|
||||
"$(YACC.y) $< \n rename y_tab.c $@",
|
||||
".l.c",
|
||||
"$(LEX.l) $< \n rename lexyy.c $@",
|
||||
|
||||
".texinfo.info",
|
||||
"$(MAKEINFO) $<",
|
||||
|
||||
".tex.dvi",
|
||||
"$(TEX) $<",
|
||||
|
||||
".cpp.o",
|
||||
"$(COMPILE.cpp) $(OUTPUT_OPTION) $<",
|
||||
".f.o",
|
||||
"$(COMPILE.f) $(OUTPUT_OPTION) $<",
|
||||
".m.o",
|
||||
"$(COMPILE.m) $(OUTPUT_OPTION) $<",
|
||||
".p.o",
|
||||
"$(COMPILE.p) $(OUTPUT_OPTION) $<",
|
||||
".r.o",
|
||||
"$(COMPILE.r) $(OUTPUT_OPTION) $<",
|
||||
".mod.o",
|
||||
"$(COMPILE.mod) -o $@ $<",
|
||||
|
||||
".c.ln",
|
||||
"$(LINT.c) -C$* $<",
|
||||
".y.ln",
|
||||
"$(YACC.y) $< \n rename y_tab.c $@",
|
||||
|
||||
".l.ln",
|
||||
"@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
|
||||
|
||||
#else /* ! VMS */
|
||||
|
||||
".o",
|
||||
"$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@",
|
||||
".s",
|
||||
|
@ -138,12 +326,20 @@ static const char *default_suffix_rules[] =
|
|||
".c.ln",
|
||||
"$(LINT.c) -C$* $<",
|
||||
".y.ln",
|
||||
#ifndef __MSDOS__
|
||||
"$(YACC.y) $< \n $(LINT.c) -C$* y.tab.c \n $(RM) y.tab.c",
|
||||
#else
|
||||
"$(YACC.y) $< \n $(LINT.c) -C$* y_tab.c \n $(RM) y_tab.c",
|
||||
#endif
|
||||
".l.ln",
|
||||
"@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
|
||||
|
||||
".y.c",
|
||||
#ifndef __MSDOS__
|
||||
"$(YACC.y) $< \n mv -f y.tab.c $@",
|
||||
#else
|
||||
"$(YACC.y) $< \n mv -f y_tab.c $@",
|
||||
#endif
|
||||
".l.c",
|
||||
"@$(RM) $@ \n $(LEX.l) $< > $@",
|
||||
".ym.m",
|
||||
|
@ -197,24 +393,158 @@ static const char *default_suffix_rules[] =
|
|||
".web.tex",
|
||||
"$(WEAVE) $<",
|
||||
|
||||
#endif /* !VMS */
|
||||
|
||||
0, 0,
|
||||
};
|
||||
|
||||
static const char *default_variables[] =
|
||||
{
|
||||
#ifdef VMS
|
||||
#ifdef __ALPHA
|
||||
"ARCH", "ALPHA",
|
||||
#endif
|
||||
#ifdef __ia64
|
||||
"ARCH", "IA64",
|
||||
#endif
|
||||
#ifdef __VAX
|
||||
"ARCH", "VAX",
|
||||
#endif
|
||||
"AR", "library",
|
||||
"LIBRARY", "library",
|
||||
"ARFLAGS", "/replace",
|
||||
"AS", "macro",
|
||||
"MACRO", "macro",
|
||||
#ifdef GCC_IS_NATIVE
|
||||
"CC", "gcc",
|
||||
#else
|
||||
"CC", "cc",
|
||||
#endif
|
||||
"CD", "builtin_cd",
|
||||
"ECHO", "builtin_echo",
|
||||
#ifdef GCC_IS_NATIVE
|
||||
"C++", "gcc/plus",
|
||||
"CXX", "gcc/plus",
|
||||
#else
|
||||
"C++", "cxx",
|
||||
"CXX", "cxx",
|
||||
#ifndef __ia64
|
||||
"CXXLD", "cxxlink",
|
||||
"CXXLINK", "cxxlink",
|
||||
#else
|
||||
/* CXXLINK is not used on VMS/IA64 */
|
||||
"CXXLD", "link",
|
||||
"CXXLINK", "link",
|
||||
#endif
|
||||
#endif
|
||||
"CO", "co",
|
||||
"CPP", "$(CC) /preprocess_only",
|
||||
"FC", "fortran",
|
||||
/* System V uses these, so explicit rules using them should work.
|
||||
However, there is no way to make implicit rules use them and FC. */
|
||||
"F77", "$(FC)",
|
||||
"F77FLAGS", "$(FFLAGS)",
|
||||
"LD", "link",
|
||||
"LEX", "lex",
|
||||
"PC", "pascal",
|
||||
"YACC", "bison/yacc",
|
||||
"YFLAGS", "/Define/Verbose",
|
||||
"BISON", "bison",
|
||||
"MAKEINFO", "makeinfo",
|
||||
"TEX", "tex",
|
||||
"TEXINDEX", "texindex",
|
||||
|
||||
"RM", "delete/nolog",
|
||||
|
||||
"CSTARTUP", "",
|
||||
#ifdef GCC_IS_NATIVE
|
||||
"CRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj",
|
||||
"CXXSTARTUP", "gnu_cc_library:crtbegin.obj",
|
||||
"CXXRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj",
|
||||
"LXLIBS", ",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib",
|
||||
"LDLIBS", ",gnu_cc_library:libgcc.olb/lib",
|
||||
#else
|
||||
"CRT0", "",
|
||||
"CXXSTARTUP", "",
|
||||
"CXXRT0", "",
|
||||
"LXLIBS", "",
|
||||
"LDLIBS", "",
|
||||
#endif
|
||||
|
||||
"LINK.o", "$(LD) $(LDFLAGS)",
|
||||
"LINK.obj", "$(LD) $(LDFLAGS)",
|
||||
#ifndef GCC_IS_NATIVE
|
||||
"CXXLINK.obj", "$(CXXLD) $(LDFLAGS)",
|
||||
"COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
#endif
|
||||
"COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
"LINK.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
|
||||
"LINK.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.C", "$(COMPILE.cc)",
|
||||
"COMPILE.cpp", "$(COMPILE.cc)",
|
||||
"LINK.C", "$(LINK.cc)",
|
||||
"LINK.cpp", "$(LINK.cc)",
|
||||
"YACC.y", "$(YACC) $(YFLAGS)",
|
||||
"LEX.l", "$(LEX) $(LFLAGS)",
|
||||
"YACC.m", "$(YACC) $(YFLAGS)",
|
||||
"LEX.m", "$(LEX) $(LFLAGS) -t",
|
||||
"COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.f", "$(FC) $(FFLAGS) $(TARGET_ARCH) -c",
|
||||
"LINK.f", "$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
|
||||
"LINK.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c",
|
||||
"LINK.r", "$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.def", "$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.mod", "$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
|
||||
"LINK.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
|
||||
"COMPILE.mar", "$(MACRO) $(MACROFLAGS)",
|
||||
"COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
|
||||
"LINK.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)",
|
||||
"COMPILE.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c",
|
||||
"PREPROCESS.S", "$(CPP) $(CPPFLAGS)",
|
||||
"PREPROCESS.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F",
|
||||
"PREPROCESS.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F",
|
||||
"LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
|
||||
"MV", "rename/new_version",
|
||||
"CP", "copy",
|
||||
".LIBPATTERNS", "%.olb lib%.a",
|
||||
|
||||
#else /* !VMS */
|
||||
|
||||
"AR", "ar",
|
||||
"ARFLAGS", "rv",
|
||||
#ifdef _AIX
|
||||
/* AIX requires object file format specification: choose -Xany. */
|
||||
"ARFLAGS", "-Xany -rv",
|
||||
#else
|
||||
"ARFLAGS", "-rv",
|
||||
#endif
|
||||
"AS", "as",
|
||||
#ifdef GCC_IS_NATIVE
|
||||
"CC", "gcc",
|
||||
"CXX", "gcc",
|
||||
"OBJC", "gcc",
|
||||
#else
|
||||
"CC", "cc",
|
||||
"CXX", "g++",
|
||||
"OBJC", "cc",
|
||||
#endif
|
||||
|
||||
#ifdef MAKE_CXX
|
||||
"CXX", MAKE_CXX,
|
||||
#else
|
||||
# ifdef GCC_IS_NATIVE
|
||||
# ifdef __MSDOS__
|
||||
"CXX", "gpp", /* g++ is an invalid name on MSDOS */
|
||||
# else
|
||||
"CXX", "gcc",
|
||||
# endif /* __MSDOS__ */
|
||||
# else
|
||||
"CXX", "g++",
|
||||
# endif
|
||||
#endif
|
||||
/* This expands to $(CO) $(COFLAGS) $< $@ if $@ does not exist,
|
||||
and to the empty string if $@ does exist. */
|
||||
"CHECKOUT,v", "+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)",
|
||||
|
@ -222,11 +552,27 @@ static const char *default_variables[] =
|
|||
"COFLAGS", "",
|
||||
|
||||
"CPP", "$(CC) -E",
|
||||
#ifdef CRAY
|
||||
"CF77PPFLAGS", "-P",
|
||||
"CF77PP", "/lib/cpp",
|
||||
"CFT", "cft77",
|
||||
"CF", "cf77",
|
||||
"FC", "$(CF)",
|
||||
#else /* Not CRAY. */
|
||||
#ifdef _IBMR2
|
||||
"FC", "xlf",
|
||||
#else
|
||||
#ifdef __convex__
|
||||
"FC", "fc",
|
||||
#else
|
||||
"FC", "f77",
|
||||
#endif /* __convex__ */
|
||||
#endif /* _IBMR2 */
|
||||
/* System V uses these, so explicit rules using them should work.
|
||||
However, there is no way to make implicit rules use them and FC. */
|
||||
"F77", "$(FC)",
|
||||
"F77FLAGS", "$(FFLAGS)",
|
||||
#endif /* Cray. */
|
||||
"GET", SCCS_GET,
|
||||
"LD", "ld",
|
||||
#ifdef GCC_IS_NATIVE
|
||||
|
@ -238,8 +584,13 @@ static const char *default_variables[] =
|
|||
"M2C", "m2c",
|
||||
#ifdef pyr
|
||||
"PC", "pascal",
|
||||
#else
|
||||
#ifdef CRAY
|
||||
"PC", "PASCAL",
|
||||
"SEGLDR", "segldr",
|
||||
#else
|
||||
"PC", "pc",
|
||||
#endif /* CRAY. */
|
||||
#endif /* pyr. */
|
||||
#ifdef GCC_IS_NATIVE
|
||||
"YACC", "bison -y",
|
||||
|
@ -296,14 +647,34 @@ static const char *default_variables[] =
|
|||
"COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
|
||||
"LINK.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)",
|
||||
"COMPILE.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c",
|
||||
"PREPROCESS.S", "$(CC) -E $(CPPFLAGS)",
|
||||
"PREPROCESS.S", "$(CPP) $(CPPFLAGS)",
|
||||
"PREPROCESS.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F",
|
||||
"PREPROCESS.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F",
|
||||
"LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
|
||||
|
||||
#ifndef NO_MINUS_C_MINUS_O
|
||||
"OUTPUT_OPTION", "-o $@",
|
||||
#endif
|
||||
|
||||
#ifdef SCCS_GET_MINUS_G
|
||||
"SCCS_OUTPUT_OPTION", "-G$@",
|
||||
#endif
|
||||
|
||||
#if defined(_AMIGA)
|
||||
".LIBPATTERNS", "%.lib",
|
||||
#elif defined(__MSDOS__)
|
||||
".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a",
|
||||
#elif defined(__APPLE__)
|
||||
".LIBPATTERNS", "lib%.dylib lib%.a",
|
||||
#elif defined(__CYGWIN__) || defined(WINDOWS32)
|
||||
".LIBPATTERNS", "lib%.dll.a %.dll.a lib%.a %.lib lib%.dll %.dll",
|
||||
#else
|
||||
".LIBPATTERNS", "lib%.so lib%.a",
|
||||
#endif
|
||||
|
||||
#endif /* !VMS */
|
||||
/* Make this assignment to avoid undefined variable warnings. */
|
||||
"GNUMAKEFLAGS", "",
|
||||
GNUMAKEFLAGS_NAME, "",
|
||||
0, 0
|
||||
};
|
||||
|
||||
|
@ -336,7 +707,7 @@ set_default_suffixes (void)
|
|||
installed after. */
|
||||
|
||||
void
|
||||
install_default_suffix_rules (void)
|
||||
install_default_suffix_rules ()
|
||||
{
|
||||
const char **s;
|
||||
|
||||
|
@ -346,15 +717,17 @@ install_default_suffix_rules (void)
|
|||
for (s = default_suffix_rules; *s != 0; s += 2)
|
||||
{
|
||||
struct file *f = enter_file (strcache_add (s[0]));
|
||||
/* This function should run before any makefile is parsed. */
|
||||
assert (f->cmds == 0);
|
||||
/* Install the default rule only if there is no user defined rule. */
|
||||
if (!f->cmds)
|
||||
{
|
||||
f->cmds = xmalloc (sizeof (struct commands));
|
||||
f->cmds->fileinfo.filenm = 0;
|
||||
f->cmds->fileinfo.filenm = NULL;
|
||||
f->cmds->commands = xstrdup (s[1]);
|
||||
f->cmds->command_lines = 0;
|
||||
f->cmds->command_lines = NULL;
|
||||
f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
|
||||
f->builtin = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
37
third_party/make/dep.h
vendored
37
third_party/make/dep.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Definitions of dependency data structures for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,9 +12,8 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/* Structure used in chains of names, for parsing and globbing. */
|
||||
|
||||
|
@ -31,26 +30,32 @@ struct nameseq
|
|||
These flags are saved in the 'flags' field of each
|
||||
'struct goaldep' in the chain returned by 'read_all_makefiles'. */
|
||||
|
||||
#define RM_NOFLAG 0
|
||||
#define RM_NO_DEFAULT_GOAL (1 << 0) /* Do not set default goal. */
|
||||
#define RM_INCLUDED (1 << 1) /* Search makefile search path. */
|
||||
#define RM_DONTCARE (1 << 2) /* No error if it doesn't exist. */
|
||||
#define RM_NO_TILDE (1 << 3) /* Don't expand ~ in file name. */
|
||||
#define RM_NOFLAG 0
|
||||
|
||||
/* Structure representing one dependency of a file.
|
||||
Each struct file's 'deps' points to a chain of these, through 'next'.
|
||||
'stem' is the stem for this dep line of static pattern rule or NULL. */
|
||||
'stem' is the stem for this dep line of static pattern rule or NULL.
|
||||
explicit is set when implicit rule search is performed and the prerequisite
|
||||
does not contain %. When explicit is set the file is not intermediate. */
|
||||
|
||||
|
||||
#define DEP(_t) \
|
||||
NAMESEQ (_t); \
|
||||
struct file *file; \
|
||||
_t *shuf; \
|
||||
const char *stem; \
|
||||
unsigned int flags : 8; \
|
||||
unsigned int changed : 1; \
|
||||
unsigned int ignore_mtime : 1; \
|
||||
unsigned int staticpattern : 1; \
|
||||
unsigned int need_2nd_expansion : 1; \
|
||||
unsigned int ignore_automatic_vars : 1
|
||||
unsigned int ignore_automatic_vars : 1; \
|
||||
unsigned int is_explicit : 1; \
|
||||
unsigned int wait_here : 1
|
||||
|
||||
struct dep
|
||||
{
|
||||
|
@ -77,6 +82,7 @@ struct goaldep
|
|||
#define PARSEFS_EXISTS 0x0008
|
||||
#define PARSEFS_NOCACHE 0x0010
|
||||
#define PARSEFS_ONEWORD 0x0020
|
||||
#define PARSEFS_WAIT 0x0040
|
||||
|
||||
#define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \
|
||||
(_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f))
|
||||
|
@ -98,22 +104,21 @@ struct nameseq *ar_glob (const char *arname, const char *member_pattern, size_t
|
|||
|
||||
#define dep_name(d) ((d)->name ? (d)->name : (d)->file->name)
|
||||
|
||||
#define alloc_seq_elt(_t) xcalloc (1, sizeof (_t))
|
||||
#define alloc_seq_elt(_t) xcalloc (sizeof (_t))
|
||||
void free_ns_chain (struct nameseq *n);
|
||||
|
||||
#if defined(MAKE_MAINTAINER_MODE) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
/* Use inline to get real type-checking. */
|
||||
#define SI static inline
|
||||
SI struct nameseq *alloc_ns() { return alloc_seq_elt (struct nameseq); }
|
||||
SI struct dep *alloc_dep() { return alloc_seq_elt (struct dep); }
|
||||
SI struct goaldep *alloc_goaldep() { return alloc_seq_elt (struct goaldep); }
|
||||
SI struct nameseq *alloc_ns (void) { return alloc_seq_elt (struct nameseq); }
|
||||
SI struct dep *alloc_dep (void) { return alloc_seq_elt (struct dep); }
|
||||
SI struct goaldep *alloc_goaldep (void) { return alloc_seq_elt (struct goaldep); }
|
||||
|
||||
SI void free_ns(struct nameseq *n) { free (n); }
|
||||
SI void free_dep(struct dep *d) { free_ns ((struct nameseq *)d); }
|
||||
SI void free_goaldep(struct goaldep *g) { free_dep ((struct dep *)g); }
|
||||
|
||||
SI void free_dep_chain(struct dep *d) { free_ns_chain((struct nameseq *)d); }
|
||||
SI void free_goal_chain(struct goaldep *g) { free_dep_chain((struct dep *)g); }
|
||||
SI void free_ns (struct nameseq *n) { free (n); }
|
||||
SI void free_dep (struct dep *d) { free_ns ((struct nameseq *)d); }
|
||||
SI void free_goaldep (struct goaldep *g) { free_dep ((struct dep *)g); }
|
||||
SI void free_dep_chain (struct dep *d) { free_ns_chain((struct nameseq *)d); }
|
||||
SI void free_goal_chain (struct goaldep *g) { free_dep_chain((struct dep *)g); }
|
||||
#else
|
||||
# define alloc_ns() alloc_seq_elt (struct nameseq)
|
||||
# define alloc_dep() alloc_seq_elt (struct dep)
|
||||
|
|
1189
third_party/make/dir.c
vendored
1189
third_party/make/dir.c
vendored
File diff suppressed because it is too large
Load diff
85
third_party/make/dirname-lgpl.c
vendored
85
third_party/make/dirname-lgpl.c
vendored
|
@ -1,85 +0,0 @@
|
|||
/* dirname.c -- return all but the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2020 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "third_party/make/config.h"
|
||||
/**/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/make/dirname.h"
|
||||
|
||||
/* Return the length of the prefix of FILE that will be used by
|
||||
dir_name. If FILE is in the working directory, this returns zero
|
||||
even though 'dir_name (FILE)' will return ".". Works properly even
|
||||
if there are trailing slashes (by effectively ignoring them). */
|
||||
|
||||
size_t
|
||||
dir_len (char const *file)
|
||||
{
|
||||
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
|
||||
size_t length;
|
||||
|
||||
/* Advance prefix_length beyond important leading slashes. */
|
||||
prefix_length += (prefix_length != 0
|
||||
? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
&& ISSLASH (file[prefix_length]))
|
||||
: (ISSLASH (file[0])
|
||||
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
|
||||
? 2 : 1))
|
||||
: 0));
|
||||
|
||||
/* Strip the basename and any redundant slashes before it. */
|
||||
for (length = last_component (file) - file;
|
||||
prefix_length < length; length--)
|
||||
if (! ISSLASH (file[length - 1]))
|
||||
break;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/* In general, we can't use the builtin 'dirname' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin 'dirname' modifies its argument.
|
||||
|
||||
Return the leading directories part of FILE, allocated with malloc.
|
||||
Works properly even if there are trailing slashes (by effectively
|
||||
ignoring them). Return NULL on failure.
|
||||
|
||||
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
|
||||
lstat (base_name (FILE)); } will access the same file. Likewise,
|
||||
if the sequence { chdir (dir_name (FILE));
|
||||
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
|
||||
to "foo" in the same directory FILE was in. */
|
||||
|
||||
char *
|
||||
mdir_name (char const *file)
|
||||
{
|
||||
size_t length = dir_len (file);
|
||||
bool append_dot = (length == 0
|
||||
|| (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
&& length == FILE_SYSTEM_PREFIX_LEN (file)
|
||||
&& file[2] != '\0' && ! ISSLASH (file[2])));
|
||||
char *dir = malloc (length + append_dot + 1);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
memcpy (dir, file, length);
|
||||
if (append_dot)
|
||||
dir[length++] = '.';
|
||||
dir[length] = '\0';
|
||||
return dir;
|
||||
}
|
52
third_party/make/dirname.h
vendored
52
third_party/make/dirname.h
vendored
|
@ -1,52 +0,0 @@
|
|||
/* Take file names apart into directory and base names.
|
||||
|
||||
Copyright (C) 1998, 2001, 2003-2006, 2009-2020 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
|
||||
#ifndef DIRNAME_H_
|
||||
# define DIRNAME_H_ 1
|
||||
#include "third_party/make/filename.h"
|
||||
|
||||
# ifndef DIRECTORY_SEPARATOR
|
||||
# define DIRECTORY_SEPARATOR '/'
|
||||
# endif
|
||||
|
||||
# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
|
||||
# endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
# if GNULIB_DIRNAME
|
||||
char *base_name (char const *file) _GL_ATTRIBUTE_MALLOC;
|
||||
char *dir_name (char const *file);
|
||||
# endif
|
||||
|
||||
char *mdir_name (char const *file);
|
||||
size_t base_len (char const *file) _GL_ATTRIBUTE_PURE;
|
||||
size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE;
|
||||
char *last_component (char const *file) _GL_ATTRIBUTE_PURE;
|
||||
|
||||
bool strip_trailing_slashes (char *file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* not DIRNAME_H_ */
|
187
third_party/make/error.c
vendored
187
third_party/make/error.c
vendored
|
@ -1,187 +0,0 @@
|
|||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000-2007, 2009-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "third_party/make/config.h"
|
||||
#include "third_party/make/error.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/make/stdio.h"
|
||||
|
||||
#if !_LIBC && ENABLE_NLS
|
||||
#include "third_party/make/gettext.h"
|
||||
# define _(msgid) gettext (msgid)
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
# define USE_UNLOCKED_IO 0
|
||||
# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b)
|
||||
# define _GL_ARG_NONNULL(a)
|
||||
#else
|
||||
#include "third_party/make/getprogname.h"
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) String
|
||||
#endif
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
void (*error_print_progname) (void);
|
||||
|
||||
/* This variable is incremented each time 'error' is called. */
|
||||
unsigned int error_message_count;
|
||||
|
||||
#undef fcntl
|
||||
#define program_name getprogname ()
|
||||
#define __strerror_r strerror_r
|
||||
|
||||
/* Return non-zero if FD is open. */
|
||||
static int
|
||||
is_open (int fd)
|
||||
{
|
||||
return 0 <= fcntl (fd, F_GETFL);
|
||||
}
|
||||
|
||||
static void
|
||||
flush_stdout (void)
|
||||
{
|
||||
#if !_LIBC
|
||||
int stdout_fd;
|
||||
|
||||
# if GNULIB_FREOPEN_SAFER
|
||||
/* Use of gnulib's freopen-safer module normally ensures that
|
||||
fileno (stdout) == 1
|
||||
whenever stdout is open. */
|
||||
stdout_fd = STDOUT_FILENO;
|
||||
# else
|
||||
/* POSIX states that fileno (stdout) after fclose is unspecified. But in
|
||||
practice it is not a problem, because stdout is statically allocated and
|
||||
the fd of a FILE stream is stored as a field in its allocated memory. */
|
||||
stdout_fd = fileno (stdout);
|
||||
# endif
|
||||
/* POSIX states that fflush (stdout) after fclose is unspecified; it
|
||||
is safe in glibc, but not on all other platforms. fflush (NULL)
|
||||
is always defined, but too draconian. */
|
||||
if (0 <= stdout_fd && is_open (stdout_fd))
|
||||
#endif
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s;
|
||||
s = strerror (errnum);
|
||||
if (! s)
|
||||
s = _("Unknown system error");
|
||||
fprintf (stderr, ": %s", s);
|
||||
}
|
||||
|
||||
static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))
|
||||
error_tail (int status, int errnum, const char *message, va_list args)
|
||||
{
|
||||
vfprintf (stderr, message, args);
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
}
|
||||
|
||||
|
||||
/* Print the program name and error message MESSAGE, which is a printf-style
|
||||
format string with optional args.
|
||||
If ERRNUM is nonzero, print its corresponding system error message.
|
||||
Exit with status STATUS if it is nonzero. */
|
||||
void
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
flush_stdout ();
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
}
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
int error_one_per_line;
|
||||
|
||||
void
|
||||
error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (error_one_per_line)
|
||||
{
|
||||
static const char *old_file_name;
|
||||
static unsigned int old_line_number;
|
||||
|
||||
if (old_line_number == line_number
|
||||
&& (file_name == old_file_name
|
||||
|| (old_file_name != NULL
|
||||
&& file_name != NULL
|
||||
&& strcmp (old_file_name, file_name) == 0)))
|
||||
|
||||
/* Simply return and print nothing. */
|
||||
return;
|
||||
|
||||
old_file_name = file_name;
|
||||
old_line_number = line_number;
|
||||
}
|
||||
|
||||
flush_stdout ();
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
}
|
||||
|
||||
fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
|
||||
file_name, line_number);
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Make the weak alias. */
|
||||
# undef error
|
||||
# undef error_at_line
|
||||
weak_alias (__error, error)
|
||||
weak_alias (__error_at_line, error_at_line)
|
||||
#endif
|
75
third_party/make/error.h
vendored
75
third_party/make/error.h
vendored
|
@ -1,75 +0,0 @@
|
|||
/* Declaration for error-reporting function
|
||||
Copyright (C) 1995-1997, 2003, 2006, 2008-2020 Free Software Foundation,
|
||||
Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
#ifndef _ERROR_H
|
||||
#define _ERROR_H 1
|
||||
|
||||
/* The __attribute__ feature is available in gcc versions 2.5 and later.
|
||||
The __-protected variants of the attributes 'format' and 'printf' are
|
||||
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
|
||||
We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
|
||||
gnulib and libintl do '#define printf __printf__' when they override
|
||||
the 'printf' function. */
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
|
||||
# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
|
||||
#else
|
||||
# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
|
||||
#endif
|
||||
|
||||
/* On mingw, the flavor of printf depends on whether the extensions module
|
||||
* is in use; the check for <stdio.h> determines the witness macro. */
|
||||
#ifndef _GL_ATTRIBUTE_SPEC_PRINTF
|
||||
# if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU
|
||||
# define _GL_ATTRIBUTE_SPEC_PRINTF __gnu_printf__
|
||||
# else
|
||||
# define _GL_ATTRIBUTE_SPEC_PRINTF __printf__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Print a message with 'fprintf (stderr, FORMAT, ...)';
|
||||
if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
|
||||
If STATUS is nonzero, terminate the program with 'exit (STATUS)'. */
|
||||
|
||||
extern void error (int __status, int __errnum, const char *__format, ...)
|
||||
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 3, 4));
|
||||
|
||||
extern void error_at_line (int __status, int __errnum, const char *__fname,
|
||||
unsigned int __lineno, const char *__format, ...)
|
||||
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 5, 6));
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
extern void (*error_print_progname) (void);
|
||||
|
||||
/* This variable is incremented each time 'error' is called. */
|
||||
extern unsigned int error_message_count;
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
extern int error_one_per_line;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* error.h */
|
18
third_party/make/exitfail.c
vendored
18
third_party/make/exitfail.c
vendored
|
@ -1,18 +0,0 @@
|
|||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002-2003, 2005-2007, 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 volatile exit_failure = 1; /*TODO: this should be EXIT_FAILURE; */
|
18
third_party/make/exitfail.h
vendored
18
third_party/make/exitfail.h
vendored
|
@ -1,18 +0,0 @@
|
|||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002, 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
extern int volatile exit_failure;
|
63
third_party/make/expand.c
vendored
63
third_party/make/expand.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Variable expansion functions for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,16 +12,18 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/make/rule.h"
|
||||
#include "makeint.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "debug.h"
|
||||
#include "filedef.h"
|
||||
#include "job.h"
|
||||
#include "variable.h"
|
||||
#include "rule.h"
|
||||
|
||||
/* Initially, any errors reported when expanding strings will be reported
|
||||
against the file where the error appears. */
|
||||
|
@ -66,14 +68,14 @@ variable_buffer_output (char *ptr, const char *string, size_t length)
|
|||
ptr = variable_buffer + offset;
|
||||
}
|
||||
|
||||
memcpy (ptr, string, length);
|
||||
return ptr + length;
|
||||
return mempcpy (ptr, string, length);
|
||||
}
|
||||
|
||||
/* Return a pointer to the beginning of the variable buffer. */
|
||||
/* Return a pointer to the beginning of the variable buffer.
|
||||
This is called from main() and it should never be null afterward. */
|
||||
|
||||
static char *
|
||||
initialize_variable_output (void)
|
||||
char *
|
||||
initialize_variable_output ()
|
||||
{
|
||||
/* If we don't have a variable output buffer yet, get one. */
|
||||
|
||||
|
@ -100,6 +102,29 @@ recursively_expand_for_file (struct variable *v, struct file *file)
|
|||
struct variable_set_list *save = 0;
|
||||
int set_reading = 0;
|
||||
|
||||
/* If we're expanding to put into the environment of a shell function then
|
||||
ignore any recursion issues: for backward-compatibility we will use
|
||||
the value of the environment variable we were started with. */
|
||||
if (v->expanding && env_recursion)
|
||||
{
|
||||
size_t nl = strlen (v->name);
|
||||
char **ep;
|
||||
DB (DB_VERBOSE,
|
||||
(_("%s:%lu: not recursively expanding %s to export to shell function\n"),
|
||||
v->fileinfo.filenm, v->fileinfo.lineno, v->name));
|
||||
|
||||
/* We could create a hash for the original environment for speed, but a
|
||||
reasonably written makefile shouldn't hit this situation... */
|
||||
for (ep = environ; *ep != 0; ++ep)
|
||||
if ((*ep)[nl] == '=' && strncmp (*ep, v->name, nl) == 0)
|
||||
return xstrdup ((*ep) + nl + 1);
|
||||
|
||||
/* If there's nothing in the parent environment, use the empty string.
|
||||
This isn't quite correct since the variable should not exist at all,
|
||||
but getting that to work would be involved. */
|
||||
return xstrdup ("");
|
||||
}
|
||||
|
||||
/* Don't install a new location if this location is empty.
|
||||
This can happen for command-line variables, builtin variables, etc. */
|
||||
saved_varp = expanding_var;
|
||||
|
@ -152,7 +177,10 @@ recursively_expand_for_file (struct variable *v, struct file *file)
|
|||
|
||||
/* Expand a simple reference to variable NAME, which is LENGTH chars long. */
|
||||
|
||||
static inline char *
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#endif
|
||||
static char *
|
||||
reference_variable (char *o, const char *name, size_t length)
|
||||
{
|
||||
struct variable *v;
|
||||
|
@ -203,7 +231,7 @@ variable_expand_string (char *line, const char *string, size_t length)
|
|||
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
|
||||
|
@ -441,7 +469,6 @@ expand_argument (const char *str, const char *end)
|
|||
|
||||
r = allocated_variable_expand (tmp);
|
||||
|
||||
if (alloc)
|
||||
free (alloc);
|
||||
|
||||
return r;
|
||||
|
|
555
third_party/make/fcntl.c
vendored
555
third_party/make/fcntl.c
vendored
|
@ -1,555 +0,0 @@
|
|||
/* Provide file descriptor control.
|
||||
|
||||
Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* Written by Eric Blake <ebb9@byu.net>. */
|
||||
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "third_party/make/config.h"
|
||||
|
||||
/* Specification. */
|
||||
#include "third_party/make/fcntl.h"
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
/* Get declarations of the native Windows API functions. */
|
||||
|
||||
/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */
|
||||
#define OPEN_MAX_MAX 0x10000
|
||||
|
||||
/* Duplicate OLDFD into the first available slot of at least NEWFD,
|
||||
which must be positive, with FLAGS determining whether the duplicate
|
||||
will be inheritable. */
|
||||
static int dupfd(int oldfd, int newfd, int flags) {
|
||||
/* Mingw has no way to create an arbitrary fd. Iterate until all
|
||||
file descriptors less than newfd are filled up. */
|
||||
HANDLE curr_process = GetCurrentProcess();
|
||||
HANDLE old_handle = (HANDLE)_get_osfhandle(oldfd);
|
||||
unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
|
||||
unsigned int fds_to_close_bound = 0;
|
||||
int result;
|
||||
BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
|
||||
int mode;
|
||||
|
||||
if (newfd < 0 || getdtablesize() <= newfd) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (old_handle == INVALID_HANDLE_VALUE ||
|
||||
(mode = setmode(oldfd, O_BINARY)) == -1) {
|
||||
/* oldfd is not open, or is an unassigned standard file
|
||||
descriptor. */
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
setmode(oldfd, mode);
|
||||
flags |= mode;
|
||||
|
||||
for (;;) {
|
||||
HANDLE new_handle;
|
||||
int duplicated_fd;
|
||||
unsigned int index;
|
||||
|
||||
if (!DuplicateHandle(curr_process, /* SourceProcessHandle */
|
||||
old_handle, /* SourceHandle */
|
||||
curr_process, /* TargetProcessHandle */
|
||||
(PHANDLE)&new_handle, /* TargetHandle */
|
||||
(DWORD)0, /* DesiredAccess */
|
||||
inherit, /* InheritHandle */
|
||||
DUPLICATE_SAME_ACCESS)) /* Options */
|
||||
{
|
||||
switch (GetLastError()) {
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
errno = EMFILE;
|
||||
break;
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case ERROR_INVALID_TARGET_HANDLE:
|
||||
case ERROR_DIRECT_ACCESS_HANDLE:
|
||||
errno = EBADF;
|
||||
break;
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
case ERROR_INVALID_ACCESS:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
default:
|
||||
errno = EACCES;
|
||||
break;
|
||||
}
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
duplicated_fd = _open_osfhandle((intptr_t)new_handle, flags);
|
||||
if (duplicated_fd < 0) {
|
||||
CloseHandle(new_handle);
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (newfd <= duplicated_fd) {
|
||||
result = duplicated_fd;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the bit duplicated_fd in fds_to_close[]. */
|
||||
index = (unsigned int)duplicated_fd / CHAR_BIT;
|
||||
if (fds_to_close_bound <= index) {
|
||||
if (sizeof fds_to_close <= index) /* Need to increase OPEN_MAX_MAX. */
|
||||
abort();
|
||||
memset(fds_to_close + fds_to_close_bound, '\0',
|
||||
index + 1 - fds_to_close_bound);
|
||||
fds_to_close_bound = index + 1;
|
||||
}
|
||||
fds_to_close[index] |= 1 << ((unsigned int)duplicated_fd % CHAR_BIT);
|
||||
}
|
||||
|
||||
/* Close the previous fds that turned out to be too small. */
|
||||
{
|
||||
int saved_errno = errno;
|
||||
unsigned int duplicated_fd;
|
||||
|
||||
for (duplicated_fd = 0; duplicated_fd < fds_to_close_bound * CHAR_BIT;
|
||||
duplicated_fd++)
|
||||
if ((fds_to_close[duplicated_fd / CHAR_BIT] >>
|
||||
(duplicated_fd % CHAR_BIT)) &
|
||||
1)
|
||||
close(duplicated_fd);
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
#if REPLACE_FCHDIR
|
||||
if (0 <= result) result = _gl_register_dup(oldfd, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
#endif /* W32 */
|
||||
|
||||
/* Forward declarations, because we '#undef fcntl' in the middle of this
|
||||
compilation unit. */
|
||||
/* Our implementation of fcntl (fd, F_DUPFD, target). */
|
||||
static int rpl_fcntl_DUPFD(int fd, int target);
|
||||
/* Our implementation of fcntl (fd, F_DUPFD_CLOEXEC, target). */
|
||||
static int rpl_fcntl_DUPFD_CLOEXEC(int fd, int target);
|
||||
#ifdef __KLIBC__
|
||||
/* Adds support for fcntl on directories. */
|
||||
static int klibc_fcntl(int fd, int action, /* arg */...);
|
||||
#endif
|
||||
|
||||
/* Perform the specified ACTION on the file descriptor FD, possibly
|
||||
using the argument ARG further described below. This replacement
|
||||
handles the following actions, and forwards all others on to the
|
||||
native fcntl. An unrecognized ACTION returns -1 with errno set to
|
||||
EINVAL.
|
||||
|
||||
F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
|
||||
If successful, return the duplicate, which will be inheritable;
|
||||
otherwise return -1 and set errno.
|
||||
|
||||
F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
|
||||
target fd. If successful, return the duplicate, which will not be
|
||||
inheritable; otherwise return -1 and set errno.
|
||||
|
||||
F_GETFD - ARG need not be present. If successful, return a
|
||||
non-negative value containing the descriptor flags of FD (only
|
||||
FD_CLOEXEC is portable, but other flags may be present); otherwise
|
||||
return -1 and set errno. */
|
||||
|
||||
int fcntl_(int fd, int action, /* arg */...)
|
||||
#undef fcntl
|
||||
#ifdef __KLIBC__
|
||||
#define fcntl_ klibc_fcntl
|
||||
#endif
|
||||
{
|
||||
va_list arg;
|
||||
int result = -1;
|
||||
va_start(arg, action);
|
||||
if (action == F_DUPFD) {
|
||||
int target = va_arg(arg, int);
|
||||
result = rpl_fcntl_DUPFD(fd, target);
|
||||
}
|
||||
|
||||
else if (action == F_DUPFD_CLOEXEC) {
|
||||
int target = va_arg(arg, int);
|
||||
result = rpl_fcntl_DUPFD_CLOEXEC(fd, target);
|
||||
}
|
||||
|
||||
#if !HAVE_FCNTL
|
||||
else if (action == F_GETFD) {
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
HANDLE handle = (HANDLE)_get_osfhandle(fd);
|
||||
DWORD flags;
|
||||
if (handle == INVALID_HANDLE_VALUE ||
|
||||
GetHandleInformation(handle, &flags) == 0)
|
||||
errno = EBADF;
|
||||
else
|
||||
result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
|
||||
#else /* !W32 */
|
||||
/* Use dup2 to reject invalid file descriptors. No way to
|
||||
access this information, so punt. */
|
||||
if (0 <= dup2(fd, fd)) result = 0;
|
||||
#endif /* !W32 */
|
||||
} /* F_GETFD */
|
||||
#endif /* !HAVE_FCNTL */
|
||||
|
||||
/* Implementing F_SETFD on mingw is not trivial - there is no
|
||||
API for changing the O_NOINHERIT bit on an fd, and merely
|
||||
changing the HANDLE_FLAG_INHERIT bit on the underlying handle
|
||||
can lead to odd state. It may be possible by duplicating the
|
||||
handle, using _open_osfhandle with the right flags, then
|
||||
using dup2 to move the duplicate onto the original, but that
|
||||
is not supported for now. */
|
||||
|
||||
else {
|
||||
#if 0
|
||||
switch (action)
|
||||
{
|
||||
#ifdef F_BARRIERFSYNC /* macOS */
|
||||
case F_BARRIERFSYNC:
|
||||
#endif
|
||||
#ifdef F_CHKCLEAN /* macOS */
|
||||
case F_CHKCLEAN:
|
||||
#endif
|
||||
#ifdef F_CLOSEM /* NetBSD, HP-UX */
|
||||
case F_CLOSEM:
|
||||
#endif
|
||||
#ifdef F_FLUSH_DATA /* macOS */
|
||||
case F_FLUSH_DATA:
|
||||
#endif
|
||||
#ifdef F_FREEZE_FS /* macOS */
|
||||
case F_FREEZE_FS:
|
||||
#endif
|
||||
#ifdef F_FULLFSYNC /* macOS */
|
||||
case F_FULLFSYNC:
|
||||
#endif
|
||||
#ifdef F_GETCONFINED /* macOS */
|
||||
case F_GETCONFINED:
|
||||
#endif
|
||||
#ifdef F_GETDEFAULTPROTLEVEL /* macOS */
|
||||
case F_GETDEFAULTPROTLEVEL:
|
||||
#endif
|
||||
#ifdef F_GETFD /* POSIX */
|
||||
case F_GETFD:
|
||||
#endif
|
||||
#ifdef F_GETFL /* POSIX */
|
||||
case F_GETFL:
|
||||
#endif
|
||||
#ifdef F_GETLEASE /* Linux */
|
||||
case F_GETLEASE:
|
||||
#endif
|
||||
#ifdef F_GETNOSIGPIPE /* macOS */
|
||||
case F_GETNOSIGPIPE:
|
||||
#endif
|
||||
#ifdef F_GETOWN /* POSIX */
|
||||
case F_GETOWN:
|
||||
#endif
|
||||
#ifdef F_GETPIPE_SZ /* Linux */
|
||||
case F_GETPIPE_SZ:
|
||||
#endif
|
||||
#ifdef F_GETPROTECTIONCLASS /* macOS */
|
||||
case F_GETPROTECTIONCLASS:
|
||||
#endif
|
||||
#ifdef F_GETPROTECTIONLEVEL /* macOS */
|
||||
case F_GETPROTECTIONLEVEL:
|
||||
#endif
|
||||
#ifdef F_GET_SEALS /* Linux */
|
||||
case F_GET_SEALS:
|
||||
#endif
|
||||
#ifdef F_GETSIG /* Linux */
|
||||
case F_GETSIG:
|
||||
#endif
|
||||
#ifdef F_MAXFD /* NetBSD */
|
||||
case F_MAXFD:
|
||||
#endif
|
||||
#ifdef F_RECYCLE /* macOS */
|
||||
case F_RECYCLE:
|
||||
#endif
|
||||
#ifdef F_SETFIFOENH /* HP-UX */
|
||||
case F_SETFIFOENH:
|
||||
#endif
|
||||
#ifdef F_THAW_FS /* macOS */
|
||||
case F_THAW_FS:
|
||||
#endif
|
||||
/* These actions take no argument. */
|
||||
result = fcntl (fd, action);
|
||||
break;
|
||||
|
||||
#ifdef F_ADD_SEALS /* Linux */
|
||||
case F_ADD_SEALS:
|
||||
#endif
|
||||
#ifdef F_BADFD /* Solaris */
|
||||
case F_BADFD:
|
||||
#endif
|
||||
#ifdef F_CHECK_OPENEVT /* macOS */
|
||||
case F_CHECK_OPENEVT:
|
||||
#endif
|
||||
#ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */
|
||||
case F_DUP2FD:
|
||||
#endif
|
||||
#ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */
|
||||
case F_DUP2FD_CLOEXEC:
|
||||
#endif
|
||||
#ifdef F_DUP2FD_CLOFORK /* Solaris */
|
||||
case F_DUP2FD_CLOFORK:
|
||||
#endif
|
||||
#ifdef F_DUPFD /* POSIX */
|
||||
case F_DUPFD:
|
||||
#endif
|
||||
#ifdef F_DUPFD_CLOEXEC /* POSIX */
|
||||
case F_DUPFD_CLOEXEC:
|
||||
#endif
|
||||
#ifdef F_DUPFD_CLOFORK /* Solaris */
|
||||
case F_DUPFD_CLOFORK:
|
||||
#endif
|
||||
#ifdef F_GETXFL /* Solaris */
|
||||
case F_GETXFL:
|
||||
#endif
|
||||
#ifdef F_GLOBAL_NOCACHE /* macOS */
|
||||
case F_GLOBAL_NOCACHE:
|
||||
#endif
|
||||
#ifdef F_MAKECOMPRESSED /* macOS */
|
||||
case F_MAKECOMPRESSED:
|
||||
#endif
|
||||
#ifdef F_MOVEDATAEXTENTS /* macOS */
|
||||
case F_MOVEDATAEXTENTS:
|
||||
#endif
|
||||
#ifdef F_NOCACHE /* macOS */
|
||||
case F_NOCACHE:
|
||||
#endif
|
||||
#ifdef F_NODIRECT /* macOS */
|
||||
case F_NODIRECT:
|
||||
#endif
|
||||
#ifdef F_NOTIFY /* Linux */
|
||||
case F_NOTIFY:
|
||||
#endif
|
||||
#ifdef F_OPLKACK /* IRIX */
|
||||
case F_OPLKACK:
|
||||
#endif
|
||||
#ifdef F_OPLKREG /* IRIX */
|
||||
case F_OPLKREG:
|
||||
#endif
|
||||
#ifdef F_RDAHEAD /* macOS */
|
||||
case F_RDAHEAD:
|
||||
#endif
|
||||
#ifdef F_SETBACKINGSTORE /* macOS */
|
||||
case F_SETBACKINGSTORE:
|
||||
#endif
|
||||
#ifdef F_SETCONFINED /* macOS */
|
||||
case F_SETCONFINED:
|
||||
#endif
|
||||
#ifdef F_SETFD /* POSIX */
|
||||
case F_SETFD:
|
||||
#endif
|
||||
#ifdef F_SETFL /* POSIX */
|
||||
case F_SETFL:
|
||||
#endif
|
||||
#ifdef F_SETLEASE /* Linux */
|
||||
case F_SETLEASE:
|
||||
#endif
|
||||
#ifdef F_SETNOSIGPIPE /* macOS */
|
||||
case F_SETNOSIGPIPE:
|
||||
#endif
|
||||
#ifdef F_SETOWN /* POSIX */
|
||||
case F_SETOWN:
|
||||
#endif
|
||||
#ifdef F_SETPIPE_SZ /* Linux */
|
||||
case F_SETPIPE_SZ:
|
||||
#endif
|
||||
#ifdef F_SETPROTECTIONCLASS /* macOS */
|
||||
case F_SETPROTECTIONCLASS:
|
||||
#endif
|
||||
#ifdef F_SETSIG /* Linux */
|
||||
case F_SETSIG:
|
||||
#endif
|
||||
#ifdef F_SINGLE_WRITER /* macOS */
|
||||
case F_SINGLE_WRITER:
|
||||
#endif
|
||||
/* These actions take an 'int' argument. */
|
||||
{
|
||||
int x = va_arg (arg, int);
|
||||
result = fcntl (fd, action, x);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other actions take a pointer argument. */
|
||||
{
|
||||
void *p = va_arg (arg, void *);
|
||||
result = fcntl (fd, action, p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
}
|
||||
va_end(arg);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int rpl_fcntl_DUPFD(int fd, int target) {
|
||||
int result;
|
||||
#if !HAVE_FCNTL
|
||||
result = dupfd(fd, target, 0);
|
||||
#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
|
||||
/* Detect invalid target; needed for cygwin 1.5.x. */
|
||||
if (target < 0 || getdtablesize() <= target) {
|
||||
result = -1;
|
||||
errno = EINVAL;
|
||||
} else {
|
||||
/* Haiku alpha 2 loses fd flags on original. */
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
if (flags < 0)
|
||||
result = -1;
|
||||
else {
|
||||
result = fcntl(fd, F_DUPFD, target);
|
||||
if (0 <= result && fcntl(fd, F_SETFD, flags) == -1) {
|
||||
int saved_errno = errno;
|
||||
close(result);
|
||||
result = -1;
|
||||
errno = saved_errno;
|
||||
}
|
||||
#if REPLACE_FCHDIR
|
||||
if (0 <= result) result = _gl_register_dup(fd, result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
result = fcntl(fd, F_DUPFD, target);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static int rpl_fcntl_DUPFD_CLOEXEC(int fd, int target) {
|
||||
int result;
|
||||
#if !HAVE_FCNTL
|
||||
result = dupfd(fd, target, O_CLOEXEC);
|
||||
#else /* HAVE_FCNTL */
|
||||
#if defined __HAIKU__
|
||||
/* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets
|
||||
the FD_CLOEXEC flag on fd, not on target. Therefore avoid the
|
||||
system fcntl in this case. */
|
||||
#define have_dupfd_cloexec -1
|
||||
#else
|
||||
/* Try the system call first, if the headers claim it exists
|
||||
(that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
|
||||
may be running with a glibc that has the macro but with an
|
||||
older kernel that does not support it. Cache the
|
||||
information on whether the system call really works, but
|
||||
avoid caching failure if the corresponding F_DUPFD fails
|
||||
for any reason. 0 = unknown, 1 = yes, -1 = no. */
|
||||
static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
|
||||
if (0 <= have_dupfd_cloexec) {
|
||||
result = fcntl(fd, F_DUPFD_CLOEXEC, target);
|
||||
if (0 <= result || errno != EINVAL) {
|
||||
have_dupfd_cloexec = 1;
|
||||
#if REPLACE_FCHDIR
|
||||
if (0 <= result) result = _gl_register_dup(fd, result);
|
||||
#endif
|
||||
} else {
|
||||
result = rpl_fcntl_DUPFD(fd, target);
|
||||
if (result >= 0) have_dupfd_cloexec = -1;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
result = rpl_fcntl_DUPFD(fd, target);
|
||||
if (0 <= result && have_dupfd_cloexec == -1) {
|
||||
int flags = fcntl(result, F_GETFD);
|
||||
if (flags < 0 || fcntl(result, F_SETFD, flags | FD_CLOEXEC) == -1) {
|
||||
int saved_errno = errno;
|
||||
close(result);
|
||||
errno = saved_errno;
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_FCNTL */
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef fcntl
|
||||
|
||||
#ifdef __KLIBC__
|
||||
|
||||
static int klibc_fcntl(int fd, int action, /* arg */...) {
|
||||
va_list arg_ptr;
|
||||
int arg;
|
||||
struct stat sbuf;
|
||||
int result;
|
||||
|
||||
va_start(arg_ptr, action);
|
||||
arg = va_arg(arg_ptr, int);
|
||||
result = fcntl(fd, action, arg);
|
||||
/* EPERM for F_DUPFD, ENOTSUP for others */
|
||||
if (result == -1 && (errno == EPERM || errno == ENOTSUP) &&
|
||||
!fstat(fd, &sbuf) && S_ISDIR(sbuf.st_mode)) {
|
||||
ULONG ulMode;
|
||||
|
||||
switch (action) {
|
||||
case F_DUPFD:
|
||||
/* Find available fd */
|
||||
while (fcntl(arg, F_GETFL) != -1 || errno != EBADF) arg++;
|
||||
|
||||
result = dup2(fd, arg);
|
||||
break;
|
||||
|
||||
/* Using underlying APIs is right ? */
|
||||
case F_GETFD:
|
||||
if (DosQueryFHState(fd, &ulMode)) break;
|
||||
|
||||
result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
|
||||
break;
|
||||
|
||||
case F_SETFD:
|
||||
if (arg & ~FD_CLOEXEC) break;
|
||||
|
||||
if (DosQueryFHState(fd, &ulMode)) break;
|
||||
|
||||
if (arg & FD_CLOEXEC)
|
||||
ulMode |= OPEN_FLAGS_NOINHERIT;
|
||||
else
|
||||
ulMode &= ~OPEN_FLAGS_NOINHERIT;
|
||||
|
||||
/* Filter supported flags. */
|
||||
ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR |
|
||||
OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
|
||||
|
||||
if (DosSetFHState(fd, ulMode)) break;
|
||||
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case F_GETFL:
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case F_SETFL:
|
||||
if (arg != 0) break;
|
||||
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(arg_ptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
810
third_party/make/fcntl.h
vendored
810
third_party/make/fcntl.h
vendored
|
@ -1,810 +0,0 @@
|
|||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Like <fcntl.h>, but with non-working flags defined to 0.
|
||||
|
||||
Copyright (C) 2006-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* written by Paul Eggert */
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if defined __need_system_fcntl_h
|
||||
/* Special invocation convention. */
|
||||
|
||||
/* Needed before <sys/stat.h>.
|
||||
May also define off_t to a 64-bit type on native Windows. */
|
||||
|
||||
/* Native Windows platforms declare open(), creat() in <io.h>. */
|
||||
#if (0 || 0 || defined GNULIB_POSIXCHECK) && \
|
||||
(defined _WIN32 && !defined __CYGWIN__)
|
||||
#endif
|
||||
|
||||
#else
|
||||
/* Normal invocation convention. */
|
||||
|
||||
#ifndef _GL_FCNTL_H
|
||||
|
||||
/* Needed before <sys/stat.h>.
|
||||
May also define off_t to a 64-bit type on native Windows. */
|
||||
/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
|
||||
<fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
|
||||
But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
|
||||
extern "C" { ... } block, which leads to errors in C++ mode with the
|
||||
overridden <sys/stat.h> from gnulib. These errors are known to be gone
|
||||
with g++ version >= 4.3. */
|
||||
#if !(defined __GLIBC__ || defined __UCLIBC__) || \
|
||||
(defined __cplusplus && defined GNULIB_NAMESPACE && \
|
||||
(defined __ICC || \
|
||||
!(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
|
||||
#endif
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
|
||||
/* Native Windows platforms declare open(), creat() in <io.h>. */
|
||||
#if (0 || 0 || defined GNULIB_POSIXCHECK) && \
|
||||
(defined _WIN32 && !defined __CYGWIN__)
|
||||
#endif
|
||||
|
||||
#ifndef _GL_FCNTL_H
|
||||
#define _GL_FCNTL_H
|
||||
|
||||
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
|
||||
/* C++ compatible function declaration macros.
|
||||
Copyright (C) 2010-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
#ifndef _GL_CXXDEFS_H
|
||||
#define _GL_CXXDEFS_H
|
||||
|
||||
/* Begin/end the GNULIB_NAMESPACE namespace. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE {
|
||||
#define _GL_END_NAMESPACE }
|
||||
#else
|
||||
#define _GL_BEGIN_NAMESPACE
|
||||
#define _GL_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
/* The three most frequent use cases of these macros are:
|
||||
|
||||
* For providing a substitute for a function that is missing on some
|
||||
platforms, but is declared and works fine on the platforms on which
|
||||
it exists:
|
||||
|
||||
#if @GNULIB_FOO@
|
||||
# if !@HAVE_FOO@
|
||||
_GL_FUNCDECL_SYS (foo, ...);
|
||||
# endif
|
||||
_GL_CXXALIAS_SYS (foo, ...);
|
||||
_GL_CXXALIASWARN (foo);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
...
|
||||
#endif
|
||||
|
||||
* For providing a replacement for a function that exists on all platforms,
|
||||
but is broken/insufficient and needs to be replaced on some platforms:
|
||||
|
||||
#if @GNULIB_FOO@
|
||||
# if @REPLACE_FOO@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef foo
|
||||
# define foo rpl_foo
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (foo, ...);
|
||||
_GL_CXXALIAS_RPL (foo, ...);
|
||||
# else
|
||||
_GL_CXXALIAS_SYS (foo, ...);
|
||||
# endif
|
||||
_GL_CXXALIASWARN (foo);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
...
|
||||
#endif
|
||||
|
||||
* For providing a replacement for a function that exists on some platforms
|
||||
but is broken/insufficient and needs to be replaced on some of them and
|
||||
is additionally either missing or undeclared on some other platforms:
|
||||
|
||||
#if @GNULIB_FOO@
|
||||
# if @REPLACE_FOO@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef foo
|
||||
# define foo rpl_foo
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (foo, ...);
|
||||
_GL_CXXALIAS_RPL (foo, ...);
|
||||
# else
|
||||
# if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@
|
||||
_GL_FUNCDECL_SYS (foo, ...);
|
||||
# endif
|
||||
_GL_CXXALIAS_SYS (foo, ...);
|
||||
# endif
|
||||
_GL_CXXALIASWARN (foo);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
...
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* _GL_EXTERN_C declaration;
|
||||
performs the declaration with C linkage. */
|
||||
#if defined __cplusplus
|
||||
#define _GL_EXTERN_C extern "C"
|
||||
#else
|
||||
#define _GL_EXTERN_C extern
|
||||
#endif
|
||||
|
||||
/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes);
|
||||
declares a replacement function, named rpl_func, with the given prototype,
|
||||
consisting of return type, parameters, and attributes.
|
||||
Example:
|
||||
_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
|
||||
_GL_ARG_NONNULL ((1)));
|
||||
*/
|
||||
#define _GL_FUNCDECL_RPL(func, rettype, parameters_and_attributes) \
|
||||
_GL_FUNCDECL_RPL_1(rpl_##func, rettype, parameters_and_attributes)
|
||||
#define _GL_FUNCDECL_RPL_1(rpl_func, rettype, parameters_and_attributes) \
|
||||
_GL_EXTERN_C rettype rpl_func parameters_and_attributes
|
||||
|
||||
/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes);
|
||||
declares the system function, named func, with the given prototype,
|
||||
consisting of return type, parameters, and attributes.
|
||||
Example:
|
||||
_GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...)
|
||||
_GL_ARG_NONNULL ((1)));
|
||||
*/
|
||||
#define _GL_FUNCDECL_SYS(func, rettype, parameters_and_attributes) \
|
||||
_GL_EXTERN_C rettype func parameters_and_attributes
|
||||
|
||||
/* _GL_CXXALIAS_RPL (func, rettype, parameters);
|
||||
declares a C++ alias called GNULIB_NAMESPACE::func
|
||||
that redirects to rpl_func, if GNULIB_NAMESPACE is defined.
|
||||
Example:
|
||||
_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
|
||||
|
||||
Wrapping rpl_func in an object with an inline conversion operator
|
||||
avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is
|
||||
actually used in the program. */
|
||||
#define _GL_CXXALIAS_RPL(func, rettype, parameters) \
|
||||
_GL_CXXALIAS_RPL_1(func, rpl_##func, rettype, parameters)
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_CXXALIAS_RPL_1(func, rpl_func, rettype, parameters) \
|
||||
namespace GNULIB_NAMESPACE { \
|
||||
static const struct _gl_##func##_wrapper { \
|
||||
typedef rettype(*type) parameters; \
|
||||
\
|
||||
inline operator type() const { \
|
||||
return ::rpl_func; \
|
||||
} \
|
||||
} func = {}; \
|
||||
} \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#else
|
||||
#define _GL_CXXALIAS_RPL_1(func, rpl_func, rettype, parameters) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters);
|
||||
is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters);
|
||||
except that the C function rpl_func may have a slightly different
|
||||
declaration. A cast is used to silence the "invalid conversion" error
|
||||
that would otherwise occur. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_CXXALIAS_RPL_CAST_1(func, rpl_func, rettype, parameters) \
|
||||
namespace GNULIB_NAMESPACE { \
|
||||
static const struct _gl_##func##_wrapper { \
|
||||
typedef rettype(*type) parameters; \
|
||||
\
|
||||
inline operator type() const { \
|
||||
return reinterpret_cast<type>(::rpl_func); \
|
||||
} \
|
||||
} func = {}; \
|
||||
} \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#else
|
||||
#define _GL_CXXALIAS_RPL_CAST_1(func, rpl_func, rettype, parameters) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
/* _GL_CXXALIAS_SYS (func, rettype, parameters);
|
||||
declares a C++ alias called GNULIB_NAMESPACE::func
|
||||
that redirects to the system provided function func, if GNULIB_NAMESPACE
|
||||
is defined.
|
||||
Example:
|
||||
_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
|
||||
|
||||
Wrapping func in an object with an inline conversion operator
|
||||
avoids a reference to func unless GNULIB_NAMESPACE::func is
|
||||
actually used in the program. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_CXXALIAS_SYS(func, rettype, parameters) \
|
||||
namespace GNULIB_NAMESPACE { \
|
||||
static const struct _gl_##func##_wrapper { \
|
||||
typedef rettype(*type) parameters; \
|
||||
\
|
||||
inline operator type() const { \
|
||||
return ::func; \
|
||||
} \
|
||||
} func = {}; \
|
||||
} \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#else
|
||||
#define _GL_CXXALIAS_SYS(func, rettype, parameters) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters);
|
||||
is like _GL_CXXALIAS_SYS (func, rettype, parameters);
|
||||
except that the C function func may have a slightly different declaration.
|
||||
A cast is used to silence the "invalid conversion" error that would
|
||||
otherwise occur. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_CXXALIAS_SYS_CAST(func, rettype, parameters) \
|
||||
namespace GNULIB_NAMESPACE { \
|
||||
static const struct _gl_##func##_wrapper { \
|
||||
typedef rettype(*type) parameters; \
|
||||
\
|
||||
inline operator type() const { \
|
||||
return reinterpret_cast<type>(::func); \
|
||||
} \
|
||||
} func = {}; \
|
||||
} \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#else
|
||||
#define _GL_CXXALIAS_SYS_CAST(func, rettype, parameters) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2);
|
||||
is like _GL_CXXALIAS_SYS (func, rettype, parameters);
|
||||
except that the C function is picked among a set of overloaded functions,
|
||||
namely the one with rettype2 and parameters2. Two consecutive casts
|
||||
are used to silence the "cannot find a match" and "invalid conversion"
|
||||
errors that would otherwise occur. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
/* The outer cast must be a reinterpret_cast.
|
||||
The inner cast: When the function is defined as a set of overloaded
|
||||
functions, it works as a static_cast<>, choosing the designated variant.
|
||||
When the function is defined as a single variant, it works as a
|
||||
reinterpret_cast<>. The parenthesized cast syntax works both ways. */
|
||||
#define _GL_CXXALIAS_SYS_CAST2(func, rettype, parameters, rettype2, \
|
||||
parameters2) \
|
||||
namespace GNULIB_NAMESPACE { \
|
||||
static const struct _gl_##func##_wrapper { \
|
||||
typedef rettype(*type) parameters; \
|
||||
\
|
||||
inline operator type() const { \
|
||||
return reinterpret_cast<type>((rettype2(*) parameters2)(::func)); \
|
||||
} \
|
||||
} func = {}; \
|
||||
} \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#else
|
||||
#define _GL_CXXALIAS_SYS_CAST2(func, rettype, parameters, rettype2, \
|
||||
parameters2) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
/* _GL_CXXALIASWARN (func);
|
||||
causes a warning to be emitted when ::func is used but not when
|
||||
GNULIB_NAMESPACE::func is used. func must be defined without overloaded
|
||||
variants. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_CXXALIASWARN(func) _GL_CXXALIASWARN_1(func, GNULIB_NAMESPACE)
|
||||
#define _GL_CXXALIASWARN_1(func, namespace) _GL_CXXALIASWARN_2(func, namespace)
|
||||
/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
|
||||
we enable the warning only when not optimizing. */
|
||||
#if !__OPTIMIZE__
|
||||
#define _GL_CXXALIASWARN_2(func, namespace) \
|
||||
_GL_WARN_ON_USE(func, \
|
||||
"The symbol ::" #func " refers to the system function. " \
|
||||
"Use " #namespace "::" #func " instead.")
|
||||
#elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
|
||||
#define _GL_CXXALIASWARN_2(func, namespace) extern __typeof__(func) func
|
||||
#else
|
||||
#define _GL_CXXALIASWARN_2(func, namespace) _GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
#else
|
||||
#define _GL_CXXALIASWARN(func) _GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes);
|
||||
causes a warning to be emitted when the given overloaded variant of ::func
|
||||
is used but not when GNULIB_NAMESPACE::func is used. */
|
||||
#if defined __cplusplus && defined GNULIB_NAMESPACE
|
||||
#define _GL_CXXALIASWARN1(func, rettype, parameters_and_attributes) \
|
||||
_GL_CXXALIASWARN1_1(func, rettype, parameters_and_attributes, \
|
||||
GNULIB_NAMESPACE)
|
||||
#define _GL_CXXALIASWARN1_1(func, rettype, parameters_and_attributes, \
|
||||
namespace) \
|
||||
_GL_CXXALIASWARN1_2(func, rettype, parameters_and_attributes, namespace)
|
||||
/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
|
||||
we enable the warning only when not optimizing. */
|
||||
#if !__OPTIMIZE__
|
||||
#define _GL_CXXALIASWARN1_2(func, rettype, parameters_and_attributes, \
|
||||
namespace) \
|
||||
_GL_WARN_ON_USE_CXX(func, rettype, parameters_and_attributes, \
|
||||
"The symbol ::" #func " refers to the system function. " \
|
||||
"Use " #namespace "::" #func " instead.")
|
||||
#elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
|
||||
#define _GL_CXXALIASWARN1_2(func, rettype, parameters_and_attributes, \
|
||||
namespace) \
|
||||
extern __typeof__(func) func
|
||||
#else
|
||||
#define _GL_CXXALIASWARN1_2(func, rettype, parameters_and_attributes, \
|
||||
namespace) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
#else
|
||||
#define _GL_CXXALIASWARN1(func, rettype, parameters_and_attributes) \
|
||||
_GL_EXTERN_C int _gl_cxxalias_dummy
|
||||
#endif
|
||||
|
||||
#endif /* _GL_CXXDEFS_H */
|
||||
|
||||
/* The definition of _GL_ARG_NONNULL is copied here. */
|
||||
/* A C macro for declaring that specific arguments must not be NULL.
|
||||
Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
|
||||
that the values passed as arguments n, ..., m must be non-NULL pointers.
|
||||
n = 1 stands for the first argument, n = 2 for the second argument etc. */
|
||||
#ifndef _GL_ARG_NONNULL
|
||||
#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
|
||||
#define _GL_ARG_NONNULL(params) __attribute__((__nonnull__ params))
|
||||
#else
|
||||
#define _GL_ARG_NONNULL(params)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The definition of _GL_WARN_ON_USE is copied here. */
|
||||
/* A C macro for emitting warnings if a function is used.
|
||||
Copyright (C) 2010-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* _GL_WARN_ON_USE (function, "literal string") issues a declaration
|
||||
for FUNCTION which will then trigger a compiler warning containing
|
||||
the text of "literal string" anywhere that function is called, if
|
||||
supported by the compiler. If the compiler does not support this
|
||||
feature, the macro expands to an unused extern declaration.
|
||||
|
||||
_GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the
|
||||
attribute used in _GL_WARN_ON_USE. If the compiler does not support
|
||||
this feature, it expands to empty.
|
||||
|
||||
These macros are useful for marking a function as a potential
|
||||
portability trap, with the intent that "literal string" include
|
||||
instructions on the replacement function that should be used
|
||||
instead.
|
||||
_GL_WARN_ON_USE is for functions with 'extern' linkage.
|
||||
_GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline'
|
||||
linkage.
|
||||
|
||||
However, one of the reasons that a function is a portability trap is
|
||||
if it has the wrong signature. Declaring FUNCTION with a different
|
||||
signature in C is a compilation error, so this macro must use the
|
||||
same type as any existing declaration so that programs that avoid
|
||||
the problematic FUNCTION do not fail to compile merely because they
|
||||
included a header that poisoned the function. But this implies that
|
||||
_GL_WARN_ON_USE is only safe to use if FUNCTION is known to already
|
||||
have a declaration. Use of this macro implies that there must not
|
||||
be any other macro hiding the declaration of FUNCTION; but
|
||||
undefining FUNCTION first is part of the poisoning process anyway
|
||||
(although for symbols that are provided only via a macro, the result
|
||||
is a compilation error rather than a warning containing
|
||||
"literal string"). Also note that in C++, it is only safe to use if
|
||||
FUNCTION has no overloads.
|
||||
|
||||
For an example, it is possible to poison 'getline' by:
|
||||
[getline]) in configure.ac, which potentially defines
|
||||
HAVE_RAW_DECL_GETLINE
|
||||
- adding this code to a header that wraps the system <stdio.h>:
|
||||
#undef getline
|
||||
#if HAVE_RAW_DECL_GETLINE
|
||||
_GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but"
|
||||
"not universally present; use the gnulib module getline");
|
||||
#endif
|
||||
|
||||
It is not possible to directly poison global variables. But it is
|
||||
possible to write a wrapper accessor function, and poison that
|
||||
(less common usage, like &environ, will cause a compilation error
|
||||
rather than issue the nice warning, but the end result of informing
|
||||
the developer about their portability problem is still achieved):
|
||||
#if HAVE_RAW_DECL_ENVIRON
|
||||
static char ***
|
||||
rpl_environ (void) { return &environ; }
|
||||
_GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
|
||||
# undef environ
|
||||
# define environ (*rpl_environ ())
|
||||
#endif
|
||||
or better (avoiding contradictory use of 'static' and 'extern'):
|
||||
#if HAVE_RAW_DECL_ENVIRON
|
||||
static char ***
|
||||
_GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared")
|
||||
rpl_environ (void) { return &environ; }
|
||||
# undef environ
|
||||
# define environ (*rpl_environ ())
|
||||
#endif
|
||||
*/
|
||||
#ifndef _GL_WARN_ON_USE
|
||||
|
||||
#if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
|
||||
/* A compiler attribute is available in gcc versions 4.3.0 and later. */
|
||||
#define _GL_WARN_ON_USE(function, message) \
|
||||
extern __typeof__(function) function __attribute__((__warning__(message)))
|
||||
#define _GL_WARN_ON_USE_ATTRIBUTE(message) __attribute__((__warning__(message)))
|
||||
#elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
|
||||
/* Verify the existence of the function. */
|
||||
#define _GL_WARN_ON_USE(function, message) extern __typeof__(function) function
|
||||
#define _GL_WARN_ON_USE_ATTRIBUTE(message)
|
||||
#else /* Unsupported. */
|
||||
#define _GL_WARN_ON_USE(function, message) _GL_WARN_EXTERN_C int _gl_warn_on_use
|
||||
#define _GL_WARN_ON_USE_ATTRIBUTE(message)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string")
|
||||
is like _GL_WARN_ON_USE (function, "string"), except that the function is
|
||||
declared with the given prototype, consisting of return type, parameters,
|
||||
and attributes.
|
||||
This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
|
||||
not work in this case. */
|
||||
#ifndef _GL_WARN_ON_USE_CXX
|
||||
#if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
|
||||
#define _GL_WARN_ON_USE_CXX(function, rettype, parameters_and_attributes, msg) \
|
||||
extern rettype function parameters_and_attributes \
|
||||
__attribute__((__warning__(msg)))
|
||||
#elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
|
||||
/* Verify the existence of the function. */
|
||||
#define _GL_WARN_ON_USE_CXX(function, rettype, parameters_and_attributes, msg) \
|
||||
extern rettype function parameters_and_attributes
|
||||
#else /* Unsupported. */
|
||||
#define _GL_WARN_ON_USE_CXX(function, rettype, parameters_and_attributes, msg) \
|
||||
_GL_WARN_EXTERN_C int _gl_warn_on_use
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* _GL_WARN_EXTERN_C declaration;
|
||||
performs the declaration with C linkage. */
|
||||
#ifndef _GL_WARN_EXTERN_C
|
||||
#if defined __cplusplus
|
||||
#define _GL_WARN_EXTERN_C extern "C"
|
||||
#else
|
||||
#define _GL_WARN_EXTERN_C extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Declare overridden functions. */
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
#if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
#undef creat
|
||||
#define creat rpl_creat
|
||||
#endif
|
||||
_GL_FUNCDECL_RPL (creat, int, (const char *filename, mode_t mode)
|
||||
_GL_ARG_NONNULL ((1)));
|
||||
_GL_CXXALIAS_RPL (creat, int, (const char *filename, mode_t mode));
|
||||
#else
|
||||
_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode));
|
||||
#endif
|
||||
_GL_CXXALIASWARN (creat);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
#undef creat
|
||||
/* Assume creat is always declared. */
|
||||
_GL_WARN_ON_USE(creat, "creat is not always POSIX compliant - "
|
||||
"use gnulib module creat for portability");
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#if 1
|
||||
#if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
#undef fcntl
|
||||
#define fcntl rpl_fcntl
|
||||
#endif
|
||||
_GL_FUNCDECL_RPL(fcntl, int, (int fd, int action, ...));
|
||||
_GL_CXXALIAS_RPL(fcntl, int, (int fd, int action, ...));
|
||||
#else
|
||||
#if !1
|
||||
_GL_FUNCDECL_SYS(fcntl, int, (int fd, int action, ...));
|
||||
#endif
|
||||
_GL_CXXALIAS_SYS(fcntl, int, (int fd, int action, ...));
|
||||
#endif
|
||||
_GL_CXXALIASWARN(fcntl);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
#undef fcntl
|
||||
#if HAVE_RAW_DECL_FCNTL
|
||||
_GL_WARN_ON_USE(fcntl, "fcntl is not always POSIX compliant - "
|
||||
"use gnulib module fcntl for portability");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
#if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
#undef open
|
||||
#define open rpl_open
|
||||
#endif
|
||||
_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
|
||||
_GL_ARG_NONNULL ((1)));
|
||||
_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
|
||||
#else
|
||||
_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
|
||||
#endif
|
||||
/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a
|
||||
default argument. _GL_CXXALIASWARN does not work in this case. */
|
||||
#if !defined __hpux
|
||||
_GL_CXXALIASWARN (open);
|
||||
#endif
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
#undef open
|
||||
/* Assume open is always declared. */
|
||||
_GL_WARN_ON_USE(open, "open is not always POSIX compliant - "
|
||||
"use gnulib module open for portability");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
#if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
#undef openat
|
||||
#define openat rpl_openat
|
||||
#endif
|
||||
_GL_FUNCDECL_RPL (openat, int,
|
||||
(int fd, char const *file, int flags, /* mode_t mode */ ...)
|
||||
_GL_ARG_NONNULL ((2)));
|
||||
_GL_CXXALIAS_RPL (openat, int,
|
||||
(int fd, char const *file, int flags, /* mode_t mode */ ...));
|
||||
#else
|
||||
#if !1
|
||||
_GL_FUNCDECL_SYS (openat, int,
|
||||
(int fd, char const *file, int flags, /* mode_t mode */ ...)
|
||||
_GL_ARG_NONNULL ((2)));
|
||||
#endif
|
||||
_GL_CXXALIAS_SYS (openat, int,
|
||||
(int fd, char const *file, int flags, /* mode_t mode */ ...));
|
||||
#endif
|
||||
_GL_CXXALIASWARN (openat);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
#undef openat
|
||||
#if HAVE_RAW_DECL_OPENAT
|
||||
_GL_WARN_ON_USE(openat, "openat is not portable - "
|
||||
"use gnulib module openat for portability");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Fix up the FD_* macros, only known to be missing on mingw. */
|
||||
|
||||
#ifndef FD_CLOEXEC
|
||||
#define FD_CLOEXEC 1
|
||||
#endif
|
||||
|
||||
/* Fix up the supported F_* macros. Intentionally leave other F_*
|
||||
macros undefined. Only known to be missing on mingw. */
|
||||
|
||||
#ifndef F_DUPFD_CLOEXEC
|
||||
#define F_DUPFD_CLOEXEC 0x40000000
|
||||
/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */
|
||||
#define GNULIB_defined_F_DUPFD_CLOEXEC 1
|
||||
#else
|
||||
#define GNULIB_defined_F_DUPFD_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#ifndef F_DUPFD
|
||||
#define F_DUPFD 1
|
||||
#endif
|
||||
|
||||
#ifndef F_GETFD
|
||||
#define F_GETFD 2
|
||||
#endif
|
||||
|
||||
/* Fix up the O_* macros. */
|
||||
|
||||
#if !defined O_DIRECT && defined O_DIRECTIO
|
||||
/* Tru64 spells it 'O_DIRECTIO'. */
|
||||
#define O_DIRECT O_DIRECTIO
|
||||
#endif
|
||||
|
||||
#if !defined O_CLOEXEC && defined O_NOINHERIT
|
||||
/* Mingw spells it 'O_NOINHERIT'. */
|
||||
#define O_CLOEXEC O_NOINHERIT
|
||||
#endif
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0x40000000 /* Try to not collide with system O_* flags. */
|
||||
#define GNULIB_defined_O_CLOEXEC 1
|
||||
#else
|
||||
#define GNULIB_defined_O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#ifndef O_DIRECT
|
||||
#define O_DIRECT 0
|
||||
#endif
|
||||
|
||||
#ifndef O_DIRECTORY
|
||||
#define O_DIRECTORY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_DSYNC
|
||||
#define O_DSYNC 0
|
||||
#endif
|
||||
|
||||
#ifndef O_EXEC
|
||||
#define O_EXEC O_RDONLY /* This is often close enough in older systems. */
|
||||
#endif
|
||||
|
||||
#ifndef O_IGNORE_CTTY
|
||||
#define O_IGNORE_CTTY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NDELAY
|
||||
#define O_NDELAY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOATIME
|
||||
#define O_NOATIME 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK O_NDELAY
|
||||
#endif
|
||||
|
||||
/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero
|
||||
value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY
|
||||
or to 0 as fallback. */
|
||||
#if 0
|
||||
#if O_NONBLOCK
|
||||
#define GNULIB_defined_O_NONBLOCK 0
|
||||
#else
|
||||
#define GNULIB_defined_O_NONBLOCK 1
|
||||
#undef O_NONBLOCK
|
||||
#define O_NONBLOCK 0x40000000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef O_NOCTTY
|
||||
#define O_NOCTTY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOLINK
|
||||
#define O_NOLINK 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOLINKS
|
||||
#define O_NOLINKS 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOTRANS
|
||||
#define O_NOTRANS 0
|
||||
#endif
|
||||
|
||||
#ifndef O_RSYNC
|
||||
#define O_RSYNC 0
|
||||
#endif
|
||||
|
||||
#ifndef O_SEARCH
|
||||
#define O_SEARCH O_RDONLY /* This is often close enough in older systems. */
|
||||
#endif
|
||||
|
||||
#ifndef O_SYNC
|
||||
#define O_SYNC 0
|
||||
#endif
|
||||
|
||||
#ifndef O_TTY_INIT
|
||||
#define O_TTY_INIT 0
|
||||
#endif
|
||||
|
||||
#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
|
||||
#undef O_ACCMODE
|
||||
#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
|
||||
#endif
|
||||
|
||||
/* For systems that distinguish between text and binary I/O.
|
||||
O_BINARY is usually declared in fcntl.h */
|
||||
#if !defined O_BINARY && defined _O_BINARY
|
||||
/* For MSC-compatible compilers. */
|
||||
#define O_BINARY _O_BINARY
|
||||
#define O_TEXT _O_TEXT
|
||||
#endif
|
||||
|
||||
#if defined __BEOS__ || defined __HAIKU__
|
||||
/* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */
|
||||
#undef O_BINARY
|
||||
#undef O_TEXT
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
#endif
|
||||
|
||||
/* Fix up the AT_* macros. */
|
||||
|
||||
/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
|
||||
value exceeds INT_MAX, so its use as an int doesn't conform to the
|
||||
C standard, and GCC and Sun C complain in some cases. If the bug
|
||||
is present, undef AT_FDCWD here, so it can be redefined below. */
|
||||
#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
|
||||
#undef AT_FDCWD
|
||||
#endif
|
||||
|
||||
/* Use the same bit pattern as Solaris 9, but with the proper
|
||||
signedness. The bit pattern is important, in case this actually is
|
||||
Solaris with the above workaround. */
|
||||
#ifndef AT_FDCWD
|
||||
#define AT_FDCWD (-3041965)
|
||||
#endif
|
||||
|
||||
/* Use the same values as Solaris 9. This shouldn't matter, but
|
||||
there's no real reason to differ. */
|
||||
#ifndef AT_SYMLINK_NOFOLLOW
|
||||
#define AT_SYMLINK_NOFOLLOW 4096
|
||||
#endif
|
||||
|
||||
#ifndef AT_REMOVEDIR
|
||||
#define AT_REMOVEDIR 1
|
||||
#endif
|
||||
|
||||
/* Solaris 9 lacks these two, so just pick unique values. */
|
||||
#ifndef AT_SYMLINK_FOLLOW
|
||||
#define AT_SYMLINK_FOLLOW 2
|
||||
#endif
|
||||
|
||||
#ifndef AT_EACCESS
|
||||
#define AT_EACCESS 4
|
||||
#endif
|
||||
|
||||
#endif /* _GL_FCNTL_H */
|
||||
#endif /* _GL_FCNTL_H */
|
||||
#endif
|
114
third_party/make/fd-hook.c
vendored
114
third_party/make/fd-hook.c
vendored
|
@ -1,114 +0,0 @@
|
|||
/* Hook for making file descriptor functions close(), ioctl() extensible.
|
||||
Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
||||
Written by Bruno Haible <bruno@clisp.org>, 2009.
|
||||
|
||||
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 the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "third_party/make/config.h"
|
||||
|
||||
/* Specification. */
|
||||
#include "third_party/make/fd-hook.h"
|
||||
|
||||
/* Currently, this entire code is only needed for the handling of sockets
|
||||
on native Windows platforms. */
|
||||
#if WINDOWS_SOCKETS
|
||||
|
||||
/* The first and last link in the doubly linked list.
|
||||
Initially the list is empty. */
|
||||
static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL };
|
||||
|
||||
int
|
||||
execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary,
|
||||
int fd)
|
||||
{
|
||||
if (remaining_list == &anchor)
|
||||
/* End of list reached. */
|
||||
return primary (fd);
|
||||
else
|
||||
return remaining_list->private_close_fn (remaining_list->private_next,
|
||||
primary, fd);
|
||||
}
|
||||
|
||||
int
|
||||
execute_all_close_hooks (gl_close_fn primary, int fd)
|
||||
{
|
||||
return execute_close_hooks (anchor.private_next, primary, fd);
|
||||
}
|
||||
|
||||
int
|
||||
execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary,
|
||||
int fd, int request, void *arg)
|
||||
{
|
||||
if (remaining_list == &anchor)
|
||||
/* End of list reached. */
|
||||
return primary (fd, request, arg);
|
||||
else
|
||||
return remaining_list->private_ioctl_fn (remaining_list->private_next,
|
||||
primary, fd, request, arg);
|
||||
}
|
||||
|
||||
int
|
||||
execute_all_ioctl_hooks (gl_ioctl_fn primary,
|
||||
int fd, int request, void *arg)
|
||||
{
|
||||
return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg);
|
||||
}
|
||||
|
||||
void
|
||||
register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link)
|
||||
{
|
||||
if (close_hook == NULL)
|
||||
close_hook = execute_close_hooks;
|
||||
if (ioctl_hook == NULL)
|
||||
ioctl_hook = execute_ioctl_hooks;
|
||||
|
||||
if (link->private_next == NULL && link->private_prev == NULL)
|
||||
{
|
||||
/* Add the link to the doubly linked list. */
|
||||
link->private_next = anchor.private_next;
|
||||
link->private_prev = &anchor;
|
||||
link->private_close_fn = close_hook;
|
||||
link->private_ioctl_fn = ioctl_hook;
|
||||
anchor.private_next->private_prev = link;
|
||||
anchor.private_next = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The link is already in use. */
|
||||
if (link->private_close_fn != close_hook
|
||||
|| link->private_ioctl_fn != ioctl_hook)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unregister_fd_hook (struct fd_hook *link)
|
||||
{
|
||||
struct fd_hook *next = link->private_next;
|
||||
struct fd_hook *prev = link->private_prev;
|
||||
|
||||
if (next != NULL && prev != NULL)
|
||||
{
|
||||
/* The link is in use. Remove it from the doubly linked list. */
|
||||
prev->private_next = next;
|
||||
next->private_prev = prev;
|
||||
/* Clear the link, to mark it unused. */
|
||||
link->private_next = NULL;
|
||||
link->private_prev = NULL;
|
||||
link->private_close_fn = NULL;
|
||||
link->private_ioctl_fn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
119
third_party/make/fd-hook.h
vendored
119
third_party/make/fd-hook.h
vendored
|
@ -1,119 +0,0 @@
|
|||
/* Hook for making file descriptor functions close(), ioctl() extensible.
|
||||
Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
|
||||
#ifndef FD_HOOK_H
|
||||
#define FD_HOOK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Currently, this entire code is only needed for the handling of sockets
|
||||
on native Windows platforms. */
|
||||
#if WINDOWS_SOCKETS
|
||||
|
||||
|
||||
/* Type of function that closes FD. */
|
||||
typedef int (*gl_close_fn) (int fd);
|
||||
|
||||
/* Type of function that applies a control request to FD. */
|
||||
typedef int (*gl_ioctl_fn) (int fd, int request, void *arg);
|
||||
|
||||
/* An element of the list of file descriptor hooks.
|
||||
In CLOS (Common Lisp Object System) speak, it consists of an "around"
|
||||
method for the close() function and an "around" method for the ioctl()
|
||||
function.
|
||||
The fields of this structure are considered private. */
|
||||
struct fd_hook
|
||||
{
|
||||
/* Doubly linked list. */
|
||||
struct fd_hook *private_next;
|
||||
struct fd_hook *private_prev;
|
||||
/* Function that treats the types of FD that it knows about and calls
|
||||
execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback. */
|
||||
int (*private_close_fn) (const struct fd_hook *remaining_list,
|
||||
gl_close_fn primary,
|
||||
int fd);
|
||||
/* Function that treats the types of FD that it knows about and calls
|
||||
execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a
|
||||
fallback. */
|
||||
int (*private_ioctl_fn) (const struct fd_hook *remaining_list,
|
||||
gl_ioctl_fn primary,
|
||||
int fd, int request, void *arg);
|
||||
};
|
||||
|
||||
/* This type of function closes FD, applying special knowledge for the FD
|
||||
types it knows about, and calls
|
||||
execute_close_hooks (REMAINING_LIST, PRIMARY, FD)
|
||||
for the other FD types.
|
||||
In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
|
||||
and PRIMARY is the "primary" method for close(). */
|
||||
typedef int (*close_hook_fn) (const struct fd_hook *remaining_list,
|
||||
gl_close_fn primary,
|
||||
int fd);
|
||||
|
||||
/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method.
|
||||
Return 0 or -1, like close() would do. */
|
||||
extern int execute_close_hooks (const struct fd_hook *remaining_list,
|
||||
gl_close_fn primary,
|
||||
int fd);
|
||||
|
||||
/* Execute all close hooks, with PRIMARY as "primary" method.
|
||||
Return 0 or -1, like close() would do. */
|
||||
extern int execute_all_close_hooks (gl_close_fn primary, int fd);
|
||||
|
||||
/* This type of function applies a control request to FD, applying special
|
||||
knowledge for the FD types it knows about, and calls
|
||||
execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG)
|
||||
for the other FD types.
|
||||
In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
|
||||
and PRIMARY is the "primary" method for ioctl(). */
|
||||
typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list,
|
||||
gl_ioctl_fn primary,
|
||||
int fd, int request, void *arg);
|
||||
|
||||
/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method.
|
||||
Return 0 or -1, like ioctl() would do. */
|
||||
extern int execute_ioctl_hooks (const struct fd_hook *remaining_list,
|
||||
gl_ioctl_fn primary,
|
||||
int fd, int request, void *arg);
|
||||
|
||||
/* Execute all ioctl hooks, with PRIMARY as "primary" method.
|
||||
Return 0 or -1, like ioctl() would do. */
|
||||
extern int execute_all_ioctl_hooks (gl_ioctl_fn primary,
|
||||
int fd, int request, void *arg);
|
||||
|
||||
/* Add a function pair to the list of file descriptor hooks.
|
||||
CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change.
|
||||
The LINK variable points to a piece of memory which is guaranteed to be
|
||||
accessible until the corresponding call to unregister_fd_hook. */
|
||||
extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook,
|
||||
struct fd_hook *link);
|
||||
|
||||
/* Removes a hook from the list of file descriptor hooks. */
|
||||
extern void unregister_fd_hook (struct fd_hook *link);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FD_HOOK_H */
|
391
third_party/make/file.c
vendored
391
third_party/make/file.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Target file management for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,20 +12,20 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "third_party/make/debug.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/make/hash.h"
|
||||
#include "makeint.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
#include "variable.h"
|
||||
#include "debug.h"
|
||||
#include "hash.h"
|
||||
#include "shuffle.h"
|
||||
|
||||
|
||||
/* Remember whether snap_deps has been invoked: we need this to be sure we
|
||||
|
@ -73,23 +73,42 @@ lookup_file (const char *name)
|
|||
{
|
||||
struct file *f;
|
||||
struct file file_key;
|
||||
#ifdef VMS
|
||||
int want_vmsify;
|
||||
#ifndef WANT_CASE_SENSITIVE_TARGETS
|
||||
char *lname;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
assert (*name != '\0');
|
||||
|
||||
while (name[0] == '.'
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
&& (name[1] == '/' || name[1] == '\\')
|
||||
#else
|
||||
&& name[1] == '/'
|
||||
/* This is also done in parse_file_seq, so this is redundant
|
||||
for names read from makefiles. It is here for names passed
|
||||
on the command line. */
|
||||
#ifdef VMS
|
||||
want_vmsify = (strpbrk (name, "]>:^") != NULL);
|
||||
# ifndef WANT_CASE_SENSITIVE_TARGETS
|
||||
if (*name != '.')
|
||||
{
|
||||
const char *n;
|
||||
char *ln;
|
||||
lname = xstrdup (name);
|
||||
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
|
||||
*ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n;
|
||||
*ln = '\0';
|
||||
name = lname;
|
||||
}
|
||||
# endif
|
||||
|
||||
while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
|
||||
name += 2;
|
||||
while (name[0] == '<' && name[1] == '>' && name[2] != '\0')
|
||||
name += 2;
|
||||
#endif
|
||||
&& name[2] != '\0')
|
||||
while (name[0] == '.' && ISDIRSEP (name[1]) && name[2] != '\0')
|
||||
{
|
||||
name += 2;
|
||||
while (*name == '/'
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
|| *name == '\\'
|
||||
#endif
|
||||
)
|
||||
while (ISDIRSEP (*name))
|
||||
/* Skip following slashes: ".//foo" is "foo", not "/foo". */
|
||||
++name;
|
||||
}
|
||||
|
@ -97,10 +116,23 @@ lookup_file (const char *name)
|
|||
if (*name == '\0')
|
||||
{
|
||||
/* It was all slashes after a dot. */
|
||||
#if defined(_AMIGA)
|
||||
name = "";
|
||||
#else
|
||||
name = "./";
|
||||
#endif
|
||||
#if defined(VMS)
|
||||
/* TODO - This section is probably not needed. */
|
||||
if (want_vmsify)
|
||||
name = "[]";
|
||||
#endif
|
||||
}
|
||||
file_key.hname = name;
|
||||
f = hash_find_item (&files, &file_key);
|
||||
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
|
||||
if (*name != '.')
|
||||
free (lname);
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
|
@ -121,6 +153,24 @@ enter_file (const char *name)
|
|||
assert (*name != '\0');
|
||||
assert (! verify_flag || strcache_iscached (name));
|
||||
|
||||
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
|
||||
if (*name != '.')
|
||||
{
|
||||
const char *n;
|
||||
char *lname, *ln;
|
||||
lname = xstrdup (name);
|
||||
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
|
||||
if (isupper ((unsigned char)*n))
|
||||
*ln = tolower ((unsigned char)*n);
|
||||
else
|
||||
*ln = *n;
|
||||
|
||||
*ln = '\0';
|
||||
name = strcache_add (lname);
|
||||
free (lname);
|
||||
}
|
||||
#endif
|
||||
|
||||
file_key.hname = name;
|
||||
file_slot = (struct file **) hash_find_slot (&files, &file_key);
|
||||
f = *file_slot;
|
||||
|
@ -130,7 +180,7 @@ enter_file (const char *name)
|
|||
return f;
|
||||
}
|
||||
|
||||
new = xcalloc (1, sizeof (struct file));
|
||||
new = xcalloc (sizeof (struct file));
|
||||
new->name = new->hname = name;
|
||||
new->update_status = us_none;
|
||||
|
||||
|
@ -211,14 +261,14 @@ rehash_file (struct file *from_file, const char *to_hname)
|
|||
{
|
||||
size_t l = strlen (from_file->name);
|
||||
/* We have two sets of commands. We will go with the
|
||||
one given in the rule explicitly mentioning this name,
|
||||
one given in the rule found through directory search,
|
||||
but give a message to let the user know what's going on. */
|
||||
if (to_file->cmds->fileinfo.filenm != 0)
|
||||
error (&from_file->cmds->fileinfo,
|
||||
l + strlen (to_file->cmds->fileinfo.filenm) + INTSTR_LENGTH,
|
||||
_("Recipe was specified for file '%s' at %s:%lu,"),
|
||||
from_file->name, to_file->cmds->fileinfo.filenm,
|
||||
to_file->cmds->fileinfo.lineno);
|
||||
from_file->name, from_file->cmds->fileinfo.filenm,
|
||||
from_file->cmds->fileinfo.lineno);
|
||||
else
|
||||
error (&from_file->cmds->fileinfo, l,
|
||||
_("Recipe for file '%s' was found by implicit rule search,"),
|
||||
|
@ -229,7 +279,7 @@ rehash_file (struct file *from_file, const char *to_hname)
|
|||
from_file->name, to_hname);
|
||||
error (&from_file->cmds->fileinfo, l,
|
||||
_("Recipe for '%s' will be ignored in favor of the one for '%s'."),
|
||||
to_hname, from_file->name);
|
||||
from_file->name, to_hname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,14 +318,19 @@ rehash_file (struct file *from_file, const char *to_hname)
|
|||
|
||||
#define MERGE(field) to_file->field |= from_file->field
|
||||
MERGE (precious);
|
||||
MERGE (loaded);
|
||||
MERGE (tried_implicit);
|
||||
MERGE (updating);
|
||||
MERGE (updated);
|
||||
MERGE (is_target);
|
||||
MERGE (cmd_target);
|
||||
MERGE (phony);
|
||||
MERGE (loaded);
|
||||
/* Don't merge intermediate because this file might be pre-existing */
|
||||
MERGE (is_explicit);
|
||||
MERGE (secondary);
|
||||
MERGE (notintermediate);
|
||||
MERGE (ignore_vpath);
|
||||
MERGE (snapped);
|
||||
#undef MERGE
|
||||
|
||||
to_file->builtin = 0;
|
||||
|
@ -310,7 +365,7 @@ remove_intermediates (int sig)
|
|||
int doneany = 0;
|
||||
|
||||
/* If there's no way we will ever remove anything anyway, punt early. */
|
||||
if (question_flag || touch_flag || all_secondary)
|
||||
if (question_flag || touch_flag || all_secondary || no_intermediates)
|
||||
return;
|
||||
|
||||
if (sig && just_print_flag)
|
||||
|
@ -327,7 +382,7 @@ remove_intermediates (int sig)
|
|||
given on the command line, and it's either a -include makefile or
|
||||
it's not precious. */
|
||||
if (f->intermediate && (f->dontcare || !f->precious)
|
||||
&& !f->secondary && !f->cmd_target)
|
||||
&& !f->secondary && !f->notintermediate && !f->cmd_target)
|
||||
{
|
||||
int status;
|
||||
if (f->update_status == us_none)
|
||||
|
@ -365,7 +420,11 @@ remove_intermediates (int sig)
|
|||
}
|
||||
}
|
||||
if (status < 0)
|
||||
perror_with_name ("unlink: ", f->name);
|
||||
{
|
||||
perror_with_name ("\nunlink: ", f->name);
|
||||
/* Start printing over. */
|
||||
doneany = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -383,8 +442,7 @@ remove_intermediates (int sig)
|
|||
struct dep *
|
||||
split_prereqs (char *p)
|
||||
{
|
||||
struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL,
|
||||
PARSEFS_NONE);
|
||||
struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL, PARSEFS_WAIT);
|
||||
|
||||
if (*p)
|
||||
{
|
||||
|
@ -393,7 +451,7 @@ split_prereqs (char *p)
|
|||
struct dep *ood;
|
||||
|
||||
++p;
|
||||
ood = PARSE_SIMPLE_SEQ (&p, struct dep);
|
||||
ood = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL, PARSEFS_WAIT);
|
||||
|
||||
if (! new)
|
||||
new = ood;
|
||||
|
@ -427,7 +485,6 @@ enter_prereqs (struct dep *deps, const char *stem)
|
|||
if (stem)
|
||||
{
|
||||
const char *pattern = "%";
|
||||
char *buffer = variable_expand ("");
|
||||
struct dep *dp = deps, *dl = 0;
|
||||
|
||||
while (dp != 0)
|
||||
|
@ -447,14 +504,15 @@ enter_prereqs (struct dep *deps, const char *stem)
|
|||
if (stem[0] == '\0')
|
||||
{
|
||||
memmove (percent, percent+1, strlen (percent));
|
||||
o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
|
||||
o = variable_buffer_output (variable_buffer, nm,
|
||||
strlen (nm) + 1);
|
||||
}
|
||||
else
|
||||
o = patsubst_expand_pat (buffer, stem, pattern, nm,
|
||||
o = patsubst_expand_pat (variable_buffer, stem, pattern, nm,
|
||||
pattern+1, percent+1);
|
||||
|
||||
/* If the name expanded to the empty string, ignore it. */
|
||||
if (buffer[0] == '\0')
|
||||
if (variable_buffer[0] == '\0')
|
||||
{
|
||||
struct dep *df = dp;
|
||||
if (dp == deps)
|
||||
|
@ -466,7 +524,8 @@ enter_prereqs (struct dep *deps, const char *stem)
|
|||
}
|
||||
|
||||
/* Save the name. */
|
||||
dp->name = strcache_add_len (buffer, o - buffer);
|
||||
dp->name = strcache_add_len (variable_buffer,
|
||||
o - variable_buffer);
|
||||
}
|
||||
dp->stem = stem;
|
||||
dp->staticpattern = 1;
|
||||
|
@ -486,21 +545,29 @@ enter_prereqs (struct dep *deps, const char *stem)
|
|||
d1->file = enter_file (d1->name);
|
||||
d1->staticpattern = 0;
|
||||
d1->name = 0;
|
||||
if (!stem)
|
||||
/* This file is explicitly mentioned as a prereq. */
|
||||
d1->file->is_explicit = 1;
|
||||
}
|
||||
|
||||
return deps;
|
||||
}
|
||||
|
||||
/* Expand and parse each dependency line. */
|
||||
static void
|
||||
/* Expand and parse each dependency line.
|
||||
For each dependency of the file, make the 'struct dep' point
|
||||
at the appropriate 'struct file' (which may have to be created). */
|
||||
void
|
||||
expand_deps (struct file *f)
|
||||
{
|
||||
struct dep *d;
|
||||
struct dep **dp;
|
||||
const char *file_stem = f->stem;
|
||||
const char *fstem;
|
||||
int initialized = 0;
|
||||
int changed_dep = 0;
|
||||
|
||||
f->updating = 0;
|
||||
if (f->snapped)
|
||||
return;
|
||||
f->snapped = 1;
|
||||
|
||||
/* Walk through the dependencies. For any dependency that needs 2nd
|
||||
expansion, expand it then insert the result into the list. */
|
||||
|
@ -510,7 +577,6 @@ expand_deps (struct file *f)
|
|||
{
|
||||
char *p;
|
||||
struct dep *new, *next;
|
||||
char *name = (char *)d->name;
|
||||
|
||||
if (! d->name || ! d->need_2nd_expansion)
|
||||
{
|
||||
|
@ -520,16 +586,46 @@ expand_deps (struct file *f)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* If it's from a static pattern rule, convert the patterns into
|
||||
"$*" so they'll expand properly. */
|
||||
/* If it's from a static pattern rule, convert the initial pattern in
|
||||
each word to "$*" so they'll expand properly. */
|
||||
if (d->staticpattern)
|
||||
{
|
||||
char *o = variable_expand ("");
|
||||
o = subst_expand (o, name, "%", "$*", 1, 2, 0);
|
||||
*o = '\0';
|
||||
free (name);
|
||||
d->name = name = xstrdup (variable_buffer);
|
||||
d->staticpattern = 0;
|
||||
const char *cs = d->name;
|
||||
size_t nperc = 0;
|
||||
|
||||
/* Count the number of % in the string. */
|
||||
while ((cs = strchr (cs, '%')) != NULL)
|
||||
{
|
||||
++nperc;
|
||||
++cs;
|
||||
}
|
||||
|
||||
if (nperc)
|
||||
{
|
||||
/* Allocate enough space to replace all % with $*. */
|
||||
size_t slen = strlen (d->name) + nperc + 1;
|
||||
const char *pcs = d->name;
|
||||
char *name = xmalloc (slen);
|
||||
char *s = name;
|
||||
|
||||
/* Substitute the first % in each word. */
|
||||
cs = strchr (pcs, '%');
|
||||
|
||||
while (cs)
|
||||
{
|
||||
s = mempcpy (s, pcs, cs - pcs);
|
||||
*(s++) = '$';
|
||||
*(s++) = '*';
|
||||
pcs = ++cs;
|
||||
|
||||
/* Find the first % after the next whitespace. */
|
||||
cs = strchr (end_of_token (cs), '%');
|
||||
}
|
||||
strcpy (s, pcs);
|
||||
|
||||
free ((char*)d->name);
|
||||
d->name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're going to do second expansion so initialize file variables for
|
||||
|
@ -541,39 +637,53 @@ expand_deps (struct file *f)
|
|||
initialized = 1;
|
||||
}
|
||||
|
||||
if (d->stem != 0)
|
||||
f->stem = d->stem;
|
||||
|
||||
set_file_variables (f);
|
||||
set_file_variables (f, d->stem ? d->stem : f->stem);
|
||||
|
||||
/* Perform second expansion. */
|
||||
p = variable_expand_for_file (d->name, f);
|
||||
|
||||
if (d->stem != 0)
|
||||
f->stem = file_stem;
|
||||
|
||||
/* At this point we don't need the name anymore: free it. */
|
||||
free (name);
|
||||
/* Free the un-expanded name. */
|
||||
free ((char*)d->name);
|
||||
|
||||
/* Parse the prerequisites and enter them into the file database. */
|
||||
new = enter_prereqs (split_prereqs (p), d->stem);
|
||||
new = split_prereqs (p);
|
||||
|
||||
/* If there were no prereqs here (blank!) then throw this one out. */
|
||||
if (new == 0)
|
||||
{
|
||||
*dp = d->next;
|
||||
changed_dep = 1;
|
||||
free_dep (d);
|
||||
d = *dp;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add newly parsed prerequisites. */
|
||||
fstem = d->stem;
|
||||
next = d->next;
|
||||
changed_dep = 1;
|
||||
free_dep (d);
|
||||
*dp = new;
|
||||
for (dp = &new->next, d = new->next; d != 0; dp = &d->next, d = d->next)
|
||||
;
|
||||
for (dp = &new, d = new; d != 0; dp = &d->next, d = d->next)
|
||||
{
|
||||
d->file = lookup_file (d->name);
|
||||
if (d->file == 0)
|
||||
d->file = enter_file (d->name);
|
||||
d->name = 0;
|
||||
d->stem = fstem;
|
||||
if (!fstem)
|
||||
/* This file is explicitly mentioned as a prereq. */
|
||||
d->file->is_explicit = 1;
|
||||
}
|
||||
*dp = next;
|
||||
d = *dp;
|
||||
}
|
||||
|
||||
/* Shuffle mode assumes '->next' and '->shuf' links both traverse the same
|
||||
dependencies (in different sequences). Regenerate '->shuf' so we don't
|
||||
refer to stale data. */
|
||||
if (changed_dep)
|
||||
shuffle_deps_recursive (f->deps);
|
||||
}
|
||||
|
||||
/* Add extra prereqs to the file in question. */
|
||||
|
@ -608,10 +718,18 @@ snap_file (const void *item, void *arg)
|
|||
if (!second_expansion)
|
||||
f->updating = 0;
|
||||
|
||||
/* If .SECONDARY is set with no deps, mark all targets as intermediate. */
|
||||
if (all_secondary)
|
||||
/* More specific setting has priority. */
|
||||
|
||||
/* If .SECONDARY is set with no deps, mark all targets as intermediate,
|
||||
unless the target is a prereq of .NOTINTERMEDIATE. */
|
||||
if (all_secondary && !f->notintermediate)
|
||||
f->intermediate = 1;
|
||||
|
||||
/* If .NOTINTERMEDIATE is set with no deps, mark all targets as
|
||||
notintermediate, unless the target is a prereq of .INTERMEDIATE. */
|
||||
if (no_intermediates && !f->intermediate && !f->secondary)
|
||||
f->notintermediate = 1;
|
||||
|
||||
/* If .EXTRA_PREREQS is set, add them as ignored by automatic variables. */
|
||||
if (f->variables)
|
||||
prereqs = expand_extra_prereqs (lookup_variable_in_set (STRING_SIZE_TUPLE(".EXTRA_PREREQS"), f->variables->set));
|
||||
|
@ -642,10 +760,7 @@ snap_file (const void *item, void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
/* For each dependency of each file, make the 'struct dep' point
|
||||
at the appropriate 'struct file' (which may have to be created).
|
||||
|
||||
Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
|
||||
/* Mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
|
||||
and various other special targets. */
|
||||
|
||||
void
|
||||
|
@ -659,37 +774,6 @@ snap_deps (void)
|
|||
longer define new targets. */
|
||||
snapped_deps = 1;
|
||||
|
||||
/* Perform second expansion and enter each dependency name as a file. We
|
||||
must use hash_dump() here because within these loops we likely add new
|
||||
files to the table, possibly causing an in-situ table expansion.
|
||||
|
||||
We only need to do this if second_expansion has been defined; if it
|
||||
hasn't then all deps were expanded as the makefile was read in. If we
|
||||
ever change make to be able to unset .SECONDARY_EXPANSION this will have
|
||||
to change. */
|
||||
|
||||
if (second_expansion)
|
||||
{
|
||||
struct file **file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
|
||||
struct file **file_end = file_slot_0 + files.ht_fill;
|
||||
struct file **file_slot;
|
||||
const char *suffixes;
|
||||
|
||||
/* Expand .SUFFIXES: its prerequisites are used for $$* calc. */
|
||||
f = lookup_file (".SUFFIXES");
|
||||
suffixes = f ? f->name : 0;
|
||||
for (; f != 0; f = f->prev)
|
||||
expand_deps (f);
|
||||
|
||||
/* For every target that's not .SUFFIXES, expand its prerequisites. */
|
||||
|
||||
for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
|
||||
for (f = *file_slot; f != 0; f = f->prev)
|
||||
if (f->name != suffixes)
|
||||
expand_deps (f);
|
||||
free (file_slot_0);
|
||||
}
|
||||
|
||||
/* Now manage all the special targets. */
|
||||
|
||||
for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
|
||||
|
@ -713,10 +797,31 @@ snap_deps (void)
|
|||
f2->mtime_before_update = NONEXISTENT_MTIME;
|
||||
}
|
||||
|
||||
for (f = lookup_file (".NOTINTERMEDIATE"); f != 0; f = f->prev)
|
||||
/* Mark .NOTINTERMEDIATE deps as notintermediate files. */
|
||||
if (f->deps)
|
||||
for (d = f->deps; d != 0; d = d->next)
|
||||
for (f2 = d->file; f2 != 0; f2 = f2->prev)
|
||||
f2->notintermediate = 1;
|
||||
/* .NOTINTERMEDIATE with no deps marks all files as notintermediate. */
|
||||
else
|
||||
no_intermediates = 1;
|
||||
|
||||
/* The same file cannot be both .INTERMEDIATE and .NOTINTERMEDIATE.
|
||||
However, it is possible for a file to be .INTERMEDIATE and also match a
|
||||
.NOTINTERMEDIATE pattern. In that case, the intermediate file has
|
||||
priority over the notintermediate pattern. This priority is enforced by
|
||||
pattern_search. */
|
||||
|
||||
for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
|
||||
/* Mark .INTERMEDIATE deps as intermediate files. */
|
||||
for (d = f->deps; d != 0; d = d->next)
|
||||
for (f2 = d->file; f2 != 0; f2 = f2->prev)
|
||||
if (f2->notintermediate)
|
||||
OS (fatal, NILF,
|
||||
_("%s cannot be both .NOTINTERMEDIATE and .INTERMEDIATE"),
|
||||
f2->name);
|
||||
else
|
||||
f2->intermediate = 1;
|
||||
/* .INTERMEDIATE with no deps does nothing.
|
||||
Marking all files as intermediates is useless since the goal targets
|
||||
|
@ -727,11 +832,20 @@ snap_deps (void)
|
|||
if (f->deps)
|
||||
for (d = f->deps; d != 0; d = d->next)
|
||||
for (f2 = d->file; f2 != 0; f2 = f2->prev)
|
||||
if (f2->notintermediate)
|
||||
OS (fatal, NILF,
|
||||
_("%s cannot be both .NOTINTERMEDIATE and .SECONDARY"),
|
||||
f2->name);
|
||||
else
|
||||
f2->intermediate = f2->secondary = 1;
|
||||
/* .SECONDARY with no deps listed marks *all* files that way. */
|
||||
else
|
||||
all_secondary = 1;
|
||||
|
||||
if (no_intermediates && all_secondary)
|
||||
O (fatal, NILF,
|
||||
_(".NOTINTERMEDIATE and .SECONDARY are mutually exclusive"));
|
||||
|
||||
f = lookup_file (".EXPORT_ALL_VARIABLES");
|
||||
if (f != 0 && f->is_target)
|
||||
export_all_variables = 1;
|
||||
|
@ -760,7 +874,19 @@ snap_deps (void)
|
|||
|
||||
f = lookup_file (".NOTPARALLEL");
|
||||
if (f != 0 && f->is_target)
|
||||
{
|
||||
struct dep *d2;
|
||||
|
||||
if (!f->deps)
|
||||
not_parallel = 1;
|
||||
else
|
||||
/* Set a wait point between every prerequisite of each target. */
|
||||
for (d = f->deps; d != NULL; d = d->next)
|
||||
for (f2 = d->file; f2 != NULL; f2 = f2->prev)
|
||||
if (f2->deps)
|
||||
for (d2 = f2->deps->next; d2 != NULL; d2 = d2->next)
|
||||
d2->wait_here = 1;
|
||||
}
|
||||
|
||||
{
|
||||
struct dep *prereqs = expand_extra_prereqs (lookup_variable (STRING_SIZE_TUPLE(".EXTRA_PREREQS")));
|
||||
|
@ -812,7 +938,7 @@ file_timestamp_cons (const char *fname, time_t stamp, long int ns)
|
|||
char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
|
||||
const char *f = fname ? fname : _("Current time");
|
||||
ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
|
||||
file_timestamp_sprintf (buf, sizeof(buf), ts);
|
||||
file_timestamp_sprintf (buf, ts);
|
||||
OSS (error, NILF,
|
||||
_("%s: Timestamp out of range; substituting %s"), f, buf);
|
||||
}
|
||||
|
@ -832,6 +958,8 @@ file_timestamp_now (int *resolution)
|
|||
/* Don't bother with high-resolution clocks if file timestamps have
|
||||
only one-second resolution. The code below should work, but it's
|
||||
not worth the hassle of debugging it on hosts where it fails. */
|
||||
#if FILE_TIMESTAMP_HI_RES
|
||||
# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
|
||||
{
|
||||
struct timespec timespec;
|
||||
if (clock_gettime (CLOCK_REALTIME, ×pec) == 0)
|
||||
|
@ -842,6 +970,8 @@ file_timestamp_now (int *resolution)
|
|||
goto got_time;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
# if HAVE_GETTIMEOFDAY
|
||||
{
|
||||
struct timeval timeval;
|
||||
if (gettimeofday (&timeval, 0) == 0)
|
||||
|
@ -852,12 +982,16 @@ file_timestamp_now (int *resolution)
|
|||
goto got_time;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
r = 1000000000;
|
||||
s = time ((time_t *) 0);
|
||||
ns = 0;
|
||||
|
||||
#if FILE_TIMESTAMP_HI_RES
|
||||
got_time:
|
||||
#endif
|
||||
*resolution = r;
|
||||
return file_timestamp_cons (0, s, ns);
|
||||
}
|
||||
|
@ -865,37 +999,30 @@ file_timestamp_now (int *resolution)
|
|||
/* Place into the buffer P a printable representation of the file
|
||||
timestamp TS. */
|
||||
void
|
||||
file_timestamp_sprintf (char *p, int n, FILE_TIMESTAMP ts)
|
||||
file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
|
||||
{
|
||||
/*
|
||||
* [jart] patch weakness upstream because buffer can probably overflow
|
||||
* if integer timestamp is irreguular
|
||||
*/
|
||||
int m;
|
||||
time_t t = FILE_TIMESTAMP_S (ts);
|
||||
struct tm *tm = localtime (&t);
|
||||
|
||||
if (tm)
|
||||
snprintf (p, n, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
{
|
||||
intmax_t year = tm->tm_year;
|
||||
sprintf (p, "%04" PRIdMAX "-%02d-%02d %02d:%02d:%02d",
|
||||
year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
else if (t < 0)
|
||||
snprintf (p, n, "%ld", (long) t);
|
||||
sprintf (p, "%" PRIdMAX, (intmax_t) t);
|
||||
else
|
||||
snprintf (p, n, "%lu", (unsigned long) t);
|
||||
m = strlen (p);
|
||||
p += m;
|
||||
n -= m;
|
||||
if (n <= 0) return;
|
||||
sprintf (p, "%" PRIuMAX, (uintmax_t) t);
|
||||
p += strlen (p);
|
||||
|
||||
/* Append nanoseconds as a fraction, but remove trailing zeros. We don't
|
||||
know the actual timestamp resolution, since clock_getres applies only to
|
||||
local times, whereas this timestamp might come from a remote filesystem.
|
||||
So removing trailing zeros is the best guess that we can do. */
|
||||
snprintf (p, n, ".%09d", FILE_TIMESTAMP_NS (ts));
|
||||
m = strlen (p) - 1;
|
||||
p += m;
|
||||
n += m;
|
||||
sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
|
||||
p += strlen (p) - 1;
|
||||
while (*p == '0')
|
||||
p--;
|
||||
p += *p != '.';
|
||||
|
@ -913,17 +1040,17 @@ print_prereqs (const struct dep *deps)
|
|||
/* Print all normal dependencies; note any order-only deps. */
|
||||
for (; deps != 0; deps = deps->next)
|
||||
if (! deps->ignore_mtime)
|
||||
printf (" %s", dep_name (deps));
|
||||
printf (" %s%s", deps->wait_here ? ".WAIT " : "", dep_name (deps));
|
||||
else if (! ood)
|
||||
ood = deps;
|
||||
|
||||
/* Print order-only deps, if we have any. */
|
||||
if (ood)
|
||||
{
|
||||
printf (" | %s", dep_name (ood));
|
||||
printf (" | %s%s", ood->wait_here ? ".WAIT " : "", dep_name (ood));
|
||||
for (ood = ood->next; ood != 0; ood = ood->next)
|
||||
if (ood->ignore_mtime)
|
||||
printf (" %s", dep_name (ood));
|
||||
printf (" %s%s", ood->wait_here ? ".WAIT " : "", dep_name (ood));
|
||||
}
|
||||
|
||||
putchar ('\n');
|
||||
|
@ -977,6 +1104,10 @@ print_file (const void *item)
|
|||
printf (_("# Implicit/static pattern stem: '%s'\n"), f->stem);
|
||||
if (f->intermediate)
|
||||
puts (_("# File is an intermediate prerequisite."));
|
||||
if (f->notintermediate)
|
||||
puts (_("# File is a prerequisite of .NOTINTERMEDIATE."));
|
||||
if (f->secondary)
|
||||
puts (_("# File is secondary (prerequisite of .SECONDARY)."));
|
||||
if (f->also_make != 0)
|
||||
{
|
||||
const struct dep *d;
|
||||
|
@ -994,7 +1125,7 @@ print_file (const void *item)
|
|||
else
|
||||
{
|
||||
char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
|
||||
file_timestamp_sprintf (buf, sizeof(buf), f->last_mtime);
|
||||
file_timestamp_sprintf (buf, f->last_mtime);
|
||||
printf (_("# Last modified %s\n"), buf);
|
||||
}
|
||||
puts (f->updated
|
||||
|
@ -1124,8 +1255,7 @@ build_target_list (char *value)
|
|||
p = &value[off];
|
||||
}
|
||||
|
||||
memcpy (p, f->name, l);
|
||||
p += l;
|
||||
p = mempcpy (p, f->name, l);
|
||||
*(p++) = ' ';
|
||||
}
|
||||
*(p-1) = '\0';
|
||||
|
@ -1139,8 +1269,7 @@ build_target_list (char *value)
|
|||
void
|
||||
init_hash_files (void)
|
||||
{
|
||||
// [jart] increased from 1000
|
||||
hash_init (&files, 32768, file_hash_1, file_hash_2, file_hash_cmp);
|
||||
hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
24
third_party/make/filedef.h
vendored
24
third_party/make/filedef.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Definition of target file data structures for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,13 +12,14 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
/* Structure that represents the info on one file
|
||||
that the makefile says how to make.
|
||||
All of these are chained together through 'next'. */
|
||||
|
||||
#include "third_party/make/hash.h"
|
||||
#include "hash.h"
|
||||
|
||||
struct commands;
|
||||
struct dep;
|
||||
|
@ -62,8 +63,6 @@ struct file
|
|||
FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */
|
||||
FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating
|
||||
has been performed. */
|
||||
FILE_TIMESTAMP touched; /* Set if file was created in order for
|
||||
Landlock LSM to sandbox it. */
|
||||
unsigned int considered; /* equal to 'considered' if file has been
|
||||
considered on current scan of goal chain */
|
||||
int command_flags; /* Flags OR'd in for cmds; see commands.h. */
|
||||
|
@ -85,6 +84,7 @@ struct file
|
|||
unsigned int builtin:1; /* True if the file is a builtin rule. */
|
||||
unsigned int precious:1; /* Non-0 means don't delete file on quit */
|
||||
unsigned int loaded:1; /* True if the file is a loaded object. */
|
||||
unsigned int unloaded:1; /* True if this loaded object was unloaded. */
|
||||
unsigned int low_resolution_time:1; /* Nonzero if this file's time stamp
|
||||
has only one-second resolution. */
|
||||
unsigned int tried_implicit:1; /* Nonzero if have searched
|
||||
|
@ -97,8 +97,11 @@ struct file
|
|||
unsigned int phony:1; /* Nonzero if this is a phony file
|
||||
i.e., a prerequisite of .PHONY. */
|
||||
unsigned int intermediate:1;/* Nonzero if this is an intermediate file. */
|
||||
unsigned int is_explicit:1; /* Nonzero if explicitly mentioned. */
|
||||
unsigned int secondary:1; /* Nonzero means remove_intermediates should
|
||||
not delete it. */
|
||||
unsigned int notintermediate:1; /* Nonzero means a file is a prereq to
|
||||
.NOTINTERMEDIATE. */
|
||||
unsigned int dontcare:1; /* Nonzero if no complaint is to be made if
|
||||
this target cannot be remade. */
|
||||
unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name. */
|
||||
|
@ -106,6 +109,10 @@ struct file
|
|||
pattern-specific variables. */
|
||||
unsigned int no_diag:1; /* True if the file failed to update and no
|
||||
diagnostics has been issued (dontcare). */
|
||||
unsigned int was_shuffled:1; /* Did we already shuffle 'deps'? used when
|
||||
--shuffle passes through the graph. */
|
||||
unsigned int snapped:1; /* True if the deps of this file have been
|
||||
secondary expanded. */
|
||||
};
|
||||
|
||||
|
||||
|
@ -116,6 +123,7 @@ struct file *lookup_file (const char *name);
|
|||
struct file *enter_file (const char *name);
|
||||
struct dep *split_prereqs (char *prereqstr);
|
||||
struct dep *enter_prereqs (struct dep *prereqs, const char *stem);
|
||||
void expand_deps (struct file *f);
|
||||
struct dep *expand_extra_prereqs (const struct variable *extra);
|
||||
void remove_intermediates (int sig);
|
||||
void snap_deps (void);
|
||||
|
@ -165,14 +173,14 @@ int stemlen_compare (const void *v1, const void *v2);
|
|||
add 4 to allow for any 4-digit epoch year (e.g. 1970);
|
||||
add 25 to allow for "-MM-DD HH:MM:SS.NNNNNNNNN". */
|
||||
#define FLOOR_LOG2_SECONDS_PER_YEAR 24
|
||||
#define FILE_TIMESTAMP_PRINT_LEN_BOUND /* 62 */ \
|
||||
#define FILE_TIMESTAMP_PRINT_LEN_BOUND \
|
||||
(((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \
|
||||
* 302 / 1000) \
|
||||
+ 1 + 1 + 4 + 25)
|
||||
|
||||
FILE_TIMESTAMP file_timestamp_cons (char const *, time_t, long int);
|
||||
FILE_TIMESTAMP file_timestamp_now (int *);
|
||||
void file_timestamp_sprintf (char *, int, FILE_TIMESTAMP );
|
||||
void file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts);
|
||||
|
||||
/* Return the mtime of file F (a struct file *), caching it.
|
||||
The value is NONEXISTENT_MTIME if the file does not exist. */
|
||||
|
@ -204,6 +212,8 @@ FILE_TIMESTAMP f_mtime (struct file *file, int search);
|
|||
<< FILE_TIMESTAMP_LO_BITS) \
|
||||
+ ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1)
|
||||
|
||||
#define is_ordinary_mtime(_t) ((_t) >= ORDINARY_MTIME_MIN && (_t) <= ORDINARY_MTIME_MAX)
|
||||
|
||||
/* Modtime value to use for 'infinitely new'. We used to get the current time
|
||||
from the system and use that whenever we wanted 'new'. But that causes
|
||||
trouble when the machine running make and the machine holding a file have
|
||||
|
|
98
third_party/make/filename.h
vendored
98
third_party/make/filename.h
vendored
|
@ -1,33 +1,95 @@
|
|||
/* Basic filename support macros.
|
||||
Copyright (C) 2001-2004, 2007-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
The GNU C Library 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.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser 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/>. */
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* From Paul Eggert and Jim Meyering. */
|
||||
|
||||
#ifndef _FILENAME_H
|
||||
#define _FILENAME_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Pathname support.
|
||||
ISSLASH(C) tests whether C is a directory separator character.
|
||||
IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
|
||||
it may be concatenated to a directory pathname.
|
||||
IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
|
||||
/* Filename support.
|
||||
ISSLASH(C) tests whether C is a directory separator
|
||||
character.
|
||||
HAS_DEVICE(Filename) tests whether Filename contains a device
|
||||
specification.
|
||||
FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification
|
||||
at the beginning of Filename,
|
||||
index of the part consisting of
|
||||
alternating components and slashes.
|
||||
FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
1 when a non-empty device specification
|
||||
can be followed by an empty or relative
|
||||
part,
|
||||
0 when a non-empty device specification
|
||||
must be followed by a slash,
|
||||
0 when device specification don't exist.
|
||||
IS_ABSOLUTE_FILE_NAME(Filename)
|
||||
tests whether Filename is independent of
|
||||
any notion of "current directory".
|
||||
IS_RELATIVE_FILE_NAME(Filename)
|
||||
tests whether Filename may be concatenated
|
||||
to a directory filename.
|
||||
Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a
|
||||
relative file name!
|
||||
IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device
|
||||
or directory specification.
|
||||
*/
|
||||
#if defined _WIN32 || defined __CYGWIN__ \
|
||||
|| defined __EMX__ || defined __MSDOS__ || defined __DJGPP__
|
||||
/* Native Windows, Cygwin, OS/2, DOS */
|
||||
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
|
||||
/* Internal macro: Tests whether a character is a drive letter. */
|
||||
# define _IS_DRIVE_LETTER(C) \
|
||||
(((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z'))
|
||||
/* Help the compiler optimizing it. This assumes ASCII. */
|
||||
# undef _IS_DRIVE_LETTER
|
||||
# define _IS_DRIVE_LETTER(C) \
|
||||
(((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a')
|
||||
# define HAS_DEVICE(Filename) \
|
||||
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':')
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0)
|
||||
# ifdef __CYGWIN__
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
# else
|
||||
/* On native Windows, OS/2, DOS, the system has the notion of a
|
||||
"current directory" on each drive. */
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
|
||||
# endif
|
||||
# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define IS_ABSOLUTE_FILE_NAME(Filename) \
|
||||
ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)])
|
||||
# else
|
||||
# define IS_ABSOLUTE_FILE_NAME(Filename) \
|
||||
(ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))
|
||||
# endif
|
||||
# define IS_RELATIVE_FILE_NAME(Filename) \
|
||||
(! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)))
|
||||
# define IS_FILE_NAME_WITH_DIR(Filename) \
|
||||
(strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \
|
||||
|| HAS_DEVICE (Filename))
|
||||
#else
|
||||
/* Unix */
|
||||
# define ISSLASH(C) ((C) == '/')
|
||||
# define HAS_DEVICE(Filename) ((void) (Filename), 0)
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
|
||||
|
@ -35,6 +97,12 @@ extern "C" {
|
|||
# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
|
||||
# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
|
||||
# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
|
||||
#endif
|
||||
|
||||
/* Deprecated macros. For backward compatibility with old users of the
|
||||
'filename' module. */
|
||||
#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME
|
||||
#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
37
third_party/make/findprog-in.c
vendored
37
third_party/make/findprog-in.c
vendored
|
@ -1,37 +1,34 @@
|
|||
/* Locating a program in a given path.
|
||||
Copyright (C) 2001-2004, 2006-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
|
||||
Written by Bruno Haible <haible@clisp.cons.org>, 2001, 2019.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This file 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.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "third_party/make/filename.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "third_party/make/config.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Specification. */
|
||||
#include "third_party/make/findprog.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "findprog.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "third_party/make/filename.h"
|
||||
#include "third_party/make/concat-filename.h"
|
||||
#include "third_party/make/xalloc.h"
|
||||
#include "filename.h"
|
||||
#include "concat-filename.h"
|
||||
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
|
||||
/* Native Windows, OS/2, DOS */
|
||||
|
|
16
third_party/make/findprog.h
vendored
16
third_party/make/findprog.h
vendored
|
@ -1,18 +1,18 @@
|
|||
/* Locating a program in PATH.
|
||||
Copyright (C) 2001-2003, 2009-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001-2003, 2009-2023 Free Software Foundation, Inc.
|
||||
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This file 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.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _FINDPROG_H
|
||||
|
|
1061
third_party/make/function.c
vendored
1061
third_party/make/function.c
vendored
File diff suppressed because it is too large
Load diff
56
third_party/make/getopt.c
vendored
56
third_party/make/getopt.c
vendored
|
@ -3,7 +3,7 @@ NOTE: getopt is now part of the C library, so if you don't know what
|
|||
"Keep this file name-space clean" means, talk to drepper@gnu.org
|
||||
before changing it!
|
||||
|
||||
Copyright (C) 1987-2020 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.
|
||||
Bugs can be reported to bug-glibc@gnu.org.
|
||||
|
@ -18,10 +18,7 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||
|
@ -30,9 +27,18 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "third_party/make/config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
|
||||
#if !defined __STDC__ || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
# ifndef const
|
||||
# define const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
|
@ -44,6 +50,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||
# include <gnu-versions.h>
|
||||
# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
# define ELIDE_CODE
|
||||
# endif
|
||||
|
@ -51,9 +58,26 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#ifndef ELIDE_CODE
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||
contain conflicting prototypes for getopt. */
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
#endif /* GNU C library. */
|
||||
|
||||
#ifdef VMS
|
||||
# include <unixlib.h>
|
||||
# if HAVE_STRING_H - 0
|
||||
# include <string.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is for other GNU distributions with internationalized messages.
|
||||
When compiling libc, the _ macro is predefined. */
|
||||
#include "third_party/make/gettext.h"
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
|
||||
|
@ -71,7 +95,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments. */
|
||||
|
||||
#include "third_party/make/getopt.h"
|
||||
#include "getopt.h"
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
|
@ -164,9 +188,16 @@ static char *posixly_correct;
|
|||
because there are many ways it can cause trouble.
|
||||
On some systems, it contains special magic macros that don't work
|
||||
in GCC. */
|
||||
# include <string.h>
|
||||
# define my_index strchr
|
||||
#else
|
||||
|
||||
# if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# else
|
||||
# include <strings.h>
|
||||
# endif
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
|
@ -405,6 +436,10 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring)
|
|||
nonoption_flags_len = 0;
|
||||
#endif
|
||||
|
||||
/* Make the compiler happy. */
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
return optstring;
|
||||
}
|
||||
|
||||
|
@ -645,7 +680,8 @@ _getopt_internal (int argc, char *const *argv, const char *optstring,
|
|||
optarg = nameend + 1;
|
||||
else
|
||||
{
|
||||
if (opterr) {
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind - 1][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr,
|
||||
|
|
11
third_party/make/getopt.h
vendored
11
third_party/make/getopt.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Declarations for getopt.
|
||||
Copyright (C) 1989-2020 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.
|
||||
Bugs can be reported to bug-glibc@gnu.org.
|
||||
|
@ -14,8 +14,7 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
#define _GETOPT_H 1
|
||||
|
@ -128,10 +127,4 @@ extern int _getopt_internal ();
|
|||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
extern int _getopt_internal (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind,
|
||||
int long_only);
|
||||
|
||||
#endif /* getopt.h */
|
||||
|
|
36
third_party/make/getopt1.c
vendored
36
third_party/make/getopt1.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987-1994, 1996-2020 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.
|
||||
Bugs can be reported to bug-glibc@gnu.org.
|
||||
|
@ -14,14 +14,24 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/getopt.h"
|
||||
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "third_party/make/config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#if !defined __STDC__ || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
|
@ -32,6 +42,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||
#include <gnu-versions.h>
|
||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
#define ELIDE_CODE
|
||||
#endif
|
||||
|
@ -39,6 +50,17 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#ifndef ELIDE_CODE
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (int argc, char *const *argv, const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
|
@ -63,6 +85,8 @@ getopt_long_only (int argc, char *const *argv, const char *options,
|
|||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
|
34
third_party/make/getprogname.c
vendored
34
third_party/make/getprogname.c
vendored
|
@ -1,34 +0,0 @@
|
|||
/* Program name management.
|
||||
Copyright (C) 2016-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "third_party/make/config.h"
|
||||
#include "third_party/make/getprogname.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "third_party/make/dirname.h"
|
||||
|
||||
char const *
|
||||
getprogname (void)
|
||||
{
|
||||
return firstnonnull(program_invocation_short_name, "unknown");
|
||||
}
|
||||
|
||||
/*
|
||||
* Hey Emacs!
|
||||
* Local Variables:
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
38
third_party/make/getprogname.h
vendored
38
third_party/make/getprogname.h
vendored
|
@ -1,38 +0,0 @@
|
|||
/* Program name management.
|
||||
Copyright (C) 2016-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
#ifndef _GL_GETPROGNAME_H
|
||||
#define _GL_GETPROGNAME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Return the base name of the executing program.
|
||||
On native Windows this will usually end in ".exe" or ".EXE". */
|
||||
#ifndef HAVE_GETPROGNAME
|
||||
extern char const *getprogname(void)
|
||||
#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
_GL_ATTRIBUTE_PURE
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
279
third_party/make/gettext.h
vendored
279
third_party/make/gettext.h
vendored
|
@ -1,99 +1,50 @@
|
|||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 1995-2023 Free Software Foundation, Inc.
|
||||
This file is part of GNU Make.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
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.
|
||||
|
||||
This program 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.
|
||||
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/>. */
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/* NLS can be disabled through the configure --disable-nls option
|
||||
or through "#define ENABLE NLS 0" before including this file. */
|
||||
#if defined ENABLE_NLS && ENABLE_NLS
|
||||
/* NLS can be disabled through the configure --disable-nls option. */
|
||||
#if ENABLE_NLS
|
||||
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
|
||||
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
|
||||
the gettext() and ngettext() macros. This is an alternative to calling
|
||||
textdomain(), and is useful for libraries. */
|
||||
# ifdef DEFAULT_TEXT_DOMAIN
|
||||
# undef gettext
|
||||
# define gettext(Msgid) \
|
||||
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
|
||||
# undef ngettext
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
|
||||
# endif
|
||||
# include <libintl.h>
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||
is OK. */
|
||||
#if defined(__sun)
|
||||
#endif
|
||||
|
||||
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
|
||||
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
|
||||
it now, to make later inclusions of <libintl.h> a NOP. */
|
||||
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
|
||||
# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
# undef gettext
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# undef dgettext
|
||||
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
|
||||
# undef dcgettext
|
||||
# define dcgettext(Domainname, Msgid, Category) \
|
||||
((void) (Category), dgettext (Domainname, Msgid))
|
||||
# undef ngettext
|
||||
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 \
|
||||
? ((void) (Msgid2), (const char *) (Msgid1)) \
|
||||
: ((void) (Msgid1), (const char *) (Msgid2)))
|
||||
# undef dngettext
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
|
||||
# undef dcngettext
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
|
||||
# undef textdomain
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# undef bindtextdomain
|
||||
# define bindtextdomain(Domainname, Dirname) \
|
||||
((void) (Domainname), (const char *) (Dirname))
|
||||
# undef bind_textdomain_codeset
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) \
|
||||
((void) (Domainname), (const char *) (Codeset))
|
||||
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
/* Prefer gnulib's setlocale override over libintl's setlocale override. */
|
||||
#ifdef GNULIB_defined_setlocale
|
||||
# undef setlocale
|
||||
# define setlocale rpl_setlocale
|
||||
#endif
|
||||
|
||||
/* A pseudo function call that serves as a marker for the automated
|
||||
extraction of messages, but does not call gettext(). The run-time
|
||||
translation is done at a different place in the code.
|
||||
|
@ -103,192 +54,4 @@
|
|||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
/* The separator between msgctxt and msgid in a .mo file. */
|
||||
#define GETTEXT_CONTEXT_GLUE "\004"
|
||||
|
||||
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
|
||||
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
|
||||
short and rarely need to change.
|
||||
The letter 'p' stands for 'particular' or 'special'. */
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#else
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#endif
|
||||
#define dpgettext(Domainname, Msgctxt, Msgid) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#else
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#endif
|
||||
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
pgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
const char *translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
if (translation == msg_ctxt_id)
|
||||
return msgid;
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
npgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
const char *translation =
|
||||
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
if (translation == msg_ctxt_id || translation == msgid_plural)
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
|
||||
can be arbitrary expressions. But for string literals these macros are
|
||||
less efficient than those above. */
|
||||
|
||||
|
||||
/* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
|
||||
This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
|
||||
the default GCC many warnings set. This allows programs to disable use
|
||||
of VLAs, which may be unintended, or may be awkward to support portably,
|
||||
or may have security implications due to non-deterministic stack usage. */
|
||||
|
||||
#if (!defined GNULIB_NO_VLA \
|
||||
&& (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
|
||||
/* || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
|
||||
|| (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ))
|
||||
# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
|
||||
#else
|
||||
# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
|
||||
#endif
|
||||
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
#endif
|
||||
|
||||
#define pgettext_expr(Msgctxt, Msgid) \
|
||||
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
|
||||
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
|
||||
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
int found_translation;
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
found_translation = (translation != msg_ctxt_id);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (found_translation)
|
||||
return translation;
|
||||
}
|
||||
return msgid;
|
||||
}
|
||||
|
||||
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcnpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
int found_translation;
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
found_translation = !(translation == msg_ctxt_id || translation == msgid_plural);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (found_translation)
|
||||
return translation;
|
||||
}
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
}
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
||||
|
|
1318
third_party/make/glob.c
vendored
Normal file
1318
third_party/make/glob.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
163
third_party/make/glob.h
vendored
Normal file
163
third_party/make/glob.h
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998, 2023 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
USA. */
|
||||
|
||||
#ifndef _GLOB_H
|
||||
#define _GLOB_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Bits set in the FLAGS argument to `glob'. */
|
||||
#define GLOB_ERR (1 << 0)/* Return on read errors. */
|
||||
#define GLOB_MARK (1 << 1)/* Append a slash to each name. */
|
||||
#define GLOB_NOSORT (1 << 2)/* Don't sort the names. */
|
||||
#define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */
|
||||
#define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */
|
||||
#define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */
|
||||
#define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */
|
||||
#define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */
|
||||
|
||||
#if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \
|
||||
|| defined _GNU_SOURCE)
|
||||
# define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */
|
||||
# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */
|
||||
# define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */
|
||||
# define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */
|
||||
# define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */
|
||||
# define GLOB_ONLYDIR (1 << 13)/* Match only directories. */
|
||||
# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error
|
||||
if the user name is not available. */
|
||||
# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
|
||||
GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \
|
||||
GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \
|
||||
GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
|
||||
#else
|
||||
# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
|
||||
GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \
|
||||
GLOB_PERIOD)
|
||||
#endif
|
||||
|
||||
/* Error returns from `glob'. */
|
||||
#define GLOB_NOSPACE 1 /* Ran out of memory. */
|
||||
#define GLOB_ABORTED 2 /* Read error. */
|
||||
#define GLOB_NOMATCH 3 /* No matches found. */
|
||||
#define GLOB_NOSYS 4 /* Not implemented. */
|
||||
#ifdef _GNU_SOURCE
|
||||
/* Previous versions of this file defined GLOB_ABEND instead of
|
||||
GLOB_ABORTED. Provide a compatibility definition here. */
|
||||
# define GLOB_ABEND GLOB_ABORTED
|
||||
#endif
|
||||
|
||||
/* Structure describing a globbing run. */
|
||||
#if !defined _AMIGA && !defined VMS /* Buggy compiler. */
|
||||
struct stat;
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
size_t gl_pathc; /* Count of paths matched by the pattern. */
|
||||
char **gl_pathv; /* List of matched pathnames. */
|
||||
size_t gl_offs; /* Slots to reserve in `gl_pathv'. */
|
||||
int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */
|
||||
|
||||
/* If the GLOB_ALTDIRFUNC flag is set, the following functions
|
||||
are used instead of the normal file access functions. */
|
||||
void (*gl_closedir) (void *);
|
||||
struct dirent *(*gl_readdir) (void *);
|
||||
void * (*gl_opendir) (const char *);
|
||||
int (*gl_lstat) (const char *, struct stat *);
|
||||
#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
|
||||
int (*gl_stat) (const char *, struct stat *, ...);
|
||||
#else
|
||||
int (*gl_stat) (const char *, struct stat *);
|
||||
#endif
|
||||
} glob_t;
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
struct stat64;
|
||||
typedef struct
|
||||
{
|
||||
size_t gl_pathc;
|
||||
char **gl_pathv;
|
||||
size_t gl_offs;
|
||||
int gl_flags;
|
||||
|
||||
/* If the GLOB_ALTDIRFUNC flag is set, the following functions
|
||||
are used instead of the normal file access functions. */
|
||||
void (*gl_closedir) (void *);
|
||||
struct dirent64 *(*gl_readdir) (void *);
|
||||
void * (*gl_opendir) (const char *);
|
||||
int (*gl_lstat) (const char *, struct stat64 *);
|
||||
int (*gl_stat) (const char *, struct stat64 *);
|
||||
} glob64_t;
|
||||
#endif
|
||||
|
||||
#if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2
|
||||
# define glob glob64
|
||||
# define globfree globfree64
|
||||
#else
|
||||
# ifdef _LARGEFILE64_SOURCE
|
||||
extern int glob64 (const char *pattern, int flags,
|
||||
int (*errfunc) (const char *, int),
|
||||
glob64_t *pglob);
|
||||
|
||||
extern void globfree64 (glob64_t *pglob);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Do glob searching for PATTERN, placing results in PGLOB.
|
||||
The bits defined above may be set in FLAGS.
|
||||
If a directory cannot be opened or read and ERRFUNC is not nil,
|
||||
it is called with the pathname that caused the error, and the
|
||||
`errno' value from the failing call; if it returns non-zero
|
||||
`glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
|
||||
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
|
||||
Otherwise, `glob' returns zero. */
|
||||
#if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2
|
||||
extern int glob (const char *pattern, int flags,
|
||||
int (*errfunc) (const char *, int),
|
||||
glob_t *pglob);
|
||||
|
||||
/* Free storage allocated in PGLOB by a previous `glob' call. */
|
||||
extern void globfree (glob_t *pglob);
|
||||
#else
|
||||
extern int glob (const char *pattern, int flags,
|
||||
int (*errfunc) (const char *, int),
|
||||
glob_t *pglob) __asm__ ("glob64");
|
||||
|
||||
extern void globfree (glob_t *pglob) __asm__ ("globfree64");
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
/* Return nonzero if PATTERN contains any metacharacters.
|
||||
Metacharacters can be quoted with backslashes if QUOTE is nonzero.
|
||||
|
||||
This function is not part of the interface specified by POSIX.2
|
||||
but several programs want to use it. */
|
||||
extern int glob_pattern_p (const char *pattern, int quote);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* glob.h */
|
12
third_party/make/gnumake.h
vendored
12
third_party/make/gnumake.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/* 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-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2013-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
|
||||
|
@ -14,7 +14,7 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GNUMAKE_H_
|
||||
#define _GNUMAKE_H_
|
||||
|
@ -41,23 +41,23 @@ typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);
|
|||
/* Free memory returned by the gmk_expand() function. */
|
||||
GMK_EXPORT void gmk_free (char *str);
|
||||
|
||||
/* Allocate memory in GNU make's context. */
|
||||
/* Allocate memory in GNU Make's context. */
|
||||
GMK_EXPORT char *gmk_alloc (unsigned int len);
|
||||
|
||||
/* Run $(eval ...) on the provided string BUFFER. */
|
||||
GMK_EXPORT void gmk_eval (const char *buffer, const gmk_floc *floc);
|
||||
|
||||
/* Run GNU make expansion on the provided string STR.
|
||||
/* Run GNU Make expansion on the provided string STR.
|
||||
Returns an allocated buffer that the caller must free with gmk_free(). */
|
||||
GMK_EXPORT char *gmk_expand (const char *str);
|
||||
|
||||
/* Register a new GNU make function NAME (maximum of 255 chars long).
|
||||
/* Register a new GNU Make function NAME (maximum of 255 chars long).
|
||||
When the function is expanded in the makefile, FUNC will be invoked with
|
||||
the appropriate arguments.
|
||||
|
||||
The return value of FUNC must be either NULL, in which case it expands to
|
||||
the empty string, or a pointer to the result of the expansion in a string
|
||||
created by gmk_alloc(). GNU make will free the memory when it's done.
|
||||
created by gmk_alloc(). GNU Make will free the memory when it's done.
|
||||
|
||||
MIN_ARGS is the minimum number of arguments the function requires.
|
||||
MAX_ARGS is the maximum number of arguments (or 0 if there's no maximum).
|
||||
|
|
142
third_party/make/guile.c
vendored
142
third_party/make/guile.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* GNU Guile interface for GNU Make.
|
||||
Copyright (C) 2011-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2011-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
|
||||
|
@ -12,12 +12,148 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "makeint.h"
|
||||
|
||||
#ifdef HAVE_GUILE
|
||||
|
||||
#include "gnumake.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
#include "variable.h"
|
||||
|
||||
#include <libguile.h>
|
||||
|
||||
/* Pre-2.0 versions of Guile don't have a typedef for gsubr function types. */
|
||||
#if SCM_MAJOR_VERSION < 2
|
||||
# define GSUBR_TYPE SCM (*) ()
|
||||
/* Guile 1.x doesn't really support i18n. */
|
||||
# define EVAL_STRING(_s) scm_c_eval_string (_s)
|
||||
#else
|
||||
# define GSUBR_TYPE scm_t_subr
|
||||
# define EVAL_STRING(_s) scm_eval_string (scm_from_utf8_string (_s))
|
||||
#endif
|
||||
|
||||
static SCM make_mod = SCM_EOL;
|
||||
static SCM obj_to_str = SCM_EOL;
|
||||
|
||||
/* Convert an SCM object into a string. */
|
||||
static char *
|
||||
cvt_scm_to_str (SCM obj)
|
||||
{
|
||||
return scm_to_locale_string (scm_call_1 (obj_to_str, obj));
|
||||
}
|
||||
|
||||
/* Perform the GNU Make expansion function. */
|
||||
static SCM
|
||||
guile_expand_wrapper (SCM obj)
|
||||
{
|
||||
char *str = cvt_scm_to_str (obj);
|
||||
SCM ret;
|
||||
char *res;
|
||||
|
||||
DB (DB_BASIC, (_("guile: Expanding '%s'\n"), str));
|
||||
res = gmk_expand (str);
|
||||
ret = scm_from_locale_string (res);
|
||||
|
||||
free (str);
|
||||
free (res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Perform the GNU Make eval function. */
|
||||
static SCM
|
||||
guile_eval_wrapper (SCM obj)
|
||||
{
|
||||
char *str = cvt_scm_to_str (obj);
|
||||
|
||||
DB (DB_BASIC, (_("guile: Evaluating '%s'\n"), str));
|
||||
gmk_eval (str, 0);
|
||||
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
|
||||
/* Invoked by scm_c_define_module(), in the context of the GNU Make module. */
|
||||
static void
|
||||
guile_define_module (void *data UNUSED)
|
||||
{
|
||||
/* Ingest the predefined Guile module for GNU Make. */
|
||||
//#include "gmk-default.h"
|
||||
|
||||
/* Register a subr for GNU Make's eval capability. */
|
||||
scm_c_define_gsubr ("gmk-expand", 1, 0, 0, (GSUBR_TYPE) guile_expand_wrapper);
|
||||
|
||||
/* Register a subr for GNU Make's eval capability. */
|
||||
scm_c_define_gsubr ("gmk-eval", 1, 0, 0, (GSUBR_TYPE) guile_eval_wrapper);
|
||||
|
||||
/* Define the rest of the module. */
|
||||
scm_c_eval_string (GUILE_module_defn);
|
||||
}
|
||||
|
||||
/* Initialize the GNU Make Guile module. */
|
||||
static void *
|
||||
guile_init (void *arg UNUSED)
|
||||
{
|
||||
/* Define the module. */
|
||||
make_mod = scm_c_define_module ("gnu make", guile_define_module, NULL);
|
||||
|
||||
/* Get a reference to the object-to-string translator, for later. */
|
||||
obj_to_str = scm_variable_ref (scm_c_module_lookup (make_mod, "obj-to-str"));
|
||||
|
||||
/* Import the GNU Make module exports into the generic space. */
|
||||
scm_c_eval_string ("(use-modules (gnu make))");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
internal_guile_eval (void *arg)
|
||||
{
|
||||
return cvt_scm_to_str (EVAL_STRING (arg));
|
||||
}
|
||||
|
||||
/* This is the function registered with make */
|
||||
static char *
|
||||
func_guile (const char *funcname UNUSED, unsigned int argc UNUSED, char **argv)
|
||||
{
|
||||
static int init = 0;
|
||||
|
||||
if (! init)
|
||||
{
|
||||
/* Initialize the Guile interpreter. */
|
||||
scm_with_guile (guile_init, NULL);
|
||||
init = 1;
|
||||
}
|
||||
|
||||
if (argv[0] && argv[0][0] != '\0')
|
||||
return scm_with_guile (internal_guile_eval, argv[0]);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----- Public interface ----- */
|
||||
|
||||
/* We could send the flocp to define_new_function(), but since guile is
|
||||
"kind of" built-in, that didn't seem so useful. */
|
||||
int
|
||||
guile_gmake_setup (const floc *flocp UNUSED)
|
||||
{
|
||||
/* Create a make function "guile". */
|
||||
gmk_add_function ("guile", func_guile, 0, 1, GMK_FUNC_DEFAULT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
guile_gmake_setup (const floc *flocp UNUSED)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
86
third_party/make/hash.c
vendored
86
third_party/make/hash.c
vendored
|
@ -12,20 +12,13 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "third_party/make/hash.h"
|
||||
#include "makeint.h"
|
||||
#include "hash.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define CALLOC(t, n) ((t *) xcalloc (1, sizeof (t) * (n)))
|
||||
#define CALLOC(t, n) ((t *) xcalloc (sizeof (t) * (n)))
|
||||
#define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n)))
|
||||
#define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n)))
|
||||
#define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n)))
|
||||
|
@ -51,11 +44,11 @@ hash_init (struct hash_table *ht, unsigned long size,
|
|||
{
|
||||
ht->ht_size = round_up_2 (size);
|
||||
ht->ht_empty_slots = ht->ht_size;
|
||||
ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size);
|
||||
ht->ht_vec = CALLOC (void *, ht->ht_size);
|
||||
if (ht->ht_vec == 0)
|
||||
{
|
||||
fprintf (stderr, _("can't allocate %lu bytes for hash table: memory exhausted"),
|
||||
ht->ht_size * (unsigned long) sizeof (struct token *));
|
||||
ht->ht_size * (unsigned long) sizeof (void *));
|
||||
exit (MAKE_TROUBLE);
|
||||
}
|
||||
|
||||
|
@ -267,7 +260,7 @@ hash_rehash (struct hash_table *ht)
|
|||
ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4);
|
||||
}
|
||||
ht->ht_rehashes++;
|
||||
ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size);
|
||||
ht->ht_vec = CALLOC (void *, ht->ht_size);
|
||||
|
||||
for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)
|
||||
{
|
||||
|
@ -322,8 +315,18 @@ hash_dump (struct hash_table *ht, void **vector_0, qsort_cmp_t compare)
|
|||
static unsigned long
|
||||
round_up_2 (unsigned long n)
|
||||
{
|
||||
if (UNLIKELY(!n)) return 1;
|
||||
return 2ul << _bsrl(n);
|
||||
n |= (n >> 1);
|
||||
n |= (n >> 2);
|
||||
n |= (n >> 4);
|
||||
n |= (n >> 8);
|
||||
n |= (n >> 16);
|
||||
|
||||
#if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295
|
||||
/* We only need this on systems where unsigned long is >32 bits. */
|
||||
n |= (n >> 32);
|
||||
#endif
|
||||
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
#define rol32(v, n) \
|
||||
|
@ -358,7 +361,7 @@ round_up_2 (unsigned long n)
|
|||
#define sum_get_unaligned_32(r, p) \
|
||||
do { \
|
||||
unsigned int val; \
|
||||
memcpy(&val, (p), 4); \
|
||||
memcpy (&val, (p), 4); \
|
||||
r += val; \
|
||||
} while(0);
|
||||
|
||||
|
@ -409,17 +412,39 @@ jhash(unsigned const char *k, int length)
|
|||
|
||||
#define UINTSZ sizeof (unsigned int)
|
||||
|
||||
/* First detect the presence of zeroes. If there is none, we can
|
||||
sum the 4 bytes directly. Otherwise, the ifs are ordered as in the
|
||||
big endian case, from the first byte in memory to the last. */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
/* The ifs are ordered from the first byte in memory to the last.
|
||||
Help the compiler optimize by using static memcpy length. */
|
||||
#define sum_up_to_nul(r, p, plen, flag) \
|
||||
do { \
|
||||
unsigned int val = 0; \
|
||||
size_t pn = (plen); \
|
||||
if (pn >= UINTSZ) \
|
||||
memcpy(&val, (p), UINTSZ); \
|
||||
memcpy (&val, (p), UINTSZ); \
|
||||
else \
|
||||
memcpy(&val, (p), pn); \
|
||||
memcpy (&val, (p), pn); \
|
||||
if ((val & 0xFF000000) == 0) \
|
||||
flag = 1; \
|
||||
else if ((val & 0xFF0000) == 0) \
|
||||
r += val & ~0xFFFF, flag = 1; \
|
||||
else if ((val & 0xFF00) == 0) \
|
||||
r += val & ~0xFF, flag = 1; \
|
||||
else \
|
||||
r += val, flag = (val & 0xFF) == 0; \
|
||||
} while (0)
|
||||
#else
|
||||
/* First detect the presence of zeroes. If there is none, we can
|
||||
sum the 4 bytes directly. Otherwise, the ifs are ordered as in the
|
||||
big endian case, from the first byte in memory to the last.
|
||||
Help the compiler optimize by using static memcpy length. */
|
||||
#define sum_up_to_nul(r, p, plen, flag) \
|
||||
do { \
|
||||
unsigned int val = 0; \
|
||||
size_t pn = (plen); \
|
||||
if (pn >= UINTSZ) \
|
||||
memcpy (&val, (p), UINTSZ); \
|
||||
else \
|
||||
memcpy (&val, (p), pn); \
|
||||
flag = ((val - 0x01010101) & ~val) & 0x80808080; \
|
||||
if (!flag) \
|
||||
r += val; \
|
||||
|
@ -433,6 +458,7 @@ jhash(unsigned const char *k, int length)
|
|||
r += val; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
jhash_string(unsigned const char *k)
|
||||
|
@ -445,35 +471,27 @@ jhash_string(unsigned const char *k)
|
|||
/* Set up the internal state */
|
||||
a = b = c = JHASH_INITVAL;
|
||||
|
||||
for (; klen > 12; k += 12, klen -= 12)
|
||||
{
|
||||
a += READ32LE (k + 0);
|
||||
b += READ32LE (k + 4);
|
||||
c += READ32LE (k + 8);
|
||||
jhash_mix (a, b, c);
|
||||
}
|
||||
|
||||
/* All but the last block: affect some 32 bits of (a,b,c) */
|
||||
for (;;) {
|
||||
sum_up_to_nul(a, k, klen, have_nul);
|
||||
if (have_nul)
|
||||
break;
|
||||
k += UINTSZ;
|
||||
DCHECK (klen >= UINTSZ);
|
||||
assert (klen >= UINTSZ);
|
||||
klen -= UINTSZ;
|
||||
|
||||
sum_up_to_nul(b, k, klen, have_nul);
|
||||
if (have_nul)
|
||||
break;
|
||||
k += UINTSZ;
|
||||
DCHECK (klen >= UINTSZ);
|
||||
assert (klen >= UINTSZ);
|
||||
klen -= UINTSZ;
|
||||
|
||||
sum_up_to_nul(c, k, klen, have_nul);
|
||||
if (have_nul)
|
||||
break;
|
||||
k += UINTSZ;
|
||||
DCHECK (klen >= UINTSZ);
|
||||
assert (klen >= UINTSZ);
|
||||
klen -= UINTSZ;
|
||||
jhash_mix(a, b, c);
|
||||
}
|
||||
|
|
9
third_party/make/hash.h
vendored
9
third_party/make/hash.h
vendored
|
@ -12,11 +12,14 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _hash_h_
|
||||
#define _hash_h_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
|
||||
# if !defined __GLIBC__ || !defined __P
|
||||
# undef __P
|
||||
|
@ -151,7 +154,7 @@ extern void *hash_deleted_item;
|
|||
#define ISTRING_HASH_1(KEY, RESULT) do { \
|
||||
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
|
||||
while (*++_key_) \
|
||||
(RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \
|
||||
(RESULT) += (tolower (*_key_) << (_key_[1] & 0xf)); \
|
||||
} while (0)
|
||||
#define return_ISTRING_HASH_1(KEY) do { \
|
||||
unsigned long _result_ = 0; \
|
||||
|
@ -162,7 +165,7 @@ extern void *hash_deleted_item;
|
|||
#define ISTRING_HASH_2(KEY, RESULT) do { \
|
||||
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
|
||||
while (*++_key_) \
|
||||
(RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \
|
||||
(RESULT) += (tolower (*_key_) << (_key_[1] & 0x7)); \
|
||||
} while (0)
|
||||
#define return_ISTRING_HASH_2(KEY) do { \
|
||||
unsigned long _result_ = 0; \
|
||||
|
|
358
third_party/make/implicit.c
vendored
358
third_party/make/implicit.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Implicit rule searching for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,19 +12,22 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/rule.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/debug.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "third_party/make/job.h" /* struct child, used inside commands.h */
|
||||
#include "third_party/make/commands.h" /* set_file_variables */
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "rule.h"
|
||||
#include "dep.h"
|
||||
#include "debug.h"
|
||||
#include "variable.h"
|
||||
#include "job.h" /* struct child, used inside commands.h */
|
||||
#include "commands.h" /* set_file_variables */
|
||||
#include "shuffle.h"
|
||||
#include <assert.h>
|
||||
|
||||
static int pattern_search (struct file *file, int archive,
|
||||
unsigned int depth, unsigned int recursions);
|
||||
unsigned int depth, unsigned int recursions,
|
||||
int allow_compat_rules);
|
||||
|
||||
/* For a FILE which has no commands specified, try to figure out some
|
||||
from the implicit pattern rules.
|
||||
|
@ -42,7 +45,7 @@ try_implicit_rule (struct file *file, unsigned int depth)
|
|||
(the archive search omits the archive name), it is more specific and
|
||||
should come first. */
|
||||
|
||||
if (pattern_search (file, 0, depth, 0))
|
||||
if (pattern_search (file, 0, depth, 0, 0))
|
||||
return 1;
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
|
@ -52,8 +55,11 @@ try_implicit_rule (struct file *file, unsigned int depth)
|
|||
{
|
||||
DBF (DB_IMPLICIT,
|
||||
_("Looking for archive-member implicit rule for '%s'.\n"));
|
||||
if (pattern_search (file, 1, depth, 0))
|
||||
if (pattern_search (file, 1, depth, 0, 0))
|
||||
return 1;
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("No archive-member implicit rule found for '%s'.\n"),
|
||||
file->name));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -153,6 +159,8 @@ struct patdeps
|
|||
struct file *file;
|
||||
unsigned int ignore_mtime : 1;
|
||||
unsigned int ignore_automatic_vars : 1;
|
||||
unsigned int is_explicit : 1;
|
||||
unsigned int wait_here : 1;
|
||||
};
|
||||
|
||||
/* This structure stores information about pattern rules that we need
|
||||
|
@ -200,7 +208,8 @@ stemlen_compare (const void *v1, const void *v2)
|
|||
|
||||
static int
|
||||
pattern_search (struct file *file, int archive,
|
||||
unsigned int depth, unsigned int recursions)
|
||||
unsigned int depth, unsigned int recursions,
|
||||
int allow_compat_rules)
|
||||
{
|
||||
/* Filename we are searching for a rule for. */
|
||||
const char *filename = archive ? strchr (file->name, '(') : file->name;
|
||||
|
@ -223,7 +232,11 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
/* Names of possible dependencies are constructed in this buffer.
|
||||
We may replace % by $(*F) for second expansion, increasing the length. */
|
||||
char *depname = alloca (namelen + max_pattern_dep_length + 4);
|
||||
size_t deplen = namelen + max_pattern_dep_length + 4;
|
||||
char *depname = alloca (deplen);
|
||||
#ifndef NDEBUG
|
||||
char *dend = depname + deplen;
|
||||
#endif
|
||||
|
||||
/* The start and length of the stem of FILENAME for the current rule. */
|
||||
const char *stem = 0;
|
||||
|
@ -251,6 +264,7 @@ pattern_search (struct file *file, int archive,
|
|||
int specific_rule_matched = 0;
|
||||
|
||||
unsigned int ri; /* uninit checks OK */
|
||||
int found_compat_rule = 0;
|
||||
struct rule *rule;
|
||||
|
||||
char *pathdir = NULL;
|
||||
|
@ -258,6 +272,8 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */
|
||||
|
||||
++depth;
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
if (archive || ar_name (filename))
|
||||
lastslash = 0;
|
||||
|
@ -268,6 +284,14 @@ pattern_search (struct file *file, int archive,
|
|||
but not counting any slash at the end. (foo/bar/ counts as
|
||||
bar/ in directory foo/, not empty in directory foo/bar/.) */
|
||||
lastslash = memrchr (filename, '/', namelen - 1);
|
||||
#ifdef VMS
|
||||
if (lastslash == NULL)
|
||||
lastslash = strrchr (filename, ']');
|
||||
if (lastslash == NULL)
|
||||
lastslash = strrchr (filename, '>');
|
||||
if (lastslash == NULL)
|
||||
lastslash = strrchr (filename, ':');
|
||||
#endif
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
/* Handle backslashes (possibly mixed with forward slashes)
|
||||
and the case of "d:file". */
|
||||
|
@ -300,7 +324,9 @@ pattern_search (struct file *file, int archive,
|
|||
don't use it here. */
|
||||
if (rule->in_use)
|
||||
{
|
||||
DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n")));
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Avoiding implicit rule recursion for rule '%s'.\n"),
|
||||
get_rule_defn (rule)));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -331,7 +357,11 @@ pattern_search (struct file *file, int archive,
|
|||
check_lastslash = 0;
|
||||
if (lastslash)
|
||||
{
|
||||
#ifdef VMS
|
||||
check_lastslash = strpbrk (target, "/]>:") == NULL;
|
||||
#else
|
||||
check_lastslash = strchr (target, '/') == 0;
|
||||
#endif
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
/* Didn't find it yet: check for DOS-type directories. */
|
||||
if (check_lastslash)
|
||||
|
@ -419,6 +449,8 @@ pattern_search (struct file *file, int archive,
|
|||
for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok)
|
||||
{
|
||||
pat = deplist;
|
||||
if (intermed_ok)
|
||||
DBS (DB_IMPLICIT, (_("Trying harder.\n")));
|
||||
|
||||
/* Try each pattern rule till we find one that applies. If it does,
|
||||
expand its dependencies (as substituted) and chain them in DEPS. */
|
||||
|
@ -467,6 +499,10 @@ pattern_search (struct file *file, int archive,
|
|||
}
|
||||
}
|
||||
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Trying pattern rule '%s' with stem '%.*s'.\n"),
|
||||
get_rule_defn (rule), (int) stemlen, stem));
|
||||
|
||||
if (stemlen + (check_lastslash ? pathlen : 0) > GET_PATH_MAX)
|
||||
{
|
||||
DBS (DB_IMPLICIT, (_("Stem too long: '%s%.*s'.\n"),
|
||||
|
@ -475,9 +511,6 @@ pattern_search (struct file *file, int archive,
|
|||
continue;
|
||||
}
|
||||
|
||||
DBS (DB_IMPLICIT, (_("Trying pattern rule with stem '%.*s'.\n"),
|
||||
(int) stemlen, stem));
|
||||
|
||||
if (!check_lastslash)
|
||||
{
|
||||
memcpy (stem_str, stem, stemlen);
|
||||
|
@ -496,10 +529,6 @@ pattern_search (struct file *file, int archive,
|
|||
if (rule->deps == 0)
|
||||
break;
|
||||
|
||||
/* Temporary assign STEM to file->stem (needed to set file
|
||||
variables below). */
|
||||
file->stem = stem_str;
|
||||
|
||||
/* Mark this rule as in use so a recursive pattern_search won't try
|
||||
to use it. */
|
||||
rule->in_use = 1;
|
||||
|
@ -514,7 +543,6 @@ pattern_search (struct file *file, int archive,
|
|||
while (1)
|
||||
{
|
||||
struct dep *dl, *d;
|
||||
char *p;
|
||||
|
||||
/* If we're out of name to parse, start the next prereq. */
|
||||
if (! nptr)
|
||||
|
@ -528,32 +556,33 @@ pattern_search (struct file *file, int archive,
|
|||
/* If we don't need a second expansion, just replace the %. */
|
||||
if (! dep->need_2nd_expansion)
|
||||
{
|
||||
p = strchr (nptr, '%');
|
||||
if (p == 0)
|
||||
char *p;
|
||||
int is_explicit = 1;
|
||||
const char *cp = strchr (nptr, '%');
|
||||
if (cp == 0)
|
||||
strcpy (depname, nptr);
|
||||
else
|
||||
{
|
||||
char *o = depname;
|
||||
if (check_lastslash)
|
||||
{
|
||||
memcpy (o, filename, pathlen);
|
||||
o += pathlen;
|
||||
}
|
||||
memcpy (o, nptr, p - nptr);
|
||||
o += p - nptr;
|
||||
memcpy (o, stem, stemlen);
|
||||
o += stemlen;
|
||||
strcpy (o, p + 1);
|
||||
o = mempcpy (o, filename, pathlen);
|
||||
o = mempcpy (o, nptr, cp - nptr);
|
||||
o = mempcpy (o, stem, stemlen);
|
||||
strcpy (o, cp + 1);
|
||||
is_explicit = 0;
|
||||
}
|
||||
|
||||
/* Parse the expanded string. It might have wildcards. */
|
||||
p = depname;
|
||||
dl = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL, PARSEFS_ONEWORD);
|
||||
dl = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL,
|
||||
PARSEFS_ONEWORD|PARSEFS_WAIT);
|
||||
for (d = dl; d != NULL; d = d->next)
|
||||
{
|
||||
++deps_found;
|
||||
d->ignore_mtime = dep->ignore_mtime;
|
||||
d->ignore_automatic_vars = dep->ignore_automatic_vars;
|
||||
d->wait_here |= dep->wait_here;
|
||||
d->is_explicit = is_explicit;
|
||||
}
|
||||
|
||||
/* We've used up this dep, so next time get a new one. */
|
||||
|
@ -573,17 +602,22 @@ pattern_search (struct file *file, int archive,
|
|||
{
|
||||
int add_dir = 0;
|
||||
size_t len;
|
||||
const char *end;
|
||||
struct dep **dptr;
|
||||
int is_explicit;
|
||||
const char *cp;
|
||||
char *p;
|
||||
|
||||
nptr = get_next_word (nptr, &len);
|
||||
if (nptr == 0)
|
||||
continue;
|
||||
end = nptr + len;
|
||||
|
||||
/* See this is a transition to order-only prereqs. */
|
||||
/* See if this is a transition to order-only prereqs. */
|
||||
if (! order_only && len == 1 && nptr[0] == '|')
|
||||
{
|
||||
order_only = 1;
|
||||
nptr += len;
|
||||
nptr = end;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -598,49 +632,76 @@ pattern_search (struct file *file, int archive,
|
|||
(since $* and $(*F) are simple variables) there won't be
|
||||
additional re-expansion of the stem. */
|
||||
|
||||
p = lindex (nptr, nptr + len, '%');
|
||||
if (p == 0)
|
||||
cp = lindex (nptr, end, '%');
|
||||
if (cp == 0)
|
||||
{
|
||||
memcpy (depname, nptr, len);
|
||||
depname[len] = '\0';
|
||||
is_explicit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i = p - nptr;
|
||||
/* Go through all % between NPTR and END.
|
||||
Copy contents of [NPTR, END) to depname, with the
|
||||
first % after NPTR and then each first % after white
|
||||
space replaced with $* or $(*F). depname has enough
|
||||
room to substitute each % with $(*F). */
|
||||
char *o = depname;
|
||||
memcpy (o, nptr, i);
|
||||
o += i;
|
||||
|
||||
is_explicit = 0;
|
||||
for (;;)
|
||||
{
|
||||
size_t i = cp - nptr;
|
||||
assert (o + i < dend);
|
||||
o = mempcpy (o, nptr, i);
|
||||
if (check_lastslash)
|
||||
{
|
||||
add_dir = 1;
|
||||
memcpy (o, "$(*F)", 5);
|
||||
o += 5;
|
||||
assert (o + 5 < dend);
|
||||
o = mempcpy (o, "$(*F)", 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (o, "$*", 2);
|
||||
o += 2;
|
||||
assert (o + 2 < dend);
|
||||
o = mempcpy (o, "$*", 2);
|
||||
}
|
||||
memcpy (o, p + 1, len - i - 1);
|
||||
o[len - i - 1] = '\0';
|
||||
assert (o < dend);
|
||||
++cp;
|
||||
assert (cp <= end);
|
||||
nptr = cp;
|
||||
if (nptr == end)
|
||||
break;
|
||||
|
||||
/* Skip the rest of this word then find the next %.
|
||||
No need to worry about order-only, or nested
|
||||
functions: NPTR went though get_next_word. */
|
||||
while (cp < end && ! END_OF_TOKEN (*cp))
|
||||
++cp;
|
||||
cp = lindex (cp, end, '%');
|
||||
if (cp == 0)
|
||||
break;
|
||||
}
|
||||
len = end - nptr;
|
||||
memcpy (o, nptr, len);
|
||||
o[len] = '\0';
|
||||
}
|
||||
|
||||
/* Set up for the next word. */
|
||||
nptr += len;
|
||||
nptr = end;
|
||||
|
||||
/* Initialize and set file variables if we haven't already
|
||||
done so. */
|
||||
if (!file_vars_initialized)
|
||||
{
|
||||
initialize_file_variables (file, 0);
|
||||
set_file_variables (file);
|
||||
set_file_variables (file, stem_str);
|
||||
file_vars_initialized = 1;
|
||||
}
|
||||
/* Update the stem value in $* for this rule. */
|
||||
else if (!file_variables_set)
|
||||
{
|
||||
define_variable_for_file (
|
||||
"*", 1, file->stem, o_automatic, 0, file);
|
||||
"*", 1, stem_str, o_automatic, 0, file);
|
||||
file_variables_set = 1;
|
||||
}
|
||||
|
||||
|
@ -654,7 +715,8 @@ pattern_search (struct file *file, int archive,
|
|||
/* Parse the expanded string. */
|
||||
struct dep *dp = PARSE_FILE_SEQ (&p, struct dep,
|
||||
order_only ? MAP_NUL : MAP_PIPE,
|
||||
add_dir ? pathdir : NULL, PARSEFS_NONE);
|
||||
add_dir ? pathdir : NULL,
|
||||
PARSEFS_WAIT);
|
||||
*dptr = dp;
|
||||
|
||||
for (d = dp; d != NULL; d = d->next)
|
||||
|
@ -662,6 +724,7 @@ pattern_search (struct file *file, int archive,
|
|||
++deps_found;
|
||||
if (order_only)
|
||||
d->ignore_mtime = 1;
|
||||
d->is_explicit = is_explicit;
|
||||
dptr = &d->next;
|
||||
}
|
||||
|
||||
|
@ -692,8 +755,10 @@ pattern_search (struct file *file, int archive,
|
|||
/* Go through the nameseq and handle each as a prereq name. */
|
||||
for (d = dl; d != 0; d = d->next)
|
||||
{
|
||||
struct dep *expl_d;
|
||||
struct file *df;
|
||||
int is_rule = d->name == dep_name (dep);
|
||||
int explicit = 0;
|
||||
struct dep *dp = 0;
|
||||
|
||||
if (file_impossible_p (d->name))
|
||||
{
|
||||
|
@ -702,9 +767,11 @@ pattern_search (struct file *file, int archive,
|
|||
second pass either since we know that will fail. */
|
||||
DBS (DB_IMPLICIT,
|
||||
(is_rule
|
||||
? _("Rejecting impossible rule prerequisite '%s'.\n")
|
||||
: _("Rejecting impossible implicit prerequisite '%s'.\n"),
|
||||
d->name));
|
||||
? _("Rejecting rule '%s' due to impossible rule"
|
||||
" prerequisite '%s'.\n")
|
||||
: _("Rejecting rule '%s' due to impossible implicit"
|
||||
" prerequisite '%s'.\n"),
|
||||
get_rule_defn (rule), d->name));
|
||||
tryrules[ri].rule = 0;
|
||||
|
||||
failed = 1;
|
||||
|
@ -714,41 +781,86 @@ pattern_search (struct file *file, int archive,
|
|||
memset (pat, '\0', sizeof (struct patdeps));
|
||||
pat->ignore_mtime = d->ignore_mtime;
|
||||
pat->ignore_automatic_vars = d->ignore_automatic_vars;
|
||||
pat->wait_here = d->wait_here;
|
||||
pat->is_explicit = d->is_explicit;
|
||||
|
||||
DBS (DB_IMPLICIT,
|
||||
(is_rule
|
||||
? _("Trying rule prerequisite '%s'.\n")
|
||||
: _("Trying implicit prerequisite '%s'.\n"), d->name));
|
||||
|
||||
/* If this prereq is also explicitly mentioned for FILE,
|
||||
skip all tests below since it must be built no matter
|
||||
which implicit rule we choose. */
|
||||
df = lookup_file (d->name);
|
||||
|
||||
for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
|
||||
if (streq (dep_name (expl_d), d->name))
|
||||
if (df && df->is_explicit)
|
||||
pat->is_explicit = 1;
|
||||
|
||||
/* If we found a file for the dep, set its intermediate flag.
|
||||
df->is_explicit is set when the dep file is mentioned
|
||||
explicitly on some other rule. d->is_explicit is set when
|
||||
the dep file is mentioned explicitly on this rule. E.g.:
|
||||
%.x : %.y ; ...
|
||||
then:
|
||||
one.x:
|
||||
one.y: # df->is_explicit
|
||||
vs.
|
||||
one.x: one.y # d->is_explicit
|
||||
*/
|
||||
if (df && !df->is_explicit && !d->is_explicit)
|
||||
df->intermediate = 1;
|
||||
|
||||
/* If the pattern prereq is also explicitly mentioned for
|
||||
FILE, skip all tests below since it must be built no
|
||||
matter which implicit rule we choose. */
|
||||
if (df && df->is_target)
|
||||
/* This prerequisite is mentioned explicitly as a target of
|
||||
some rule. */
|
||||
explicit = 1;
|
||||
else
|
||||
for (dp = file->deps; dp != 0; dp = dp->next)
|
||||
if (streq (d->name, dep_name (dp)))
|
||||
break;
|
||||
if (expl_d != 0)
|
||||
|
||||
/* If dp is set, this prerequisite is mentioned explicitly as
|
||||
a prerequisite of the current target. */
|
||||
|
||||
if (explicit || dp)
|
||||
{
|
||||
(pat++)->name = d->name;
|
||||
DBS (DB_IMPLICIT, (_("'%s' ought to exist.\n"), d->name));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The DEP->changed flag says that this dependency resides
|
||||
in a nonexistent directory. So we normally can skip
|
||||
looking for the file. However, if CHECK_LASTSLASH is
|
||||
set, then the dependency file we are actually looking for
|
||||
is in a different directory (the one gotten by prepending
|
||||
FILENAME's directory), so it might actually exist. */
|
||||
|
||||
/* @@ dep->changed check is disabled. */
|
||||
if (lookup_file (d->name) != 0
|
||||
/*|| ((!dep->changed || check_lastslash) && */
|
||||
|| file_exists_p (d->name))
|
||||
if (file_exists_p (d->name))
|
||||
{
|
||||
(pat++)->name = d->name;
|
||||
DBS (DB_IMPLICIT, (_("Found '%s'.\n"), d->name));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (df && allow_compat_rules)
|
||||
{
|
||||
(pat++)->name = d->name;
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Using compatibility rule '%s' due to '%s'.\n"),
|
||||
get_rule_defn (rule), d->name));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (df)
|
||||
{
|
||||
/* This prerequisite is mentioned explicitly as a
|
||||
prerequisite on some rule, but it is not a
|
||||
prerequisite of the current target. Therefore, this
|
||||
prerequisite does not qualify as ought-to-exist. Keep
|
||||
note of this rule and continue the search. If a more
|
||||
suitable rule is not found, then use this rule. */
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Prerequisite '%s' of rule '%s' does not qualify"
|
||||
" as ought to exist.\n"),
|
||||
d->name, get_rule_defn (rule)));
|
||||
found_compat_rule = 1;
|
||||
}
|
||||
|
||||
/* This code, given FILENAME = "lib/foo.o", dependency name
|
||||
"lib/foo.c", and VPATH=src, searches for
|
||||
"src/lib/foo.c". */
|
||||
|
@ -757,7 +869,7 @@ pattern_search (struct file *file, int archive,
|
|||
if (vname)
|
||||
{
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Found prerequisite '%s' as VPATH '%s'\n"),
|
||||
(_("Found prerequisite '%s' as VPATH '%s'.\n"),
|
||||
d->name, vname));
|
||||
(pat++)->name = d->name;
|
||||
continue;
|
||||
|
@ -765,13 +877,15 @@ pattern_search (struct file *file, int archive,
|
|||
}
|
||||
|
||||
/* We could not find the file in any place we should look.
|
||||
Try to make this dependency as an intermediate file, but
|
||||
Look for an implicit rule to make this dependency, but
|
||||
only on the second pass. */
|
||||
|
||||
if (intermed_ok)
|
||||
{
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Looking for a rule with intermediate file '%s'.\n"),
|
||||
(d->is_explicit || (df && df->is_explicit)
|
||||
? _("Looking for a rule with explicit file '%s'.\n")
|
||||
: _("Looking for a rule with intermediate file '%s'.\n"),
|
||||
d->name));
|
||||
|
||||
if (int_file == 0)
|
||||
|
@ -781,8 +895,9 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
if (pattern_search (int_file,
|
||||
0,
|
||||
depth + 1,
|
||||
recursions + 1))
|
||||
depth,
|
||||
recursions + 1,
|
||||
allow_compat_rules))
|
||||
{
|
||||
pat->pattern = int_file->name;
|
||||
int_file->name = d->name;
|
||||
|
@ -799,11 +914,24 @@ pattern_search (struct file *file, int archive,
|
|||
free_variable_set (int_file->variables);
|
||||
if (int_file->pat_variables)
|
||||
free_variable_set (int_file->pat_variables);
|
||||
|
||||
/* Keep prerequisites explicitly mentioned on unrelated
|
||||
rules as "possible" to let compatibility search find
|
||||
such prerequisites. */
|
||||
if (df == 0)
|
||||
file_impossible (d->name);
|
||||
}
|
||||
|
||||
/* A dependency of this rule does not exist. Therefore, this
|
||||
rule fails. */
|
||||
if (intermed_ok)
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Rejecting rule '%s' "
|
||||
"due to impossible prerequisite '%s'.\n"),
|
||||
get_rule_defn (rule), d->name));
|
||||
else
|
||||
DBS (DB_IMPLICIT, (_("Not found '%s'.\n"), d->name));
|
||||
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -815,10 +943,6 @@ pattern_search (struct file *file, int archive,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Reset the stem in FILE. */
|
||||
|
||||
file->stem = 0;
|
||||
|
||||
/* This rule is no longer 'in use' for recursive searches. */
|
||||
rule->in_use = 0;
|
||||
|
||||
|
@ -870,24 +994,24 @@ pattern_search (struct file *file, int archive,
|
|||
struct file *imf = pat->file;
|
||||
struct file *f = lookup_file (imf->name);
|
||||
|
||||
/* We don't want to delete an intermediate file that happened
|
||||
to be a prerequisite of some (other) target. Mark it as
|
||||
secondary. We don't want it to be precious as that disables
|
||||
DELETE_ON_ERROR etc. */
|
||||
if (f != 0)
|
||||
f->secondary = 1;
|
||||
else
|
||||
if (!f)
|
||||
f = enter_file (imf->name);
|
||||
|
||||
f->deps = imf->deps;
|
||||
f->cmds = imf->cmds;
|
||||
f->stem = imf->stem;
|
||||
f->variables = imf->variables;
|
||||
/* Setting target specific variables for a file causes the file to be
|
||||
entered to the database as a prerequisite. Implicit search then
|
||||
treats this file as explicitly mentioned. Preserve target specific
|
||||
variables of this file. */
|
||||
merge_variable_set_lists(&f->variables, imf->variables);
|
||||
f->pat_variables = imf->pat_variables;
|
||||
f->pat_searched = imf->pat_searched;
|
||||
f->also_make = imf->also_make;
|
||||
f->is_target = 1;
|
||||
f->intermediate = 1;
|
||||
f->is_explicit |= imf->is_explicit || pat->is_explicit;
|
||||
f->notintermediate |= imf->notintermediate || no_intermediates;
|
||||
f->intermediate |= !f->is_explicit && !f->notintermediate;
|
||||
f->tried_implicit = 1;
|
||||
|
||||
imf = lookup_file (pat->pattern);
|
||||
|
@ -904,7 +1028,9 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
dep = alloc_dep ();
|
||||
dep->ignore_mtime = pat->ignore_mtime;
|
||||
dep->is_explicit = pat->is_explicit;
|
||||
dep->ignore_automatic_vars = pat->ignore_automatic_vars;
|
||||
dep->wait_here = pat->wait_here;
|
||||
s = strcache_add (pat->name);
|
||||
if (recursions)
|
||||
dep->name = s;
|
||||
|
@ -930,8 +1056,14 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
dep->next = file->deps;
|
||||
file->deps = dep;
|
||||
|
||||
/* The file changed its dependencies; schedule the shuffle. */
|
||||
file->was_shuffled = 0;
|
||||
}
|
||||
|
||||
if (!file->was_shuffled)
|
||||
shuffle_deps_recursive (file->deps);
|
||||
|
||||
if (!tryrules[foundrule].checked_lastslash)
|
||||
{
|
||||
/* Always allocate new storage, since STEM might be on the stack for an
|
||||
|
@ -953,11 +1085,16 @@ pattern_search (struct file *file, int archive,
|
|||
file->cmds = rule->cmds;
|
||||
file->is_target = 1;
|
||||
|
||||
/* Set precious flag. */
|
||||
/* Set precious and notintermediate flags. */
|
||||
{
|
||||
struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]);
|
||||
if (f && f->precious)
|
||||
if (f)
|
||||
{
|
||||
if (f->precious)
|
||||
file->precious = 1;
|
||||
if (f->notintermediate || no_intermediates)
|
||||
file->notintermediate = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this rule builds other targets, too, put the others into FILE's
|
||||
|
@ -973,11 +1110,9 @@ pattern_search (struct file *file, int archive,
|
|||
struct dep *new = alloc_dep ();
|
||||
|
||||
/* GKM FIMXE: handle '|' here too */
|
||||
memcpy (p, rule->targets[ri],
|
||||
p = mempcpy (p, rule->targets[ri],
|
||||
rule->suffixes[ri] - rule->targets[ri] - 1);
|
||||
p += rule->suffixes[ri] - rule->targets[ri] - 1;
|
||||
memcpy (p, file->stem, fullstemlen);
|
||||
p += fullstemlen;
|
||||
p = mempcpy (p, file->stem, fullstemlen);
|
||||
memcpy (p, rule->suffixes[ri],
|
||||
rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1);
|
||||
new->name = strcache_add (nm);
|
||||
|
@ -986,8 +1121,13 @@ pattern_search (struct file *file, int archive,
|
|||
|
||||
/* Set precious flag. */
|
||||
f = lookup_file (rule->targets[ri]);
|
||||
if (f && f->precious)
|
||||
if (f)
|
||||
{
|
||||
if (f->precious)
|
||||
new->file->precious = 1;
|
||||
if (f->notintermediate || no_intermediates)
|
||||
new->file->notintermediate = 1;
|
||||
}
|
||||
|
||||
/* Set the is_target flag so that this file is not treated as
|
||||
intermediate by the pattern rule search algorithm and
|
||||
|
@ -1001,5 +1141,23 @@ pattern_search (struct file *file, int archive,
|
|||
free (tryrules);
|
||||
free (deplist);
|
||||
|
||||
return rule != 0;
|
||||
--depth;
|
||||
|
||||
if (rule)
|
||||
{
|
||||
DBS (DB_IMPLICIT, (_("Found implicit rule '%s' for '%s'.\n"),
|
||||
get_rule_defn (rule), filename));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (found_compat_rule)
|
||||
{
|
||||
DBS (DB_IMPLICIT, (_("Searching for a compatibility rule for '%s'.\n"),
|
||||
filename));
|
||||
assert (allow_compat_rules == 0);
|
||||
return pattern_search (file, archive, depth, recursions, 1);
|
||||
}
|
||||
|
||||
DBS (DB_IMPLICIT, (_("No implicit rule found for '%s'.\n"), filename));
|
||||
return 0;
|
||||
}
|
||||
|
|
583
third_party/make/intprops.h
vendored
583
third_party/make/intprops.h
vendored
|
@ -1,583 +0,0 @@
|
|||
/* intprops.h -- properties of integer types
|
||||
|
||||
Copyright (C) 2001-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#ifndef _GL_INTPROPS_H
|
||||
#define _GL_INTPROPS_H
|
||||
|
||||
|
||||
/* Return a value with the common real type of E and V and the value of V.
|
||||
Do not evaluate E. */
|
||||
#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
|
||||
|
||||
/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
|
||||
<https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */
|
||||
#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
|
||||
|
||||
/* The extra casts in the following macros work around compiler bugs,
|
||||
e.g., in Cray C 5.0.3.0. */
|
||||
|
||||
/* True if the arithmetic type T is an integer type. bool counts as
|
||||
an integer. */
|
||||
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
|
||||
|
||||
/* True if the real type T is signed. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* Return 1 if the real expression E, after promotion, has a
|
||||
signed or floating type. Do not evaluate E. */
|
||||
#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
|
||||
|
||||
|
||||
/* Minimum and maximum values for integer types and expressions. */
|
||||
|
||||
/* The width in bits of the integer type or expression T.
|
||||
Do not evaluate T.
|
||||
Padding bits are not supported; this is checked at compile-time below. */
|
||||
#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
|
||||
|
||||
/* The maximum and minimum values for the integer type T. */
|
||||
#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
|
||||
#define TYPE_MAXIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) -1 \
|
||||
: ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
|
||||
|
||||
/* The maximum and minimum values for the type of the expression E,
|
||||
after integer promotion. E is not evaluated. */
|
||||
#define _GL_INT_MINIMUM(e) \
|
||||
(EXPR_SIGNED (e) \
|
||||
? ~ _GL_SIGNED_INT_MAXIMUM (e) \
|
||||
: _GL_INT_CONVERT (e, 0))
|
||||
#define _GL_INT_MAXIMUM(e) \
|
||||
(EXPR_SIGNED (e) \
|
||||
? _GL_SIGNED_INT_MAXIMUM (e) \
|
||||
: _GL_INT_NEGATE_CONVERT (e, 1))
|
||||
#define _GL_SIGNED_INT_MAXIMUM(e) \
|
||||
(((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1)
|
||||
|
||||
/* Work around OpenVMS incompatibility with C99. */
|
||||
#if !defined LLONG_MAX && defined __INT64_MAX
|
||||
# define LLONG_MAX __INT64_MAX
|
||||
# define LLONG_MIN __INT64_MIN
|
||||
#endif
|
||||
|
||||
/* This include file assumes that signed types are two's complement without
|
||||
padding bits; the above macros have undefined behavior otherwise.
|
||||
If this is a problem for you, please let us know how to fix it for your host.
|
||||
This assumption is tested by the intprops-tests module. */
|
||||
|
||||
/* Does the __typeof__ keyword work? This could be done by
|
||||
'configure', but for now it's easier to do it by hand. */
|
||||
#if (2 <= __GNUC__ \
|
||||
|| (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
|
||||
|| (0x5110 <= __SUNPRO_C && !__STDC__))
|
||||
# define _GL_HAVE___TYPEOF__ 1
|
||||
#else
|
||||
# define _GL_HAVE___TYPEOF__ 0
|
||||
#endif
|
||||
|
||||
/* Return 1 if the integer type or expression T might be signed. Return 0
|
||||
if it is definitely unsigned. This macro does not evaluate its argument,
|
||||
and expands to an integer constant expression. */
|
||||
#if _GL_HAVE___TYPEOF__
|
||||
# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
|
||||
#else
|
||||
# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
|
||||
#endif
|
||||
|
||||
/* Bound on length of the string representing an unsigned integer
|
||||
value representable in B bits. log10 (2.0) < 146/485. The
|
||||
smallest value of B where this bound is not tight is 2621. */
|
||||
#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
|
||||
|
||||
/* Bound on length of the string representing an integer type or expression T.
|
||||
Subtract 1 for the sign bit if T is signed, and then add 1 more for
|
||||
a minus sign if needed.
|
||||
|
||||
Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 1 when its argument is
|
||||
unsigned, this macro may overestimate the true bound by one byte when
|
||||
applied to unsigned types of size 2, 4, 16, ... bytes. */
|
||||
#define INT_STRLEN_BOUND(t) \
|
||||
(INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
|
||||
+ _GL_SIGNED_TYPE_OR_EXPR (t))
|
||||
|
||||
/* Bound on buffer size needed to represent an integer type or expression T,
|
||||
including the terminating null. */
|
||||
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
|
||||
|
||||
|
||||
/* Range overflow checks.
|
||||
|
||||
The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C
|
||||
operators might not yield numerically correct answers due to
|
||||
arithmetic overflow. They do not rely on undefined or
|
||||
implementation-defined behavior. Their implementations are simple
|
||||
and straightforward, but they are a bit harder to use than the
|
||||
INT_<op>_OVERFLOW macros described below.
|
||||
|
||||
Example usage:
|
||||
|
||||
long int i = ...;
|
||||
long int j = ...;
|
||||
if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX))
|
||||
printf ("multiply would overflow");
|
||||
else
|
||||
printf ("product is %ld", i * j);
|
||||
|
||||
Restrictions on *_RANGE_OVERFLOW macros:
|
||||
|
||||
These macros do not check for all possible numerical problems or
|
||||
undefined or unspecified behavior: they do not check for division
|
||||
by zero, for bad shift counts, or for shifting negative numbers.
|
||||
|
||||
These macros may evaluate their arguments zero or multiple times,
|
||||
so the arguments should not have side effects. The arithmetic
|
||||
arguments (including the MIN and MAX arguments) must be of the same
|
||||
integer type after the usual arithmetic conversions, and the type
|
||||
must have minimum value MIN and maximum MAX. Unsigned types should
|
||||
use a zero MIN of the proper type.
|
||||
|
||||
These macros are tuned for constant MIN and MAX. For commutative
|
||||
operations such as A + B, they are also tuned for constant B. */
|
||||
|
||||
/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. */
|
||||
#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \
|
||||
((b) < 0 \
|
||||
? (a) < (min) - (b) \
|
||||
: (max) - (b) < (a))
|
||||
|
||||
/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. */
|
||||
#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \
|
||||
((b) < 0 \
|
||||
? (max) + (b) < (a) \
|
||||
: (a) < (min) + (b))
|
||||
|
||||
/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. */
|
||||
#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
|
||||
((min) < 0 \
|
||||
? (a) < - (max) \
|
||||
: 0 < (a))
|
||||
|
||||
/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. Avoid && and || as they tickle
|
||||
bugs in Sun C 5.11 2010/08/13 and other compilers; see
|
||||
<https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>. */
|
||||
#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
|
||||
((b) < 0 \
|
||||
? ((a) < 0 \
|
||||
? (a) < (max) / (b) \
|
||||
: (b) == -1 \
|
||||
? 0 \
|
||||
: (min) / (b) < (a)) \
|
||||
: (b) == 0 \
|
||||
? 0 \
|
||||
: ((a) < 0 \
|
||||
? (a) < (min) / (b) \
|
||||
: (max) / (b) < (a)))
|
||||
|
||||
/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. Do not check for division by zero. */
|
||||
#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \
|
||||
((min) < 0 && (b) == -1 && (a) < - (max))
|
||||
|
||||
/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. Do not check for division by zero.
|
||||
Mathematically, % should never overflow, but on x86-like hosts
|
||||
INT_MIN % -1 traps, and the C standard permits this, so treat this
|
||||
as an overflow too. */
|
||||
#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \
|
||||
INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max)
|
||||
|
||||
/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic.
|
||||
See above for restrictions. Here, MIN and MAX are for A only, and B need
|
||||
not be of the same type as the other arguments. The C standard says that
|
||||
behavior is undefined for shifts unless 0 <= B < wordwidth, and that when
|
||||
A is negative then A << B has undefined behavior and A >> B has
|
||||
implementation-defined behavior, but do not check these other
|
||||
restrictions. */
|
||||
#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \
|
||||
((a) < 0 \
|
||||
? (a) < (min) >> (b) \
|
||||
: (max) >> (b) < (a))
|
||||
|
||||
/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
|
||||
(A, B, P) work when P is non-null. */
|
||||
#if 5 <= __GNUC__ && !defined __ICC
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
|
||||
#elif defined __has_builtin
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
|
||||
#else
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
|
||||
#endif
|
||||
|
||||
/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */
|
||||
#ifdef __clang__
|
||||
/* Work around Clang bug <https://bugs.llvm.org/show_bug.cgi?id=16404>. */
|
||||
# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0
|
||||
#else
|
||||
# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW
|
||||
#endif
|
||||
|
||||
/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
|
||||
__builtin_mul_overflow_p and __builtin_mul_overflow_p. */
|
||||
#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
|
||||
|
||||
/* The _GL*_OVERFLOW macros have the same restrictions as the
|
||||
*_RANGE_OVERFLOW macros, except that they do not assume that operands
|
||||
(e.g., A and B) have the same type as MIN and MAX. Instead, they assume
|
||||
that the result (e.g., A + B) has that type. */
|
||||
#if _GL_HAS_BUILTIN_OVERFLOW_P
|
||||
# define _GL_ADD_OVERFLOW(a, b, min, max) \
|
||||
__builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)
|
||||
# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
|
||||
__builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0)
|
||||
# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
|
||||
__builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0)
|
||||
#else
|
||||
# define _GL_ADD_OVERFLOW(a, b, min, max) \
|
||||
((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \
|
||||
: (a) < 0 ? (b) <= (a) + (b) \
|
||||
: (b) < 0 ? (a) <= (a) + (b) \
|
||||
: (a) + (b) < (b))
|
||||
# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
|
||||
((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \
|
||||
: (a) < 0 ? 1 \
|
||||
: (b) < 0 ? (a) - (b) <= (a) \
|
||||
: (a) < (b))
|
||||
# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
|
||||
(((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \
|
||||
|| INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
|
||||
#endif
|
||||
#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \
|
||||
((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
|
||||
: (a) < 0 ? (b) <= (a) + (b) - 1 \
|
||||
: (b) < 0 && (a) + (b) <= (a))
|
||||
#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \
|
||||
((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
|
||||
: (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \
|
||||
: (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max))
|
||||
|
||||
/* Return a nonzero value if A is a mathematical multiple of B, where
|
||||
A is unsigned, B is negative, and MAX is the maximum value of A's
|
||||
type. A's type must be the same as (A % B)'s type. Normally (A %
|
||||
-B == 0) suffices, but things get tricky if -B would overflow. */
|
||||
#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \
|
||||
(((b) < -_GL_SIGNED_INT_MAXIMUM (b) \
|
||||
? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \
|
||||
? (a) \
|
||||
: (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \
|
||||
: (a) % - (b)) \
|
||||
== 0)
|
||||
|
||||
/* Check for integer overflow, and report low order bits of answer.
|
||||
|
||||
The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
|
||||
might not yield numerically correct answers due to arithmetic overflow.
|
||||
The INT_<op>_WRAPV macros compute the low-order bits of the sum,
|
||||
difference, and product of two C integers, and return 1 if these
|
||||
low-order bits are not numerically correct.
|
||||
These macros work correctly on all known practical hosts, and do not rely
|
||||
on undefined behavior due to signed arithmetic overflow.
|
||||
|
||||
Example usage, assuming A and B are long int:
|
||||
|
||||
if (INT_MULTIPLY_OVERFLOW (a, b))
|
||||
printf ("result would overflow\n");
|
||||
else
|
||||
printf ("result is %ld (no overflow)\n", a * b);
|
||||
|
||||
Example usage with WRAPV flavor:
|
||||
|
||||
long int result;
|
||||
bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
|
||||
printf ("result is %ld (%s)\n", result,
|
||||
overflow ? "after overflow" : "no overflow");
|
||||
|
||||
Restrictions on these macros:
|
||||
|
||||
These macros do not check for all possible numerical problems or
|
||||
undefined or unspecified behavior: they do not check for division
|
||||
by zero, for bad shift counts, or for shifting negative numbers.
|
||||
|
||||
These macros may evaluate their arguments zero or multiple times, so the
|
||||
arguments should not have side effects.
|
||||
|
||||
The WRAPV macros are not constant expressions. They support only
|
||||
+, binary -, and *. Because the WRAPV macros convert the result,
|
||||
they report overflow in different circumstances than the OVERFLOW
|
||||
macros do.
|
||||
|
||||
These macros are tuned for their last input argument being a constant.
|
||||
|
||||
Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
|
||||
A % B, and A << B would overflow, respectively. */
|
||||
|
||||
#define INT_ADD_OVERFLOW(a, b) \
|
||||
_GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
|
||||
#define INT_SUBTRACT_OVERFLOW(a, b) \
|
||||
_GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
|
||||
#if _GL_HAS_BUILTIN_OVERFLOW_P
|
||||
# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a)
|
||||
#else
|
||||
# define INT_NEGATE_OVERFLOW(a) \
|
||||
INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
|
||||
#endif
|
||||
#define INT_MULTIPLY_OVERFLOW(a, b) \
|
||||
_GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
|
||||
#define INT_DIVIDE_OVERFLOW(a, b) \
|
||||
_GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
|
||||
#define INT_REMAINDER_OVERFLOW(a, b) \
|
||||
_GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW)
|
||||
#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
|
||||
INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
|
||||
_GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
|
||||
|
||||
/* Return 1 if the expression A <op> B would overflow,
|
||||
where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
|
||||
assuming MIN and MAX are the minimum and maximum for the result type.
|
||||
Arguments should be free of side effects. */
|
||||
#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \
|
||||
op_result_overflow (a, b, \
|
||||
_GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
|
||||
_GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))
|
||||
|
||||
/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
|
||||
Return 1 if the result overflows. See above for restrictions. */
|
||||
#if _GL_HAS_BUILTIN_ADD_OVERFLOW
|
||||
# define INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r)
|
||||
# define INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r)
|
||||
#else
|
||||
# define INT_ADD_WRAPV(a, b, r) \
|
||||
_GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW)
|
||||
# define INT_SUBTRACT_WRAPV(a, b, r) \
|
||||
_GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
|
||||
#endif
|
||||
#if _GL_HAS_BUILTIN_MUL_OVERFLOW
|
||||
# if (9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
|
||||
|| (__GNUC__ == 8 && 4 <= __GNUC_MINOR__))
|
||||
# define INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
|
||||
# else
|
||||
/* Work around GCC bug 91450. */
|
||||
# define INT_MULTIPLY_WRAPV(a, b, r) \
|
||||
((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && EXPR_SIGNED (a) && EXPR_SIGNED (b) \
|
||||
&& _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, 0, (__typeof__ (*(r))) -1)) \
|
||||
? ((void) __builtin_mul_overflow (a, b, r), 1) \
|
||||
: __builtin_mul_overflow (a, b, r))
|
||||
# endif
|
||||
#else
|
||||
# define INT_MULTIPLY_WRAPV(a, b, r) \
|
||||
_GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW)
|
||||
#endif
|
||||
|
||||
/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See:
|
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
|
||||
https://llvm.org/bugs/show_bug.cgi?id=25390
|
||||
For now, assume all versions of GCC-like compilers generate bogus
|
||||
warnings for _Generic. This matters only for compilers that
|
||||
lack relevant builtins. */
|
||||
#if __GNUC__
|
||||
# define _GL__GENERIC_BOGUS 1
|
||||
#else
|
||||
# define _GL__GENERIC_BOGUS 0
|
||||
#endif
|
||||
|
||||
/* Store the low-order bits of A <op> B into *R, where OP specifies
|
||||
the operation and OVERFLOW the overflow predicate. Return 1 if the
|
||||
result overflows. See above for restrictions. */
|
||||
#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
|
||||
# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
|
||||
(_Generic \
|
||||
(*(r), \
|
||||
signed char: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
signed char, SCHAR_MIN, SCHAR_MAX), \
|
||||
unsigned char: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned char, 0, UCHAR_MAX), \
|
||||
short int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
short int, SHRT_MIN, SHRT_MAX), \
|
||||
unsigned short int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned short int, 0, USHRT_MAX), \
|
||||
int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
int, INT_MIN, INT_MAX), \
|
||||
unsigned int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned int, 0, UINT_MAX), \
|
||||
long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
long int, LONG_MIN, LONG_MAX), \
|
||||
unsigned long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
unsigned long int, 0, ULONG_MAX), \
|
||||
long long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
long long int, LLONG_MIN, LLONG_MAX), \
|
||||
unsigned long long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
unsigned long long int, 0, ULLONG_MAX)))
|
||||
#else
|
||||
/* Store the low-order bits of A <op> B into *R, where OP specifies
|
||||
the operation and OVERFLOW the overflow predicate. If *R is
|
||||
signed, its type is ST with bounds SMIN..SMAX; otherwise its type
|
||||
is UT with bounds U..UMAX. ST and UT are narrower than int.
|
||||
Return 1 if the result overflows. See above for restrictions. */
|
||||
# if _GL_HAVE___TYPEOF__
|
||||
# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
|
||||
(TYPE_SIGNED (__typeof__ (*(r))) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax))
|
||||
# else
|
||||
# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
|
||||
(overflow (a, b, smin, smax) \
|
||||
? (overflow (a, b, 0, umax) \
|
||||
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \
|
||||
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \
|
||||
: (overflow (a, b, 0, umax) \
|
||||
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \
|
||||
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0)))
|
||||
# endif
|
||||
|
||||
# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
|
||||
(sizeof *(r) == sizeof (signed char) \
|
||||
? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
|
||||
signed char, SCHAR_MIN, SCHAR_MAX, \
|
||||
unsigned char, UCHAR_MAX) \
|
||||
: sizeof *(r) == sizeof (short int) \
|
||||
? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
|
||||
short int, SHRT_MIN, SHRT_MAX, \
|
||||
unsigned short int, USHRT_MAX) \
|
||||
: sizeof *(r) == sizeof (int) \
|
||||
? (EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
int, INT_MIN, INT_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned int, 0, UINT_MAX)) \
|
||||
: _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
|
||||
# ifdef LLONG_MAX
|
||||
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
|
||||
(sizeof *(r) == sizeof (long int) \
|
||||
? (EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
long int, LONG_MIN, LONG_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
unsigned long int, 0, ULONG_MAX)) \
|
||||
: (EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
long long int, LLONG_MIN, LLONG_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
unsigned long long int, 0, ULLONG_MAX)))
|
||||
# else
|
||||
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
|
||||
(EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
long int, LONG_MIN, LONG_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
unsigned long int, 0, ULONG_MAX))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Store the low-order bits of A <op> B into *R, where the operation
|
||||
is given by OP. Use the unsigned type UT for calculation to avoid
|
||||
overflow problems. *R's type is T, with extrema TMIN and TMAX.
|
||||
T must be a signed integer type. Return 1 if the result overflows. */
|
||||
#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
|
||||
(overflow (a, b, tmin, tmax) \
|
||||
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
|
||||
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
|
||||
|
||||
/* Return the low-order bits of A <op> B, where the operation is given
|
||||
by OP. Use the unsigned type UT for calculation to avoid undefined
|
||||
behavior on signed integer overflow, and convert the result to type T.
|
||||
UT is at least as wide as T and is no narrower than unsigned int,
|
||||
T is two's complement, and there is no padding or trap representations.
|
||||
Assume that converting UT to T yields the low-order bits, as is
|
||||
done in all known two's-complement C compilers. E.g., see:
|
||||
https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
|
||||
|
||||
According to the C standard, converting UT to T yields an
|
||||
implementation-defined result or signal for values outside T's
|
||||
range. However, code that works around this theoretical problem
|
||||
runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
|
||||
https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
|
||||
As the compiler bug is real, don't try to work around the
|
||||
theoretical problem. */
|
||||
|
||||
#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
|
||||
((t) ((ut) (a) op (ut) (b)))
|
||||
|
||||
/* Return true if the numeric values A + B, A - B, A * B fall outside
|
||||
the range TMIN..TMAX. Arguments should be integer expressions
|
||||
without side effects. TMIN should be signed and nonpositive.
|
||||
TMAX should be positive, and should be signed unless TMIN is zero. */
|
||||
#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \
|
||||
((b) < 0 \
|
||||
? (((tmin) \
|
||||
? ((EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \
|
||||
&& (a) < (tmin) - (b)) \
|
||||
: (a) <= -1 - (b)) \
|
||||
|| ((EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \
|
||||
: (a) < 0 \
|
||||
? (((tmin) \
|
||||
? ((EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \
|
||||
&& (b) < (tmin) - (a)) \
|
||||
: (b) <= -1 - (a)) \
|
||||
|| ((EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \
|
||||
&& (tmax) < (a) + (b))) \
|
||||
: (tmax) < (b) || (tmax) - (b) < (a))
|
||||
#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \
|
||||
(((a) < 0) == ((b) < 0) \
|
||||
? ((a) < (b) \
|
||||
? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \
|
||||
: (tmax) < (a) - (b)) \
|
||||
: (a) < 0 \
|
||||
? ((!EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
|
||||
|| (a) - (tmin) < (b)) \
|
||||
: ((! (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
|
||||
&& EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \
|
||||
&& (tmax) <= -1 - (b)) \
|
||||
|| (tmax) + (b) < (a)))
|
||||
#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \
|
||||
((b) < 0 \
|
||||
? ((a) < 0 \
|
||||
? (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
|
||||
? (a) < (tmax) / (b) \
|
||||
: ((INT_NEGATE_OVERFLOW (b) \
|
||||
? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (b) - 1) \
|
||||
: (tmax) / -(b)) \
|
||||
<= -1 - (a))) \
|
||||
: INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
|
||||
? (EXPR_SIGNED (a) \
|
||||
? 0 < (a) + (tmin) \
|
||||
: 0 < (a) && -1 - (tmin) < (a) - 1) \
|
||||
: (tmin) / (b) < (a)) \
|
||||
: (b) == 0 \
|
||||
? 0 \
|
||||
: ((a) < 0 \
|
||||
? (INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \
|
||||
? (EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \
|
||||
: (tmin) / (a) < (b)) \
|
||||
: (tmax) / (b) < (a)))
|
||||
|
||||
#endif /* _GL_INTPROPS_H */
|
2687
third_party/make/job.c
vendored
2687
third_party/make/job.c
vendored
File diff suppressed because it is too large
Load diff
28
third_party/make/job.h
vendored
28
third_party/make/job.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Definitions for managing subprocesses in GNU Make.
|
||||
Copyright (C) 1992-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992-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
|
||||
|
@ -12,16 +12,24 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/output.h"
|
||||
#include "output.h"
|
||||
|
||||
/* Structure describing a running or dead child process. */
|
||||
|
||||
#ifdef VMS
|
||||
#define VMSCHILD \
|
||||
char *comname; /* Temporary command file name */ \
|
||||
int efn; /* Completion event flag number */ \
|
||||
int cstatus; /* Completion status */ \
|
||||
int vms_launch_status; /* non-zero if lib$spawn, etc failed */
|
||||
#else
|
||||
#define VMSCHILD
|
||||
#endif
|
||||
|
||||
#define CHILDBASE \
|
||||
char *cmd_name; /* Alloced copy of command run. */ \
|
||||
char *cmd_name; /* Allocated copy of command run. */ \
|
||||
char **environment; /* Environment for commands. */ \
|
||||
VMSCHILD \
|
||||
struct output output /* Output for this child. */
|
||||
|
@ -40,7 +48,6 @@ struct child
|
|||
|
||||
struct file *file; /* File being remade. */
|
||||
|
||||
char *tmpdir; /* Temporary directory */
|
||||
char *sh_batch_file; /* Script file for shell commands */
|
||||
char **command_lines; /* Array of variable-expanded cmd lines. */
|
||||
char *command_ptr; /* Ptr into command_lines[command_line]. */
|
||||
|
@ -61,28 +68,25 @@ struct child
|
|||
extern struct child *children;
|
||||
|
||||
/* A signal handler for SIGCHLD, if needed. */
|
||||
RETSIGTYPE child_handler (int sig);
|
||||
void child_handler (int sig);
|
||||
int is_bourne_compatible_shell(const char *path);
|
||||
void new_job (struct file *file);
|
||||
void reap_children (int block, int err);
|
||||
void start_waiting_jobs (void);
|
||||
void free_childbase (struct childbase* child);
|
||||
|
||||
char **construct_command_argv (char *line, char **restp, struct file *file,
|
||||
int cmd_flags, char** batch_file);
|
||||
|
||||
pid_t child_execute_job (struct childbase *, int, char **, bool);
|
||||
pid_t child_execute_job (struct childbase *child, int good_stdin, char **argv);
|
||||
|
||||
#ifdef _AMIGA
|
||||
void exec_command (char **argv) NORETURN;
|
||||
#elif defined(__EMX__)
|
||||
int exec_command (char **argv, char **envp);
|
||||
#else
|
||||
void exec_command (char **argv, char **envp) NORETURN;
|
||||
pid_t exec_command (char **argv, char **envp);
|
||||
#endif
|
||||
|
||||
void unblock_all_sigs (void);
|
||||
|
||||
extern unsigned int job_slots_used;
|
||||
extern unsigned int jobserver_tokens;
|
||||
|
||||
void delete_tmpdir (struct child *);
|
||||
|
|
243
third_party/make/load.c
vendored
243
third_party/make/load.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Loading dynamic objects for GNU Make.
|
||||
Copyright (C) 2012-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-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
|
||||
|
@ -12,22 +12,251 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "makeint.h"
|
||||
|
||||
#if MAKE_LOAD
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define SYMBOL_EXTENSION "_gmk_setup"
|
||||
|
||||
#include "debug.h"
|
||||
#include "filedef.h"
|
||||
#include "variable.h"
|
||||
|
||||
/* Tru64 V4.0 does not have this flag */
|
||||
#ifndef RTLD_GLOBAL
|
||||
# define RTLD_GLOBAL 0
|
||||
#endif
|
||||
|
||||
struct load_list
|
||||
{
|
||||
struct load_list *next;
|
||||
const char *name;
|
||||
void *dlp;
|
||||
};
|
||||
|
||||
static struct load_list *loaded_syms = NULL;
|
||||
|
||||
static load_func_t
|
||||
load_object (const floc *flocp, int noerror, const char *ldname,
|
||||
const char *symname)
|
||||
{
|
||||
static void *global_dl = NULL;
|
||||
load_func_t symp;
|
||||
|
||||
if (! global_dl)
|
||||
{
|
||||
global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);
|
||||
if (! global_dl)
|
||||
{
|
||||
const char *err = dlerror ();
|
||||
OS (fatal, flocp, _("Failed to open global symbol table: %s"), err);
|
||||
}
|
||||
}
|
||||
|
||||
symp = (load_func_t) dlsym (global_dl, symname);
|
||||
if (! symp)
|
||||
{
|
||||
struct load_list *new;
|
||||
void *dlp = NULL;
|
||||
|
||||
/* If the path has no "/", try the current directory first. */
|
||||
if (! strchr (ldname, '/')
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
&& ! strchr (ldname, '\\')
|
||||
#endif
|
||||
)
|
||||
dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
/* If we haven't opened it yet, try the default search path. */
|
||||
if (! dlp)
|
||||
dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
/* Still no? Then fail. */
|
||||
if (! dlp)
|
||||
{
|
||||
const char *err = dlerror ();
|
||||
if (noerror)
|
||||
DB (DB_BASIC, ("%s\n", err));
|
||||
else
|
||||
OS (error, flocp, "%s", err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DB (DB_VERBOSE, (_("Loaded shared object %s\n"), ldname));
|
||||
|
||||
/* Assert that the GPL license symbol is defined. */
|
||||
symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
|
||||
if (! symp)
|
||||
OS (fatal, flocp,
|
||||
_("Loaded object %s is not declared to be GPL compatible"),
|
||||
ldname);
|
||||
|
||||
symp = (load_func_t) dlsym (dlp, symname);
|
||||
if (! symp)
|
||||
{
|
||||
const char *err = dlerror ();
|
||||
OSSS (fatal, flocp, _("Failed to load symbol %s from %s: %s"),
|
||||
symname, ldname, err);
|
||||
}
|
||||
|
||||
/* Add this symbol to a trivial lookup table. This is not efficient but
|
||||
it's highly unlikely we'll be loading lots of objects, and we only
|
||||
need it to look them up on unload, if we rebuild them. */
|
||||
new = xmalloc (sizeof (struct load_list));
|
||||
new->name = xstrdup (ldname);
|
||||
new->dlp = dlp;
|
||||
new->next = loaded_syms;
|
||||
loaded_syms = new;
|
||||
}
|
||||
|
||||
return symp;
|
||||
}
|
||||
|
||||
int
|
||||
load_file (const floc *flocp, const char **ldname UNUSED, int noerror)
|
||||
load_file (const floc *flocp, struct file *file, int noerror)
|
||||
{
|
||||
const char *ldname = file->name;
|
||||
size_t nmlen = strlen (ldname);
|
||||
char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
|
||||
char *symname = NULL;
|
||||
const char *fp;
|
||||
int r;
|
||||
load_func_t symp;
|
||||
|
||||
/* Break the input into an object file name and a symbol name. If no symbol
|
||||
name was provided, compute one from the object file name. */
|
||||
fp = strchr (ldname, '(');
|
||||
if (fp)
|
||||
{
|
||||
const char *ep;
|
||||
|
||||
/* There's an open paren, so see if there's a close paren: if so use
|
||||
that as the symbol name. We can't have whitespace: it would have
|
||||
been chopped up before this function is called. */
|
||||
ep = strchr (fp+1, ')');
|
||||
if (ep && ep[1] == '\0')
|
||||
{
|
||||
size_t l = fp - ldname;
|
||||
|
||||
++fp;
|
||||
if (fp == ep)
|
||||
OS (fatal, flocp, _("Empty symbol name for load: %s"), ldname);
|
||||
|
||||
/* Make a copy of the ldname part. */
|
||||
memcpy (new, ldname, l);
|
||||
new[l] = '\0';
|
||||
ldname = new;
|
||||
nmlen = l;
|
||||
|
||||
/* Make a copy of the symbol name part. */
|
||||
symname = new + l + 1;
|
||||
memcpy (symname, fp, ep - fp);
|
||||
symname[ep - fp] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure this name is in the string cache. */
|
||||
ldname = file->name = strcache_add (ldname);
|
||||
|
||||
/* If this object has been loaded, we're done: return -1 to ensure make does
|
||||
not rebuild again. If a rebuild is allowed it was set up when this
|
||||
object was initially loaded. */
|
||||
file = lookup_file (ldname);
|
||||
if (file && file->loaded)
|
||||
return -1;
|
||||
|
||||
/* If we didn't find a symbol name yet, construct it from the ldname. */
|
||||
if (! symname)
|
||||
{
|
||||
char *p = new;
|
||||
|
||||
fp = strrchr (ldname, '/');
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
if (fp)
|
||||
{
|
||||
const char *fp2 = strchr (fp, '\\');
|
||||
|
||||
if (fp2 > fp)
|
||||
fp = fp2;
|
||||
}
|
||||
else
|
||||
fp = strrchr (ldname, '\\');
|
||||
/* The (improbable) case of d:foo. */
|
||||
if (fp && *fp && fp[1] == ':')
|
||||
fp++;
|
||||
#endif
|
||||
if (!fp)
|
||||
fp = ldname;
|
||||
else
|
||||
++fp;
|
||||
while (isalnum ((unsigned char) *fp) || *fp == '_')
|
||||
*(p++) = *(fp++);
|
||||
strcpy (p, SYMBOL_EXTENSION);
|
||||
symname = new;
|
||||
}
|
||||
|
||||
DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, ldname));
|
||||
|
||||
/* Load it! */
|
||||
symp = load_object (flocp, noerror, ldname, symname);
|
||||
if (! symp)
|
||||
return 0;
|
||||
|
||||
/* Invoke the symbol. */
|
||||
r = (*symp) (flocp);
|
||||
|
||||
/* If the load didn't fail, add the file to the .LOADED variable. */
|
||||
if (r)
|
||||
do_variable_definition(flocp, ".LOADED", ldname, o_file, f_append_value, 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
unload_file (const char *name)
|
||||
{
|
||||
int rc = 0;
|
||||
struct load_list *d;
|
||||
|
||||
for (d = loaded_syms; d != NULL; d = d->next)
|
||||
if (streq (d->name, name) && d->dlp)
|
||||
{
|
||||
DB (DB_VERBOSE, (_("Unloading shared object %s\n"), name));
|
||||
rc = dlclose (d->dlp);
|
||||
if (rc)
|
||||
perror_with_name ("dlclose: ", d->name);
|
||||
else
|
||||
d->dlp = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
load_file (const floc *flocp, struct file *file UNUSED, int noerror)
|
||||
{
|
||||
if (! noerror)
|
||||
O (fatal, flocp,
|
||||
_("The 'load' operation is not supported on this platform."));
|
||||
_("The 'load' operation is not supported on this platform"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
unload_file (const char *name UNUSED)
|
||||
{
|
||||
O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported!");
|
||||
O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported");
|
||||
}
|
||||
|
||||
#endif /* MAKE_LOAD */
|
||||
|
|
12
third_party/make/loadapi.c
vendored
12
third_party/make/loadapi.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* API for GNU Make dynamic objects.
|
||||
Copyright (C) 2013-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2013-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
|
||||
|
@ -12,13 +12,13 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "makeint.h"
|
||||
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "filedef.h"
|
||||
#include "variable.h"
|
||||
#include "dep.h"
|
||||
|
||||
/* Allocate a buffer in our context, so we can free it. */
|
||||
char *
|
||||
|
|
1755
third_party/make/main.c
vendored
1755
third_party/make/main.c
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/* Miscellaneous global declarations and portability cruft for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,59 +12,27 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/makedev.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/stat.macros.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prio.h"
|
||||
#include "libc/sysv/consts/rlim.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/consts/rusage.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#include "libc/temp.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "third_party/musl/glob.h"
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because makeint.h was found in $srcdir). */
|
||||
#include "third_party/make/config.h"
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#undef HAVE_CONFIG_H
|
||||
#define HAVE_CONFIG_H 1
|
||||
#include "config.h"
|
||||
|
||||
/* Specify we want GNU source code. This must be defined before any
|
||||
system headers are included. */
|
||||
/* Some versions of GCC (e.g., 10.x) set the warn_unused_result attribute on
|
||||
__builtin_alloca. This causes alloca(0) to fail and is not easily worked
|
||||
around so avoid it via the preprocessor.
|
||||
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98055 */
|
||||
|
||||
#define POSIX 1
|
||||
#define _GNU_SOURCE 1
|
||||
#if defined (__has_builtin)
|
||||
# if __has_builtin (__builtin_alloca)
|
||||
# define free_alloca()
|
||||
# else
|
||||
# define free_alloca() alloca (0)
|
||||
# endif
|
||||
#else
|
||||
# define free_alloca() alloca (0)
|
||||
#endif
|
||||
|
||||
/* Disable assert() unless we're a maintainer.
|
||||
Some asserts are compute-intensive. */
|
||||
|
@ -79,23 +47,106 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#ifdef WINDOWS32
|
||||
# define GMK_BUILDING_MAKE
|
||||
#endif
|
||||
#include "third_party/make/gnumake.h"
|
||||
#include "gnumake.h"
|
||||
|
||||
#ifdef CRAY
|
||||
/* This must happen before #include <signal.h> so
|
||||
that the declaration therein is changed. */
|
||||
# define signal bsdsignal
|
||||
#endif
|
||||
|
||||
/* If we're compiling for the dmalloc debugger, turn off string inlining. */
|
||||
#if defined(HAVE_DMALLOC_H) && defined(__GNUC__)
|
||||
# define __NO_STRING_INLINES
|
||||
#endif
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
# define RETSIGTYPE void
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIMEB_H
|
||||
/* SCO 3.2 "devsys 4.2" has a prototype for 'ftime' in <time.h> that bombs
|
||||
unless <sys/timeb.h> has been included first. */
|
||||
# include <sys/timeb.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Define macros specifying which OS we are building for. */
|
||||
#if __gnu_hurd__
|
||||
# define MK_OS_HURD 1
|
||||
#endif
|
||||
#if __CYGWIN__
|
||||
# define MK_OS_CYGWIN 1
|
||||
#endif
|
||||
#if defined(__MVS__)
|
||||
# define MK_OS_ZOS 1
|
||||
#endif
|
||||
|
||||
#ifdef __VMS
|
||||
/* 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.
|
||||
*/
|
||||
# ifndef VMS
|
||||
# define VMS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
/* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get
|
||||
POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself! */
|
||||
# if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS)
|
||||
# define POSIX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some systems define _POSIX_VERSION but are not really POSIX.1. */
|
||||
#if (defined (butterfly) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386)))
|
||||
# undef POSIX
|
||||
#endif
|
||||
|
||||
#if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE)
|
||||
# define POSIX 1
|
||||
#endif
|
||||
|
||||
#ifndef sigmask
|
||||
# define sigmask(sig) (1 << ((sig) - 1))
|
||||
#endif
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
# define MAXPATHLEN 1024
|
||||
#ifndef HAVE_SA_RESTART
|
||||
# define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VFORK_H
|
||||
# include <vfork.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# ifdef MAXPATHLEN
|
||||
# define PATH_MAX MAXPATHLEN
|
||||
# else
|
||||
/* Some systems (HURD) have fully dynamic pathnames with no maximum.
|
||||
Ideally we'd support this but it will take some work. */
|
||||
# define PATH_MAX 4096
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PATH_MAX
|
||||
|
@ -139,6 +190,30 @@ unsigned int get_path_max (void);
|
|||
# endif
|
||||
#endif /* STAT_MACROS_BROKEN. */
|
||||
|
||||
#ifndef S_ISREG
|
||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
# include <fcntl.h>
|
||||
# include <types.h>
|
||||
# include <unixlib.h>
|
||||
# include <unixio.h>
|
||||
# include <perror.h>
|
||||
/* Needed to use alloca on VMS. */
|
||||
# include <builtins.h>
|
||||
|
||||
extern int vms_use_mcr_command;
|
||||
extern int vms_always_use_cmd_file;
|
||||
extern int vms_gnv_shell;
|
||||
extern int vms_comma_separator;
|
||||
extern int vms_legacy_behavior;
|
||||
extern int vms_unix_simulation;
|
||||
#endif
|
||||
|
||||
#if !defined(__attribute__) && (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__)
|
||||
/* Don't use __attribute__ if it's not supported. */
|
||||
# define ATTRIBUTE(x)
|
||||
|
@ -157,16 +232,26 @@ unsigned int get_path_max (void);
|
|||
#define NORETURN ATTRIBUTE ((noreturn))
|
||||
|
||||
#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# define ANSI_STRING 1
|
||||
#else /* No standard headers. */
|
||||
# ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# define ANSI_STRING 1
|
||||
# else
|
||||
# endif
|
||||
# ifdef HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# else
|
||||
void *malloc (int);
|
||||
void *realloc (void *, int);
|
||||
void free (void *);
|
||||
|
||||
void abort (void) NORETURN;
|
||||
void exit (int) NORETURN;
|
||||
# endif /* HAVE_STDLIB_H. */
|
||||
|
||||
#endif /* Standard headers. */
|
||||
|
@ -180,6 +265,7 @@ unsigned int get_path_max (void);
|
|||
#endif
|
||||
|
||||
#ifndef ANSI_STRING
|
||||
|
||||
/* SCO Xenix has a buggy macro definition in <string.h>. */
|
||||
#undef strerror
|
||||
#if !defined(__DECC)
|
||||
|
@ -189,6 +275,31 @@ char *strerror (int errnum);
|
|||
#endif /* !ANSI_STRING. */
|
||||
#undef ANSI_STRING
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRINGS_H
|
||||
# include <strings.h> /* Needed for strcasecmp / strncasecmp. */
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
# define MK_PRI64_PREFIX "I64"
|
||||
#else
|
||||
# define MK_PRI64_PREFIX "ll"
|
||||
#endif
|
||||
#ifndef PRIdMAX
|
||||
# define PRIdMAX MK_PRI64_PREFIX "d"
|
||||
#endif
|
||||
#ifndef PRIuMAX
|
||||
# define PRIuMAX MK_PRI64_PREFIX "u"
|
||||
#endif
|
||||
#ifndef SCNdMAX
|
||||
# define SCNdMAX PRIdMAX
|
||||
#endif
|
||||
#define FILE_TIMESTAMP uintmax_t
|
||||
|
||||
#if !defined(HAVE_STRSIGNAL)
|
||||
|
@ -238,13 +349,26 @@ extern mode_t umask (mode_t);
|
|||
|
||||
/* Handle gettext and locales. */
|
||||
|
||||
#include "third_party/make/gettext.h"
|
||||
#if HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#else
|
||||
# define setlocale(category, locale)
|
||||
#endif
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) gettext_noop (msgid)
|
||||
#define S_(msg1,msg2,num) ngettext (msg1,msg2,num)
|
||||
|
||||
/* This is needed for getcwd() and chdir(), on some W32 systems. */
|
||||
#if defined(HAVE_DIRECT_H)
|
||||
# include <direct.h>
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS32
|
||||
# include <fcntl.h>
|
||||
# include <malloc.h>
|
||||
# define pipe(_p) _pipe((_p), 512, O_BINARY)
|
||||
# define kill(_pid,_sig) w32_kill((_pid),(_sig))
|
||||
/* MSVC and Watcom C don't have ftruncate. */
|
||||
|
@ -272,14 +396,19 @@ extern int unixy_shell;
|
|||
# endif
|
||||
|
||||
/* Include only the minimal stuff from windows.h. */
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
#endif /* WINDOWS32 */
|
||||
|
||||
/* ALL_SET() evaluates the second argument twice. */
|
||||
#define ANY_SET(_v,_m) (((_v)&(_m)) != 0)
|
||||
#define NONE_SET(_v,_m) (! ANY_SET ((_v),(_m)))
|
||||
#define ALL_SET(_v,_m) (((_v)&(_m)) == (_m))
|
||||
|
||||
/* Bitmasks for the STOPCHAR array. */
|
||||
#define MAP_NUL 0x0001
|
||||
#define MAP_BLANK 0x0002
|
||||
#define MAP_BLANK 0x0002 /* space, TAB */
|
||||
#define MAP_NEWLINE 0x0004
|
||||
#define MAP_COMMENT 0x0008
|
||||
#define MAP_SEMI 0x0010
|
||||
|
@ -297,7 +426,11 @@ extern int unixy_shell;
|
|||
/* The set of characters which are directory separators is OS-specific. */
|
||||
#define MAP_DIRSEP 0x8000
|
||||
|
||||
#define MAP_VMSCOMMA 0x0000
|
||||
#ifdef VMS
|
||||
# define MAP_VMSCOMMA MAP_COMMA
|
||||
#else
|
||||
# define MAP_VMSCOMMA 0x0000
|
||||
#endif
|
||||
|
||||
#define MAP_SPACE (MAP_BLANK|MAP_NEWLINE)
|
||||
|
||||
|
@ -323,27 +456,58 @@ extern int unixy_shell;
|
|||
# define MAP_PATHSEP MAP_SEMI
|
||||
#elif PATH_SEPARATOR_CHAR == ','
|
||||
# define MAP_PATHSEP MAP_COMMA
|
||||
|
||||
#else
|
||||
# error "Unknown PATH_SEPARATOR_CHAR"
|
||||
#endif
|
||||
|
||||
#define STOP_SET(_v,_m) ANY_SET(stopchar_map[(unsigned char)(_v)],(_m))
|
||||
|
||||
/* True if C is whitespace but not newline. */
|
||||
#define ISBLANK(c) STOP_SET((c),MAP_BLANK)
|
||||
/* True if C is whitespace including newlines. */
|
||||
#define ISSPACE(c) STOP_SET((c),MAP_SPACE)
|
||||
/* True if C is nul or whitespace (including newline). */
|
||||
#define END_OF_TOKEN(c) STOP_SET((c),MAP_SPACE|MAP_NUL)
|
||||
/* Move S past all whitespace (including newlines). */
|
||||
#define NEXT_TOKEN(s) while (ISSPACE (*(s))) ++(s)
|
||||
#define END_OF_TOKEN(s) while (! STOP_SET (*(s), MAP_SPACE|MAP_NUL)) ++(s)
|
||||
|
||||
/* True if C is a directory separator on the current system. */
|
||||
#define ISDIRSEP(c) STOP_SET((c),MAP_DIRSEP)
|
||||
|
||||
/* True if S starts with a drive specifier. */
|
||||
#if defined(HAVE_DOS_PATHS)
|
||||
# define HAS_DRIVESPEC(_s) ((((_s)[0] >= 'a' && (_s)[0] <= 'z') \
|
||||
|| ((_s)[0] >= 'A' && (_s)[0] <= 'Z')) \
|
||||
&& (_s)[1] == ':')
|
||||
#else
|
||||
# define HAS_DRIVESPEC(_s) 0
|
||||
#endif
|
||||
|
||||
/* We can't run setrlimit when using posix_spawn. */
|
||||
#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) && !defined(USE_POSIX_SPAWN)
|
||||
# define SET_STACK_SIZE
|
||||
#endif
|
||||
#ifdef SET_STACK_SIZE
|
||||
# include <sys/resource.h>
|
||||
extern struct rlimit stack_limit;
|
||||
#endif
|
||||
|
||||
#include "glob.h"
|
||||
|
||||
#define NILF ((floc *)0)
|
||||
|
||||
/* Number of characters in a string constant. Does NOT include the \0 byte. */
|
||||
#define CSTRLEN(_s) (sizeof (_s)-1)
|
||||
|
||||
/* Only usable when NOT calling a macro: only use it for local functions. */
|
||||
#define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s)
|
||||
|
||||
/* The number of bytes needed to represent the largest integer as a string. */
|
||||
#define INTSTR_LENGTH CSTRLEN ("18446744073709551616")
|
||||
/* The number of bytes needed to represent the largest signed and unsigned
|
||||
integers as a string.
|
||||
Does NOT include space for \0 so be sure to add it if needed.
|
||||
Math suggested by Edward Welbourne <edward.welbourne@qt.io> */
|
||||
#define INTSTR_LENGTH (53 * sizeof(uintmax_t) / 22 + 3)
|
||||
|
||||
#define DEFAULT_TTYNAME "true"
|
||||
#ifdef HAVE_TTYNAME
|
||||
|
@ -352,8 +516,19 @@ extern struct rlimit stack_limit;
|
|||
# define TTYNAME(_f) DEFAULT_TTYNAME
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
# define DEFAULT_TMPDIR "/sys$scratch/"
|
||||
#elif defined(P_tmpdir)
|
||||
# define DEFAULT_TMPDIR P_tmpdir
|
||||
#else
|
||||
# define DEFAULT_TMPDIR "/tmp"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
struct file;
|
||||
|
||||
/* Specify the location of elements read from makefiles. */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -369,7 +544,7 @@ void error (const floc *flocp, size_t length, const char *fmt, ...)
|
|||
ATTRIBUTE ((__format__ (__printf__, 3, 4)));
|
||||
void fatal (const floc *flocp, size_t length, const char *fmt, ...)
|
||||
ATTRIBUTE ((noreturn, __format__ (__printf__, 3, 4)));
|
||||
void out_of_memory () NORETURN;
|
||||
void out_of_memory (void) NORETURN;
|
||||
|
||||
/* When adding macros to this list be sure to update the value of
|
||||
XGETTEXT_OPTIONS in the po/Makevars file. */
|
||||
|
@ -387,11 +562,25 @@ void out_of_memory () NORETURN;
|
|||
#define ONS(_t,_a,_f,_n,_s) _t((_a), INTSTR_LENGTH + strlen (_s), \
|
||||
(_f), (_n), (_s))
|
||||
|
||||
enum variable_origin;
|
||||
struct variable;
|
||||
|
||||
void reset_makeflags (enum variable_origin origin);
|
||||
struct variable *define_makeflags (int makefile);
|
||||
int should_print_dir (void);
|
||||
void temp_stdin_unlink (void);
|
||||
void die (int) NORETURN;
|
||||
void pfatal_with_name (const char *) NORETURN;
|
||||
void perror_with_name (const char *, const char *);
|
||||
#define xstrlen(_s) ((_s)==NULL ? 0 : strlen (_s))
|
||||
unsigned int make_toui (const char*, const char**);
|
||||
char *make_lltoa (long long, char *);
|
||||
char *make_ulltoa (unsigned long long, char *);
|
||||
void make_seed (unsigned int);
|
||||
unsigned int make_rand (void);
|
||||
pid_t make_pid (void);
|
||||
void *xmalloc (size_t);
|
||||
void *xcalloc (size_t);
|
||||
void *xrealloc (void *, size_t);
|
||||
char *xstrdup (const char *);
|
||||
char *xstrndup (const char *, size_t);
|
||||
|
@ -404,23 +593,30 @@ int alpha_compare (const void *, const void *);
|
|||
void print_spaces (unsigned int);
|
||||
char *find_percent (char *);
|
||||
const char *find_percent_cached (const char **);
|
||||
FILE *get_tmpfile (char **, const char *);
|
||||
const char *get_tmpdir (void);
|
||||
int get_tmpfd (char **);
|
||||
FILE *get_tmpfile (char **);
|
||||
ssize_t writebuf (int, const void *, size_t);
|
||||
ssize_t readbuf (int, void *, size_t);
|
||||
|
||||
#ifndef HAVE_MEMRCHR
|
||||
void *memrchr(const void *, int, size_t);
|
||||
#endif
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
int ar_name (const char *);
|
||||
void ar_parse_name (const char *, char **, char **);
|
||||
int ar_touch (const char *);
|
||||
time_t ar_member_date (const char *);
|
||||
|
||||
typedef long int (*ar_member_func_t) (int desc, const char *mem, int truncated,
|
||||
typedef intmax_t (*ar_member_func_t) (int desc, const char *mem, int truncated,
|
||||
long int hdrpos, long int datapos,
|
||||
long int size, long int date, int uid,
|
||||
long int size, intmax_t date, int uid,
|
||||
int gid, unsigned int mode,
|
||||
const void *arg);
|
||||
|
||||
long int ar_scan (const char *archive, ar_member_func_t function, const void *arg);
|
||||
intmax_t ar_scan (const char *archive, ar_member_func_t function,
|
||||
const void *arg);
|
||||
int ar_name_equal (const char *name, const char *mem, int truncated);
|
||||
#ifndef VMS
|
||||
int ar_member_touch (const char *arname, const char *memname);
|
||||
|
@ -450,10 +646,6 @@ int gpath_search (const char *file, size_t len);
|
|||
|
||||
void construct_include_path (const char **arg_dirs);
|
||||
|
||||
void user_access (void);
|
||||
void make_access (void);
|
||||
void child_access (void);
|
||||
|
||||
char *strip_whitespace (const char **begpp, const char **endpp);
|
||||
|
||||
void show_goal_error (void);
|
||||
|
@ -470,15 +662,19 @@ int guile_gmake_setup (const floc *flocp);
|
|||
|
||||
/* Loadable object support. Sets to the strcached name of the loaded file. */
|
||||
typedef int (*load_func_t)(const floc *flocp);
|
||||
int load_file (const floc *flocp, const char **filename, int noerror);
|
||||
void unload_file (const char *name);
|
||||
int load_file (const floc *flocp, struct file *file, int noerror);
|
||||
int unload_file (const char *name);
|
||||
|
||||
/* Maintainer mode support */
|
||||
#ifdef MAKE_MAINTAINER_MODE
|
||||
# define SPIN(_s) spin (_s)
|
||||
void spin (const char* suffix);
|
||||
# define DBG(_f) dbg _f
|
||||
void dbg (const char *fmt, ...);
|
||||
#else
|
||||
# define SPIN(_s)
|
||||
/* Never put this code into Git or a release. */
|
||||
# define DBG(_f) compile-error
|
||||
#endif
|
||||
|
||||
/* We omit these declarations on non-POSIX systems which define _POSIX_VERSION,
|
||||
|
@ -486,17 +682,16 @@ void spin (const char* suffix);
|
|||
|
||||
#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32)
|
||||
|
||||
long int atol ();
|
||||
# ifndef VMS
|
||||
long int lseek ();
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_GETCWD
|
||||
# if !defined(VMS) && !defined(__DECC)
|
||||
char *getcwd ();
|
||||
char *getcwd (void);
|
||||
# endif
|
||||
# else
|
||||
char *getwd ();
|
||||
char *getwd (void);
|
||||
# define getcwd(buf, len) getwd (buf)
|
||||
# endif
|
||||
|
||||
|
@ -507,9 +702,6 @@ char *getwd ();
|
|||
# define strcasecmp stricmp
|
||||
# elif HAVE_STRCMPI
|
||||
# define strcasecmp strcmpi
|
||||
# else
|
||||
/* Create our own, in misc.c */
|
||||
int strcasecmp (const char *s1, const char *s2);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -518,9 +710,6 @@ int strcasecmp (const char *s1, const char *s2);
|
|||
# define strncasecmp strnicmp
|
||||
# elif HAVE_STRNCMPI
|
||||
# define strncasecmp strncmpi
|
||||
# else
|
||||
/* Create our own, in misc.c */
|
||||
int strncasecmp (const char *s1, const char *s2, int n);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -540,21 +729,38 @@ extern unsigned short stopchar_map[];
|
|||
extern int just_print_flag, run_silent, ignore_errors_flag, keep_going_flag;
|
||||
extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
|
||||
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
|
||||
extern int print_version_flag, print_directory_flag, check_symlink_flag;
|
||||
extern int warn_undefined_variables_flag, trace_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 rebuilding_makefiles, one_shell, output_sync, verify_flag;
|
||||
extern unsigned long command_count;
|
||||
|
||||
extern const char *default_shell;
|
||||
|
||||
/* can we run commands via 'sh -c xxx' or must we use batch files? */
|
||||
extern int batch_mode_shell;
|
||||
|
||||
#define GNUMAKEFLAGS_NAME "GNUMAKEFLAGS"
|
||||
#define MAKEFLAGS_NAME "MAKEFLAGS"
|
||||
|
||||
/* Resetting the command script introduction prefix character. */
|
||||
#define RECIPEPREFIX_NAME ".RECIPEPREFIX"
|
||||
#define RECIPEPREFIX_DEFAULT '\t'
|
||||
extern char cmd_prefix;
|
||||
|
||||
extern unsigned int no_intermediates;
|
||||
|
||||
#if HAVE_MKFIFO
|
||||
/* It seems that mkfifo() is not working correctly, or at least not the way
|
||||
GNU make wants it to work, on GNU/Hurd and Cygwin so don't use it there. */
|
||||
# if !defined(JOBSERVER_USE_FIFO) && !MK_OS_HURD && !MK_OS_CYGWIN
|
||||
# define JOBSERVER_USE_FIFO 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define JOBSERVER_AUTH_OPT "jobserver-auth"
|
||||
|
||||
extern char *jobserver_auth;
|
||||
extern unsigned int job_slots;
|
||||
extern double max_load_average;
|
||||
|
||||
|
@ -607,7 +813,14 @@ extern char *version_string, *remote_description, *make_host;
|
|||
|
||||
extern unsigned int commands_started;
|
||||
|
||||
extern int handling_fatal_signal;
|
||||
extern volatile sig_atomic_t handling_fatal_signal;
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(_a,_b) ((_a)>(_b)?(_a):(_b))
|
||||
#endif
|
||||
|
||||
#define MAKE_SUCCESS 0
|
||||
#define MAKE_TROUBLE 1
|
||||
|
@ -615,6 +828,37 @@ extern int handling_fatal_signal;
|
|||
|
||||
/* Set up heap debugging library dmalloc. */
|
||||
|
||||
#ifdef HAVE_DMALLOC_H
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#ifndef initialize_main
|
||||
# ifdef __EMX__
|
||||
# define initialize_main(pargc, pargv) \
|
||||
{ _wildcard(pargc, pargv); _response(pargc, pargv); }
|
||||
# else
|
||||
# define initialize_main(pargc, pargv)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__
|
||||
# if !defined chdir
|
||||
# define chdir _chdir2
|
||||
# endif
|
||||
# if !defined getcwd
|
||||
# define getcwd _getcwd2
|
||||
# endif
|
||||
|
||||
/* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of
|
||||
chdir() and getcwd(). This avoids some error messages for the
|
||||
make testsuite but restricts the drive letter support. */
|
||||
# ifdef NO_CHDIR2
|
||||
# warning NO_CHDIR2: usage of drive letters restricted
|
||||
# undef chdir
|
||||
# undef getcwd
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef initialize_main
|
||||
# define initialize_main(pargc, pargv)
|
||||
#endif
|
896
third_party/make/misc.c
vendored
896
third_party/make/misc.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Miscellaneous generic support functions for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,15 +12,97 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/debug.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
#include "os.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* GNU make no longer supports pre-ANSI89 environments. */
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__
|
||||
# define INCL_DOS
|
||||
# include <os2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
make_toui (const char *str, const char **error)
|
||||
{
|
||||
char *end;
|
||||
unsigned long val = strtoul (str, &end, 10);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (str[0] == '\0')
|
||||
*error = "Missing value";
|
||||
else if (*end != '\0')
|
||||
*error = "Invalid value";
|
||||
else
|
||||
*error = NULL;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Convert val into a string, written to buf. buf must be large enough
|
||||
to hold the largest possible value, plus a nul byte. Returns buf.
|
||||
We can't use standard PRI* here: those are based on intNN_t types. */
|
||||
|
||||
char *
|
||||
make_lltoa (long long val, char *buf)
|
||||
{
|
||||
sprintf (buf, "%" MK_PRI64_PREFIX "d", val);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
make_ulltoa (unsigned long long val, char *buf)
|
||||
{
|
||||
sprintf (buf, "%" MK_PRI64_PREFIX "u", val);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Simple random number generator, for use with shuffle.
|
||||
This doesn't need to be truly random, just pretty random. Use our own
|
||||
implementation rather than relying on the C runtime's rand() so we always
|
||||
get the same results for a given seed, regardless of C runtime. */
|
||||
|
||||
static unsigned int mk_state = 0;
|
||||
|
||||
void
|
||||
make_seed (unsigned int seed)
|
||||
{
|
||||
mk_state = seed;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
make_rand ()
|
||||
{
|
||||
/* mk_state must never be 0. */
|
||||
if (mk_state == 0)
|
||||
mk_state = (unsigned int)(time (NULL) ^ make_pid ()) + 1;
|
||||
|
||||
/* A simple xorshift RNG. */
|
||||
mk_state ^= mk_state << 13;
|
||||
mk_state ^= mk_state >> 17;
|
||||
mk_state ^= mk_state << 5;
|
||||
|
||||
return mk_state;
|
||||
}
|
||||
|
||||
/* Compare strings *S1 and *S2.
|
||||
Return negative if the first is less, positive if it is greater,
|
||||
|
@ -81,7 +163,7 @@ collapse_continuations (char *line)
|
|||
if (i & 1)
|
||||
{
|
||||
/* Backslash/newline handling:
|
||||
In traditional GNU make all trailing whitespace, consecutive
|
||||
In traditional GNU Make all trailing whitespace, consecutive
|
||||
backslash/newlines, and any leading non-newline whitespace on the
|
||||
next line is reduced to a single space.
|
||||
In POSIX, each backslash/newline and is replaced by a space. */
|
||||
|
@ -162,6 +244,85 @@ concat (unsigned int num, ...)
|
|||
}
|
||||
|
||||
|
||||
#ifndef HAVE_UNISTD_H
|
||||
pid_t getpid ();
|
||||
#endif
|
||||
|
||||
pid_t make_pid ()
|
||||
{
|
||||
return getpid ();
|
||||
}
|
||||
|
||||
/* Like malloc but get fatal error if memory is exhausted. */
|
||||
/* Don't bother if we're using dmalloc; it provides these for us. */
|
||||
|
||||
#ifndef HAVE_DMALLOC_H
|
||||
|
||||
#undef xmalloc
|
||||
#undef xcalloc
|
||||
#undef xrealloc
|
||||
#undef xstrdup
|
||||
|
||||
void *
|
||||
xmalloc (size_t size)
|
||||
{
|
||||
/* Make sure we don't allocate 0, for pre-ISO implementations. */
|
||||
void *result = malloc (size ? size : 1);
|
||||
if (result == 0)
|
||||
out_of_memory ();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
xcalloc (size_t size)
|
||||
{
|
||||
/* Make sure we don't allocate 0, for pre-ISO implementations. */
|
||||
void *result = calloc (size ? size : 1, 1);
|
||||
if (result == 0)
|
||||
out_of_memory ();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
xrealloc (void *ptr, size_t size)
|
||||
{
|
||||
void *result;
|
||||
|
||||
/* Some older implementations of realloc() don't conform to ISO. */
|
||||
if (! size)
|
||||
size = 1;
|
||||
result = ptr ? realloc (ptr, size) : malloc (size);
|
||||
if (result == 0)
|
||||
out_of_memory ();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
xstrdup (const char *ptr)
|
||||
{
|
||||
char *result;
|
||||
|
||||
#ifdef HAVE_STRDUP
|
||||
result = strdup (ptr);
|
||||
#else
|
||||
result = malloc (strlen (ptr) + 1);
|
||||
#endif
|
||||
|
||||
if (result == 0)
|
||||
out_of_memory ();
|
||||
|
||||
#ifdef HAVE_STRDUP
|
||||
return result;
|
||||
#else
|
||||
return strcpy (result, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HAVE_DMALLOC_H */
|
||||
|
||||
char *
|
||||
xstrndup (const char *str, size_t length)
|
||||
{
|
||||
|
@ -181,6 +342,29 @@ xstrndup (const char *str, size_t length)
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifndef HAVE_MEMRCHR
|
||||
void *
|
||||
memrchr(const void* str, int ch, size_t len)
|
||||
{
|
||||
const char* sp = str;
|
||||
const char* cp = sp;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
cp += len - 1;
|
||||
|
||||
while (cp[0] != ch)
|
||||
{
|
||||
if (cp == sp)
|
||||
return NULL;
|
||||
--cp;
|
||||
}
|
||||
|
||||
return (void*)cp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Limited INDEX:
|
||||
|
@ -204,7 +388,8 @@ lindex (const char *s, const char *limit, int c)
|
|||
char *
|
||||
end_of_token (const char *s)
|
||||
{
|
||||
END_OF_TOKEN (s);
|
||||
while (! END_OF_TOKEN (*s))
|
||||
++s;
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
|
@ -340,11 +525,31 @@ spin (const char* type)
|
|||
{
|
||||
fprintf (stderr, "SPIN on %s\n", filenm);
|
||||
do
|
||||
#ifdef WINDOWS32
|
||||
Sleep (1000);
|
||||
#else
|
||||
sleep (1);
|
||||
#endif
|
||||
while (stat (filenm, &dummy) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dbg (const char *fmt, ...)
|
||||
{
|
||||
FILE *fp = fopen ("/tmp/gmkdebug.log", "a+");
|
||||
va_list args;
|
||||
char buf[4096];
|
||||
|
||||
va_start (args, fmt);
|
||||
vsprintf (buf, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
fprintf(fp, "%u: %s\n", (unsigned) make_pid (), buf);
|
||||
fflush (fp);
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -359,283 +564,314 @@ char *mktemp (char *template);
|
|||
# endif
|
||||
#endif
|
||||
|
||||
FILE *
|
||||
get_tmpfile (char **name, const char *template)
|
||||
#ifndef HAVE_UMASK
|
||||
mode_t
|
||||
umask (mode_t mask)
|
||||
{
|
||||
FILE *file;
|
||||
#ifdef HAVE_FDOPEN
|
||||
int fd;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
# define DEFAULT_TMPFILE "sys$scratch:gnv$make_cmdXXXXXX.com"
|
||||
#else
|
||||
# define DEFAULT_TMPFILE "GmXXXXXX"
|
||||
#endif
|
||||
|
||||
const char *
|
||||
get_tmpdir ()
|
||||
{
|
||||
static const char *tmpdir = NULL;
|
||||
|
||||
if (!tmpdir)
|
||||
{
|
||||
#if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
|
||||
# define TMP_EXTRAS "TMP", "TEMP",
|
||||
#else
|
||||
# define TMP_EXTRAS
|
||||
#endif
|
||||
const char *tlist[] = { "MAKE_TMPDIR", "TMPDIR", TMP_EXTRAS NULL };
|
||||
const char **tp;
|
||||
unsigned int found = 0;
|
||||
|
||||
for (tp = tlist; *tp; ++tp)
|
||||
if ((tmpdir = getenv (*tp)) && *tmpdir != '\0')
|
||||
{
|
||||
struct stat st;
|
||||
int r;
|
||||
found = 1;
|
||||
EINTRLOOP(r, stat (tmpdir, &st));
|
||||
if (r < 0)
|
||||
OSSS (error, NILF,
|
||||
_("%s value %s: %s"), *tp, tmpdir, strerror (errno));
|
||||
else if (! S_ISDIR (st.st_mode))
|
||||
OSS (error, NILF,
|
||||
_("%s value %s: not a directory"), *tp, tmpdir);
|
||||
else
|
||||
return tmpdir;
|
||||
}
|
||||
|
||||
tmpdir = DEFAULT_TMPDIR;
|
||||
|
||||
if (found)
|
||||
OS (error, NILF, _("using default temporary directory '%s'"), tmpdir);
|
||||
}
|
||||
|
||||
return tmpdir;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_tmptemplate ()
|
||||
{
|
||||
const char *tmpdir = get_tmpdir ();
|
||||
char *template;
|
||||
char *cp;
|
||||
|
||||
template = xmalloc (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2);
|
||||
cp = stpcpy (template, tmpdir);
|
||||
|
||||
#if !defined VMS
|
||||
/* It's not possible for tmpdir to be empty. */
|
||||
if (! ISDIRSEP (cp[-1]))
|
||||
*(cp++) = '/';
|
||||
#endif
|
||||
|
||||
strcpy (cp, DEFAULT_TMPFILE);
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
#if !HAVE_MKSTEMP || !HAVE_FDOPEN
|
||||
/* Generate a temporary filename. This is not safe as another program could
|
||||
snipe our filename after we've generated it: use this only on systems
|
||||
without more secure alternatives. */
|
||||
|
||||
static char *
|
||||
get_tmppath ()
|
||||
{
|
||||
char *path;
|
||||
|
||||
# ifdef HAVE_MKTEMP
|
||||
path = get_tmptemplate ();
|
||||
if (*mktemp (path) == '\0')
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("cannot generate temp path from %s: %s"), path, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
# else
|
||||
path = xmalloc (L_tmpnam + 1);
|
||||
if (tmpnam (path) == NULL)
|
||||
{
|
||||
OS (error, NILF,
|
||||
_("cannot generate temp name: %s"), strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
# endif
|
||||
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Generate a temporary file and return an fd for it. If name is NULL then
|
||||
the temp file is anonymous and will be deleted when the process exits. If
|
||||
name is not null then *name will point to an allocated buffer, or set to
|
||||
NULL on failure. */
|
||||
int
|
||||
get_tmpfd (char **name)
|
||||
{
|
||||
int fd = -1;
|
||||
char *tmpnm;
|
||||
mode_t mask;
|
||||
|
||||
if (name)
|
||||
*name = NULL;
|
||||
else
|
||||
{
|
||||
/* If there's an os-specific way to get an anonymous temp file use it. */
|
||||
fd = os_anontmp ();
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Preserve the current umask, and set a restrictive one for temp files.
|
||||
Only really needed for mkstemp() but won't hurt for the open method. */
|
||||
mask = umask (0077);
|
||||
|
||||
#if defined(HAVE_MKSTEMP)
|
||||
tmpnm = get_tmptemplate ();
|
||||
|
||||
/* It's safest to use mkstemp(), if we can. */
|
||||
EINTRLOOP (fd, mkstemp (tmpnm));
|
||||
#else
|
||||
tmpnm = get_tmppath ();
|
||||
if (!tmpnm)
|
||||
return -1;
|
||||
|
||||
/* Can't use mkstemp(), but try to guard against a race condition. */
|
||||
EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
|
||||
#endif
|
||||
if (fd < 0)
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("cannot create temporary file %s: %s"), tmpnm, strerror (errno));
|
||||
free (tmpnm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name)
|
||||
*name = tmpnm;
|
||||
else
|
||||
{
|
||||
int r;
|
||||
EINTRLOOP (r, unlink (tmpnm));
|
||||
if (r < 0)
|
||||
OSS (error, NILF,
|
||||
_("cannot unlink temporary file %s: %s"), tmpnm, strerror (errno));
|
||||
free (tmpnm);
|
||||
}
|
||||
|
||||
umask (mask);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Return a FILE* for a temporary file, opened in the safest way possible.
|
||||
Set name to point to an allocated buffer containing the name of the file,
|
||||
or NULL on failure. Note, name cannot be NULL! */
|
||||
FILE *
|
||||
get_tmpfile (char **name)
|
||||
{
|
||||
/* Be consistent with tmpfile, which opens as if by "wb+". */
|
||||
const char *tmpfile_mode = "wb+";
|
||||
FILE *file;
|
||||
|
||||
#if defined(HAVE_FDOPEN)
|
||||
int fd;
|
||||
assert (name);
|
||||
fd = get_tmpfd (name);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
assert (*name);
|
||||
|
||||
ENULLLOOP (file, fdopen (fd, tmpfile_mode));
|
||||
if (file == NULL)
|
||||
OSS (error, NILF,
|
||||
_("fdopen: temporary file %s: %s"), *name, strerror (errno));
|
||||
#else
|
||||
/* Preserve the current umask, and set a restrictive one for temp files. */
|
||||
mode_t mask = umask (0077);
|
||||
|
||||
#if defined(HAVE_MKSTEMP) || defined(HAVE_MKTEMP)
|
||||
# define TEMPLATE_LEN strlen (template)
|
||||
#else
|
||||
# define TEMPLATE_LEN L_tmpnam
|
||||
#endif
|
||||
*name = xmalloc (TEMPLATE_LEN + 1);
|
||||
strcpy (*name, template);
|
||||
assert (name);
|
||||
*name = get_tmppath ();
|
||||
if (!*name)
|
||||
return NULL;
|
||||
|
||||
#if defined(HAVE_MKSTEMP) && defined(HAVE_FDOPEN)
|
||||
/* It's safest to use mkstemp(), if we can. */
|
||||
EINTRLOOP (fd, mkstemp (*name));
|
||||
if (fd == -1)
|
||||
file = NULL;
|
||||
else
|
||||
file = fdopen (fd, "w");
|
||||
#else
|
||||
# ifdef HAVE_MKTEMP
|
||||
(void) mktemp (*name);
|
||||
# else
|
||||
(void) tmpnam (*name);
|
||||
# endif
|
||||
/* Although this fopen is insecure, it is executed only on non-fdopen
|
||||
platforms, which should be a rarity nowadays. */
|
||||
|
||||
# ifdef HAVE_FDOPEN
|
||||
/* Can't use mkstemp(), but guard against a race condition. */
|
||||
EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
file = fdopen (fd, "w");
|
||||
# else
|
||||
/* Not secure, but what can we do? */
|
||||
file = fopen (*name, "w");
|
||||
# endif
|
||||
#endif
|
||||
ENULLLOOP (file, fopen (*name, tmpfile_mode));
|
||||
if (file == NULL)
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("fopen: temporary file %s: %s"), *name, strerror (errno));
|
||||
free (*name);
|
||||
*name = NULL;
|
||||
}
|
||||
|
||||
umask (mask);
|
||||
#endif
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
#ifdef GETLOADAVG_PRIVILEGED
|
||||
|
||||
#ifdef POSIX
|
||||
|
||||
/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
|
||||
functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
|
||||
for example) which claim to be POSIX.1 also have the BSD setreuid and
|
||||
setregid functions, but they don't work as in BSD and only the POSIX.1
|
||||
way works. */
|
||||
|
||||
#undef HAVE_SETREUID
|
||||
#undef HAVE_SETREGID
|
||||
|
||||
#else /* Not POSIX. */
|
||||
|
||||
/* Some POSIX.1 systems have the seteuid and setegid functions. In a
|
||||
POSIX-like system, they are the best thing to use. However, some
|
||||
non-POSIX systems have them too but they do not work in the POSIX style
|
||||
and we must use setreuid and setregid instead. */
|
||||
|
||||
#undef HAVE_SETEUID
|
||||
#undef HAVE_SETEGID
|
||||
|
||||
#endif /* POSIX. */
|
||||
|
||||
/* Keep track of the user and group IDs for user- and make- access. */
|
||||
static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
|
||||
#define access_inited (user_uid != -1)
|
||||
static enum { make, user } current_access;
|
||||
|
||||
|
||||
/* Under -d, write a message describing the current IDs. */
|
||||
|
||||
static void
|
||||
log_access (const char *flavor)
|
||||
#if HAVE_TTYNAME && defined(__EMX__)
|
||||
/* OS/2 kLIBC has a declaration for ttyname(), so configure finds it.
|
||||
But, it is not implemented! Roll our own. */
|
||||
char *ttyname (int fd)
|
||||
{
|
||||
if (! ISDB (DB_JOBS))
|
||||
return;
|
||||
ULONG type;
|
||||
ULONG attr;
|
||||
ULONG rc;
|
||||
|
||||
/* All the other debugging messages go to stdout,
|
||||
but we write this one to stderr because it might be
|
||||
run in a child fork whose stdout is piped. */
|
||||
rc = DosQueryHType (fd, &type, &attr);
|
||||
if (rc)
|
||||
{
|
||||
errno = EBADF;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
|
||||
flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
|
||||
(unsigned long) getegid (), (unsigned long) getgid ());
|
||||
fflush (stderr);
|
||||
if (type == HANDTYPE_DEVICE)
|
||||
{
|
||||
if (attr & 3) /* 1 = KBD$, 2 = SCREEN$ */
|
||||
return (char *) "/dev/con";
|
||||
|
||||
if (attr & 4) /* 4 = NUL */
|
||||
return (char *) "/dev/nul";
|
||||
|
||||
if (attr & 8) /* 8 = CLOCK$ */
|
||||
return (char *) "/dev/clock$";
|
||||
}
|
||||
|
||||
errno = ENOTTY;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
|
||||
/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
|
||||
for it, define our own version. */
|
||||
|
||||
static void
|
||||
init_access (void)
|
||||
int
|
||||
strcasecmp (const char *s1, const char *s2)
|
||||
{
|
||||
user_uid = getuid ();
|
||||
user_gid = getgid ();
|
||||
while (1)
|
||||
{
|
||||
int c1 = (unsigned char) *(s1++);
|
||||
int c2 = (unsigned char) *(s2++);
|
||||
|
||||
make_uid = geteuid ();
|
||||
make_gid = getegid ();
|
||||
if (isalpha (c1))
|
||||
c1 = tolower (c1);
|
||||
if (isalpha (c2))
|
||||
c2 = tolower (c2);
|
||||
|
||||
/* Do these ever fail? */
|
||||
if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
|
||||
pfatal_with_name ("get{e}[gu]id");
|
||||
if (c1 != '\0' && c1 == c2)
|
||||
continue;
|
||||
|
||||
log_access (_("Initialized access"));
|
||||
|
||||
current_access = make;
|
||||
return (c1 - c2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GETLOADAVG_PRIVILEGED */
|
||||
#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI
|
||||
/* If we don't have strncasecmp() (from POSIX), or anything that can
|
||||
substitute for it, define our own version. */
|
||||
|
||||
/* Give the process appropriate permissions for access to
|
||||
user data (i.e., to stat files, or to spawn a child process). */
|
||||
void
|
||||
user_access (void)
|
||||
int
|
||||
strncasecmp (const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
#ifdef GETLOADAVG_PRIVILEGED
|
||||
while (n-- > 0)
|
||||
{
|
||||
int c1 = (unsigned char) *(s1++);
|
||||
int c2 = (unsigned char) *(s2++);
|
||||
|
||||
if (!access_inited)
|
||||
init_access ();
|
||||
if (isalpha (c1))
|
||||
c1 = tolower (c1);
|
||||
if (isalpha (c2))
|
||||
c2 = tolower (c2);
|
||||
|
||||
if (current_access == user)
|
||||
return;
|
||||
if (c1 != '\0' && c1 == c2)
|
||||
continue;
|
||||
|
||||
/* We are in "make access" mode. This means that the effective user and
|
||||
group IDs are those of make (if it was installed setuid or setgid).
|
||||
We now want to set the effective user and group IDs to the real IDs,
|
||||
which are the IDs of the process that exec'd make. */
|
||||
return (c1 - c2);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETEUID
|
||||
|
||||
/* Modern systems have the seteuid/setegid calls which set only the
|
||||
effective IDs, which is ideal. */
|
||||
|
||||
if (seteuid (user_uid) < 0)
|
||||
pfatal_with_name ("user_access: seteuid");
|
||||
|
||||
#else /* Not HAVE_SETEUID. */
|
||||
|
||||
#ifndef HAVE_SETREUID
|
||||
|
||||
/* System V has only the setuid/setgid calls to set user/group IDs.
|
||||
There is an effective ID, which can be set by setuid/setgid.
|
||||
It can be set (unless you are root) only to either what it already is
|
||||
(returned by geteuid/getegid, now in make_uid/make_gid),
|
||||
the real ID (return by getuid/getgid, now in user_uid/user_gid),
|
||||
or the saved set ID (what the effective ID was before this set-ID
|
||||
executable (make) was exec'd). */
|
||||
|
||||
if (setuid (user_uid) < 0)
|
||||
pfatal_with_name ("user_access: setuid");
|
||||
|
||||
#else /* HAVE_SETREUID. */
|
||||
|
||||
/* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
|
||||
They may be set to themselves or each other. So you have two alternatives
|
||||
at any one time. If you use setuid/setgid, the effective will be set to
|
||||
the real, leaving only one alternative. Using setreuid/setregid, however,
|
||||
you can toggle between your two alternatives by swapping the values in a
|
||||
single setreuid or setregid call. */
|
||||
|
||||
if (setreuid (make_uid, user_uid) < 0)
|
||||
pfatal_with_name ("user_access: setreuid");
|
||||
|
||||
#endif /* Not HAVE_SETREUID. */
|
||||
#endif /* HAVE_SETEUID. */
|
||||
|
||||
#ifdef HAVE_SETEGID
|
||||
if (setegid (user_gid) < 0)
|
||||
pfatal_with_name ("user_access: setegid");
|
||||
#else
|
||||
#ifndef HAVE_SETREGID
|
||||
if (setgid (user_gid) < 0)
|
||||
pfatal_with_name ("user_access: setgid");
|
||||
#else
|
||||
if (setregid (make_gid, user_gid) < 0)
|
||||
pfatal_with_name ("user_access: setregid");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
current_access = user;
|
||||
|
||||
log_access (_("User access"));
|
||||
|
||||
#endif /* GETLOADAVG_PRIVILEGED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Give the process appropriate permissions for access to
|
||||
make data (i.e., the load average). */
|
||||
void
|
||||
make_access (void)
|
||||
{
|
||||
#ifdef GETLOADAVG_PRIVILEGED
|
||||
|
||||
if (!access_inited)
|
||||
init_access ();
|
||||
|
||||
if (current_access == make)
|
||||
return;
|
||||
|
||||
/* See comments in user_access, above. */
|
||||
|
||||
#ifdef HAVE_SETEUID
|
||||
if (seteuid (make_uid) < 0)
|
||||
pfatal_with_name ("make_access: seteuid");
|
||||
#else
|
||||
#ifndef HAVE_SETREUID
|
||||
if (setuid (make_uid) < 0)
|
||||
pfatal_with_name ("make_access: setuid");
|
||||
#else
|
||||
if (setreuid (user_uid, make_uid) < 0)
|
||||
pfatal_with_name ("make_access: setreuid");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETEGID
|
||||
if (setegid (make_gid) < 0)
|
||||
pfatal_with_name ("make_access: setegid");
|
||||
#else
|
||||
#ifndef HAVE_SETREGID
|
||||
if (setgid (make_gid) < 0)
|
||||
pfatal_with_name ("make_access: setgid");
|
||||
#else
|
||||
if (setregid (user_gid, make_gid) < 0)
|
||||
pfatal_with_name ("make_access: setregid");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
current_access = make;
|
||||
|
||||
log_access (_("Make access"));
|
||||
|
||||
#endif /* GETLOADAVG_PRIVILEGED */
|
||||
}
|
||||
|
||||
/* Give the process appropriate permissions for a child process.
|
||||
This is like user_access, but you can't get back to make_access. */
|
||||
void
|
||||
child_access (void)
|
||||
{
|
||||
#ifdef GETLOADAVG_PRIVILEGED
|
||||
|
||||
if (!access_inited)
|
||||
abort ();
|
||||
|
||||
/* Set both the real and effective UID and GID to the user's.
|
||||
They cannot be changed back to make's. */
|
||||
|
||||
#ifndef HAVE_SETREUID
|
||||
if (setuid (user_uid) < 0)
|
||||
pfatal_with_name ("child_access: setuid");
|
||||
#else
|
||||
if (setreuid (user_uid, user_uid) < 0)
|
||||
pfatal_with_name ("child_access: setreuid");
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETREGID
|
||||
if (setgid (user_gid) < 0)
|
||||
pfatal_with_name ("child_access: setgid");
|
||||
#else
|
||||
if (setregid (user_gid, user_gid) < 0)
|
||||
pfatal_with_name ("child_access: setregid");
|
||||
#endif
|
||||
|
||||
log_access (_("Child access"));
|
||||
|
||||
#endif /* GETLOADAVG_PRIVILEGED */
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEED_GET_PATH_MAX
|
||||
unsigned int
|
||||
|
@ -645,13 +881,163 @@ get_path_max (void)
|
|||
|
||||
if (value == 0)
|
||||
{
|
||||
long int x = pathconf ("/", _PC_PATH_MAX);
|
||||
long x = pathconf ("/", _PC_PATH_MAX);
|
||||
if (x > 0)
|
||||
value = x;
|
||||
value = (unsigned int) x;
|
||||
else
|
||||
return MAXPATHLEN;
|
||||
value = PATH_MAX;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_MEMPCPY
|
||||
void *
|
||||
mempcpy (void *dest, const void *src, size_t n)
|
||||
{
|
||||
return (char *) memcpy (dest, src, n) + n;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_STPCPY
|
||||
char *
|
||||
stpcpy (char *dest, const char *src)
|
||||
{
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
|
||||
do
|
||||
*d++ = *s;
|
||||
while (*s++ != '\0');
|
||||
|
||||
return d - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_STRTOLL
|
||||
# undef UNSIGNED
|
||||
# undef USE_NUMBER_GROUPING
|
||||
# undef USE_WIDE_CHAR
|
||||
# define QUAD 1
|
||||
# include <strtol.c>
|
||||
#endif
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
char *
|
||||
strerror (int errnum)
|
||||
{
|
||||
static char msg[256];
|
||||
|
||||
#define SETMSG(_e, _m) case _e: strcpy(msg, _m); break
|
||||
|
||||
switch (errnum)
|
||||
{
|
||||
#ifdef EPERM
|
||||
SETMSG (EPERM , "Operation not permitted");
|
||||
#endif
|
||||
#ifdef ENOENT
|
||||
SETMSG (ENOENT , "No such file or directory");
|
||||
#endif
|
||||
#ifdef ESRCH
|
||||
SETMSG (ESRCH , "No such process");
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
SETMSG (EINTR , "Interrupted system call");
|
||||
#endif
|
||||
#ifdef EIO
|
||||
SETMSG (EIO , "I/O error");
|
||||
#endif
|
||||
#ifdef ENXIO
|
||||
SETMSG (ENXIO , "No such device or address");
|
||||
#endif
|
||||
#ifdef E2BIG
|
||||
SETMSG (E2BIG , "Argument list too long");
|
||||
#endif
|
||||
#ifdef ENOEXEC
|
||||
SETMSG (ENOEXEC, "Exec format error");
|
||||
#endif
|
||||
#ifdef EBADF
|
||||
SETMSG (EBADF , "Bad file number");
|
||||
#endif
|
||||
#ifdef ECHILD
|
||||
SETMSG (ECHILD , "No child processes");
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
SETMSG (EAGAIN , "Try again");
|
||||
#endif
|
||||
#ifdef ENOMEM
|
||||
SETMSG (ENOMEM , "Out of memory");
|
||||
#endif
|
||||
#ifdef EACCES
|
||||
SETMSG (EACCES , "Permission denied");
|
||||
#endif
|
||||
#ifdef EFAULT
|
||||
SETMSG (EFAULT , "Bad address");
|
||||
#endif
|
||||
#ifdef ENOTBLK
|
||||
SETMSG (ENOTBLK, "Block device required");
|
||||
#endif
|
||||
#ifdef EBUSY
|
||||
SETMSG (EBUSY , "Device or resource busy");
|
||||
#endif
|
||||
#ifdef EEXIST
|
||||
SETMSG (EEXIST , "File exists");
|
||||
#endif
|
||||
#ifdef EXDEV
|
||||
SETMSG (EXDEV , "Cross-device link");
|
||||
#endif
|
||||
#ifdef ENODEV
|
||||
SETMSG (ENODEV , "No such device");
|
||||
#endif
|
||||
#ifdef ENOTDIR
|
||||
SETMSG (ENOTDIR, "Not a directory");
|
||||
#endif
|
||||
#ifdef EISDIR
|
||||
SETMSG (EISDIR , "Is a directory");
|
||||
#endif
|
||||
#ifdef EINVAL
|
||||
SETMSG (EINVAL , "Invalid argument");
|
||||
#endif
|
||||
#ifdef ENFILE
|
||||
SETMSG (ENFILE , "File table overflow");
|
||||
#endif
|
||||
#ifdef EMFILE
|
||||
SETMSG (EMFILE , "Too many open files");
|
||||
#endif
|
||||
#ifdef ENOTTY
|
||||
SETMSG (ENOTTY , "Not a typewriter");
|
||||
#endif
|
||||
#ifdef ETXTBSY
|
||||
SETMSG (ETXTBSY, "Text file busy");
|
||||
#endif
|
||||
#ifdef EFBIG
|
||||
SETMSG (EFBIG , "File too large");
|
||||
#endif
|
||||
#ifdef ENOSPC
|
||||
SETMSG (ENOSPC , "No space left on device");
|
||||
#endif
|
||||
#ifdef ESPIPE
|
||||
SETMSG (ESPIPE , "Illegal seek");
|
||||
#endif
|
||||
#ifdef EROFS
|
||||
SETMSG (EROFS , "Read-only file system");
|
||||
#endif
|
||||
#ifdef EMLINK
|
||||
SETMSG (EMLINK , "Too many links");
|
||||
#endif
|
||||
#ifdef EPIPE
|
||||
SETMSG (EPIPE , "Broken pipe");
|
||||
#endif
|
||||
#ifdef EDOM
|
||||
SETMSG (EDOM , "Math argument out of domain of func");
|
||||
#endif
|
||||
#ifdef ERANGE
|
||||
SETMSG (ERANGE , "Math result not representable");
|
||||
#endif
|
||||
default: sprintf (msg, "Unknown error %d", errnum); break;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
#endif
|
||||
|
|
37
third_party/make/mkconfig.h
vendored
Normal file
37
third_party/make/mkconfig.h
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* src/mkconfig.h. Generated from mkconfig.h.in by configure. */
|
||||
/* Autoconf values for use on non-POSIX systems.
|
||||
Copyright (C) 2022-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/>. */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "make"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "bug-make@gnu.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "GNU Make"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "GNU Make 4.4.1"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "make"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL "https://www.gnu.org/software/make/"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "4.4.1"
|
65
third_party/make/mkcustom.h
vendored
Normal file
65
third_party/make/mkcustom.h
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* Miscellaneous global declarations and portability cruft for GNU Make.
|
||||
Copyright (C) 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/>. */
|
||||
|
||||
/*
|
||||
This file is included at the end of config.h
|
||||
|
||||
That means it's included _everywhere_ as the first thing,
|
||||
INCLUDING content imported from gnulib. BE AWARE!!
|
||||
*/
|
||||
|
||||
#undef HAVE_CONFIG_H
|
||||
#define HAVE_CONFIG_H 1
|
||||
|
||||
/* Specify we want GNU source code. This must be defined before any
|
||||
system headers are included. */
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
#else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# if !defined(__GNUC__) && !defined(WINDOWS32)
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare function prototypes for src/misc.c functions if needed. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
|
||||
int strcasecmp (const char *s1, const char *s2);
|
||||
#endif
|
||||
|
||||
#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI
|
||||
int strncasecmp (const char *s1, const char *s2, size_t n);
|
||||
#endif
|
||||
|
||||
#if !HAVE_MEMPCPY
|
||||
void *mempcpy (void *dest, const void *src, size_t n);
|
||||
#endif
|
||||
|
||||
#if !HAVE_STPCPY
|
||||
char *stpcpy (char *dest, const char *src);
|
||||
#endif
|
101
third_party/make/os.h
vendored
101
third_party/make/os.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Declarations for operating system interfaces for GNU Make.
|
||||
Copyright (C) 2016-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2016-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
|
||||
|
@ -12,8 +12,35 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define IO_UNKNOWN 0x0001
|
||||
#define IO_COMBINED_OUTERR 0x0002
|
||||
#define IO_STDIN_OK 0x0004
|
||||
#define IO_STDOUT_OK 0x0008
|
||||
#define IO_STDERR_OK 0x0010
|
||||
|
||||
#if defined(VMS) || defined(_AMIGA) || defined(__MSDOS__)
|
||||
# define check_io_state() (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)
|
||||
# define fd_inherit(_i) (0)
|
||||
# define fd_noinherit(_i) (0)
|
||||
# define fd_set_append(_i) (void)(0)
|
||||
# define os_anontmp() (-1)
|
||||
#else
|
||||
|
||||
/* Determine the state of stdin/stdout/stderr. */
|
||||
unsigned int check_io_state (void);
|
||||
|
||||
/* Set a file descriptor to close/not close in a subprocess. */
|
||||
void fd_inherit (int);
|
||||
void fd_noinherit (int);
|
||||
|
||||
/* If the file descriptor is for a file put it into append mode. */
|
||||
void fd_set_append (int);
|
||||
|
||||
/* Return a file descriptor for a new anonymous temp file, or -1. */
|
||||
int os_anontmp (void);
|
||||
#endif
|
||||
|
||||
/* This section provides OS-specific functions to support the jobserver. */
|
||||
|
||||
|
@ -22,19 +49,26 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
/* Returns 1 if the jobserver is enabled, else 0. */
|
||||
unsigned int jobserver_enabled (void);
|
||||
|
||||
/* Called in the master instance to set up the jobserver initially. */
|
||||
unsigned int jobserver_setup (int job_slots);
|
||||
/* Called in the parent make to set up the jobserver initially. */
|
||||
unsigned int jobserver_setup (int job_slots, const char *style);
|
||||
|
||||
/* Called in a child instance to connect to the jobserver. */
|
||||
/* Called in a child instance to connect to the jobserver.
|
||||
Return 1 if we got a valid auth, else 0. */
|
||||
unsigned int jobserver_parse_auth (const char* auth);
|
||||
|
||||
/* Returns an allocated buffer used to pass to child instances. */
|
||||
char *jobserver_get_auth (void);
|
||||
|
||||
/* Clear this instance's jobserver configuration. */
|
||||
/* Returns a pointer to a static string used to indicate that the child
|
||||
cannot access the jobserver, or NULL if it always can. */
|
||||
const char *jobserver_get_invalid_auth (void);
|
||||
|
||||
/* Clear this instance's jobserver configuration.
|
||||
This method might be invoked from a signal handler. */
|
||||
void jobserver_clear (void);
|
||||
|
||||
/* Recover all the jobserver tokens and return the number we got. */
|
||||
/* Recover all the jobserver tokens and return the number we got.
|
||||
Will also run jobserver_clear() as a side-effect. */
|
||||
unsigned int jobserver_acquire_all (void);
|
||||
|
||||
/* Release a jobserver token. If it fails and is_fatal is 1, fatal. */
|
||||
|
@ -62,9 +96,10 @@ unsigned int jobserver_acquire (int timeout);
|
|||
#else
|
||||
|
||||
#define jobserver_enabled() (0)
|
||||
#define jobserver_setup(_slots) (0)
|
||||
#define jobserver_setup(_slots, _style) (0)
|
||||
#define jobserver_parse_auth(_auth) (0)
|
||||
#define jobserver_get_auth() (NULL)
|
||||
#define jobserver_get_invalid_auth() (NULL)
|
||||
#define jobserver_clear() (void)(0)
|
||||
#define jobserver_release(_fatal) (void)(0)
|
||||
#define jobserver_acquire_all() (0)
|
||||
|
@ -74,7 +109,46 @@ unsigned int jobserver_acquire (int timeout);
|
|||
#define jobserver_pre_acquire() (void)(0)
|
||||
#define jobserver_acquire(_tmout) (0)
|
||||
|
||||
#endif
|
||||
#endif /* MAKE_JOBSERVER */
|
||||
|
||||
#ifndef NO_OUTPUT_SYNC
|
||||
|
||||
/* Returns 1 if output sync is enabled, else 0. */
|
||||
unsigned int osync_enabled (void);
|
||||
|
||||
/* Called in the parent make to set up output sync initially. */
|
||||
void osync_setup (void);
|
||||
|
||||
/* Returns an allocated buffer containing output sync info to pass to child
|
||||
instances, or NULL if not needed. */
|
||||
char *osync_get_mutex (void);
|
||||
|
||||
/* Called in a child instance to obtain info on the output sync mutex.
|
||||
Return 1 if we got a valid mutex, else 0. */
|
||||
unsigned int osync_parse_mutex (const char *mutex);
|
||||
|
||||
/* Clean up this instance's output sync facilities.
|
||||
This method might be invoked from a signal handler. */
|
||||
void osync_clear (void);
|
||||
|
||||
/* Acquire the output sync lock. This will wait until available.
|
||||
Returns 0 if there was an error getting the semaphore. */
|
||||
unsigned int osync_acquire (void);
|
||||
|
||||
/* Release the output sync lock. */
|
||||
void osync_release (void);
|
||||
|
||||
#else
|
||||
|
||||
#define osync_enabled() (0)
|
||||
#define osync_setup() (void)(0)
|
||||
#define osync_get_mutex() (0)
|
||||
#define osync_parse_mutex(_s) (0)
|
||||
#define osync_clear() (void)(0)
|
||||
#define osync_acquire() (1)
|
||||
#define osync_release() (void)(0)
|
||||
|
||||
#endif /* NO_OUTPUT_SYNC */
|
||||
|
||||
/* Create a "bad" file descriptor for stdin when parallel jobs are run. */
|
||||
#if defined(VMS) || defined(WINDOWS32) || defined(_AMIGA) || defined(__MSDOS__)
|
||||
|
@ -82,12 +156,3 @@ unsigned int jobserver_acquire (int timeout);
|
|||
#else
|
||||
int get_bad_stdin (void);
|
||||
#endif
|
||||
|
||||
/* Set a file descriptor to close/not close in a subprocess. */
|
||||
#if defined(VMS) || defined(_AMIGA) || defined(__MSDOS__)
|
||||
# define fd_inherit(_i) 0
|
||||
# define fd_noinherit(_i) 0
|
||||
#else
|
||||
void fd_inherit (int);
|
||||
void fd_noinherit (int);
|
||||
#endif
|
||||
|
|
310
third_party/make/output.c
vendored
310
third_party/make/output.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Output to stdout / stderr for GNU make
|
||||
Copyright (C) 2013-2020 Free Software Foundation, Inc.
|
||||
/* Output to stdout / stderr for GNU Make
|
||||
Copyright (C) 2013-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
|
||||
|
@ -12,15 +12,27 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/os.h"
|
||||
#include "third_party/make/output.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "makeint.h"
|
||||
#include "os.h"
|
||||
#include "output.h"
|
||||
|
||||
/* GNU make no longer supports pre-ANSI89 environments. */
|
||||
/* GNU Make no longer supports pre-ANSI89 environments. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
struct output *output_context = NULL;
|
||||
unsigned int stdio_traced = 0;
|
||||
|
@ -29,30 +41,28 @@ unsigned int stdio_traced = 0;
|
|||
|
||||
#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
|
||||
#else
|
||||
# define STREAM_OK(_s) 1
|
||||
#endif
|
||||
|
||||
/* Write a string to the current STDOUT or STDERR. */
|
||||
static void
|
||||
_outputs (struct output *out, int is_err, const char *msg)
|
||||
{
|
||||
if (! out || ! out->syncout)
|
||||
{
|
||||
FILE *f = is_err ? stderr : stdout;
|
||||
fputs (msg, f);
|
||||
fflush (f);
|
||||
}
|
||||
else
|
||||
FILE *f;
|
||||
|
||||
if (out && out->syncout)
|
||||
{
|
||||
int fd = is_err ? out->err : out->out;
|
||||
if (fd != OUTPUT_NONE)
|
||||
{
|
||||
size_t len = strlen (msg);
|
||||
int r;
|
||||
EINTRLOOP (r, lseek (fd, 0, SEEK_END));
|
||||
writebuf (fd, msg, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
f = is_err ? stderr : stdout;
|
||||
fputs (msg, f);
|
||||
fflush (f);
|
||||
}
|
||||
|
||||
/* Write a message indicating that we've just entered or
|
||||
|
@ -125,73 +135,10 @@ log_working_directory (int entering)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set a file descriptor to be in O_APPEND mode.
|
||||
If it fails, just ignore it. */
|
||||
|
||||
static void
|
||||
set_append_mode (int fd)
|
||||
{
|
||||
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
|
||||
int flags = fcntl (fd, F_GETFL, 0);
|
||||
if (flags >= 0)
|
||||
{
|
||||
int r;
|
||||
EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_OUTPUT_SYNC
|
||||
|
||||
/* Semaphore for use in -j mode with output_sync. */
|
||||
static sync_handle_t sync_handle = -1;
|
||||
|
||||
#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
|
||||
|
||||
/* Set up the sync handle. Disables output_sync on error. */
|
||||
static int
|
||||
sync_init (void)
|
||||
{
|
||||
int combined_output = 0;
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
|
||||
|| (sync_handle = create_mutex ()) == -1)
|
||||
{
|
||||
perror_with_name ("output-sync suppressed: ", "stderr");
|
||||
output_sync = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
combined_output = same_stream (stdout, stderr);
|
||||
prepare_mutex_handle_string (sync_handle);
|
||||
}
|
||||
|
||||
#else
|
||||
if (STREAM_OK (stdout))
|
||||
{
|
||||
struct stat stbuf_o, stbuf_e;
|
||||
|
||||
sync_handle = fileno (stdout);
|
||||
combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
|
||||
&& fstat (fileno (stderr), &stbuf_e) == 0
|
||||
&& stbuf_o.st_dev == stbuf_e.st_dev
|
||||
&& stbuf_o.st_ino == stbuf_e.st_ino);
|
||||
}
|
||||
else if (STREAM_OK (stderr))
|
||||
sync_handle = fileno (stderr);
|
||||
else
|
||||
{
|
||||
perror_with_name ("output-sync suppressed: ", "stderr");
|
||||
output_sync = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return combined_output;
|
||||
}
|
||||
|
||||
/* Support routine for output_sync() */
|
||||
static void
|
||||
pump_from_tmp (int from, FILE *to)
|
||||
|
@ -232,55 +179,13 @@ pump_from_tmp (int from, FILE *to)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Obtain the lock for writing output. */
|
||||
static void *
|
||||
acquire_semaphore (void)
|
||||
{
|
||||
static struct flock fl;
|
||||
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 1;
|
||||
if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
|
||||
return &fl;
|
||||
perror ("fcntl()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Release the lock for writing output. */
|
||||
static void
|
||||
release_semaphore (void *sem)
|
||||
{
|
||||
struct flock *flp = (struct flock *)sem;
|
||||
flp->l_type = F_UNLCK;
|
||||
if (fcntl (sync_handle, F_SETLKW, flp) == -1)
|
||||
perror ("fcntl()");
|
||||
}
|
||||
|
||||
/* Returns a file descriptor to a temporary file. The file is automatically
|
||||
closed/deleted on exit. Don't use a FILE* stream. */
|
||||
/* Returns a file descriptor to a temporary file, that will be automatically
|
||||
deleted on exit. */
|
||||
int
|
||||
output_tmpfd (void)
|
||||
{
|
||||
mode_t mask = umask (0077);
|
||||
int fd = -1;
|
||||
FILE *tfile = tmpfile ();
|
||||
|
||||
if (! tfile)
|
||||
pfatal_with_name ("tmpfile");
|
||||
|
||||
/* Create a duplicate so we can close the stream. */
|
||||
fd = dup (fileno (tfile));
|
||||
if (fd < 0)
|
||||
pfatal_with_name ("dup");
|
||||
|
||||
fclose (tfile);
|
||||
|
||||
set_append_mode (fd);
|
||||
|
||||
umask (mask);
|
||||
|
||||
int fd = get_tmpfd (NULL);
|
||||
fd_set_append (fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -291,13 +196,25 @@ output_tmpfd (void)
|
|||
static void
|
||||
setup_tmpfile (struct output *out)
|
||||
{
|
||||
/* Is make's stdout going to the same place as stderr? */
|
||||
static int combined_output = -1;
|
||||
static unsigned int in_setup = 0;
|
||||
unsigned int io_state;
|
||||
|
||||
if (combined_output < 0)
|
||||
combined_output = sync_init ();
|
||||
/* If something fails during setup we might recurse back into this function
|
||||
while writing errors. Make sure we don't do so infinitely. */
|
||||
if (in_setup)
|
||||
return;
|
||||
in_setup = 1;
|
||||
|
||||
if (STREAM_OK (stdout))
|
||||
io_state = check_io_state ();
|
||||
|
||||
if (NONE_SET (io_state, IO_STDOUT_OK|IO_STDERR_OK))
|
||||
{
|
||||
/* This is probably useless since stdout/stderr aren't working. */
|
||||
perror_with_name ("output-sync suppressed: ", "stderr");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ANY_SET (io_state, IO_STDOUT_OK))
|
||||
{
|
||||
int fd = output_tmpfd ();
|
||||
if (fd < 0)
|
||||
|
@ -306,9 +223,9 @@ setup_tmpfile (struct output *out)
|
|||
out->out = fd;
|
||||
}
|
||||
|
||||
if (STREAM_OK (stderr))
|
||||
if (ANY_SET (io_state, IO_STDERR_OK))
|
||||
{
|
||||
if (out->out != OUTPUT_NONE && combined_output)
|
||||
if (out->out != OUTPUT_NONE && ANY_SET (io_state, IO_COMBINED_OUTERR))
|
||||
out->err = out->out;
|
||||
else
|
||||
{
|
||||
|
@ -320,12 +237,18 @@ setup_tmpfile (struct output *out)
|
|||
}
|
||||
}
|
||||
|
||||
in_setup = 0;
|
||||
return;
|
||||
|
||||
/* If we failed to create a temp file, disable output sync going forward. */
|
||||
error:
|
||||
O (error, NILF,
|
||||
_("cannot open output-sync lock file, suppressing output-sync."));
|
||||
|
||||
output_close (out);
|
||||
output_sync = OUTPUT_SYNC_NONE;
|
||||
osync_clear ();
|
||||
in_setup = 0;
|
||||
}
|
||||
|
||||
/* Synchronize the output of jobs in -j mode to keep the results of
|
||||
|
@ -336,6 +259,8 @@ setup_tmpfile (struct output *out)
|
|||
void
|
||||
output_dump (struct output *out)
|
||||
{
|
||||
#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
|
||||
|
||||
int outfd_not_empty = FD_NOT_EMPTY (out->out);
|
||||
int errfd_not_empty = FD_NOT_EMPTY (out->err);
|
||||
|
||||
|
@ -346,10 +271,16 @@ output_dump (struct output *out)
|
|||
/* Try to acquire the semaphore. If it fails, dump the output
|
||||
unsynchronized; still better than silently discarding it.
|
||||
We want to keep this lock for as little time as possible. */
|
||||
void *sem = acquire_semaphore ();
|
||||
if (!osync_acquire ())
|
||||
{
|
||||
O (error, NILF,
|
||||
_("warning: Cannot acquire output lock, disabling output sync."));
|
||||
osync_clear ();
|
||||
}
|
||||
|
||||
/* Log the working directory for this dump. */
|
||||
if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
|
||||
|
||||
if (output_sync != OUTPUT_SYNC_RECURSE && should_print_dir ())
|
||||
traced = log_working_directory (1);
|
||||
|
||||
if (outfd_not_empty)
|
||||
|
@ -361,8 +292,7 @@ output_dump (struct output *out)
|
|||
log_working_directory (0);
|
||||
|
||||
/* Exit the critical section. */
|
||||
if (sem)
|
||||
release_semaphore (sem);
|
||||
osync_release ();
|
||||
|
||||
/* Truncate and reset the output, in case we use it again. */
|
||||
if (out->out != OUTPUT_NONE)
|
||||
|
@ -382,53 +312,6 @@ output_dump (struct output *out)
|
|||
#endif /* NO_OUTPUT_SYNC */
|
||||
|
||||
|
||||
/* This code is stolen from gnulib.
|
||||
If/when we abandon the requirement to work with K&R compilers, we can
|
||||
remove this (and perhaps other parts of GNU make!) and migrate to using
|
||||
gnulib directly.
|
||||
|
||||
This is called only through atexit(), which means die() has already been
|
||||
invoked. So, call exit() here directly. Apparently that works...?
|
||||
*/
|
||||
|
||||
/* Close standard output, exiting with status 'exit_failure' on failure.
|
||||
If a program writes *anything* to stdout, that program should close
|
||||
stdout and make sure that it succeeds before exiting. Otherwise,
|
||||
suppose that you go to the extreme of checking the return status
|
||||
of every function that does an explicit write to stdout. The last
|
||||
printf can succeed in writing to the internal stream buffer, and yet
|
||||
the fclose(stdout) could still fail (due e.g., to a disk full error)
|
||||
when it tries to write out that buffered data. Thus, you would be
|
||||
left with an incomplete output file and the offending program would
|
||||
exit successfully. Even calling fflush is not always sufficient,
|
||||
since some file systems (NFS and CODA) buffer written/flushed data
|
||||
until an actual close call.
|
||||
|
||||
Besides, it's wasteful to check the return value from every call
|
||||
that writes to stdout -- just let the internal stream state record
|
||||
the failure. That's what the ferror test is checking below.
|
||||
|
||||
It's important to detect such failures and exit nonzero because many
|
||||
tools (most notably 'make' and other build-management systems) depend
|
||||
on being able to detect failure in other tools via their exit status. */
|
||||
|
||||
static void
|
||||
close_stdout (void)
|
||||
{
|
||||
int prev_fail = ferror (stdout);
|
||||
int fclose_fail = fclose (stdout);
|
||||
|
||||
if (prev_fail || fclose_fail)
|
||||
{
|
||||
if (fclose_fail)
|
||||
perror_with_name (_("write error: stdout"), "");
|
||||
else
|
||||
O (error, NILF, _("write error: stdout"));
|
||||
exit (MAKE_TROUBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
output_init (struct output *out)
|
||||
{
|
||||
|
@ -439,28 +322,10 @@ output_init (struct output *out)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Configure this instance of make. Be sure stdout is line-buffered. */
|
||||
|
||||
#ifdef HAVE_SETVBUF
|
||||
# ifdef SETVBUF_REVERSED
|
||||
setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
|
||||
# else /* setvbuf not reversed. */
|
||||
/* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
|
||||
setvbuf (stdout, 0, _IOLBF, BUFSIZ);
|
||||
# endif /* setvbuf reversed. */
|
||||
#elif HAVE_SETLINEBUF
|
||||
setlinebuf (stdout);
|
||||
#endif /* setlinebuf missing. */
|
||||
|
||||
/* Force stdout/stderr into append mode. This ensures parallel jobs won't
|
||||
lose output due to overlapping writes. */
|
||||
set_append_mode (fileno (stdout));
|
||||
set_append_mode (fileno (stderr));
|
||||
|
||||
#ifdef HAVE_ATEXIT
|
||||
if (STREAM_OK (stdout))
|
||||
atexit (close_stdout);
|
||||
#endif
|
||||
/* Force stdout/stderr into append mode (if they are files) to ensure
|
||||
parallel jobs won't lose output due to overlapping writes. */
|
||||
fd_set_append (fileno (stdout));
|
||||
fd_set_append (fileno (stderr));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -499,7 +364,7 @@ output_start (void)
|
|||
/* If we're not syncing this output per-line or per-target, make sure we emit
|
||||
the "Entering..." message where appropriate. */
|
||||
if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
|
||||
if (! stdio_traced && print_directory_flag)
|
||||
if (! stdio_traced && should_print_dir ())
|
||||
stdio_traced = log_working_directory (1);
|
||||
}
|
||||
|
||||
|
@ -542,10 +407,11 @@ void
|
|||
message (int prefix, size_t len, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *start;
|
||||
char *p;
|
||||
|
||||
len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
|
||||
p = get_buffer (len);
|
||||
start = p = get_buffer (len);
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
|
@ -562,8 +428,8 @@ message (int prefix, size_t len, const char *fmt, ...)
|
|||
|
||||
strcat (p, "\n");
|
||||
|
||||
assert (fmtbuf.buffer[len-1] == '\0');
|
||||
outputs (0, fmtbuf.buffer);
|
||||
assert (start[len-1] == '\0');
|
||||
outputs (0, start);
|
||||
}
|
||||
|
||||
/* Print an error message. */
|
||||
|
@ -572,12 +438,13 @@ void
|
|||
error (const floc *flocp, size_t len, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *start;
|
||||
char *p;
|
||||
|
||||
len += (strlen (fmt) + strlen (program)
|
||||
+ (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
|
||||
+ INTSTR_LENGTH + 4 + 1 + 1);
|
||||
p = get_buffer (len);
|
||||
start = p = get_buffer (len);
|
||||
|
||||
if (flocp && flocp->filenm)
|
||||
sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
|
||||
|
@ -593,8 +460,8 @@ error (const floc *flocp, size_t len, const char *fmt, ...)
|
|||
|
||||
strcat (p, "\n");
|
||||
|
||||
assert (fmtbuf.buffer[len-1] == '\0');
|
||||
outputs (1, fmtbuf.buffer);
|
||||
assert (start[len-1] == '\0');
|
||||
outputs (1, start);
|
||||
}
|
||||
|
||||
/* Print an error message and exit. */
|
||||
|
@ -604,12 +471,13 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
|
|||
{
|
||||
va_list args;
|
||||
const char *stop = _(". Stop.\n");
|
||||
char *start;
|
||||
char *p;
|
||||
|
||||
len += (strlen (fmt) + strlen (program)
|
||||
+ (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
|
||||
+ INTSTR_LENGTH + 8 + strlen (stop) + 1);
|
||||
p = get_buffer (len);
|
||||
start = p = get_buffer (len);
|
||||
|
||||
if (flocp && flocp->filenm)
|
||||
sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
|
||||
|
@ -625,8 +493,8 @@ fatal (const floc *flocp, size_t len, const char *fmt, ...)
|
|||
|
||||
strcat (p, stop);
|
||||
|
||||
assert (fmtbuf.buffer[len-1] == '\0');
|
||||
outputs (1, fmtbuf.buffer);
|
||||
assert (start[len-1] == '\0');
|
||||
outputs (1, start);
|
||||
|
||||
die (MAKE_FAILURE);
|
||||
}
|
||||
|
|
54
third_party/make/output.h
vendored
54
third_party/make/output.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Output to stdout / stderr for GNU make
|
||||
Copyright (C) 2013-2020 Free Software Foundation, Inc.
|
||||
/* Output to stdout / stderr for GNU Make
|
||||
Copyright (C) 2013-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
|
||||
|
@ -12,7 +12,7 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
struct output
|
||||
{
|
||||
|
@ -50,51 +50,9 @@ void output_start (void);
|
|||
/* Show a message on stdout or stderr. Will start the output if needed. */
|
||||
void outputs (int is_err, const char *msg);
|
||||
|
||||
#ifdef NO_OUTPUT_SYNC
|
||||
# define RECORD_SYNC_MUTEX(m) \
|
||||
O (error, NILF, \
|
||||
_("-O[TYPE] (--output-sync[=TYPE]) is not configured for this build."));
|
||||
#if defined(NO_OUTPUT_SYNC)
|
||||
# define output_dump(_o) (void)(0)
|
||||
#else
|
||||
int output_tmpfd (void);
|
||||
/* Dump any child output content to stdout, and reset it. */
|
||||
void output_dump (struct output *out);
|
||||
|
||||
# ifdef WINDOWS32
|
||||
/* For emulations in w32/compat/posixfcn.c. */
|
||||
# define F_GETFD 1
|
||||
# define F_SETLKW 2
|
||||
/* Implementation note: None of the values of l_type below can be zero
|
||||
-- they are compared with a static instance of the struct, so zero
|
||||
means unknown/invalid, see w32/compat/posixfcn.c. */
|
||||
# define F_WRLCK 1
|
||||
# define F_UNLCK 2
|
||||
|
||||
struct flock
|
||||
{
|
||||
short l_type;
|
||||
short l_whence;
|
||||
off_t l_start;
|
||||
off_t l_len;
|
||||
pid_t l_pid;
|
||||
};
|
||||
|
||||
/* This type is actually a HANDLE, but we want to avoid including
|
||||
windows.h as much as possible. */
|
||||
typedef intptr_t sync_handle_t;
|
||||
|
||||
/* Public functions emulated/provided in posixfcn.c. */
|
||||
int fcntl (intptr_t fd, int cmd, ...);
|
||||
intptr_t create_mutex (void);
|
||||
int same_stream (FILE *f1, FILE *f2);
|
||||
|
||||
# define RECORD_SYNC_MUTEX(m) record_sync_mutex(m)
|
||||
void record_sync_mutex (const char *str);
|
||||
void prepare_mutex_handle_string (intptr_t hdl);
|
||||
# else /* !WINDOWS32 */
|
||||
|
||||
typedef int sync_handle_t; /* file descriptor */
|
||||
|
||||
# define RECORD_SYNC_MUTEX(m) (void)(m)
|
||||
|
||||
# endif
|
||||
#endif /* !NO_OUTPUT_SYNC */
|
||||
#endif
|
||||
|
|
764
third_party/make/posixos.c
vendored
764
third_party/make/posixos.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* POSIX-based operating system interface for GNU Make.
|
||||
Copyright (C) 2016-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2016-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
|
||||
|
@ -12,26 +12,79 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "third_party/make/config.h"
|
||||
#include "third_party/make/debug.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/os.h"
|
||||
#include "libc/dce.h"
|
||||
#include "makeint.h"
|
||||
|
||||
#ifdef MAKE_JOBSERVER
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
# define FD_OK(_f) (fcntl ((_f), F_GETFD) != -1)
|
||||
#elif defined(HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#if MK_OS_ZOS
|
||||
/* FIXME: HAVE_PSELECT path hangs on z/OS */
|
||||
#undef HAVE_PSELECT
|
||||
#endif
|
||||
|
||||
#if !defined(FD_OK)
|
||||
# define FD_OK(_f) 1
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PSELECT) && defined(HAVE_SYS_SELECT_H)
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "job.h"
|
||||
#include "os.h"
|
||||
|
||||
#define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
|
||||
|
||||
unsigned int
|
||||
check_io_state ()
|
||||
{
|
||||
static unsigned int state = IO_UNKNOWN;
|
||||
|
||||
/* We only need to compute this once per process. */
|
||||
if (state != IO_UNKNOWN)
|
||||
return state;
|
||||
|
||||
if (STREAM_OK (stdin))
|
||||
state |= IO_STDIN_OK;
|
||||
if (STREAM_OK (stdout))
|
||||
state |= IO_STDOUT_OK;
|
||||
if (STREAM_OK (stderr))
|
||||
state |= IO_STDERR_OK;
|
||||
|
||||
if (ALL_SET (state, IO_STDOUT_OK|IO_STDERR_OK))
|
||||
{
|
||||
struct stat stbuf_o, stbuf_e;
|
||||
|
||||
if (fstat (fileno (stdout), &stbuf_o) == 0
|
||||
&& fstat (fileno (stderr), &stbuf_e) == 0
|
||||
&& stbuf_o.st_dev == stbuf_e.st_dev
|
||||
&& stbuf_o.st_ino == stbuf_e.st_ino)
|
||||
state |= IO_COMBINED_OUTERR;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
#if defined(MAKE_JOBSERVER)
|
||||
|
||||
#define FIFO_PREFIX "fifo:"
|
||||
|
||||
/* This section provides OS-specific functions to support the jobserver. */
|
||||
|
||||
/* True if this is the root make instance. */
|
||||
static unsigned char job_root = 0;
|
||||
|
||||
/* These track the state of the jobserver pipe. Passed to child instances. */
|
||||
static int job_fds[2] = {-1, -1};
|
||||
static int job_fds[2] = { -1, -1 };
|
||||
|
||||
/* Used to signal read() that a SIGCHLD happened. Always CLOEXEC.
|
||||
If we use pselect() this will never be created and always -1.
|
||||
|
@ -41,162 +94,357 @@ static int job_rfd = -1;
|
|||
/* Token written to the pipe (could be any character...) */
|
||||
static char token = '+';
|
||||
|
||||
static int make_job_rfd(void) {
|
||||
/* The type of jobserver we're using. */
|
||||
enum js_type
|
||||
{
|
||||
js_none = 0, /* No jobserver. */
|
||||
js_pipe, /* Use a simple pipe as the jobserver. */
|
||||
js_fifo /* Use a named pipe as the jobserver. */
|
||||
};
|
||||
|
||||
static enum js_type js_type = js_none;
|
||||
|
||||
/* The name of the named pipe (if used). */
|
||||
static char *fifo_name = NULL;
|
||||
|
||||
static int
|
||||
make_job_rfd ()
|
||||
{
|
||||
#ifdef HAVE_PSELECT
|
||||
/* Pretend we succeeded. */
|
||||
return 0;
|
||||
#else
|
||||
EINTRLOOP(job_rfd, dup(job_fds[0]));
|
||||
if (job_rfd >= 0) fd_noinherit(job_rfd);
|
||||
EINTRLOOP (job_rfd, dup (job_fds[0]));
|
||||
if (job_rfd >= 0)
|
||||
fd_noinherit (job_rfd);
|
||||
|
||||
return job_rfd;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_blocking(int fd, int blocking) {
|
||||
static void
|
||||
set_blocking (int fd, int blocking)
|
||||
{
|
||||
/* If we're not using pselect() don't change the blocking. */
|
||||
#ifdef HAVE_PSELECT
|
||||
int flags;
|
||||
EINTRLOOP(flags, fcntl(fd, F_GETFL));
|
||||
if (flags >= 0) {
|
||||
EINTRLOOP (flags, fcntl (fd, F_GETFL));
|
||||
if (flags >= 0)
|
||||
{
|
||||
int r;
|
||||
flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
|
||||
EINTRLOOP(r, fcntl(fd, F_SETFL, flags));
|
||||
if (r < 0) pfatal_with_name("fcntl(O_NONBLOCK)");
|
||||
EINTRLOOP (r, fcntl (fd, F_SETFL, flags));
|
||||
if (r < 0)
|
||||
pfatal_with_name ("fcntl(O_NONBLOCK)");
|
||||
}
|
||||
#else
|
||||
(void) fd;
|
||||
(void) blocking;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int jobserver_setup(int slots) {
|
||||
unsigned int
|
||||
jobserver_setup (int slots, const char *style)
|
||||
{
|
||||
int r;
|
||||
|
||||
EINTRLOOP(r, pipe(job_fds));
|
||||
if (r < 0) pfatal_with_name(_("creating jobs pipe"));
|
||||
#if JOBSERVER_USE_FIFO
|
||||
if (!style || strcmp (style, "fifo") == 0)
|
||||
{
|
||||
/* Unfortunately glibc warns about uses of mktemp even though we aren't
|
||||
using it in dangerous way here. So avoid this by generating our own
|
||||
temporary file name. */
|
||||
# define FNAME_PREFIX "GMfifo"
|
||||
const char *tmpdir = get_tmpdir ();
|
||||
|
||||
fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX)
|
||||
+ INTSTR_LENGTH + 2);
|
||||
sprintf (fifo_name, "%s/" FNAME_PREFIX "%" MK_PRI64_PREFIX "d",
|
||||
tmpdir, (long long)make_pid ());
|
||||
|
||||
EINTRLOOP (r, mkfifo (fifo_name, 0600));
|
||||
if (r < 0)
|
||||
{
|
||||
perror_with_name("jobserver mkfifo: ", fifo_name);
|
||||
free (fifo_name);
|
||||
fifo_name = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have to open the read side in non-blocking mode, else it will
|
||||
hang until the write side is open. */
|
||||
EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY|O_NONBLOCK));
|
||||
if (job_fds[0] < 0)
|
||||
OSS (fatal, NILF, _("cannot open jobserver %s: %s"),
|
||||
fifo_name, strerror (errno));
|
||||
|
||||
EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));
|
||||
if (job_fds[0] < 0)
|
||||
OSS (fatal, NILF, _("cannot open jobserver %s: %s"),
|
||||
fifo_name, strerror (errno));
|
||||
|
||||
js_type = js_fifo;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (js_type == js_none)
|
||||
{
|
||||
if (style && strcmp (style, "pipe") != 0)
|
||||
OS (fatal, NILF, _("unknown jobserver auth style '%s'"), style);
|
||||
|
||||
EINTRLOOP (r, pipe (job_fds));
|
||||
if (r < 0)
|
||||
pfatal_with_name (_("creating jobs pipe"));
|
||||
|
||||
js_type = js_pipe;
|
||||
}
|
||||
|
||||
/* By default we don't send the job pipe FDs to our children.
|
||||
See jobserver_pre_child() and jobserver_post_child(). */
|
||||
fd_noinherit(job_fds[0]);
|
||||
fd_noinherit(job_fds[1]);
|
||||
fd_noinherit (job_fds[0]);
|
||||
fd_noinherit (job_fds[1]);
|
||||
|
||||
if (make_job_rfd() < 0) pfatal_with_name(_("duping jobs pipe"));
|
||||
if (make_job_rfd () < 0)
|
||||
pfatal_with_name (_("duping jobs pipe"));
|
||||
|
||||
while (slots--) {
|
||||
EINTRLOOP(r, write(job_fds[1], &token, 1));
|
||||
if (r != 1) pfatal_with_name(_("init jobserver pipe"));
|
||||
while (slots--)
|
||||
{
|
||||
EINTRLOOP (r, write (job_fds[1], &token, 1));
|
||||
if (r != 1)
|
||||
pfatal_with_name (_("init jobserver pipe"));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
unsigned int jobserver_parse_auth(const char *auth) {
|
||||
unsigned int
|
||||
jobserver_parse_auth (const char *auth)
|
||||
{
|
||||
int rfd, wfd;
|
||||
|
||||
/* Given the command-line parameter, parse it. */
|
||||
if (sscanf(auth, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
|
||||
OS(fatal, NILF, _("internal error: invalid --jobserver-auth string '%s'"),
|
||||
auth);
|
||||
|
||||
DB(DB_JOBS, (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
|
||||
/* First see if we're using a named pipe. */
|
||||
if (strncmp (auth, FIFO_PREFIX, CSTRLEN (FIFO_PREFIX)) == 0)
|
||||
{
|
||||
fifo_name = xstrdup (auth + CSTRLEN (FIFO_PREFIX));
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#define FD_OK(_f) (fcntl((_f), F_GETFD) != -1)
|
||||
#else
|
||||
#define FD_OK(_f) 1
|
||||
#endif
|
||||
EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY));
|
||||
if (job_fds[0] < 0)
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("cannot open jobserver %s: %s"), fifo_name, strerror (errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure our pipeline is valid, and (possibly) create a duplicate pipe,
|
||||
that will be closed in the SIGCHLD handler. If this fails with EBADF,
|
||||
the parent has closed the pipe on us because it didn't think we were a
|
||||
submake. If so, warn and default to -j1. */
|
||||
EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));
|
||||
if (job_fds[1] < 0)
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("cannot open jobserver %s: %s"), fifo_name, strerror (errno));
|
||||
return 0;
|
||||
}
|
||||
js_type = js_fifo;
|
||||
}
|
||||
/* If not, it must be a simple pipe. */
|
||||
else if (sscanf (auth, "%d,%d", &rfd, &wfd) == 2)
|
||||
{
|
||||
/* The parent overrode our FDs because we aren't a recursive make. */
|
||||
if (rfd == -2 || wfd == -2)
|
||||
return 0;
|
||||
|
||||
if (!FD_OK(job_fds[0]) || !FD_OK(job_fds[1]) || make_job_rfd() < 0) {
|
||||
if (errno != EBADF) pfatal_with_name(_("jobserver pipeline"));
|
||||
/* Make sure our pipeline is valid. */
|
||||
if (!FD_OK (rfd) || !FD_OK (wfd))
|
||||
return 0;
|
||||
|
||||
job_fds[0] = job_fds[1] = -1;
|
||||
job_fds[0] = rfd;
|
||||
job_fds[1] = wfd;
|
||||
|
||||
js_type = js_pipe;
|
||||
}
|
||||
/* Who knows what it is? */
|
||||
else
|
||||
{
|
||||
OS (error, NILF, _("invalid --jobserver-auth string '%s'"), auth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a duplicate pipe, if needed, that will be closed in the SIGCHLD
|
||||
handler. If this fails with EBADF, the parent closed the pipe on us as
|
||||
it didn't think we were a submake. If so, warn and default to -j1. */
|
||||
|
||||
if (make_job_rfd () < 0)
|
||||
{
|
||||
if (errno != EBADF)
|
||||
pfatal_with_name ("jobserver readfd");
|
||||
|
||||
jobserver_clear ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When using pselect() we want the read to be non-blocking. */
|
||||
set_blocking(job_fds[0], 0);
|
||||
set_blocking (job_fds[0], 0);
|
||||
|
||||
/* By default we don't send the job pipe FDs to our children.
|
||||
See jobserver_pre_child() and jobserver_post_child(). */
|
||||
fd_noinherit (job_fds[0]);
|
||||
fd_noinherit (job_fds[1]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *jobserver_get_auth(void) {
|
||||
char *auth = xmalloc((INTSTR_LENGTH * 2) + 2);
|
||||
sprintf(auth, "%d,%d", job_fds[0], job_fds[1]);
|
||||
char *
|
||||
jobserver_get_auth ()
|
||||
{
|
||||
char *auth;
|
||||
|
||||
if (js_type == js_fifo) {
|
||||
auth = xmalloc (strlen (fifo_name) + CSTRLEN (FIFO_PREFIX) + 1);
|
||||
sprintf (auth, FIFO_PREFIX "%s", fifo_name);
|
||||
} else {
|
||||
auth = xmalloc ((INTSTR_LENGTH * 2) + 2);
|
||||
sprintf (auth, "%d,%d", job_fds[0], job_fds[1]);
|
||||
}
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
unsigned int jobserver_enabled(void) {
|
||||
return job_fds[0] >= 0;
|
||||
const char *
|
||||
jobserver_get_invalid_auth ()
|
||||
{
|
||||
/* If we're using a named pipe we don't need to invalidate the jobserver. */
|
||||
if (js_type == js_fifo) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* It's not really great that we are assuming the command line option
|
||||
here but other alternatives are also gross. */
|
||||
return " --" JOBSERVER_AUTH_OPT "=-2,-2";
|
||||
}
|
||||
|
||||
void jobserver_clear(void) {
|
||||
if (job_fds[0] >= 0) close(job_fds[0]);
|
||||
if (job_fds[1] >= 0) close(job_fds[1]);
|
||||
if (job_rfd >= 0) close(job_rfd);
|
||||
unsigned int
|
||||
jobserver_enabled ()
|
||||
{
|
||||
return js_type != js_none;
|
||||
}
|
||||
|
||||
void
|
||||
jobserver_clear ()
|
||||
{
|
||||
if (job_fds[0] >= 0)
|
||||
close (job_fds[0]);
|
||||
if (job_fds[1] >= 0)
|
||||
close (job_fds[1]);
|
||||
if (job_rfd >= 0)
|
||||
close (job_rfd);
|
||||
|
||||
job_fds[0] = job_fds[1] = job_rfd = -1;
|
||||
|
||||
if (fifo_name)
|
||||
{
|
||||
if (job_root)
|
||||
{
|
||||
int r;
|
||||
EINTRLOOP (r, unlink (fifo_name));
|
||||
}
|
||||
|
||||
if (!handling_fatal_signal)
|
||||
{
|
||||
free (fifo_name);
|
||||
fifo_name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
js_type = js_none;
|
||||
}
|
||||
|
||||
void jobserver_release(int is_fatal) {
|
||||
void
|
||||
jobserver_release (int is_fatal)
|
||||
{
|
||||
int r;
|
||||
EINTRLOOP(r, write(job_fds[1], &token, 1));
|
||||
if (r != 1) {
|
||||
if (is_fatal) pfatal_with_name(_("write jobserver"));
|
||||
perror_with_name("write", "");
|
||||
EINTRLOOP (r, write (job_fds[1], &token, 1));
|
||||
if (r != 1)
|
||||
{
|
||||
if (is_fatal)
|
||||
pfatal_with_name (_("write jobserver"));
|
||||
perror_with_name ("write", "");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int jobserver_acquire_all(void) {
|
||||
unsigned int
|
||||
jobserver_acquire_all ()
|
||||
{
|
||||
int r;
|
||||
unsigned int tokens = 0;
|
||||
|
||||
/* Use blocking reads to wait for all outstanding jobs. */
|
||||
set_blocking(job_fds[0], 1);
|
||||
set_blocking (job_fds[0], 1);
|
||||
|
||||
/* Close the write side, so the read() won't hang forever. */
|
||||
close(job_fds[1]);
|
||||
close (job_fds[1]);
|
||||
job_fds[1] = -1;
|
||||
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
char intake;
|
||||
int r;
|
||||
EINTRLOOP(r, read(job_fds[0], &intake, 1));
|
||||
if (r != 1) return tokens;
|
||||
EINTRLOOP (r, read (job_fds[0], &intake, 1));
|
||||
if (r != 1)
|
||||
break;
|
||||
++tokens;
|
||||
}
|
||||
|
||||
DB (DB_JOBS, ("Acquired all %u jobserver tokens.\n", tokens));
|
||||
|
||||
jobserver_clear ();
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/* Prepare the jobserver to start a child process. */
|
||||
void jobserver_pre_child(int recursive) {
|
||||
if (recursive && job_fds[0] >= 0) {
|
||||
fd_inherit(job_fds[0]);
|
||||
fd_inherit(job_fds[1]);
|
||||
void
|
||||
jobserver_pre_child (int recursive)
|
||||
{
|
||||
if (recursive && js_type == js_pipe)
|
||||
{
|
||||
fd_inherit (job_fds[0]);
|
||||
fd_inherit (job_fds[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reconfigure the jobserver after starting a child process. */
|
||||
void jobserver_post_child(int recursive) {
|
||||
if (recursive && job_fds[0] >= 0) {
|
||||
fd_noinherit(job_fds[0]);
|
||||
fd_noinherit(job_fds[1]);
|
||||
void
|
||||
jobserver_post_child (int recursive)
|
||||
{
|
||||
if (recursive && js_type == js_pipe)
|
||||
{
|
||||
fd_noinherit (job_fds[0]);
|
||||
fd_noinherit (job_fds[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void jobserver_signal(void) {
|
||||
if (job_rfd >= 0) {
|
||||
close(job_rfd);
|
||||
void
|
||||
jobserver_signal ()
|
||||
{
|
||||
if (job_rfd >= 0)
|
||||
{
|
||||
close (job_rfd);
|
||||
job_rfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void jobserver_pre_acquire(void) {
|
||||
void
|
||||
jobserver_pre_acquire ()
|
||||
{
|
||||
/* Make sure we have a dup'd FD. */
|
||||
if (job_rfd < 0 && job_fds[0] >= 0 && make_job_rfd() < 0)
|
||||
pfatal_with_name(_("duping jobs pipe"));
|
||||
if (job_rfd < 0 && job_fds[0] >= 0 && make_job_rfd () < 0)
|
||||
pfatal_with_name (_("duping jobs pipe"));
|
||||
}
|
||||
|
||||
#ifdef HAVE_PSELECT
|
||||
|
@ -208,55 +456,66 @@ void jobserver_pre_acquire(void) {
|
|||
and only unblocked (atomically) within the pselect() call, so we can
|
||||
never miss a SIGCHLD.
|
||||
*/
|
||||
unsigned int jobserver_acquire(int timeout) {
|
||||
unsigned int
|
||||
jobserver_acquire (int timeout)
|
||||
{
|
||||
struct timespec spec;
|
||||
struct timespec *specp = NULL;
|
||||
sigset_t empty;
|
||||
|
||||
sigemptyset(&empty);
|
||||
sigemptyset (&empty);
|
||||
|
||||
if (timeout) {
|
||||
if (timeout)
|
||||
{
|
||||
/* Alarm after one second (is this too granular?) */
|
||||
spec.tv_sec = 1;
|
||||
spec.tv_nsec = 0;
|
||||
specp = &spec;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
fd_set readfds;
|
||||
int r;
|
||||
char intake;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(job_fds[0], &readfds);
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (job_fds[0], &readfds);
|
||||
|
||||
r = pselect(job_fds[0] + 1, &readfds, NULL, NULL, specp, &empty);
|
||||
r = pselect (job_fds[0]+1, &readfds, NULL, NULL, specp, &empty);
|
||||
if (r < 0)
|
||||
switch (errno)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
case EINTR:
|
||||
/* SIGCHLD will show up as an EINTR. */
|
||||
return 0;
|
||||
if (errno == EBADF)
|
||||
|
||||
case EBADF:
|
||||
/* Someone closed the jobs pipe.
|
||||
That shouldn't happen but if it does we're done. */
|
||||
O(fatal, NILF, _("job server shut down"));
|
||||
pfatal_with_name(_("pselect jobs pipe"));
|
||||
O (fatal, NILF, _("job server shut down"));
|
||||
|
||||
default:
|
||||
pfatal_with_name (_("pselect jobs pipe"));
|
||||
}
|
||||
|
||||
if (r == 0) /* Timeout. */
|
||||
if (r == 0)
|
||||
/* Timeout. */
|
||||
return 0;
|
||||
|
||||
/* The read FD is ready: read it! This is non-blocking. */
|
||||
EINTRLOOP(r, read(job_fds[0], &intake, 1));
|
||||
EINTRLOOP (r, read (job_fds[0], &intake, 1));
|
||||
|
||||
if (r < 0) {
|
||||
if (r < 0)
|
||||
{
|
||||
/* Someone sniped our token! Try again. */
|
||||
if (errno == EAGAIN) continue;
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
|
||||
pfatal_with_name(_("read jobs pipe"));
|
||||
pfatal_with_name (_("read jobs pipe"));
|
||||
}
|
||||
|
||||
/* read() should never return 0: only the master make can reap all the
|
||||
/* read() should never return 0: only the parent make can reap all the
|
||||
tokens and close the write side...?? */
|
||||
return r > 0;
|
||||
}
|
||||
|
@ -288,69 +547,89 @@ unsigned int jobserver_acquire(int timeout) {
|
|||
during the section mentioned above, the read(2) will be invoked with an
|
||||
invalid FD and will return immediately with EBADF. */
|
||||
|
||||
static RETSIGTYPE job_noop(int sig UNUSED) {
|
||||
static void
|
||||
job_noop (int sig UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Set the child handler action flags to FLAGS. */
|
||||
static void set_child_handler_action_flags(int set_handler, int set_alarm) {
|
||||
static void
|
||||
set_child_handler_action_flags (int set_handler, int set_alarm)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, '\0', sizeof sa);
|
||||
#ifdef __EMX__
|
||||
/* The child handler must be turned off here. */
|
||||
signal (SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
|
||||
memset (&sa, '\0', sizeof sa);
|
||||
sa.sa_handler = child_handler;
|
||||
sa.sa_flags = set_handler ? 0 : SA_RESTART;
|
||||
|
||||
#if defined SIGCHLD
|
||||
if (sigaction(SIGCHLD, &sa, NULL) < 0) pfatal_with_name("sigaction: SIGCHLD");
|
||||
if (sigaction (SIGCHLD, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGCHLD");
|
||||
#endif
|
||||
|
||||
#if defined SIGCLD && SIGCLD != SIGCHLD
|
||||
if (sigaction(SIGCLD, &sa, NULL) < 0) pfatal_with_name("sigaction: SIGCLD");
|
||||
if (sigaction (SIGCLD, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGCLD");
|
||||
#endif
|
||||
|
||||
#if defined SIGALRM
|
||||
if (set_alarm) {
|
||||
if (set_alarm)
|
||||
{
|
||||
/* If we're about to enter the read(), set an alarm to wake up in a
|
||||
second so we can check if the load has dropped and we can start more
|
||||
work. On the way out, turn off the alarm and set SIG_DFL. */
|
||||
if (set_handler) {
|
||||
if (set_handler)
|
||||
{
|
||||
sa.sa_handler = job_noop;
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction(SIGALRM, &sa, NULL) < 0)
|
||||
pfatal_with_name("sigaction: SIGALRM");
|
||||
alarm(1);
|
||||
} else {
|
||||
alarm(0);
|
||||
if (sigaction (SIGALRM, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGALRM");
|
||||
alarm (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm (0);
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction(SIGALRM, &sa, NULL) < 0)
|
||||
pfatal_with_name("sigaction: SIGALRM");
|
||||
if (sigaction (SIGALRM, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGALRM");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int jobserver_acquire(int timeout) {
|
||||
unsigned int
|
||||
jobserver_acquire (int timeout)
|
||||
{
|
||||
char intake;
|
||||
int got_token;
|
||||
int saved_errno;
|
||||
|
||||
/* Set interruptible system calls, and read() for a job token. */
|
||||
set_child_handler_action_flags(1, timeout);
|
||||
set_child_handler_action_flags (1, timeout);
|
||||
|
||||
EINTRLOOP(got_token, read(job_rfd, &intake, 1));
|
||||
EINTRLOOP (got_token, read (job_rfd, &intake, 1));
|
||||
saved_errno = errno;
|
||||
|
||||
set_child_handler_action_flags(0, timeout);
|
||||
set_child_handler_action_flags (0, timeout);
|
||||
|
||||
if (got_token == 1) return 1;
|
||||
if (got_token == 1)
|
||||
return 1;
|
||||
|
||||
/* If the error _wasn't_ expected (EINTR or EBADF), fatal. Otherwise,
|
||||
go back and reap_children(), and try again. */
|
||||
errno = saved_errno;
|
||||
|
||||
if (errno != EINTR && errno != EBADF) pfatal_with_name(_("read jobs pipe"));
|
||||
if (errno != EINTR && errno != EBADF && errno != EAGAIN)
|
||||
pfatal_with_name (_("read jobs pipe"));
|
||||
|
||||
if (errno == EBADF) DB(DB_JOBS, ("Read returned EBADF.\n"));
|
||||
if (errno == EBADF)
|
||||
DB (DB_JOBS, ("Read returned EBADF.\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -359,26 +638,151 @@ unsigned int jobserver_acquire(int timeout) {
|
|||
|
||||
#endif /* MAKE_JOBSERVER */
|
||||
|
||||
#if !defined(NO_OUTPUT_SYNC)
|
||||
|
||||
#define MUTEX_PREFIX "fnm:"
|
||||
|
||||
static int osync_handle = -1;
|
||||
|
||||
static char *osync_tmpfile = NULL;
|
||||
|
||||
static unsigned int sync_root = 0;
|
||||
|
||||
unsigned int
|
||||
osync_enabled ()
|
||||
{
|
||||
return osync_handle >= 0;
|
||||
}
|
||||
|
||||
void
|
||||
osync_setup ()
|
||||
{
|
||||
osync_handle = get_tmpfd (&osync_tmpfile);
|
||||
fd_noinherit (osync_handle);
|
||||
sync_root = 1;
|
||||
}
|
||||
|
||||
char *
|
||||
osync_get_mutex ()
|
||||
{
|
||||
char *mutex = NULL;
|
||||
|
||||
if (osync_enabled ())
|
||||
{
|
||||
/* Prepare the mutex handle string for our children. */
|
||||
mutex = xmalloc (strlen (osync_tmpfile) + CSTRLEN (MUTEX_PREFIX) + 1);
|
||||
sprintf (mutex, MUTEX_PREFIX "%s", osync_tmpfile);
|
||||
}
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
osync_parse_mutex (const char *mutex)
|
||||
{
|
||||
if (strncmp (mutex, MUTEX_PREFIX, CSTRLEN (MUTEX_PREFIX)) != 0)
|
||||
{
|
||||
OS (error, NILF, _("invalid --sync-mutex string '%s'"), mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free (osync_tmpfile);
|
||||
osync_tmpfile = xstrdup (mutex + CSTRLEN (MUTEX_PREFIX));
|
||||
|
||||
EINTRLOOP (osync_handle, open (osync_tmpfile, O_WRONLY));
|
||||
if (osync_handle < 0)
|
||||
OSS (fatal, NILF, _("cannot open output sync mutex %s: %s"),
|
||||
osync_tmpfile, strerror (errno));
|
||||
|
||||
fd_noinherit (osync_handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
osync_clear ()
|
||||
{
|
||||
if (osync_handle >= 0)
|
||||
{
|
||||
close (osync_handle);
|
||||
osync_handle = -1;
|
||||
}
|
||||
|
||||
if (sync_root && osync_tmpfile)
|
||||
{
|
||||
int r;
|
||||
|
||||
EINTRLOOP (r, unlink (osync_tmpfile));
|
||||
free (osync_tmpfile);
|
||||
osync_tmpfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
osync_acquire ()
|
||||
{
|
||||
if (osync_enabled())
|
||||
{
|
||||
struct flock fl;
|
||||
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 1;
|
||||
/* We don't want to keep waiting on EINTR. */
|
||||
if (fcntl (osync_handle, F_SETLKW, &fl) == -1)
|
||||
{
|
||||
perror ("fcntl()");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
osync_release ()
|
||||
{
|
||||
if (osync_enabled())
|
||||
{
|
||||
struct flock fl;
|
||||
|
||||
fl.l_type = F_UNLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 1;
|
||||
/* We don't want to keep waiting on EINTR. */
|
||||
if (fcntl (osync_handle, F_SETLKW, &fl) == -1)
|
||||
perror ("fcntl()");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Create a "bad" file descriptor for stdin when parallel jobs are run. */
|
||||
int get_bad_stdin(void) {
|
||||
int
|
||||
get_bad_stdin ()
|
||||
{
|
||||
static int bad_stdin = -1;
|
||||
|
||||
/* Set up a bad standard input that reads from a broken pipe. */
|
||||
|
||||
if (bad_stdin == -1) {
|
||||
if (bad_stdin == -1)
|
||||
{
|
||||
/* Make a file descriptor that is the read end of a broken pipe.
|
||||
This will be used for some children's standard inputs. */
|
||||
int pd[2];
|
||||
if (pipe(pd) == 0) {
|
||||
if (pipe (pd) == 0)
|
||||
{
|
||||
/* Close the write side. */
|
||||
(void)close(pd[1]);
|
||||
close (pd[1]);
|
||||
/* Save the read side. */
|
||||
bad_stdin = pd[0];
|
||||
|
||||
/* Set the descriptor to close on exec, so it does not litter any
|
||||
child's descriptor table. When it is dup2'd onto descriptor 0,
|
||||
that descriptor will not close on exec. */
|
||||
fd_noinherit(bad_stdin);
|
||||
fd_noinherit (bad_stdin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,31 +792,107 @@ int get_bad_stdin(void) {
|
|||
/* Set file descriptors to be inherited / not inherited by subprocesses. */
|
||||
|
||||
#if !defined(F_SETFD) || !defined(F_GETFD)
|
||||
void fd_inherit(int fd) {}
|
||||
void fd_noinherit(int fd) {}
|
||||
void fd_inherit (int fd) {}
|
||||
void fd_noinherit (int fd) {}
|
||||
|
||||
#else
|
||||
|
||||
#ifndef FD_CLOEXEC
|
||||
#define FD_CLOEXEC 1
|
||||
#endif
|
||||
# ifndef FD_CLOEXEC
|
||||
# define FD_CLOEXEC 1
|
||||
# endif
|
||||
|
||||
void fd_inherit(int fd) {
|
||||
void
|
||||
fd_inherit (int fd)
|
||||
{
|
||||
int flags;
|
||||
EINTRLOOP(flags, fcntl(fd, F_GETFD));
|
||||
if (flags >= 0) {
|
||||
EINTRLOOP (flags, fcntl (fd, F_GETFD));
|
||||
if (flags >= 0)
|
||||
{
|
||||
int r;
|
||||
flags &= ~FD_CLOEXEC;
|
||||
EINTRLOOP(r, fcntl(fd, F_SETFD, flags));
|
||||
EINTRLOOP (r, fcntl (fd, F_SETFD, flags));
|
||||
}
|
||||
}
|
||||
|
||||
void fd_noinherit(int fd) {
|
||||
void
|
||||
fd_noinherit (int fd)
|
||||
{
|
||||
int flags;
|
||||
EINTRLOOP(flags, fcntl(fd, F_GETFD));
|
||||
if (flags >= 0) {
|
||||
EINTRLOOP (flags, fcntl(fd, F_GETFD));
|
||||
if (flags >= 0)
|
||||
{
|
||||
int r;
|
||||
flags |= FD_CLOEXEC;
|
||||
EINTRLOOP(r, fcntl(fd, F_SETFD, flags));
|
||||
EINTRLOOP (r, fcntl(fd, F_SETFD, flags));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set a file descriptor referring to a regular file to be in O_APPEND mode.
|
||||
If it fails, just ignore it. */
|
||||
|
||||
void
|
||||
fd_set_append (int fd)
|
||||
{
|
||||
#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
|
||||
struct stat stbuf;
|
||||
int flags;
|
||||
if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode))
|
||||
{
|
||||
flags = fcntl (fd, F_GETFL, 0);
|
||||
if (flags >= 0)
|
||||
{
|
||||
int r;
|
||||
EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return a file descriptor for a new anonymous temp file, or -1. */
|
||||
int
|
||||
os_anontmp ()
|
||||
{
|
||||
const char *tdir = get_tmpdir ();
|
||||
int fd = -1;
|
||||
|
||||
if (IsLinux ())
|
||||
{
|
||||
static unsigned int tmpfile_works = 1;
|
||||
|
||||
if (tmpfile_works)
|
||||
{
|
||||
EINTRLOOP (fd, open (tdir, O_RDWR | O_TMPFILE | O_EXCL, 0600));
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
|
||||
DB (DB_BASIC, (_("Cannot open '%s' with O_TMPFILE: %s.\n"),
|
||||
tdir, strerror (errno)));
|
||||
tmpfile_works = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_DUP
|
||||
/* If we can dup and we are creating temp files in the default location then
|
||||
try tmpfile() + dup() + fclose() to avoid ever having a named file. */
|
||||
if (streq (tdir, DEFAULT_TMPDIR))
|
||||
{
|
||||
mode_t mask = umask (0077);
|
||||
FILE *tfile;
|
||||
ENULLLOOP (tfile, tmpfile ());
|
||||
if (!tfile)
|
||||
{
|
||||
OS (error, NILF, "tmpfile: %s", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
umask (mask);
|
||||
|
||||
EINTRLOOP (fd, dup (fileno (tfile)));
|
||||
if (fd < 0)
|
||||
OS (error, NILF, "dup: %s", strerror (errno));
|
||||
fclose (tfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
597
third_party/make/read.c
vendored
597
third_party/make/read.c
vendored
File diff suppressed because it is too large
Load diff
291
third_party/make/remake.c
vendored
291
third_party/make/remake.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Basic dependency engine for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,16 +12,39 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
#include "dep.h"
|
||||
#include "variable.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#include <starlet.h>
|
||||
#endif
|
||||
#ifdef WINDOWS32
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
/* VC7 or later supports _stat64 to access 64-bit file size. */
|
||||
#define STAT _stat64
|
||||
#else
|
||||
#define STAT stat
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/make/debug.h"
|
||||
|
||||
/* The test for circular dependencies is based on the 'updating' bit in
|
||||
'struct file'. However, double colon targets have separate 'struct
|
||||
|
@ -56,8 +79,27 @@ static FILE_TIMESTAMP name_mtime (const char *name);
|
|||
static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr);
|
||||
|
||||
|
||||
/* Remake all the goals in the 'struct dep' chain GOALS. Return -1 if nothing
|
||||
was done, 0 if all goals were updated successfully, or 1 if a goal failed.
|
||||
static void
|
||||
check_also_make (const struct file *file)
|
||||
{
|
||||
struct dep *ad;
|
||||
FILE_TIMESTAMP mtime = file->last_mtime;
|
||||
|
||||
if (mtime == UNKNOWN_MTIME)
|
||||
mtime = name_mtime (file->name);
|
||||
|
||||
/* If we updated the file, check its also-make files. */
|
||||
|
||||
if (is_ordinary_mtime (mtime) && mtime > file->mtime_before_update)
|
||||
for (ad = file->also_make; ad; ad = ad->next)
|
||||
if (ad->file->last_mtime == NONEXISTENT_MTIME)
|
||||
OS (error, file->cmds ? &file->cmds->fileinfo : NILF,
|
||||
_("warning: pattern recipe did not update peer target '%s'."),
|
||||
ad->file->name);
|
||||
}
|
||||
|
||||
/* Remake all the goals in the 'struct dep' chain GOALS. Return update_status
|
||||
representing the totality of the status of the goals.
|
||||
|
||||
If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q,
|
||||
and -n should be disabled for them unless they were also command-line
|
||||
|
@ -67,12 +109,13 @@ static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr);
|
|||
enum update_status
|
||||
update_goal_chain (struct goaldep *goaldeps)
|
||||
{
|
||||
unsigned long last_cmd_count = 0;
|
||||
int t = touch_flag, q = question_flag, n = just_print_flag;
|
||||
enum update_status status = us_none;
|
||||
|
||||
/* Duplicate the chain so we can remove things from it. */
|
||||
|
||||
struct dep *goals = copy_dep_chain ((struct dep *)goaldeps);
|
||||
struct dep *goals_orig = copy_dep_chain ((struct dep *)goaldeps);
|
||||
struct dep *goals = goals_orig;
|
||||
|
||||
goal_list = rebuilding_makefiles ? goaldeps : NULL;
|
||||
|
||||
|
@ -86,24 +129,29 @@ update_goal_chain (struct goaldep *goaldeps)
|
|||
|
||||
while (goals != 0)
|
||||
{
|
||||
struct dep *g, *lastgoal;
|
||||
struct dep *gu, *g, *lastgoal;
|
||||
|
||||
/* Start jobs that are waiting for the load to go down. */
|
||||
|
||||
start_waiting_jobs ();
|
||||
|
||||
/* Wait for a child to die. */
|
||||
/* Check for exited children. If no children have finished since the
|
||||
last time we looked, then block until one exits. If some have
|
||||
exited don't block, so we can possibly do more work. */
|
||||
|
||||
reap_children (1, 0);
|
||||
reap_children (last_cmd_count == command_count, 0);
|
||||
last_cmd_count = command_count;
|
||||
|
||||
lastgoal = 0;
|
||||
g = goals;
|
||||
while (g != 0)
|
||||
gu = goals;
|
||||
while (gu != 0)
|
||||
{
|
||||
/* Iterate over all double-colon entries for this file. */
|
||||
struct file *file;
|
||||
int stop = 0, any_not_updated = 0;
|
||||
|
||||
g = gu->shuf ? gu->shuf : gu;
|
||||
|
||||
goal_dep = g;
|
||||
|
||||
for (file = g->file->double_colon ? g->file->double_colon : g->file;
|
||||
|
@ -163,8 +211,7 @@ update_goal_chain (struct goaldep *goaldeps)
|
|||
FILE_TIMESTAMP mtime = MTIME (file);
|
||||
check_renamed (file);
|
||||
|
||||
if (file->updated && g->changed &&
|
||||
mtime != file->mtime_before_update)
|
||||
if (file->updated && mtime != file->mtime_before_update)
|
||||
{
|
||||
/* Updating was done. If this is a makefile and
|
||||
just_print_flag or question_flag is set (meaning
|
||||
|
@ -214,31 +261,30 @@ update_goal_chain (struct goaldep *goaldeps)
|
|||
|
||||
/* This goal is finished. Remove it from the chain. */
|
||||
if (lastgoal == 0)
|
||||
goals = g->next;
|
||||
goals = gu->next;
|
||||
else
|
||||
lastgoal->next = g->next;
|
||||
lastgoal->next = gu->next;
|
||||
|
||||
/* Free the storage. */
|
||||
free (g);
|
||||
|
||||
g = lastgoal == 0 ? goals : lastgoal->next;
|
||||
gu = lastgoal == 0 ? goals : lastgoal->next;
|
||||
|
||||
if (stop)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastgoal = g;
|
||||
g = g->next;
|
||||
lastgoal = gu;
|
||||
gu = gu->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we reached the end of the dependency graph update CONSIDERED
|
||||
for the next pass. */
|
||||
if (g == 0)
|
||||
if (gu == 0)
|
||||
++considered;
|
||||
}
|
||||
|
||||
free_dep_chain (goals_orig);
|
||||
|
||||
if (rebuilding_makefiles)
|
||||
{
|
||||
touch_flag = t;
|
||||
|
@ -266,7 +312,7 @@ show_goal_error (void)
|
|||
if (goal->error)
|
||||
{
|
||||
OSS (error, &goal->floc, "%s: %s",
|
||||
goal->file->name, strerror ((int)goal->error));
|
||||
goal->file->name, strerror (goal->error));
|
||||
goal->error = 0;
|
||||
}
|
||||
return;
|
||||
|
@ -322,8 +368,7 @@ update_file (struct file *file, unsigned int depth)
|
|||
check_renamed (f);
|
||||
|
||||
/* Clean up any alloca() used during the update. */
|
||||
void *volatile wat = alloca (0);
|
||||
(void)wat;
|
||||
free_alloca ();
|
||||
|
||||
/* If we got an error, don't bother with double_colon etc. */
|
||||
if (new && !keep_going_flag)
|
||||
|
@ -395,7 +440,7 @@ complain (struct file *file)
|
|||
}
|
||||
|
||||
/* Consider a single 'struct file' and update it as appropriate.
|
||||
Return 0 on success, or non-0 on failure. */
|
||||
Return an update_status value; use us_success if we aren't sure yet. */
|
||||
|
||||
static enum update_status
|
||||
update_file_1 (struct file *file, unsigned int depth)
|
||||
|
@ -404,7 +449,7 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
FILE_TIMESTAMP this_mtime;
|
||||
int noexist, must_make, deps_changed;
|
||||
struct file *ofile;
|
||||
struct dep *d, *ad;
|
||||
struct dep *du, *d, *ad;
|
||||
struct dep amake;
|
||||
int running = 0;
|
||||
|
||||
|
@ -428,7 +473,7 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
}
|
||||
|
||||
DBF (DB_VERBOSE, _("File '%s' was considered already.\n"));
|
||||
return 0;
|
||||
return us_success;
|
||||
}
|
||||
|
||||
switch (file->command_state)
|
||||
|
@ -438,7 +483,7 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
break;
|
||||
case cs_running:
|
||||
DBF (DB_VERBOSE, _("Still updating file '%s'.\n"));
|
||||
return 0;
|
||||
return us_success;
|
||||
case cs_finished:
|
||||
DBF (DB_VERBOSE, _("Finished updating file '%s'.\n"));
|
||||
return file->update_status;
|
||||
|
@ -450,8 +495,6 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
fail. */
|
||||
file->no_diag = file->dontcare;
|
||||
|
||||
++depth;
|
||||
|
||||
/* Notice recursive update of the same file. */
|
||||
start_updating (file);
|
||||
|
||||
|
@ -459,6 +502,9 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
remember this one to turn off updating. */
|
||||
ofile = file;
|
||||
|
||||
/* Increase the depth for reporting how we build the file. */
|
||||
++depth;
|
||||
|
||||
/* Looking at the file's modtime beforehand allows the possibility
|
||||
that its name may be changed by a VPATH search, and thus it may
|
||||
not need an implicit rule. If this were not done, the file
|
||||
|
@ -470,8 +516,7 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
noexist = this_mtime == NONEXISTENT_MTIME;
|
||||
if (noexist)
|
||||
DBF (DB_BASIC, _("File '%s' does not exist.\n"));
|
||||
else if (ORDINARY_MTIME_MIN <= this_mtime && this_mtime <= ORDINARY_MTIME_MAX
|
||||
&& file->low_resolution_time)
|
||||
else if (is_ordinary_mtime (this_mtime) && file->low_resolution_time)
|
||||
{
|
||||
/* Avoid spurious rebuilds due to low resolution time stamps. */
|
||||
int ns = FILE_TIMESTAMP_NS (this_mtime);
|
||||
|
@ -482,17 +527,34 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;
|
||||
}
|
||||
|
||||
/* If any also_make target doesn't exist, we must remake this one too.
|
||||
If they do exist choose the oldest mtime so they will rebuild. */
|
||||
|
||||
for (ad = file->also_make; ad && !noexist; ad = ad->next)
|
||||
{
|
||||
struct file *adfile = ad->file;
|
||||
FILE_TIMESTAMP fmtime = file_mtime (adfile);
|
||||
|
||||
noexist = fmtime == NONEXISTENT_MTIME;
|
||||
if (noexist)
|
||||
{
|
||||
check_renamed (adfile);
|
||||
DBS (DB_BASIC,
|
||||
(_("Grouped target peer '%s' of file '%s' does not exist.\n"),
|
||||
adfile->name, file->name));
|
||||
}
|
||||
else if (fmtime < this_mtime)
|
||||
this_mtime = fmtime;
|
||||
}
|
||||
|
||||
must_make = noexist;
|
||||
|
||||
/* If file was specified as a target with no commands,
|
||||
come up with some default commands. */
|
||||
/* If file was specified as a target with no commands, come up with some
|
||||
default commands. This may also add more also_make files. */
|
||||
|
||||
if (!file->phony && file->cmds == 0 && !file->tried_implicit)
|
||||
{
|
||||
if (try_implicit_rule (file, depth))
|
||||
DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n"));
|
||||
else
|
||||
DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n"));
|
||||
try_implicit_rule (file, depth);
|
||||
file->tried_implicit = 1;
|
||||
}
|
||||
if (file->cmds == 0 && !file->is_target
|
||||
|
@ -514,17 +576,28 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
{
|
||||
struct dep *lastd = 0;
|
||||
|
||||
/* Perform second expansion and enter each dependency name as a file.
|
||||
We only need to do this if second_expansion has been defined; if it
|
||||
hasn't then all deps were expanded as the makefile was read in. */
|
||||
if (second_expansion)
|
||||
expand_deps (ad->file);
|
||||
|
||||
/* Find the deps we're scanning */
|
||||
d = ad->file->deps;
|
||||
du = ad->file->deps;
|
||||
ad = ad->next;
|
||||
|
||||
while (d)
|
||||
while (du)
|
||||
{
|
||||
enum update_status new;
|
||||
FILE_TIMESTAMP mtime;
|
||||
int maybe_make;
|
||||
int dontcare = 0;
|
||||
|
||||
d = du->shuf ? du->shuf : du;
|
||||
|
||||
if (d->wait_here && running)
|
||||
break;
|
||||
|
||||
check_renamed (d->file);
|
||||
|
||||
mtime = file_mtime (d->file);
|
||||
|
@ -534,14 +607,16 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
{
|
||||
OSS (error, NILF, _("Circular %s <- %s dependency dropped."),
|
||||
file->name, d->file->name);
|
||||
|
||||
/* We cannot free D here because our the caller will still have
|
||||
a reference to it when we were called recursively via
|
||||
check_dep below. */
|
||||
if (lastd == 0)
|
||||
file->deps = d->next;
|
||||
file->deps = du->next;
|
||||
else
|
||||
lastd->next = d->next;
|
||||
d = d->next;
|
||||
lastd->next = du->next;
|
||||
|
||||
du = du->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -590,8 +665,8 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
d->changed = ((file_mtime (d->file) != mtime)
|
||||
|| (mtime == NONEXISTENT_MTIME));
|
||||
|
||||
lastd = d;
|
||||
d = d->next;
|
||||
lastd = du;
|
||||
du = du->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,7 +675,13 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
|
||||
if (must_make || always_make_flag)
|
||||
{
|
||||
for (d = file->deps; d != 0; d = d->next)
|
||||
for (du = file->deps; du != 0; du = du->next)
|
||||
{
|
||||
d = du->shuf ? du->shuf : du;
|
||||
|
||||
if (d->wait_here && running)
|
||||
break;
|
||||
|
||||
if (d->file->intermediate)
|
||||
{
|
||||
enum update_status new;
|
||||
|
@ -653,20 +734,23 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
|| file_mtime (d->file) != mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finish_updating (file);
|
||||
finish_updating (ofile);
|
||||
|
||||
DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n"));
|
||||
/* We've decided what we need to do to build the file. */
|
||||
--depth;
|
||||
|
||||
if (running)
|
||||
{
|
||||
set_command_state (file, cs_deps_running);
|
||||
--depth;
|
||||
DBF (DB_VERBOSE, _("The prerequisites of '%s' are being made.\n"));
|
||||
return 0;
|
||||
return us_success;
|
||||
}
|
||||
|
||||
DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n"));
|
||||
|
||||
/* If any dependency failed, give up now. */
|
||||
|
||||
if (dep_status)
|
||||
|
@ -675,8 +759,6 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
file->update_status = dep_status == us_none ? us_failed : dep_status;
|
||||
notice_finished_file (file);
|
||||
|
||||
--depth;
|
||||
|
||||
DBF (DB_VERBOSE, _("Giving up on target file '%s'.\n"));
|
||||
|
||||
if (depth == 0 && keep_going_flag
|
||||
|
@ -751,16 +833,13 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
|
||||
if (fmt)
|
||||
{
|
||||
print_spaces (depth);
|
||||
print_spaces (depth+1);
|
||||
printf (fmt, dep_name (d), file->name);
|
||||
fflush (stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Here depth returns to the value it had when we were called. */
|
||||
depth--;
|
||||
|
||||
if (file->double_colon && file->deps == 0)
|
||||
{
|
||||
must_make = 1;
|
||||
|
@ -792,6 +871,11 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
fflush (stdout);
|
||||
}
|
||||
|
||||
/* Since make has not created this file, make should not remove it,
|
||||
even if the file is intermediate. */
|
||||
if (!file->notintermediate && no_intermediates == 0)
|
||||
file->secondary = 1;
|
||||
|
||||
notice_finished_file (file);
|
||||
|
||||
/* Since we don't need to remake the file, convert it to use the
|
||||
|
@ -804,7 +888,7 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
file = file->prev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return us_success;
|
||||
}
|
||||
|
||||
DBF (DB_BASIC, _("Must remake target '%s'.\n"));
|
||||
|
@ -823,7 +907,7 @@ update_file_1 (struct file *file, unsigned int depth)
|
|||
if (file->command_state != cs_finished)
|
||||
{
|
||||
DBF (DB_VERBOSE, _("Recipe of '%s' is being run.\n"));
|
||||
return 0;
|
||||
return us_success;
|
||||
}
|
||||
|
||||
switch (file->update_status)
|
||||
|
@ -876,7 +960,7 @@ notice_finished_file (struct file *file)
|
|||
we don't want to do the touching. */
|
||||
unsigned int i;
|
||||
for (i = 0; i < file->cmds->ncommand_lines; ++i)
|
||||
if (!(file->cmds->lines_flags[i] & COMMANDS_RECURSE))
|
||||
if (NONE_SET (file->cmds->lines_flags[i], COMMANDS_RECURSE))
|
||||
goto have_nonrecursing;
|
||||
}
|
||||
else
|
||||
|
@ -917,7 +1001,7 @@ notice_finished_file (struct file *file)
|
|||
if ((question_flag || just_print_flag || touch_flag) && file->cmds)
|
||||
{
|
||||
for (i = file->cmds->ncommand_lines; i > 0; --i)
|
||||
if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE))
|
||||
if (NONE_SET (file->cmds->lines_flags[i-1], COMMANDS_RECURSE))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -958,6 +1042,7 @@ notice_finished_file (struct file *file)
|
|||
}
|
||||
|
||||
if (ran && file->update_status != us_none)
|
||||
{
|
||||
/* We actually tried to update FILE, which has
|
||||
updated its also_make's as well (if it worked).
|
||||
If it didn't work, it wouldn't work again for them.
|
||||
|
@ -975,6 +1060,12 @@ notice_finished_file (struct file *file)
|
|||
never be done because the target is already updated. */
|
||||
f_mtime (d->file, 0);
|
||||
}
|
||||
|
||||
/* If the target was created by an implicit rule, and it was updated,
|
||||
warn about any of its also_make targets that don't exist. */
|
||||
if (file->tried_implicit && file->also_make)
|
||||
check_also_make (file);
|
||||
}
|
||||
else if (file->update_status == us_none)
|
||||
/* Nothing was done for FILE, but it needed nothing done.
|
||||
So mark it now as "succeeded". */
|
||||
|
@ -995,7 +1086,6 @@ check_dep (struct file *file, unsigned int depth,
|
|||
struct dep *d;
|
||||
enum update_status dep_status = us_success;
|
||||
|
||||
++depth;
|
||||
start_updating (file);
|
||||
|
||||
/* We might change file if we find a different one via vpath;
|
||||
|
@ -1021,10 +1111,7 @@ check_dep (struct file *file, unsigned int depth,
|
|||
|
||||
if (!file->phony && file->cmds == 0 && !file->tried_implicit)
|
||||
{
|
||||
if (try_implicit_rule (file, depth))
|
||||
DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n"));
|
||||
else
|
||||
DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n"));
|
||||
try_implicit_rule (file, depth);
|
||||
file->tried_implicit = 1;
|
||||
}
|
||||
if (file->cmds == 0 && !file->is_target
|
||||
|
@ -1063,6 +1150,12 @@ check_dep (struct file *file, unsigned int depth,
|
|||
}
|
||||
|
||||
ld = 0;
|
||||
/* Perform second expansion and enter each dependency name as a file.
|
||||
We only need to do this if second_expansion has been defined; if it
|
||||
hasn't then all deps were expanded as the makefile was read in. */
|
||||
if (second_expansion)
|
||||
expand_deps (file);
|
||||
|
||||
d = file->deps;
|
||||
while (d != 0)
|
||||
{
|
||||
|
@ -1090,7 +1183,7 @@ check_dep (struct file *file, unsigned int depth,
|
|||
|
||||
d->file->parent = file;
|
||||
maybe_make = *must_make_ptr;
|
||||
new = check_dep (d->file, depth, this_mtime, &maybe_make);
|
||||
new = check_dep (d->file, depth+1, this_mtime, &maybe_make);
|
||||
if (new > dep_status)
|
||||
dep_status = new;
|
||||
|
||||
|
@ -1249,7 +1342,7 @@ f_mtime (struct file *file, int search)
|
|||
if (ar_name (file->name))
|
||||
{
|
||||
/* This file is an archive-member reference. */
|
||||
|
||||
FILE_TIMESTAMP memmtime;
|
||||
char *arname, *memname;
|
||||
struct file *arfile;
|
||||
time_t member_date;
|
||||
|
@ -1257,6 +1350,9 @@ f_mtime (struct file *file, int search)
|
|||
/* Find the archive's name. */
|
||||
ar_parse_name (file->name, &arname, &memname);
|
||||
|
||||
/* Find the mtime of the member file (it might not exist). */
|
||||
memmtime = name_mtime (memname);
|
||||
|
||||
/* Find the modification time of the archive itself.
|
||||
Also allow for its name to be changed via VPATH search. */
|
||||
arfile = lookup_file (arname);
|
||||
|
@ -1300,9 +1396,16 @@ f_mtime (struct file *file, int search)
|
|||
return NONEXISTENT_MTIME;
|
||||
|
||||
member_date = ar_member_date (file->hname);
|
||||
mtime = (member_date == (time_t) -1
|
||||
? NONEXISTENT_MTIME
|
||||
: file_timestamp_cons (file->hname, member_date, 0));
|
||||
|
||||
if (member_date == (time_t) -1
|
||||
|| (memmtime != NONEXISTENT_MTIME
|
||||
&& (time_t) FILE_TIMESTAMP_S (memmtime) > member_date))
|
||||
/* If the member file exists and is newer than the member in the
|
||||
archive, pretend it's nonexistent. This means the member file was
|
||||
updated but not added to the archive yet. */
|
||||
mtime = NONEXISTENT_MTIME;
|
||||
else
|
||||
mtime = file_timestamp_cons (file->hname, member_date, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1328,7 +1431,13 @@ f_mtime (struct file *file, int search)
|
|||
/* If we found it in VPATH, see if it's in GPATH too; if so,
|
||||
change the name right now; if not, defer until after the
|
||||
dependencies are updated. */
|
||||
#ifndef VMS
|
||||
name_len = strlen (name) - strlen (file->name) - 1;
|
||||
#else
|
||||
name_len = strlen (name) - strlen (file->name);
|
||||
if (name[name_len - 1] == '/')
|
||||
name_len--;
|
||||
#endif
|
||||
if (gpath_search (name, name_len))
|
||||
{
|
||||
rename_file (file, name);
|
||||
|
@ -1386,7 +1495,7 @@ f_mtime (struct file *file, int search)
|
|||
/ 1e9));
|
||||
char from_now_string[100];
|
||||
|
||||
if (from_now >= 99 && from_now <= ULONG_MAX)
|
||||
if (from_now >= 100.0 && from_now < (double) ULONG_MAX)
|
||||
sprintf (from_now_string, "%lu", (unsigned long) from_now);
|
||||
else
|
||||
sprintf (from_now_string, "%.2g", from_now);
|
||||
|
@ -1438,12 +1547,16 @@ static FILE_TIMESTAMP
|
|||
name_mtime (const char *name)
|
||||
{
|
||||
FILE_TIMESTAMP mtime;
|
||||
#if defined(WINDOWS32)
|
||||
struct STAT st;
|
||||
#else
|
||||
struct stat st;
|
||||
#endif
|
||||
int e;
|
||||
|
||||
#if defined(WINDOWS32)
|
||||
{
|
||||
char tem[MAXPATHLEN], *tstart, *tend;
|
||||
char tem[MAX_PATH+1], *tstart, *tend;
|
||||
const char *p = name + strlen (name);
|
||||
|
||||
/* Remove any trailing slashes and "."/"..". MS-Windows stat
|
||||
|
@ -1461,7 +1574,7 @@ name_mtime (const char *name)
|
|||
tend--;
|
||||
if (*tend == '.' && tend > tstart)
|
||||
tend--;
|
||||
for ( ; tend > tstart && (*tend == '/' || *tend == '\\'); tend--)
|
||||
for ( ; tend > tstart && ISDIRSEP (*tend); tend--)
|
||||
*tend = '\0';
|
||||
}
|
||||
else
|
||||
|
@ -1470,7 +1583,11 @@ name_mtime (const char *name)
|
|||
tend = &tem[0];
|
||||
}
|
||||
|
||||
#if defined(WINDOWS32)
|
||||
e = STAT (tem, &st);
|
||||
#else
|
||||
e = stat (tem, &st);
|
||||
#endif
|
||||
if (e == 0 && !_S_ISDIR (st.st_mode) && tend < tem + (p - name - 1))
|
||||
{
|
||||
errno = ENOTDIR;
|
||||
|
@ -1535,7 +1652,7 @@ name_mtime (const char *name)
|
|||
mtime = ltime;
|
||||
|
||||
/* Set up to check the file pointed to by this link. */
|
||||
EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX));
|
||||
EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX - 1));
|
||||
if (llen < 0)
|
||||
{
|
||||
/* Eh? Just take what we have. */
|
||||
|
@ -1572,7 +1689,7 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
|||
{
|
||||
static const char *dirs[] =
|
||||
{
|
||||
#if !defined(_AMIGA) && !defined(__COSMOPOLITAN__)
|
||||
#ifndef _AMIGA
|
||||
"/lib",
|
||||
"/usr/lib",
|
||||
#endif
|
||||
|
@ -1583,7 +1700,7 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
|||
*/
|
||||
#define LIBDIR "."
|
||||
#endif
|
||||
LIBDIR, /* Defined by configuration. */
|
||||
// LIBDIR, /* Defined by configuration. */
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -1618,7 +1735,7 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
|||
static size_t buflen = 0;
|
||||
static size_t libdir_maxlen = 0;
|
||||
static unsigned int std_dirs = 0;
|
||||
char *libbuf = variable_expand ("");
|
||||
char *libbuf;
|
||||
|
||||
/* Expand the pattern using LIB as a replacement. */
|
||||
{
|
||||
|
@ -1635,10 +1752,12 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
|||
p[len] = c;
|
||||
continue;
|
||||
}
|
||||
p4 = variable_buffer_output (libbuf, p, p3-p);
|
||||
p4 = variable_buffer_output (variable_buffer, p, p3-p);
|
||||
p4 = variable_buffer_output (p4, lib, liblen);
|
||||
p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
|
||||
p[len] = c;
|
||||
|
||||
libbuf = variable_buffer;
|
||||
}
|
||||
|
||||
/* Look first for 'libNAME.a' in the current directory. */
|
||||
|
|
297
third_party/make/remote-cstms.c
vendored
Normal file
297
third_party/make/remote-cstms.c
vendored
Normal file
|
@ -0,0 +1,297 @@
|
|||
/* GNU Make remote job exportation interface to the Customs daemon.
|
||||
THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT.
|
||||
Please do not send bug reports or questions about it to
|
||||
the Make maintainers.
|
||||
|
||||
Copyright (C) 1988-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 "filedef.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
#include "debug.h"
|
||||
|
||||
#if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
|
||||
#include "customs.h"
|
||||
|
||||
char *remote_description = "Customs";
|
||||
|
||||
/* File name of the Customs 'export' client command.
|
||||
A full path name can be used to avoid some path-searching overhead. */
|
||||
#define EXPORT_COMMAND "/usr/local/bin/export"
|
||||
|
||||
/* ExportPermit gotten by start_remote_job_p, and used by start_remote_job. */
|
||||
static ExportPermit permit;
|
||||
|
||||
/* Normalized path name of the current directory. */
|
||||
static char *normalized_cwd;
|
||||
|
||||
/* Call once at startup even if no commands are run. */
|
||||
|
||||
void
|
||||
remote_setup (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Called before exit. */
|
||||
|
||||
void
|
||||
remote_cleanup (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Return nonzero if the next job should be done remotely. */
|
||||
|
||||
int
|
||||
start_remote_job_p (int first_p)
|
||||
{
|
||||
static int inited = 0;
|
||||
int status;
|
||||
int njobs;
|
||||
|
||||
if (!inited)
|
||||
{
|
||||
/* Allow the user to turn off job exportation (useful while he is
|
||||
debugging Customs, for example). */
|
||||
if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0)
|
||||
{
|
||||
inited = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ISDB (DB_JOBS))
|
||||
Rpc_Debug (1);
|
||||
|
||||
/* Ping the daemon once to see if it is there. */
|
||||
inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1;
|
||||
|
||||
if (starting_directory == 0)
|
||||
/* main couldn't figure it out. */
|
||||
inited = -1;
|
||||
else
|
||||
{
|
||||
/* Normalize the current directory path name to something
|
||||
that should work on all machines exported to. */
|
||||
|
||||
normalized_cwd = xmalloc (GET_PATH_MAX);
|
||||
strcpy (normalized_cwd, starting_directory);
|
||||
if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0)
|
||||
/* Path normalization failure means using Customs
|
||||
won't work, but it's not really an error. */
|
||||
inited = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (inited < 0)
|
||||
return 0;
|
||||
|
||||
njobs = job_slots_used;
|
||||
if (!first_p)
|
||||
njobs -= 1; /* correction for being called from reap_children() */
|
||||
|
||||
/* the first job should run locally, or, if the -l flag is given, we use
|
||||
that as clue as to how many local jobs should be scheduled locally */
|
||||
if (max_load_average < 0 && njobs == 0 || njobs < max_load_average)
|
||||
return 0;
|
||||
|
||||
status = Customs_Host (EXPORT_SAME, &permit);
|
||||
if (status != RPC_SUCCESS)
|
||||
{
|
||||
DB (DB_JOBS, (_("Customs won't export: %s\n"),
|
||||
Rpc_ErrorMessage (status)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !CUSTOMS_FAIL (&permit.addr);
|
||||
}
|
||||
|
||||
/* Start a remote job running the command in ARGV, with environment from
|
||||
ENVP. It gets standard input from STDIN_FD. On failure, return
|
||||
nonzero. On success, return zero, and set *USED_STDIN to nonzero if it
|
||||
will actually use STDIN_FD, zero if not, set *ID_PTR to a unique
|
||||
identification, and set *IS_REMOTE to nonzero if the job is remote, zero
|
||||
if it is local (meaning *ID_PTR is a process ID). */
|
||||
|
||||
int
|
||||
start_remote_job (char **argv, char **envp, int stdin_fd,
|
||||
int *is_remote, pid_t *id_ptr, int *used_stdin)
|
||||
{
|
||||
char waybill[MAX_DATA_SIZE], msg[128];
|
||||
struct hostent *host;
|
||||
struct timeval timeout;
|
||||
struct sockaddr_in sin;
|
||||
int len;
|
||||
int retsock, retport, sock;
|
||||
Rpc_Stat status;
|
||||
pid_t pid;
|
||||
|
||||
/* Create the return socket. */
|
||||
retsock = Rpc_UdpCreate (True, 0);
|
||||
if (retsock < 0)
|
||||
{
|
||||
O (error, NILF, "exporting: Couldn't create return socket.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the return socket's port number. */
|
||||
len = sizeof (sin);
|
||||
if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0)
|
||||
{
|
||||
(void) close (retsock);
|
||||
perror_with_name ("exporting: ", "getsockname");
|
||||
return 1;
|
||||
}
|
||||
retport = sin.sin_port;
|
||||
|
||||
/* Create the TCP socket for talking to the remote child. */
|
||||
sock = Rpc_TcpCreate (False, 0);
|
||||
|
||||
/* Create a WayBill to give to the server. */
|
||||
len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv,
|
||||
envp, retport, waybill);
|
||||
|
||||
/* Modify the waybill for the child's uid/gid. */
|
||||
{
|
||||
WayBill *wb = (WayBill *) waybill;
|
||||
wb->ruid = wb->euid;
|
||||
wb->rgid = wb->egid;
|
||||
}
|
||||
|
||||
/* Send the request to the server, timing out in 20 seconds. */
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 20;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons (Customs_Port ());
|
||||
sin.sin_addr = permit.addr;
|
||||
status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT,
|
||||
len, (Rpc_Opaque) waybill,
|
||||
sizeof (msg), (Rpc_Opaque) msg,
|
||||
1, &timeout);
|
||||
|
||||
host = gethostbyaddr ((char *)&permit.addr, sizeof(permit.addr), AF_INET);
|
||||
|
||||
{
|
||||
const char *hnm = host ? host->h_name : inet_ntoa (permit.addr);
|
||||
size_t hlen = strlen (hnm);
|
||||
|
||||
if (status != RPC_SUCCESS)
|
||||
{
|
||||
const char *err = Rpc_ErrorMessage (status);
|
||||
(void) close (retsock);
|
||||
(void) close (sock);
|
||||
error (NILF, hlen + strlen (err),
|
||||
"exporting to %s: %s", hnm, err);
|
||||
return 1;
|
||||
}
|
||||
else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0')
|
||||
{
|
||||
(void) close (retsock);
|
||||
(void) close (sock);
|
||||
error (NILF, hlen + strlen (msg), "exporting to %s: %s", hnm, msg);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error (NILF, hlen + INTSTR_LENGTH,
|
||||
"*** exported to %s (id %u)", hnm, permit.id);
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
pid = vfork ();
|
||||
if (pid < 0)
|
||||
{
|
||||
/* The fork failed! */
|
||||
perror_with_name ("fork", "");
|
||||
return 1;
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
/* Child side. Run 'export' to handle the connection. */
|
||||
static char sock_buf[INTSTR_LENGTH], retsock_buf[INTSTR_LENGTH];
|
||||
static char id_buf[INTSTR_LENGTH];
|
||||
static char *new_argv[6] =
|
||||
{ EXPORT_COMMAND, "-id", sock_buf, retsock_buf, id_buf, 0 };
|
||||
|
||||
/* Set up the arguments. */
|
||||
(void) sprintf (sock_buf, "%d", sock);
|
||||
(void) sprintf (retsock_buf, "%d", retsock);
|
||||
(void) sprintf (id_buf, "%x", permit.id);
|
||||
|
||||
/* Get the right stdin. */
|
||||
if (stdin_fd != 0)
|
||||
(void) dup2 (stdin_fd, 0);
|
||||
|
||||
/* Unblock signals in the child. */
|
||||
unblock_all_sigs ();
|
||||
|
||||
/* Run the command. */
|
||||
exec_command (new_argv, envp);
|
||||
}
|
||||
|
||||
/* Parent side. Return the 'export' process's ID. */
|
||||
(void) close (retsock);
|
||||
(void) close (sock);
|
||||
*is_remote = 0;
|
||||
*id_ptr = pid;
|
||||
*used_stdin = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the status of a dead remote child. Block waiting for one to die
|
||||
if BLOCK is nonzero. Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR
|
||||
to the termination signal or zero if it exited normally, and *COREDUMP_PTR
|
||||
nonzero if it dumped core. Return the ID of the child that died,
|
||||
0 if we would have to block and !BLOCK, or < 0 if there were none. */
|
||||
|
||||
int
|
||||
remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr,
|
||||
int block)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Block asynchronous notification of remote child death.
|
||||
If this notification is done by raising the child termination
|
||||
signal, do not block that signal. */
|
||||
void
|
||||
block_remote_children (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Restore asynchronous notification of remote child death.
|
||||
If this is done by raising the child termination signal,
|
||||
do not unblock that signal. */
|
||||
void
|
||||
unblock_remote_children (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send signal SIG to child ID. Return 0 if successful, -1 if not. */
|
||||
int
|
||||
remote_kill (pid_t id, int sig)
|
||||
{
|
||||
return -1;
|
||||
}
|
12
third_party/make/remote-stub.c
vendored
12
third_party/make/remote-stub.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Template for the remote job exportation interface to GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,12 +12,12 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
|
||||
|
||||
char *remote_description = 0;
|
||||
|
|
122
third_party/make/rule.c
vendored
122
third_party/make/rule.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Pattern and suffix rule internals for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,16 +12,18 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/make/rule.h"
|
||||
#include "makeint.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
#include "variable.h"
|
||||
#include "rule.h"
|
||||
|
||||
static void freerule (struct rule *rule, struct rule *lastrule);
|
||||
|
||||
|
@ -57,6 +59,63 @@ struct file *suffix_file;
|
|||
/* Maximum length of a suffix. */
|
||||
|
||||
static size_t maxsuffix;
|
||||
|
||||
/* Return the rule definition: space separated rule targets, followed by
|
||||
either a colon or two colons in the case of a terminal rule, followed by
|
||||
space separated rule prerequisites, followed by a pipe, followed by
|
||||
order-only prerequisites, if present. */
|
||||
|
||||
const char *
|
||||
get_rule_defn (struct rule *r)
|
||||
{
|
||||
if (r->_defn == NULL)
|
||||
{
|
||||
size_t len = 8; /* Reserve for ":: ", " | ", and nul. */
|
||||
unsigned int k;
|
||||
char *p;
|
||||
const char *sep = "";
|
||||
const struct dep *dep, *ood = 0;
|
||||
|
||||
for (k = 0; k < r->num; ++k)
|
||||
len += r->lens[k] + 1;
|
||||
|
||||
for (dep = r->deps; dep; dep = dep->next)
|
||||
len += strlen (dep_name (dep)) + (dep->wait_here ? CSTRLEN (" .WAIT") : 0) + 1;
|
||||
|
||||
p = r->_defn = xmalloc (len);
|
||||
for (k = 0; k < r->num; ++k, sep = " ")
|
||||
p = mempcpy (mempcpy (p, sep, strlen (sep)), r->targets[k], r->lens[k]);
|
||||
*p++ = ':';
|
||||
if (r->terminal)
|
||||
*p++ = ':';
|
||||
|
||||
/* Copy all normal dependencies; note any order-only deps. */
|
||||
for (dep = r->deps; dep; dep = dep->next)
|
||||
if (dep->ignore_mtime == 0)
|
||||
{
|
||||
if (dep->wait_here)
|
||||
p = mempcpy (p, " .WAIT", CSTRLEN (" .WAIT"));
|
||||
p = mempcpy (mempcpy (p, " ", 1), dep_name (dep),
|
||||
strlen (dep_name (dep)));
|
||||
}
|
||||
else if (ood == 0)
|
||||
ood = dep;
|
||||
|
||||
/* Copy order-only deps, if we have any. */
|
||||
for (sep = " | "; ood; ood = ood->next, sep = " ")
|
||||
if (ood->ignore_mtime)
|
||||
{
|
||||
p = mempcpy (p, sep, strlen (sep));
|
||||
if (ood->wait_here)
|
||||
p = mempcpy (p, ".WAIT ", CSTRLEN (".WAIT "));
|
||||
p = mempcpy (p, dep_name (ood), strlen (dep_name (ood)));
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
return r->_defn;
|
||||
}
|
||||
|
||||
|
||||
/* Compute the maximum dependency length and maximum number of dependencies of
|
||||
all implicit rules. Also sets the subdir flag for a rule when appropriate,
|
||||
|
@ -78,7 +137,18 @@ snap_implicit_rules (void)
|
|||
|
||||
for (dep = prereqs; dep; dep = dep->next)
|
||||
{
|
||||
size_t l = strlen (dep_name (dep));
|
||||
const char *d = dep_name (dep);
|
||||
size_t l = strlen (d);
|
||||
|
||||
if (dep->need_2nd_expansion)
|
||||
/* When pattern_search allocates a buffer, allow 5 bytes per each % to
|
||||
substitute each % with $(*F) while avoiding realloc. */
|
||||
while ((d = strchr (d, '%')) != 0)
|
||||
{
|
||||
l += 4;
|
||||
++d;
|
||||
}
|
||||
|
||||
if (l > max_pattern_dep_length)
|
||||
max_pattern_dep_length = l;
|
||||
++pre_deps;
|
||||
|
@ -101,8 +171,16 @@ snap_implicit_rules (void)
|
|||
const char *dname = dep_name (dep);
|
||||
size_t len = strlen (dname);
|
||||
|
||||
#ifdef VMS
|
||||
const char *p = strrchr (dname, ']');
|
||||
const char *p2;
|
||||
if (p == 0)
|
||||
p = strrchr (dname, ':');
|
||||
p2 = p ? strchr (p, '%') : 0;
|
||||
#else
|
||||
const char *p = strrchr (dname, '/');
|
||||
const char *p2 = p ? strchr (p, '%') : 0;
|
||||
#endif
|
||||
ndeps++;
|
||||
|
||||
if (len > max_pattern_dep_length)
|
||||
|
@ -172,7 +250,11 @@ convert_suffix_rule (const char *target, const char *source,
|
|||
{
|
||||
/* Special case: TARGET being nil means we are defining a '.X.a' suffix
|
||||
rule; the target pattern is always '(%.o)'. */
|
||||
#ifdef VMS
|
||||
*names = strcache_add_len ("(%.obj)", 7);
|
||||
#else
|
||||
*names = strcache_add_len ("(%.o)", 5);
|
||||
#endif
|
||||
*percents = *names + 1;
|
||||
}
|
||||
else
|
||||
|
@ -264,7 +346,7 @@ convert_to_pattern (void)
|
|||
|
||||
/* POSIX says that suffix rules can't have prerequisites.
|
||||
In POSIX mode, don't make this a suffix rule. Previous versions
|
||||
of GNU make did treat this as a suffix rule and ignored the
|
||||
of GNU Make did treat this as a suffix rule and ignored the
|
||||
prerequisites, which is bad. In the future we'll do the same as
|
||||
POSIX, but for now preserve the old behavior and warn about it. */
|
||||
if (f->deps != 0)
|
||||
|
@ -384,6 +466,7 @@ install_pattern_rule (struct pspec *p, int terminal)
|
|||
r->targets = xmalloc (sizeof (const char *));
|
||||
r->suffixes = xmalloc (sizeof (const char *));
|
||||
r->lens = xmalloc (sizeof (unsigned int));
|
||||
r->_defn = NULL;
|
||||
|
||||
r->lens[0] = (unsigned int) strlen (p->target);
|
||||
r->targets[0] = p->target;
|
||||
|
@ -425,6 +508,7 @@ freerule (struct rule *rule, struct rule *lastrule)
|
|||
free ((void *)rule->targets);
|
||||
free ((void *)rule->suffixes);
|
||||
free (rule->lens);
|
||||
free ((void *) rule->_defn);
|
||||
|
||||
/* We can't free the storage for the commands because there
|
||||
are ways that they could be in more than one place:
|
||||
|
@ -474,6 +558,7 @@ create_pattern_rule (const char **targets, const char **target_percents,
|
|||
r->targets = targets;
|
||||
r->suffixes = target_percents;
|
||||
r->lens = xmalloc (n * sizeof (unsigned int));
|
||||
r->_defn = NULL;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
|
@ -491,17 +576,8 @@ create_pattern_rule (const char **targets, const char **target_percents,
|
|||
static void /* Useful to call from gdb. */
|
||||
print_rule (struct rule *r)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < r->num; ++i)
|
||||
{
|
||||
fputs (r->targets[i], stdout);
|
||||
putchar ((i + 1 == r->num) ? ':' : ' ');
|
||||
}
|
||||
if (r->terminal)
|
||||
putchar (':');
|
||||
|
||||
print_prereqs (r->deps);
|
||||
fputs (get_rule_defn (r), stdout);
|
||||
putchar ('\n');
|
||||
|
||||
if (r->cmds != 0)
|
||||
print_commands (r->cmds);
|
||||
|
|
6
third_party/make/rule.h
vendored
6
third_party/make/rule.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Definitions for using pattern rules in GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,7 +12,7 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
/* Structure used for pattern (implicit) rules. */
|
||||
|
@ -25,6 +25,7 @@ struct rule
|
|||
const char **suffixes; /* Suffixes (after '%') of each target. */
|
||||
struct dep *deps; /* Dependencies of the rule. */
|
||||
struct commands *cmds; /* Commands to execute. */
|
||||
char *_defn; /* Definition of the rule. */
|
||||
unsigned short num; /* Number of targets. */
|
||||
char terminal; /* If terminal (double-colon). */
|
||||
char in_use; /* If in use by a parent pattern_search. */
|
||||
|
@ -54,4 +55,5 @@ void install_pattern_rule (struct pspec *p, int terminal);
|
|||
void create_pattern_rule (const char **targets, const char **target_percents,
|
||||
unsigned short num, int terminal, struct dep *deps,
|
||||
struct commands *commands, int override);
|
||||
const char *get_rule_defn (struct rule *rule);
|
||||
void print_rule_data_base (void);
|
||||
|
|
237
third_party/make/shuffle.c
vendored
Normal file
237
third_party/make/shuffle.c
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
/* Provide prerequisite shuffle support.
|
||||
Copyright (C) 2022-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 "shuffle.h"
|
||||
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
|
||||
/* Supported shuffle modes. */
|
||||
static void random_shuffle_array (void ** a, size_t len);
|
||||
static void reverse_shuffle_array (void ** a, size_t len);
|
||||
static void identity_shuffle_array (void ** a, size_t len);
|
||||
|
||||
/* The way goals and rules are shuffled during update. */
|
||||
enum shuffle_mode
|
||||
{
|
||||
/* No shuffle data is populated or used. */
|
||||
sm_none,
|
||||
/* Random within dependency list. */
|
||||
sm_random,
|
||||
/* Inverse order. */
|
||||
sm_reverse,
|
||||
/* identity order. Differs from SM_NONE by explicitly populating
|
||||
the traversal order. */
|
||||
sm_identity,
|
||||
};
|
||||
|
||||
/* Shuffle configuration. */
|
||||
static struct
|
||||
{
|
||||
enum shuffle_mode mode;
|
||||
unsigned int seed;
|
||||
void (*shuffler) (void **a, size_t len);
|
||||
char strval[INTSTR_LENGTH + 1];
|
||||
} config = { sm_none, 0, NULL, "" };
|
||||
|
||||
/* Return string value of --shuffle= option passed.
|
||||
If none was passed or --shuffle=none was used function
|
||||
returns NULL. */
|
||||
const char *
|
||||
shuffle_get_mode ()
|
||||
{
|
||||
return config.strval[0] == '\0' ? NULL : config.strval;
|
||||
}
|
||||
|
||||
void
|
||||
shuffle_set_mode (const char *cmdarg)
|
||||
{
|
||||
/* Parse supported '--shuffle' mode. */
|
||||
if (strcasecmp (cmdarg, "reverse") == 0)
|
||||
{
|
||||
config.mode = sm_reverse;
|
||||
config.shuffler = reverse_shuffle_array;
|
||||
strcpy (config.strval, "reverse");
|
||||
}
|
||||
else if (strcasecmp (cmdarg, "identity") == 0)
|
||||
{
|
||||
config.mode = sm_identity;
|
||||
config.shuffler = identity_shuffle_array;
|
||||
strcpy (config.strval, "identity");
|
||||
}
|
||||
else if (strcasecmp (cmdarg, "none") == 0)
|
||||
{
|
||||
config.mode = sm_none;
|
||||
config.shuffler = NULL;
|
||||
config.strval[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcasecmp (cmdarg, "random") == 0)
|
||||
config.seed = make_rand ();
|
||||
else
|
||||
{
|
||||
/* Assume explicit seed. */
|
||||
const char *err;
|
||||
config.seed = make_toui (cmdarg, &err);
|
||||
if (err)
|
||||
OSS (fatal, NILF, _("invalid shuffle mode: %s: '%s'"), err, cmdarg);
|
||||
}
|
||||
|
||||
config.mode = sm_random;
|
||||
config.shuffler = random_shuffle_array;
|
||||
sprintf (config.strval, "%u", config.seed);
|
||||
}
|
||||
}
|
||||
|
||||
/* Shuffle array elements using RAND(). */
|
||||
static void
|
||||
random_shuffle_array (void **a, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
void *t;
|
||||
|
||||
/* Pick random element and swap. */
|
||||
unsigned int j = make_rand () % len;
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
/* Swap. */
|
||||
t = a[i];
|
||||
a[i] = a[j];
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shuffle array elements using reverse order. */
|
||||
static void
|
||||
reverse_shuffle_array (void **a, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < len / 2; i++)
|
||||
{
|
||||
void *t;
|
||||
|
||||
/* Pick mirror and swap. */
|
||||
size_t j = len - 1 - i;
|
||||
|
||||
/* Swap. */
|
||||
t = a[i];
|
||||
a[i] = a[j];
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shuffle array elements using identity order. */
|
||||
static void
|
||||
identity_shuffle_array (void **a UNUSED, size_t len UNUSED)
|
||||
{
|
||||
/* No-op! */
|
||||
}
|
||||
|
||||
/* Shuffle list of dependencies by populating '->shuf'
|
||||
field in each 'struct dep'. */
|
||||
static void
|
||||
shuffle_deps (struct dep *deps)
|
||||
{
|
||||
size_t ndeps = 0;
|
||||
struct dep *dep;
|
||||
void **da;
|
||||
void **dp;
|
||||
|
||||
for (dep = deps; dep; dep = dep->next)
|
||||
{
|
||||
/* Do not reshuffle prerequisites if any .WAIT is present. */
|
||||
if (dep->wait_here)
|
||||
return;
|
||||
|
||||
ndeps++;
|
||||
}
|
||||
|
||||
if (ndeps == 0)
|
||||
return;
|
||||
|
||||
/* Allocate array of all deps, store, shuffle, write back. */
|
||||
da = xmalloc (sizeof (struct dep *) * ndeps);
|
||||
|
||||
/* Store locally. */
|
||||
for (dep = deps, dp = da; dep; dep = dep->next, dp++)
|
||||
*dp = dep;
|
||||
|
||||
/* Shuffle. */
|
||||
config.shuffler (da, ndeps);
|
||||
|
||||
/* Write back. */
|
||||
for (dep = deps, dp = da; dep; dep = dep->next, dp++)
|
||||
dep->shuf = *dp;
|
||||
|
||||
free (da);
|
||||
}
|
||||
|
||||
/* Shuffle 'deps' of each 'file' recursively. */
|
||||
static void
|
||||
shuffle_file_deps_recursive (struct file *f)
|
||||
{
|
||||
struct dep *dep;
|
||||
|
||||
/* Implicit rules do not always provide any depends. */
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
/* Avoid repeated shuffles and loops. */
|
||||
if (f->was_shuffled)
|
||||
return;
|
||||
f->was_shuffled = 1;
|
||||
|
||||
shuffle_deps (f->deps);
|
||||
|
||||
/* Shuffle dependencies. */
|
||||
for (dep = f->deps; dep; dep = dep->next)
|
||||
shuffle_file_deps_recursive (dep->file);
|
||||
}
|
||||
|
||||
/* Shuffle goal dependencies first, then shuffle dependency list
|
||||
of each file reachable from goaldep recursively. Used by
|
||||
--shuffle flag to introduce artificial non-determinism in build
|
||||
order. .*/
|
||||
|
||||
void
|
||||
shuffle_deps_recursive (struct dep *deps)
|
||||
{
|
||||
struct dep *dep;
|
||||
|
||||
/* Exit early if shuffling was not requested. */
|
||||
if (config.mode == sm_none)
|
||||
return;
|
||||
|
||||
/* Do not reshuffle prerequisites if .NOTPARALLEL was specified. */
|
||||
if (not_parallel)
|
||||
return;
|
||||
|
||||
/* Set specific seed at the top level of recursion. */
|
||||
if (config.mode == sm_random)
|
||||
make_seed (config.seed);
|
||||
|
||||
shuffle_deps (deps);
|
||||
|
||||
/* Shuffle dependencies. */
|
||||
for (dep = deps; dep; dep = dep->next)
|
||||
shuffle_file_deps_recursive (dep->file);
|
||||
}
|
26
third_party/make/shuffle.h
vendored
Normal file
26
third_party/make/shuffle.h
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* Declarations for target shuffling support.
|
||||
Copyright (C) 2022-2022 Free Software Foundation, Inc.
|
||||
This file is part of GNU Make.
|
||||
|
||||
GNU Make is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
struct dep;
|
||||
struct goaldep;
|
||||
|
||||
void shuffle_set_mode (const char *cmdarg);
|
||||
const char *shuffle_get_mode (void);
|
||||
void shuffle_deps_recursive (struct dep* g);
|
||||
|
||||
#define shuffle_goaldeps_recursive(_g) do{ \
|
||||
shuffle_deps_recursive ((struct dep *)_g); \
|
||||
} while(0)
|
254
third_party/make/signame.c
vendored
Normal file
254
third_party/make/signame.c
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
/* Convert between signal names and numbers.
|
||||
Copyright (C) 1990-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"
|
||||
|
||||
/* If the system provides strsignal, we don't need it. */
|
||||
|
||||
#if !HAVE_STRSIGNAL
|
||||
|
||||
/* If the system provides sys_siglist, we'll use that.
|
||||
Otherwise create our own.
|
||||
*/
|
||||
|
||||
#if !HAVE_DECL_SYS_SIGLIST
|
||||
|
||||
/* Some systems do not define NSIG in <signal.h>. */
|
||||
#ifndef NSIG
|
||||
#ifdef _NSIG
|
||||
#define NSIG _NSIG
|
||||
#else
|
||||
#define NSIG 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* There is too much variation in Sys V signal numbers and names, so
|
||||
we must initialize them at runtime. */
|
||||
|
||||
static const char *undoc;
|
||||
|
||||
static const char *sys_siglist[NSIG];
|
||||
|
||||
/* Table of abbreviations for signals. Note: A given number can
|
||||
appear more than once with different abbreviations. */
|
||||
#define SIG_TABLE_SIZE (NSIG*2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int number;
|
||||
const char *abbrev;
|
||||
} num_abbrev;
|
||||
|
||||
static num_abbrev sig_table[SIG_TABLE_SIZE];
|
||||
|
||||
/* Number of elements of sig_table used. */
|
||||
static int sig_table_nelts = 0;
|
||||
|
||||
/* Enter signal number NUMBER into the tables with ABBREV and NAME. */
|
||||
|
||||
static void
|
||||
init_sig (int number, const char *abbrev, const char *name)
|
||||
{
|
||||
/* If this value is ever greater than NSIG it seems like it'd be a bug in
|
||||
the system headers, but... better safe than sorry. We know, for
|
||||
example, that this isn't always true on VMS. */
|
||||
|
||||
if (number >= 0 && number < NSIG)
|
||||
sys_siglist[number] = name;
|
||||
|
||||
if (sig_table_nelts < SIG_TABLE_SIZE)
|
||||
{
|
||||
sig_table[sig_table_nelts].number = number;
|
||||
sig_table[sig_table_nelts++].abbrev = abbrev;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
signame_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
undoc = xstrdup (_("unknown signal"));
|
||||
|
||||
/* Initialize signal names. */
|
||||
for (i = 0; i < NSIG; i++)
|
||||
sys_siglist[i] = undoc;
|
||||
|
||||
/* Initialize signal names. */
|
||||
#if defined (SIGHUP)
|
||||
init_sig (SIGHUP, "HUP", _("Hangup"));
|
||||
#endif
|
||||
#if defined (SIGINT)
|
||||
init_sig (SIGINT, "INT", _("Interrupt"));
|
||||
#endif
|
||||
#if defined (SIGQUIT)
|
||||
init_sig (SIGQUIT, "QUIT", _("Quit"));
|
||||
#endif
|
||||
#if defined (SIGILL)
|
||||
init_sig (SIGILL, "ILL", _("Illegal Instruction"));
|
||||
#endif
|
||||
#if defined (SIGTRAP)
|
||||
init_sig (SIGTRAP, "TRAP", _("Trace/breakpoint trap"));
|
||||
#endif
|
||||
/* If SIGIOT == SIGABRT, we want to print it as SIGABRT because
|
||||
SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't. */
|
||||
#if defined (SIGABRT)
|
||||
init_sig (SIGABRT, "ABRT", _("Aborted"));
|
||||
#endif
|
||||
#if defined (SIGIOT)
|
||||
init_sig (SIGIOT, "IOT", _("IOT trap"));
|
||||
#endif
|
||||
#if defined (SIGEMT)
|
||||
init_sig (SIGEMT, "EMT", _("EMT trap"));
|
||||
#endif
|
||||
#if defined (SIGFPE)
|
||||
init_sig (SIGFPE, "FPE", _("Floating point exception"));
|
||||
#endif
|
||||
#if defined (SIGKILL)
|
||||
init_sig (SIGKILL, "KILL", _("Killed"));
|
||||
#endif
|
||||
#if defined (SIGBUS)
|
||||
init_sig (SIGBUS, "BUS", _("Bus error"));
|
||||
#endif
|
||||
#if defined (SIGSEGV)
|
||||
init_sig (SIGSEGV, "SEGV", _("Segmentation fault"));
|
||||
#endif
|
||||
#if defined (SIGSYS)
|
||||
init_sig (SIGSYS, "SYS", _("Bad system call"));
|
||||
#endif
|
||||
#if defined (SIGPIPE)
|
||||
init_sig (SIGPIPE, "PIPE", _("Broken pipe"));
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
init_sig (SIGALRM, "ALRM", _("Alarm clock"));
|
||||
#endif
|
||||
#if defined (SIGTERM)
|
||||
init_sig (SIGTERM, "TERM", _("Terminated"));
|
||||
#endif
|
||||
#if defined (SIGUSR1)
|
||||
init_sig (SIGUSR1, "USR1", _("User defined signal 1"));
|
||||
#endif
|
||||
#if defined (SIGUSR2)
|
||||
init_sig (SIGUSR2, "USR2", _("User defined signal 2"));
|
||||
#endif
|
||||
/* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that
|
||||
is what is in POSIX.1. */
|
||||
#if defined (SIGCHLD)
|
||||
init_sig (SIGCHLD, "CHLD", _("Child exited"));
|
||||
#endif
|
||||
#if defined (SIGCLD)
|
||||
init_sig (SIGCLD, "CLD", _("Child exited"));
|
||||
#endif
|
||||
#if defined (SIGPWR)
|
||||
init_sig (SIGPWR, "PWR", _("Power failure"));
|
||||
#endif
|
||||
#if defined (SIGTSTP)
|
||||
init_sig (SIGTSTP, "TSTP", _("Stopped"));
|
||||
#endif
|
||||
#if defined (SIGTTIN)
|
||||
init_sig (SIGTTIN, "TTIN", _("Stopped (tty input)"));
|
||||
#endif
|
||||
#if defined (SIGTTOU)
|
||||
init_sig (SIGTTOU, "TTOU", _("Stopped (tty output)"));
|
||||
#endif
|
||||
#if defined (SIGSTOP)
|
||||
init_sig (SIGSTOP, "STOP", _("Stopped (signal)"));
|
||||
#endif
|
||||
#if defined (SIGXCPU)
|
||||
init_sig (SIGXCPU, "XCPU", _("CPU time limit exceeded"));
|
||||
#endif
|
||||
#if defined (SIGXFSZ)
|
||||
init_sig (SIGXFSZ, "XFSZ", _("File size limit exceeded"));
|
||||
#endif
|
||||
#if defined (SIGVTALRM)
|
||||
init_sig (SIGVTALRM, "VTALRM", _("Virtual timer expired"));
|
||||
#endif
|
||||
#if defined (SIGPROF)
|
||||
init_sig (SIGPROF, "PROF", _("Profiling timer expired"));
|
||||
#endif
|
||||
#if defined (SIGWINCH)
|
||||
/* "Window size changed" might be more accurate, but even if that
|
||||
is all that it means now, perhaps in the future it will be
|
||||
extended to cover other kinds of window changes. */
|
||||
init_sig (SIGWINCH, "WINCH", _("Window changed"));
|
||||
#endif
|
||||
#if defined (SIGCONT)
|
||||
init_sig (SIGCONT, "CONT", _("Continued"));
|
||||
#endif
|
||||
#if defined (SIGURG)
|
||||
init_sig (SIGURG, "URG", _("Urgent I/O condition"));
|
||||
#endif
|
||||
#if defined (SIGIO)
|
||||
/* "I/O pending" has also been suggested. A disadvantage is that signal
|
||||
only happens when the process has asked for it, not every time I/O is
|
||||
pending. Another disadvantage is the confusion from giving it a
|
||||
different name than under Unix. */
|
||||
init_sig (SIGIO, "IO", _("I/O possible"));
|
||||
#endif
|
||||
#if defined (SIGWIND)
|
||||
init_sig (SIGWIND, "WIND", _("SIGWIND"));
|
||||
#endif
|
||||
#if defined (SIGPHONE)
|
||||
init_sig (SIGPHONE, "PHONE", _("SIGPHONE"));
|
||||
#endif
|
||||
#if defined (SIGPOLL)
|
||||
init_sig (SIGPOLL, "POLL", _("I/O possible"));
|
||||
#endif
|
||||
#if defined (SIGLOST)
|
||||
init_sig (SIGLOST, "LOST", _("Resource lost"));
|
||||
#endif
|
||||
#if defined (SIGDANGER)
|
||||
init_sig (SIGDANGER, "DANGER", _("Danger signal"));
|
||||
#endif
|
||||
#if defined (SIGINFO)
|
||||
init_sig (SIGINFO, "INFO", _("Information request"));
|
||||
#endif
|
||||
#if defined (SIGNOFP)
|
||||
init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available"));
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DECL_SYS_SIGLIST */
|
||||
|
||||
|
||||
char *
|
||||
strsignal (int sig)
|
||||
{
|
||||
static char buf[] = "Signal 12345678901234567890";
|
||||
|
||||
#if ! HAVE_DECL_SYS_SIGLIST
|
||||
# if HAVE_DECL__SYS_SIGLIST
|
||||
# define sys_siglist _sys_siglist
|
||||
# elif HAVE_DECL___SYS_SIGLIST
|
||||
# define sys_siglist __sys_siglist
|
||||
# else
|
||||
static int sig_initted = 0;
|
||||
|
||||
if (!sig_initted)
|
||||
sig_initted = signame_init ();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (sig > 0 && sig < NSIG)
|
||||
return (char *) sys_siglist[sig];
|
||||
|
||||
sprintf (buf, "Signal %d", sig);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* HAVE_STRSIGNAL */
|
119
third_party/make/stddef.h
vendored
119
third_party/make/stddef.h
vendored
|
@ -1,119 +0,0 @@
|
|||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* A substitute for POSIX 2008 <stddef.h>, for platforms that have issues.
|
||||
|
||||
Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* Written by Eric Blake. */
|
||||
|
||||
/*
|
||||
* POSIX 2008 <stddef.h> for platforms that have issues.
|
||||
* <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html>
|
||||
*/
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __need_wchar_t || defined __need_size_t \
|
||||
|| defined __need_ptrdiff_t || defined __need_NULL \
|
||||
|| defined __need_wint_t
|
||||
/* Special invocation convention inside gcc header files. In
|
||||
particular, gcc provides a version of <stddef.h> that blindly
|
||||
redefines NULL even when __need_wint_t was defined, even though
|
||||
wint_t is not normally provided by <stddef.h>. Hence, we must
|
||||
remember if special invocation has ever been used to obtain wint_t,
|
||||
in which case we need to clean up NULL yet again. */
|
||||
|
||||
# if !(defined _GL_STDDEF_H && defined _GL_STDDEF_WINT_T)
|
||||
# ifdef __need_wint_t
|
||||
# define _GL_STDDEF_WINT_T
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#else
|
||||
/* Normal invocation convention. */
|
||||
|
||||
# ifndef _GL_STDDEF_H
|
||||
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
|
||||
|
||||
/* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */
|
||||
# if (0 \
|
||||
&& (!defined _GL_STDDEF_H || defined _GL_STDDEF_WINT_T))
|
||||
# undef NULL
|
||||
# ifdef __cplusplus
|
||||
/* ISO C++ says that the macro NULL must expand to an integer constant
|
||||
expression, hence '((void *) 0)' is not allowed in C++. */
|
||||
# if __GNUG__ >= 3
|
||||
/* GNU C++ has a __null macro that behaves like an integer ('int' or
|
||||
'long') but has the same size as a pointer. Use that, to avoid
|
||||
warnings. */
|
||||
# define NULL __null
|
||||
# else
|
||||
# define NULL 0L
|
||||
# endif
|
||||
# else
|
||||
# define NULL ((void *) 0)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef _GL_STDDEF_H
|
||||
# define _GL_STDDEF_H
|
||||
|
||||
/* Some platforms lack wchar_t. */
|
||||
#if !1
|
||||
# define wchar_t int
|
||||
#endif
|
||||
|
||||
/* Some platforms lack max_align_t. The check for _GCC_MAX_ALIGN_T is
|
||||
a hack in case the configure-time test was done with g++ even though
|
||||
we are currently compiling with gcc.
|
||||
On MSVC, max_align_t is defined only in C++ mode, after <cstddef> was
|
||||
included. Its definition is good since it has an alignment of 8 (on x86
|
||||
and x86_64). */
|
||||
#if defined _MSC_VER && defined __cplusplus
|
||||
#else
|
||||
# if ! (0 || defined _GCC_MAX_ALIGN_T)
|
||||
# if !GNULIB_defined_max_align_t
|
||||
/* On the x86, the maximum storage alignment of double, long, etc. is 4,
|
||||
but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8,
|
||||
and the C11 standard allows this. Work around this problem by
|
||||
using __alignof__ (which returns 8 for double) rather than _Alignof
|
||||
(which returns 4), and align each union member accordingly. */
|
||||
# ifdef __GNUC__
|
||||
# define _GL_STDDEF_ALIGNAS(type) \
|
||||
__attribute__ ((__aligned__ (__alignof__ (type))))
|
||||
# else
|
||||
# define _GL_STDDEF_ALIGNAS(type) /* */
|
||||
# endif
|
||||
typedef union
|
||||
{
|
||||
char *__p _GL_STDDEF_ALIGNAS (char *);
|
||||
double __d _GL_STDDEF_ALIGNAS (double);
|
||||
long double __ld _GL_STDDEF_ALIGNAS (long double);
|
||||
long int __i _GL_STDDEF_ALIGNAS (long int);
|
||||
} rpl_max_align_t;
|
||||
# define max_align_t rpl_max_align_t
|
||||
# define GNULIB_defined_max_align_t 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# endif /* _GL_STDDEF_H */
|
||||
# endif /* _GL_STDDEF_H */
|
||||
#endif /* __need_XXX */
|
735
third_party/make/stdint.h
vendored
735
third_party/make/stdint.h
vendored
|
@ -1,735 +0,0 @@
|
|||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Copyright (C) 2001-2002, 2004-2020 Free Software Foundation, Inc.
|
||||
Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
|
||||
This file is part of gnulib.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/*
|
||||
* ISO C 99 <stdint.h> for platforms that lack it.
|
||||
* <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html>
|
||||
*/
|
||||
|
||||
#ifndef _GL_STDINT_H
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
|
||||
/* When including a system file that in turn includes <inttypes.h>,
|
||||
use the system <inttypes.h>, not our substitute. This avoids
|
||||
problems with (for example) VMS, whose <sys/bitypes.h> includes
|
||||
<inttypes.h>. */
|
||||
#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
|
||||
|
||||
/* On Android (Bionic libc), <sys/types.h> includes this file before
|
||||
having defined 'time_t'. Therefore in this case avoid including
|
||||
other system header files; just include the system's <stdint.h>.
|
||||
Ideally we should test __BIONIC__ here, but it is only defined after
|
||||
<sys/cdefs.h> has been included; hence test __ANDROID__ instead. */
|
||||
#if defined __ANDROID__ && defined _GL_INCLUDING_SYS_TYPES_H
|
||||
#else
|
||||
|
||||
/* Get those types that are already defined in other system include
|
||||
files, so that we can "#define int8_t signed char" below without
|
||||
worrying about a later system include file containing a "typedef
|
||||
signed char int8_t;" that will get messed up by our macro. Our
|
||||
macros should all be consistent with the system versions, except
|
||||
for the "fast" types and macros, which we recommend against using
|
||||
in public interfaces due to compiler differences. */
|
||||
|
||||
#if 1
|
||||
# if defined __sgi && ! defined __c99
|
||||
/* Bypass IRIX's <stdint.h> if in C89 mode, since it merely annoys users
|
||||
with "This header file is to be used only for c99 mode compilations"
|
||||
diagnostics. */
|
||||
# define __STDINT_H__
|
||||
# endif
|
||||
|
||||
/* Some pre-C++11 <stdint.h> implementations need this. */
|
||||
# ifdef __cplusplus
|
||||
# ifndef __STDC_CONSTANT_MACROS
|
||||
# define __STDC_CONSTANT_MACROS 1
|
||||
# endif
|
||||
# ifndef __STDC_LIMIT_MACROS
|
||||
# define __STDC_LIMIT_MACROS 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Other systems may have an incomplete or buggy <stdint.h>.
|
||||
in <inttypes.h> would reinclude us, skipping our contents because
|
||||
_GL_STDINT_H is defined.
|
||||
The include_next requires a split double-inclusion guard. */
|
||||
#endif
|
||||
|
||||
#if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H
|
||||
#define _GL_STDINT_H
|
||||
|
||||
/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX,
|
||||
LONG_MIN, LONG_MAX, ULONG_MAX, _GL_INTEGER_WIDTH. */
|
||||
|
||||
/* Override WINT_MIN and WINT_MAX if gnulib's <wchar.h> or <wctype.h> overrides
|
||||
wint_t. */
|
||||
#if 0
|
||||
# undef WINT_MIN
|
||||
# undef WINT_MAX
|
||||
# define WINT_MIN 0x0U
|
||||
# define WINT_MAX 0xffffffffU
|
||||
#endif
|
||||
|
||||
#if ! 0
|
||||
|
||||
/* <sys/types.h> defines some of the stdint.h types as well, on glibc,
|
||||
IRIX 6.5, and OpenBSD 3.8 (via <machine/types.h>).
|
||||
AIX 5.2 <sys/types.h> isn't needed and causes troubles.
|
||||
Mac OS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but
|
||||
relies on the system <stdint.h> definitions, so include
|
||||
<sys/types.h> after <stdint.h>. */
|
||||
# if 1 && ! defined _AIX
|
||||
# endif
|
||||
|
||||
# if 1
|
||||
/* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines
|
||||
int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__.
|
||||
<inttypes.h> also defines intptr_t and uintptr_t. */
|
||||
# elif 0
|
||||
/* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and
|
||||
the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */
|
||||
# endif
|
||||
|
||||
# if 0 && ! defined __BIT_TYPES_DEFINED__
|
||||
/* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines
|
||||
int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is
|
||||
included by <sys/types.h>. */
|
||||
# endif
|
||||
|
||||
# undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
|
||||
|
||||
/* Minimum and maximum values for an integer type under the usual assumption.
|
||||
Return an unspecified value if BITS == 0, adding a check to pacify
|
||||
picky compilers. */
|
||||
|
||||
/* These are separate macros, because if you try to merge these macros into
|
||||
a single one, HP-UX cc rejects the resulting expression in constant
|
||||
expressions. */
|
||||
# define _STDINT_UNSIGNED_MIN(bits, zero) \
|
||||
(zero)
|
||||
# define _STDINT_SIGNED_MIN(bits, zero) \
|
||||
(~ _STDINT_MAX (1, bits, zero))
|
||||
|
||||
# define _STDINT_MAX(signed, bits, zero) \
|
||||
(((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1)
|
||||
|
||||
#if !GNULIB_defined_stdint_types
|
||||
|
||||
/* 7.18.1.1. Exact-width integer types */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits. */
|
||||
|
||||
# undef int8_t
|
||||
# undef uint8_t
|
||||
typedef signed char gl_int8_t;
|
||||
typedef unsigned char gl_uint8_t;
|
||||
# define int8_t gl_int8_t
|
||||
# define uint8_t gl_uint8_t
|
||||
|
||||
# undef int16_t
|
||||
# undef uint16_t
|
||||
typedef short int gl_int16_t;
|
||||
typedef unsigned short int gl_uint16_t;
|
||||
# define int16_t gl_int16_t
|
||||
# define uint16_t gl_uint16_t
|
||||
|
||||
# undef int32_t
|
||||
# undef uint32_t
|
||||
typedef int gl_int32_t;
|
||||
typedef unsigned int gl_uint32_t;
|
||||
# define int32_t gl_int32_t
|
||||
# define uint32_t gl_uint32_t
|
||||
|
||||
/* If the system defines INT64_MAX, assume int64_t works. That way,
|
||||
if the underlying platform defines int64_t to be a 64-bit long long
|
||||
int, the code below won't mistakenly define it to be a 64-bit long
|
||||
int, which would mess up C++ name mangling. We must use #ifdef
|
||||
rather than #if, to avoid an error with HP-UX 10.20 cc. */
|
||||
|
||||
# ifdef INT64_MAX
|
||||
# define GL_INT64_T
|
||||
# else
|
||||
/* Do not undefine int64_t if gnulib is not being used with 64-bit
|
||||
types, since otherwise it breaks platforms like Tandem/NSK. */
|
||||
# if LONG_MAX >> 31 >> 31 == 1
|
||||
# undef int64_t
|
||||
typedef long int gl_int64_t;
|
||||
# define int64_t gl_int64_t
|
||||
# define GL_INT64_T
|
||||
# elif defined _MSC_VER
|
||||
# undef int64_t
|
||||
typedef __int64 gl_int64_t;
|
||||
# define int64_t gl_int64_t
|
||||
# define GL_INT64_T
|
||||
# else
|
||||
# undef int64_t
|
||||
typedef long long int gl_int64_t;
|
||||
# define int64_t gl_int64_t
|
||||
# define GL_INT64_T
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef UINT64_MAX
|
||||
# define GL_UINT64_T
|
||||
# else
|
||||
# if ULONG_MAX >> 31 >> 31 >> 1 == 1
|
||||
# undef uint64_t
|
||||
typedef unsigned long int gl_uint64_t;
|
||||
# define uint64_t gl_uint64_t
|
||||
# define GL_UINT64_T
|
||||
# elif defined _MSC_VER
|
||||
# undef uint64_t
|
||||
typedef unsigned __int64 gl_uint64_t;
|
||||
# define uint64_t gl_uint64_t
|
||||
# define GL_UINT64_T
|
||||
# else
|
||||
# undef uint64_t
|
||||
typedef unsigned long long int gl_uint64_t;
|
||||
# define uint64_t gl_uint64_t
|
||||
# define GL_UINT64_T
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Avoid collision with Solaris 2.5.1 <pthread.h> etc. */
|
||||
# define _UINT8_T
|
||||
# define _UINT32_T
|
||||
# define _UINT64_T
|
||||
|
||||
|
||||
/* 7.18.1.2. Minimum-width integer types */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
|
||||
are the same as the corresponding N_t types. */
|
||||
|
||||
# undef int_least8_t
|
||||
# undef uint_least8_t
|
||||
# undef int_least16_t
|
||||
# undef uint_least16_t
|
||||
# undef int_least32_t
|
||||
# undef uint_least32_t
|
||||
# undef int_least64_t
|
||||
# undef uint_least64_t
|
||||
# define int_least8_t int8_t
|
||||
# define uint_least8_t uint8_t
|
||||
# define int_least16_t int16_t
|
||||
# define uint_least16_t uint16_t
|
||||
# define int_least32_t int32_t
|
||||
# define uint_least32_t uint32_t
|
||||
# ifdef GL_INT64_T
|
||||
# define int_least64_t int64_t
|
||||
# endif
|
||||
# ifdef GL_UINT64_T
|
||||
# define uint_least64_t uint64_t
|
||||
# endif
|
||||
|
||||
/* 7.18.1.3. Fastest minimum-width integer types */
|
||||
|
||||
/* Note: Other <stdint.h> substitutes may define these types differently.
|
||||
It is not recommended to use these types in public header files. */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
|
||||
are taken from the same list of types. The following code normally
|
||||
uses types consistent with glibc, as that lessens the chance of
|
||||
incompatibility with older GNU hosts. */
|
||||
|
||||
# undef int_fast8_t
|
||||
# undef uint_fast8_t
|
||||
# undef int_fast16_t
|
||||
# undef uint_fast16_t
|
||||
# undef int_fast32_t
|
||||
# undef uint_fast32_t
|
||||
# undef int_fast64_t
|
||||
# undef uint_fast64_t
|
||||
typedef signed char gl_int_fast8_t;
|
||||
typedef unsigned char gl_uint_fast8_t;
|
||||
|
||||
# ifdef __sun
|
||||
/* Define types compatible with SunOS 5.10, so that code compiled under
|
||||
earlier SunOS versions works with code compiled under SunOS 5.10. */
|
||||
typedef int gl_int_fast32_t;
|
||||
typedef unsigned int gl_uint_fast32_t;
|
||||
# else
|
||||
typedef long int gl_int_fast32_t;
|
||||
typedef unsigned long int gl_uint_fast32_t;
|
||||
# endif
|
||||
typedef gl_int_fast32_t gl_int_fast16_t;
|
||||
typedef gl_uint_fast32_t gl_uint_fast16_t;
|
||||
|
||||
# define int_fast8_t gl_int_fast8_t
|
||||
# define uint_fast8_t gl_uint_fast8_t
|
||||
# define int_fast16_t gl_int_fast16_t
|
||||
# define uint_fast16_t gl_uint_fast16_t
|
||||
# define int_fast32_t gl_int_fast32_t
|
||||
# define uint_fast32_t gl_uint_fast32_t
|
||||
# ifdef GL_INT64_T
|
||||
# define int_fast64_t int64_t
|
||||
# endif
|
||||
# ifdef GL_UINT64_T
|
||||
# define uint_fast64_t uint64_t
|
||||
# endif
|
||||
|
||||
/* 7.18.1.4. Integer types capable of holding object pointers */
|
||||
|
||||
/* kLIBC's <stdint.h> defines _INTPTR_T_DECLARED and needs its own
|
||||
definitions of intptr_t and uintptr_t (which use int and unsigned)
|
||||
to avoid clashes with declarations of system functions like sbrk.
|
||||
Similarly, mingw 5.22 <crtdefs.h> defines _INTPTR_T_DEFINED and
|
||||
_UINTPTR_T_DEFINED and needs its own definitions of intptr_t and
|
||||
uintptr_t to avoid conflicting declarations of system functions like
|
||||
_findclose in <io.h>. */
|
||||
# if !((defined __KLIBC__ && defined _INTPTR_T_DECLARED) \
|
||||
|| (defined __MINGW32__ && defined _INTPTR_T_DEFINED && defined _UINTPTR_T_DEFINED))
|
||||
# undef intptr_t
|
||||
# undef uintptr_t
|
||||
# ifdef _WIN64
|
||||
typedef long long int gl_intptr_t;
|
||||
typedef unsigned long long int gl_uintptr_t;
|
||||
# else
|
||||
typedef long int gl_intptr_t;
|
||||
typedef unsigned long int gl_uintptr_t;
|
||||
# endif
|
||||
# define intptr_t gl_intptr_t
|
||||
# define uintptr_t gl_uintptr_t
|
||||
# endif
|
||||
|
||||
/* 7.18.1.5. Greatest-width integer types */
|
||||
|
||||
/* Note: These types are compiler dependent. It may be unwise to use them in
|
||||
public header files. */
|
||||
|
||||
/* If the system defines INTMAX_MAX, assume that intmax_t works, and
|
||||
similarly for UINTMAX_MAX and uintmax_t. This avoids problems with
|
||||
assuming one type where another is used by the system. */
|
||||
|
||||
# ifndef INTMAX_MAX
|
||||
# undef INTMAX_C
|
||||
# undef intmax_t
|
||||
# if LONG_MAX >> 30 == 1
|
||||
typedef long long int gl_intmax_t;
|
||||
# define intmax_t gl_intmax_t
|
||||
# elif defined GL_INT64_T
|
||||
# define intmax_t int64_t
|
||||
# else
|
||||
typedef long int gl_intmax_t;
|
||||
# define intmax_t gl_intmax_t
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef UINTMAX_MAX
|
||||
# undef UINTMAX_C
|
||||
# undef uintmax_t
|
||||
# if ULONG_MAX >> 31 == 1
|
||||
typedef unsigned long long int gl_uintmax_t;
|
||||
# define uintmax_t gl_uintmax_t
|
||||
# elif defined GL_UINT64_T
|
||||
# define uintmax_t uint64_t
|
||||
# else
|
||||
typedef unsigned long int gl_uintmax_t;
|
||||
# define uintmax_t gl_uintmax_t
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Verify that intmax_t and uintmax_t have the same size. Too much code
|
||||
breaks if this is not the case. If this check fails, the reason is likely
|
||||
to be found in the autoconf macros. */
|
||||
typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
|
||||
? 1 : -1];
|
||||
|
||||
# define GNULIB_defined_stdint_types 1
|
||||
# endif /* !GNULIB_defined_stdint_types */
|
||||
|
||||
/* 7.18.2. Limits of specified-width integer types */
|
||||
|
||||
/* 7.18.2.1. Limits of exact-width integer types */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits. */
|
||||
|
||||
# undef INT8_MIN
|
||||
# undef INT8_MAX
|
||||
# undef UINT8_MAX
|
||||
# define INT8_MIN (~ INT8_MAX)
|
||||
# define INT8_MAX 127
|
||||
# define UINT8_MAX 255
|
||||
|
||||
# undef INT16_MIN
|
||||
# undef INT16_MAX
|
||||
# undef UINT16_MAX
|
||||
# define INT16_MIN (~ INT16_MAX)
|
||||
# define INT16_MAX 32767
|
||||
# define UINT16_MAX 65535
|
||||
|
||||
# undef INT32_MIN
|
||||
# undef INT32_MAX
|
||||
# undef UINT32_MAX
|
||||
# define INT32_MIN (~ INT32_MAX)
|
||||
# define INT32_MAX 2147483647
|
||||
# define UINT32_MAX 4294967295U
|
||||
|
||||
# if defined GL_INT64_T && ! defined INT64_MAX
|
||||
/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0
|
||||
evaluates the latter incorrectly in preprocessor expressions. */
|
||||
# define INT64_MIN (- INTMAX_C (1) << 63)
|
||||
# define INT64_MAX INTMAX_C (9223372036854775807)
|
||||
# endif
|
||||
|
||||
# if defined GL_UINT64_T && ! defined UINT64_MAX
|
||||
# define UINT64_MAX UINTMAX_C (18446744073709551615)
|
||||
# endif
|
||||
|
||||
/* 7.18.2.2. Limits of minimum-width integer types */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
|
||||
are the same as the corresponding N_t types. */
|
||||
|
||||
# undef INT_LEAST8_MIN
|
||||
# undef INT_LEAST8_MAX
|
||||
# undef UINT_LEAST8_MAX
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
|
||||
# undef INT_LEAST16_MIN
|
||||
# undef INT_LEAST16_MAX
|
||||
# undef UINT_LEAST16_MAX
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
|
||||
# undef INT_LEAST32_MIN
|
||||
# undef INT_LEAST32_MAX
|
||||
# undef UINT_LEAST32_MAX
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
|
||||
# undef INT_LEAST64_MIN
|
||||
# undef INT_LEAST64_MAX
|
||||
# ifdef GL_INT64_T
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
# endif
|
||||
|
||||
# undef UINT_LEAST64_MAX
|
||||
# ifdef GL_UINT64_T
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
# endif
|
||||
|
||||
/* 7.18.2.3. Limits of fastest minimum-width integer types */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
|
||||
are taken from the same list of types. */
|
||||
|
||||
# undef INT_FAST8_MIN
|
||||
# undef INT_FAST8_MAX
|
||||
# undef UINT_FAST8_MAX
|
||||
# define INT_FAST8_MIN SCHAR_MIN
|
||||
# define INT_FAST8_MAX SCHAR_MAX
|
||||
# define UINT_FAST8_MAX UCHAR_MAX
|
||||
|
||||
# undef INT_FAST16_MIN
|
||||
# undef INT_FAST16_MAX
|
||||
# undef UINT_FAST16_MAX
|
||||
# define INT_FAST16_MIN INT_FAST32_MIN
|
||||
# define INT_FAST16_MAX INT_FAST32_MAX
|
||||
# define UINT_FAST16_MAX UINT_FAST32_MAX
|
||||
|
||||
# undef INT_FAST32_MIN
|
||||
# undef INT_FAST32_MAX
|
||||
# undef UINT_FAST32_MAX
|
||||
# ifdef __sun
|
||||
# define INT_FAST32_MIN INT_MIN
|
||||
# define INT_FAST32_MAX INT_MAX
|
||||
# define UINT_FAST32_MAX UINT_MAX
|
||||
# else
|
||||
# define INT_FAST32_MIN LONG_MIN
|
||||
# define INT_FAST32_MAX LONG_MAX
|
||||
# define UINT_FAST32_MAX ULONG_MAX
|
||||
# endif
|
||||
|
||||
# undef INT_FAST64_MIN
|
||||
# undef INT_FAST64_MAX
|
||||
# ifdef GL_INT64_T
|
||||
# define INT_FAST64_MIN INT64_MIN
|
||||
# define INT_FAST64_MAX INT64_MAX
|
||||
# endif
|
||||
|
||||
# undef UINT_FAST64_MAX
|
||||
# ifdef GL_UINT64_T
|
||||
# define UINT_FAST64_MAX UINT64_MAX
|
||||
# endif
|
||||
|
||||
/* 7.18.2.4. Limits of integer types capable of holding object pointers */
|
||||
|
||||
# undef INTPTR_MIN
|
||||
# undef INTPTR_MAX
|
||||
# undef UINTPTR_MAX
|
||||
# ifdef _WIN64
|
||||
# define INTPTR_MIN LLONG_MIN
|
||||
# define INTPTR_MAX LLONG_MAX
|
||||
# define UINTPTR_MAX ULLONG_MAX
|
||||
# else
|
||||
# define INTPTR_MIN LONG_MIN
|
||||
# define INTPTR_MAX LONG_MAX
|
||||
# define UINTPTR_MAX ULONG_MAX
|
||||
# endif
|
||||
|
||||
/* 7.18.2.5. Limits of greatest-width integer types */
|
||||
|
||||
# ifndef INTMAX_MAX
|
||||
# undef INTMAX_MIN
|
||||
# ifdef INT64_MAX
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# else
|
||||
# define INTMAX_MIN INT32_MIN
|
||||
# define INTMAX_MAX INT32_MAX
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef UINTMAX_MAX
|
||||
# ifdef UINT64_MAX
|
||||
# define UINTMAX_MAX UINT64_MAX
|
||||
# else
|
||||
# define UINTMAX_MAX UINT32_MAX
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* 7.18.3. Limits of other integer types */
|
||||
|
||||
/* ptrdiff_t limits */
|
||||
# undef PTRDIFF_MIN
|
||||
# undef PTRDIFF_MAX
|
||||
# if 0
|
||||
# ifdef _LP64
|
||||
# define PTRDIFF_MIN _STDINT_SIGNED_MIN (64, 0l)
|
||||
# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l)
|
||||
# else
|
||||
# define PTRDIFF_MIN _STDINT_SIGNED_MIN (32, 0)
|
||||
# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0)
|
||||
# endif
|
||||
# else
|
||||
# define PTRDIFF_MIN \
|
||||
_STDINT_SIGNED_MIN (64, 0l)
|
||||
# define PTRDIFF_MAX \
|
||||
_STDINT_MAX (1, 64, 0l)
|
||||
# endif
|
||||
|
||||
/* sig_atomic_t limits */
|
||||
# undef SIG_ATOMIC_MIN
|
||||
# undef SIG_ATOMIC_MAX
|
||||
# if 1
|
||||
# define SIG_ATOMIC_MIN \
|
||||
_STDINT_SIGNED_MIN (32, 0)
|
||||
# else
|
||||
# define SIG_ATOMIC_MIN \
|
||||
_STDINT_UNSIGNED_MIN (32, 0)
|
||||
# endif
|
||||
# define SIG_ATOMIC_MAX \
|
||||
_STDINT_MAX (1, 32, \
|
||||
0)
|
||||
|
||||
|
||||
/* size_t limit */
|
||||
# undef SIZE_MAX
|
||||
# if 0
|
||||
# ifdef _LP64
|
||||
# define SIZE_MAX _STDINT_MAX (0, 64, 0ul)
|
||||
# else
|
||||
# define SIZE_MAX _STDINT_MAX (0, 32, 0ul)
|
||||
# endif
|
||||
# else
|
||||
# define SIZE_MAX _STDINT_MAX (0, 64, 0ul)
|
||||
# endif
|
||||
|
||||
/* wchar_t limits */
|
||||
/* Get WCHAR_MIN, WCHAR_MAX.
|
||||
This include is not on the top, above, because on OSF/1 4.0 we have a
|
||||
sequence of nested includes
|
||||
<wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter includes
|
||||
<stdint.h> and assumes its types are already defined. */
|
||||
# if 1 && ! (defined WCHAR_MIN && defined WCHAR_MAX)
|
||||
/* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
|
||||
included before <wchar.h>. */
|
||||
# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
|
||||
# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
|
||||
# endif
|
||||
# undef WCHAR_MIN
|
||||
# undef WCHAR_MAX
|
||||
# if 1
|
||||
# define WCHAR_MIN \
|
||||
_STDINT_SIGNED_MIN (32, 0)
|
||||
# else
|
||||
# define WCHAR_MIN \
|
||||
_STDINT_UNSIGNED_MIN (32, 0)
|
||||
# endif
|
||||
# define WCHAR_MAX \
|
||||
_STDINT_MAX (1, 32, 0)
|
||||
|
||||
/* wint_t limits */
|
||||
/* If gnulib's <wchar.h> or <wctype.h> overrides wint_t, u is not
|
||||
accurate, therefore use the definitions from above. */
|
||||
# if !0
|
||||
# undef WINT_MIN
|
||||
# undef WINT_MAX
|
||||
# if 0
|
||||
# define WINT_MIN \
|
||||
_STDINT_SIGNED_MIN (32, 0u)
|
||||
# else
|
||||
# define WINT_MIN \
|
||||
_STDINT_UNSIGNED_MIN (32, 0u)
|
||||
# endif
|
||||
# define WINT_MAX \
|
||||
_STDINT_MAX (0, 32, 0u)
|
||||
# endif
|
||||
|
||||
/* 7.18.4. Macros for integer constants */
|
||||
|
||||
/* 7.18.4.1. Macros for minimum-width integer constants */
|
||||
/* According to ISO C 99 Technical Corrigendum 1 */
|
||||
|
||||
/* Here we assume a standard architecture where the hardware integer
|
||||
types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */
|
||||
|
||||
# undef INT8_C
|
||||
# undef UINT8_C
|
||||
# define INT8_C(x) x
|
||||
# define UINT8_C(x) x
|
||||
|
||||
# undef INT16_C
|
||||
# undef UINT16_C
|
||||
# define INT16_C(x) x
|
||||
# define UINT16_C(x) x
|
||||
|
||||
# undef INT32_C
|
||||
# undef UINT32_C
|
||||
# define INT32_C(x) x
|
||||
# define UINT32_C(x) x ## U
|
||||
|
||||
# undef INT64_C
|
||||
# undef UINT64_C
|
||||
# if LONG_MAX >> 31 >> 31 == 1
|
||||
# define INT64_C(x) x##L
|
||||
# elif defined _MSC_VER
|
||||
# define INT64_C(x) x##i64
|
||||
# else
|
||||
# define INT64_C(x) x##LL
|
||||
# endif
|
||||
# if ULONG_MAX >> 31 >> 31 >> 1 == 1
|
||||
# define UINT64_C(x) x##UL
|
||||
# elif defined _MSC_VER
|
||||
# define UINT64_C(x) x##ui64
|
||||
# else
|
||||
# define UINT64_C(x) x##ULL
|
||||
# endif
|
||||
|
||||
/* 7.18.4.2. Macros for greatest-width integer constants */
|
||||
|
||||
# ifndef INTMAX_C
|
||||
# if LONG_MAX >> 30 == 1
|
||||
# define INTMAX_C(x) x##LL
|
||||
# elif defined GL_INT64_T
|
||||
# define INTMAX_C(x) INT64_C(x)
|
||||
# else
|
||||
# define INTMAX_C(x) x##L
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef UINTMAX_C
|
||||
# if ULONG_MAX >> 31 == 1
|
||||
# define UINTMAX_C(x) x##ULL
|
||||
# elif defined GL_UINT64_T
|
||||
# define UINTMAX_C(x) UINT64_C(x)
|
||||
# else
|
||||
# define UINTMAX_C(x) x##UL
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* !0 */
|
||||
|
||||
/* Macros specified by ISO/IEC TS 18661-1:2014. */
|
||||
|
||||
#if (!defined UINTMAX_WIDTH \
|
||||
&& (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__))
|
||||
# ifdef INT8_MAX
|
||||
# define INT8_WIDTH _GL_INTEGER_WIDTH (INT8_MIN, INT8_MAX)
|
||||
# endif
|
||||
# ifdef UINT8_MAX
|
||||
# define UINT8_WIDTH _GL_INTEGER_WIDTH (0, UINT8_MAX)
|
||||
# endif
|
||||
# ifdef INT16_MAX
|
||||
# define INT16_WIDTH _GL_INTEGER_WIDTH (INT16_MIN, INT16_MAX)
|
||||
# endif
|
||||
# ifdef UINT16_MAX
|
||||
# define UINT16_WIDTH _GL_INTEGER_WIDTH (0, UINT16_MAX)
|
||||
# endif
|
||||
# ifdef INT32_MAX
|
||||
# define INT32_WIDTH _GL_INTEGER_WIDTH (INT32_MIN, INT32_MAX)
|
||||
# endif
|
||||
# ifdef UINT32_MAX
|
||||
# define UINT32_WIDTH _GL_INTEGER_WIDTH (0, UINT32_MAX)
|
||||
# endif
|
||||
# ifdef INT64_MAX
|
||||
# define INT64_WIDTH _GL_INTEGER_WIDTH (INT64_MIN, INT64_MAX)
|
||||
# endif
|
||||
# ifdef UINT64_MAX
|
||||
# define UINT64_WIDTH _GL_INTEGER_WIDTH (0, UINT64_MAX)
|
||||
# endif
|
||||
# define INT_LEAST8_WIDTH _GL_INTEGER_WIDTH (INT_LEAST8_MIN, INT_LEAST8_MAX)
|
||||
# define UINT_LEAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST8_MAX)
|
||||
# define INT_LEAST16_WIDTH _GL_INTEGER_WIDTH (INT_LEAST16_MIN, INT_LEAST16_MAX)
|
||||
# define UINT_LEAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST16_MAX)
|
||||
# define INT_LEAST32_WIDTH _GL_INTEGER_WIDTH (INT_LEAST32_MIN, INT_LEAST32_MAX)
|
||||
# define UINT_LEAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST32_MAX)
|
||||
# define INT_LEAST64_WIDTH _GL_INTEGER_WIDTH (INT_LEAST64_MIN, INT_LEAST64_MAX)
|
||||
# define UINT_LEAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST64_MAX)
|
||||
# define INT_FAST8_WIDTH _GL_INTEGER_WIDTH (INT_FAST8_MIN, INT_FAST8_MAX)
|
||||
# define UINT_FAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST8_MAX)
|
||||
# define INT_FAST16_WIDTH _GL_INTEGER_WIDTH (INT_FAST16_MIN, INT_FAST16_MAX)
|
||||
# define UINT_FAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST16_MAX)
|
||||
# define INT_FAST32_WIDTH _GL_INTEGER_WIDTH (INT_FAST32_MIN, INT_FAST32_MAX)
|
||||
# define UINT_FAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST32_MAX)
|
||||
# define INT_FAST64_WIDTH _GL_INTEGER_WIDTH (INT_FAST64_MIN, INT_FAST64_MAX)
|
||||
# define UINT_FAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST64_MAX)
|
||||
# define INTPTR_WIDTH _GL_INTEGER_WIDTH (INTPTR_MIN, INTPTR_MAX)
|
||||
# define UINTPTR_WIDTH _GL_INTEGER_WIDTH (0, UINTPTR_MAX)
|
||||
# define INTMAX_WIDTH _GL_INTEGER_WIDTH (INTMAX_MIN, INTMAX_MAX)
|
||||
# define UINTMAX_WIDTH _GL_INTEGER_WIDTH (0, UINTMAX_MAX)
|
||||
# define PTRDIFF_WIDTH _GL_INTEGER_WIDTH (PTRDIFF_MIN, PTRDIFF_MAX)
|
||||
# define SIZE_WIDTH _GL_INTEGER_WIDTH (0, SIZE_MAX)
|
||||
# define WCHAR_WIDTH _GL_INTEGER_WIDTH (WCHAR_MIN, WCHAR_MAX)
|
||||
# ifdef WINT_MAX
|
||||
# define WINT_WIDTH _GL_INTEGER_WIDTH (WINT_MIN, WINT_MAX)
|
||||
# endif
|
||||
# ifdef SIG_ATOMIC_MAX
|
||||
# define SIG_ATOMIC_WIDTH _GL_INTEGER_WIDTH (SIG_ATOMIC_MIN, SIG_ATOMIC_MAX)
|
||||
# endif
|
||||
#endif /* !WINT_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */
|
||||
|
||||
#endif /* _GL_STDINT_H */
|
||||
#endif /* !(defined __ANDROID__ && ...) */
|
||||
#endif /* !defined _GL_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */
|
1906
third_party/make/stdio.h
vendored
1906
third_party/make/stdio.h
vendored
File diff suppressed because it is too large
Load diff
1615
third_party/make/stdlib.h
vendored
1615
third_party/make/stdlib.h
vendored
File diff suppressed because it is too large
Load diff
17
third_party/make/strcache.c
vendored
17
third_party/make/strcache.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Constant string caching for GNU Make.
|
||||
Copyright (C) 2006-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2006-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
|
||||
|
@ -12,10 +12,14 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/hash.h"
|
||||
#include "makeint.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
/* A string cached here will never be freed, so we don't need to worry about
|
||||
reference counting. We just store the string, and then remember it in a
|
||||
|
@ -49,7 +53,7 @@ static unsigned long total_size = 0;
|
|||
|
||||
/* Add a new buffer to the cache. Add it at the front to reduce search time.
|
||||
This can also increase the overhead, since it's less likely that older
|
||||
buffers will be filled in. However, GNU make has so many smaller strings
|
||||
buffers will be filled in. However, GNU Make has so many smaller strings
|
||||
that this doesn't seem to be much of an issue in practice.
|
||||
*/
|
||||
static struct strcache *
|
||||
|
@ -252,8 +256,7 @@ strcache_add_len (const char *str, size_t len)
|
|||
void
|
||||
strcache_init (void)
|
||||
{
|
||||
// [jart] increased from 8000
|
||||
hash_init (&strings, 131072, str_hash_1, str_hash_2, str_hash_cmp);
|
||||
hash_init (&strings, 8000, str_hash_1, str_hash_2, str_hash_cmp);
|
||||
}
|
||||
|
||||
|
||||
|
|
45
third_party/make/stripslash.c
vendored
45
third_party/make/stripslash.c
vendored
|
@ -1,45 +0,0 @@
|
|||
/* stripslash.c -- remove redundant trailing slashes from a file name
|
||||
|
||||
Copyright (C) 1990, 2001, 2003-2006, 2009-2020 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "third_party/make/config.h"
|
||||
|
||||
#include "third_party/make/dirname.h"
|
||||
|
||||
/* Remove trailing slashes from FILE. Return true if a trailing slash
|
||||
was removed. This is useful when using file name completion from a
|
||||
shell that adds a "/" after directory names (such as tcsh and
|
||||
bash), because on symlinks to directories, several system calls
|
||||
have different semantics according to whether a trailing slash is
|
||||
present. */
|
||||
|
||||
bool
|
||||
strip_trailing_slashes (char *file)
|
||||
{
|
||||
char *base = last_component (file);
|
||||
char *base_lim;
|
||||
bool had_slash;
|
||||
|
||||
/* last_component returns "" for file system roots, but we need to turn
|
||||
"///" into "/". */
|
||||
if (! *base)
|
||||
base = file;
|
||||
base_lim = base + base_len (base);
|
||||
had_slash = (*base_lim != '\0');
|
||||
*base_lim = '\0';
|
||||
return had_slash;
|
||||
}
|
4
third_party/make/unistd.c
vendored
4
third_party/make/unistd.c
vendored
|
@ -1,4 +0,0 @@
|
|||
#include "third_party/make/config.h"
|
||||
#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE
|
||||
#include "third_party/make/unistd.h"
|
||||
typedef int dummy;
|
2173
third_party/make/unistd.h
vendored
2173
third_party/make/unistd.h
vendored
File diff suppressed because it is too large
Load diff
969
third_party/make/variable.c
vendored
969
third_party/make/variable.c
vendored
File diff suppressed because it is too large
Load diff
40
third_party/make/variable.h
vendored
40
third_party/make/variable.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Definitions for using variables in GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,9 +12,11 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/hash.h"
|
||||
#include "hash.h"
|
||||
|
||||
struct file;
|
||||
|
||||
/* Codes in a variable definition saying where the definition came from.
|
||||
Increasing numeric values signify less-overridable definitions. */
|
||||
|
@ -35,12 +37,21 @@ enum variable_flavor
|
|||
f_bogus, /* Bogus (error) */
|
||||
f_simple, /* Simple definition (:= or ::=) */
|
||||
f_recursive, /* Recursive definition (=) */
|
||||
f_expand, /* POSIX :::= assignment */
|
||||
f_append, /* Appending definition (+=) */
|
||||
f_conditional, /* Conditional definition (?=) */
|
||||
f_shell, /* Shell assignment (!=) */
|
||||
f_append_value /* Append unexpanded value */
|
||||
};
|
||||
|
||||
enum variable_export
|
||||
{
|
||||
v_default = 0, /* Decide in target_environment. */
|
||||
v_export, /* Export this variable. */
|
||||
v_noexport, /* Don't export this variable. */
|
||||
v_ifset /* Export it if it has a non-default value. */
|
||||
};
|
||||
|
||||
/* Structure that represents one variable definition.
|
||||
Each bucket of the hash table is a chain of these,
|
||||
chained through 'next'. */
|
||||
|
@ -73,12 +84,7 @@ struct variable
|
|||
enum variable_origin
|
||||
origin ENUM_BITFIELD (3); /* Variable origin. */
|
||||
enum variable_export
|
||||
{
|
||||
v_export, /* Export this variable. */
|
||||
v_noexport, /* Don't export this variable. */
|
||||
v_ifset, /* Export it if it has a non-default value. */
|
||||
v_default /* Decide in target_environment. */
|
||||
} export ENUM_BITFIELD (2);
|
||||
export ENUM_BITFIELD (2); /* Export control. */
|
||||
};
|
||||
|
||||
/* Structure that represents a variable set. */
|
||||
|
@ -108,6 +114,7 @@ struct pattern_var
|
|||
struct variable variable;
|
||||
};
|
||||
|
||||
extern unsigned long long env_recursion;
|
||||
extern char *variable_buffer;
|
||||
extern struct variable_set_list *current_variable_set_list;
|
||||
extern struct variable *default_goal_var;
|
||||
|
@ -126,6 +133,7 @@ char *allocated_variable_expand_for_file (const char *line, struct file *file);
|
|||
allocated_variable_expand_for_file (line, (struct file *) 0)
|
||||
char *expand_argument (const char *str, const char *end);
|
||||
char *variable_expand_string (char *line, const char *string, size_t length);
|
||||
char *initialize_variable_output (void);
|
||||
void install_variable_buffer (char **bufp, size_t *lenp);
|
||||
void restore_variable_buffer (char *buf, size_t len);
|
||||
|
||||
|
@ -174,6 +182,8 @@ void define_new_function(const floc *flocp, const char *name,
|
|||
unsigned int min, unsigned int max, unsigned int flags,
|
||||
gmk_func_ptr func);
|
||||
struct variable *lookup_variable (const char *name, size_t length);
|
||||
struct variable *lookup_variable_for_file (const char *name, size_t length,
|
||||
struct file *file);
|
||||
struct variable *lookup_variable_in_set (const char *name, size_t length,
|
||||
const struct variable_set *set);
|
||||
|
||||
|
@ -183,6 +193,7 @@ struct variable *define_variable_in_set (const char *name, size_t length,
|
|||
int recursive,
|
||||
struct variable_set *set,
|
||||
const floc *flocp);
|
||||
void warn_undefined (const char* name, size_t length);
|
||||
|
||||
/* Define a variable in the current variable set. */
|
||||
|
||||
|
@ -221,16 +232,7 @@ void undefine_variable_in_set (const char *name, size_t length,
|
|||
#define undefine_variable_global(n,l,o) \
|
||||
undefine_variable_in_set((n),(l),(o),NULL)
|
||||
|
||||
/* Warn that NAME is an undefined variable. */
|
||||
|
||||
#define warn_undefined(n,l) do{\
|
||||
if (warn_undefined_variables_flag) \
|
||||
error (reading_file, (l), \
|
||||
_("warning: undefined variable '%.*s'"), \
|
||||
(int)(l), (n)); \
|
||||
}while(0)
|
||||
|
||||
char **target_environment (struct file *file);
|
||||
char **target_environment (struct file *file, int recursive);
|
||||
|
||||
struct pattern_var *create_pattern_var (const char *target,
|
||||
const char *suffix);
|
||||
|
|
10
third_party/make/version.c
vendored
10
third_party/make/version.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Record version and build host architecture for GNU make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
/* Record version and build host architecture for GNU Make.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,18 +12,18 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because makeint.h was found in $srcdir). */
|
||||
#include "third_party/make/config.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifndef MAKE_HOST
|
||||
# define MAKE_HOST "unknown"
|
||||
#endif
|
||||
|
||||
const char *version_string = VERSION;
|
||||
const char *version_string = PACKAGE_VERSION;
|
||||
const char *make_host = MAKE_HOST;
|
||||
|
||||
/*
|
||||
|
|
81
third_party/make/vpath.c
vendored
81
third_party/make/vpath.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Implementation of pattern-matching file search paths for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-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
|
||||
|
@ -12,11 +12,11 @@ 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 <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/variable.h"
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "variable.h"
|
||||
|
||||
|
||||
/* Structure used to represent a selective VPATH searchpath. */
|
||||
|
@ -65,20 +65,11 @@ build_vpath_lists (void)
|
|||
|
||||
vpaths = new;
|
||||
|
||||
/* If there is a VPATH variable with a nonnull value, construct the
|
||||
general VPATH list from it. We use variable_expand rather than just
|
||||
calling lookup_variable so that it will be recursively expanded. */
|
||||
|
||||
{
|
||||
/* Turn off --warn-undefined-variables while we expand SHELL and IFS. */
|
||||
int save = warn_undefined_variables_flag;
|
||||
warn_undefined_variables_flag = 0;
|
||||
/* If there is a VPATH variable with a nonnull expanded value, construct the
|
||||
general VPATH list from it. */
|
||||
|
||||
p = variable_expand ("$(strip $(VPATH))");
|
||||
|
||||
warn_undefined_variables_flag = save;
|
||||
}
|
||||
|
||||
if (*p != '\0')
|
||||
{
|
||||
/* Save the list of vpaths. */
|
||||
|
@ -98,20 +89,11 @@ build_vpath_lists (void)
|
|||
vpaths = save_vpaths;
|
||||
}
|
||||
|
||||
/* If there is a GPATH variable with a nonnull value, construct the
|
||||
GPATH list from it. We use variable_expand rather than just
|
||||
calling lookup_variable so that it will be recursively expanded. */
|
||||
|
||||
{
|
||||
/* Turn off --warn-undefined-variables while we expand SHELL and IFS. */
|
||||
int save = warn_undefined_variables_flag;
|
||||
warn_undefined_variables_flag = 0;
|
||||
/* If there is a GPATH variable with a nonnull expanded value, construct the
|
||||
GPATH list from it. */
|
||||
|
||||
p = variable_expand ("$(strip $(GPATH))");
|
||||
|
||||
warn_undefined_variables_flag = save;
|
||||
}
|
||||
|
||||
if (*p != '\0')
|
||||
{
|
||||
/* Save the list of vpaths. */
|
||||
|
@ -236,8 +218,7 @@ construct_vpath_list (char *pattern, char *dirpath)
|
|||
also define HAVE_DOS_PATHS would like us to recognize
|
||||
colons after the drive letter in the likes of
|
||||
"D:/foo/bar:C:/xyzzy". */
|
||||
&& (*p != PATH_SEPARATOR_CHAR
|
||||
|| (p == v + 1 && (p[1] == '/' || p[1] == '\\')))
|
||||
&& (*p != PATH_SEPARATOR_CHAR || (p == v + 1 && ISDIRSEP (p[1])))
|
||||
#else
|
||||
&& *p != PATH_SEPARATOR_CHAR
|
||||
#endif
|
||||
|
@ -274,7 +255,7 @@ construct_vpath_list (char *pattern, char *dirpath)
|
|||
entry, to where the nil-pointer terminator goes.
|
||||
Usually this is maxelem - 1. If not, shrink down. */
|
||||
if (elem < (maxelem - 1))
|
||||
vpath = xrealloc (vpath, (elem+1) * sizeof (const char *));
|
||||
vpath = xrealloc ((void *)vpath, (elem+1) * sizeof (const char *));
|
||||
|
||||
/* Put the nil-pointer terminator on the end of the VPATH list. */
|
||||
vpath[elem] = NULL;
|
||||
|
@ -376,15 +357,19 @@ selective_vpath_search (struct vpath *path, const char *file,
|
|||
size_t vlen = strlen (vpath[i]);
|
||||
|
||||
/* Put the next VPATH entry into NAME at P and increment P past it. */
|
||||
memcpy (p, vpath[i], vlen);
|
||||
p += vlen;
|
||||
p = mempcpy (p, vpath[i], vlen);
|
||||
|
||||
/* Add the directory prefix already in *FILE. */
|
||||
if (name_dplen > 0)
|
||||
{
|
||||
#ifndef VMS
|
||||
*p++ = '/';
|
||||
memcpy (p, file, name_dplen);
|
||||
p += name_dplen;
|
||||
#else
|
||||
/* VMS: if this is not in VMS format, treat as Unix format */
|
||||
if ((*p != ':') && (*p != ']') && (*p != '>'))
|
||||
*p++ = '/';
|
||||
#endif
|
||||
p = mempcpy (p, file, name_dplen);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DOS_PATHS
|
||||
|
@ -393,12 +378,23 @@ selective_vpath_search (struct vpath *path, const char *file,
|
|||
p[-1] = '/';
|
||||
#endif
|
||||
/* Now add the name-within-directory at the end of NAME. */
|
||||
#ifndef VMS
|
||||
if (p != name && p[-1] != '/')
|
||||
{
|
||||
*p = '/';
|
||||
memcpy (p + 1, filename, flen + 1);
|
||||
}
|
||||
else
|
||||
#else
|
||||
/* VMS use a slash if no directory terminator present */
|
||||
if (p != name && p[-1] != '/' && p[-1] != ':' &&
|
||||
p[-1] != '>' && p[-1] != ']')
|
||||
{
|
||||
*p = '/';
|
||||
memcpy (p + 1, filename, flen + 1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
memcpy (p, filename, flen + 1);
|
||||
|
||||
/* Check if the file is mentioned in a makefile. If *FILE is not
|
||||
|
@ -440,6 +436,14 @@ selective_vpath_search (struct vpath *path, const char *file,
|
|||
{
|
||||
/* That file wasn't mentioned in the makefile.
|
||||
See if it actually exists. */
|
||||
|
||||
#ifdef VMS
|
||||
/* For VMS syntax just use the original vpath */
|
||||
if (*p != '/')
|
||||
exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Clobber a null into the name at the last slash.
|
||||
Now NAME is the name of the directory to look in. */
|
||||
*p = '\0';
|
||||
|
@ -448,6 +452,7 @@ selective_vpath_search (struct vpath *path, const char *file,
|
|||
Does the file we seek exist in it? */
|
||||
exists_in_cache = exists = dir_file_exists_p (name, filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (exists)
|
||||
{
|
||||
|
@ -459,8 +464,14 @@ selective_vpath_search (struct vpath *path, const char *file,
|
|||
|
||||
struct stat st;
|
||||
|
||||
#ifndef VMS
|
||||
/* Put the slash back in NAME. */
|
||||
*p = '/';
|
||||
#else
|
||||
/* If the slash was removed, put it back */
|
||||
if (*p == 0)
|
||||
*p = '/';
|
||||
#endif
|
||||
|
||||
if (exists_in_cache) /* Makefile-mentioned file need not exist. */
|
||||
{
|
||||
|
@ -554,6 +565,8 @@ vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Print the data base of VPATH search paths. */
|
||||
|
||||
|
|
41
third_party/make/xalloc-die.c
vendored
41
third_party/make/xalloc-die.c
vendored
|
@ -1,41 +0,0 @@
|
|||
/* Report a memory allocation failure and exit.
|
||||
|
||||
Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2020 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "libc/runtime/runtime.h"
|
||||
#include "third_party/make/config.h"
|
||||
|
||||
#include "third_party/make/xalloc.h"
|
||||
|
||||
|
||||
#include "third_party/make/error.h"
|
||||
#include "third_party/make/exitfail.h"
|
||||
|
||||
#include "third_party/make/gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (exit_failure, 0, "%s", _("memory exhausted"));
|
||||
|
||||
/* _Noreturn cannot be given to error, since it may return if
|
||||
its first argument is 0. To help compilers understand the
|
||||
xalloc_die does not return, call abort. Also, the abort is a
|
||||
safety feature if exit_failure is 0 (which shouldn't happen). */
|
||||
abort ();
|
||||
}
|
58
third_party/make/xalloc-oversized.h
vendored
58
third_party/make/xalloc-oversized.h
vendored
|
@ -1,58 +0,0 @@
|
|||
/* xalloc-oversized.h -- memory allocation size checking
|
||||
|
||||
Copyright (C) 1990-2000, 2003-2004, 2006-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
#ifndef XALLOC_OVERSIZED_H_
|
||||
#define XALLOC_OVERSIZED_H_
|
||||
|
||||
|
||||
/* True if N * S would overflow in a size_t calculation,
|
||||
or would generate a value larger than PTRDIFF_MAX.
|
||||
This expands to a constant expression if N and S are both constants.
|
||||
By gnulib convention, SIZE_MAX represents overflow in size
|
||||
calculations, so the conservative size_t-based dividend to use here
|
||||
is SIZE_MAX - 1. */
|
||||
#define __xalloc_oversized(n, s) \
|
||||
((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n))
|
||||
|
||||
#if PTRDIFF_MAX < SIZE_MAX
|
||||
typedef ptrdiff_t __xalloc_count_type;
|
||||
#else
|
||||
typedef size_t __xalloc_count_type;
|
||||
#endif
|
||||
|
||||
/* Return 1 if an array of N objects, each of size S, cannot exist
|
||||
reliably due to size or ptrdiff_t arithmetic overflow. S must be
|
||||
positive and N must be nonnegative. This is a macro, not a
|
||||
function, so that it works correctly even when SIZE_MAX < N. */
|
||||
|
||||
#if 7 <= __GNUC__
|
||||
# define xalloc_oversized(n, s) \
|
||||
__builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1)
|
||||
#elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__
|
||||
# define xalloc_oversized(n, s) \
|
||||
(__builtin_constant_p (n) && __builtin_constant_p (s) \
|
||||
? __xalloc_oversized (n, s) \
|
||||
: ({ __xalloc_count_type __xalloc_count; \
|
||||
__builtin_mul_overflow (n, s, &__xalloc_count); }))
|
||||
|
||||
/* Other compilers use integer division; this may be slower but is
|
||||
more portable. */
|
||||
#else
|
||||
# define xalloc_oversized(n, s) __xalloc_oversized (n, s)
|
||||
#endif
|
||||
|
||||
#endif /* !XALLOC_OVERSIZED_H_ */
|
261
third_party/make/xalloc.h
vendored
261
third_party/make/xalloc.h
vendored
|
@ -1,261 +0,0 @@
|
|||
/* xalloc.h -- malloc with out-of-memory checking
|
||||
|
||||
Copyright (C) 1990-2000, 2003-2004, 2006-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
#ifndef XALLOC_H_
|
||||
#define XALLOC_H_
|
||||
|
||||
#include "libc/limits.h"
|
||||
|
||||
#include "third_party/make/xalloc-oversized.h"
|
||||
|
||||
#ifndef _GL_INLINE_HEADER_BEGIN
|
||||
#error "Please include config.h first."
|
||||
#endif
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef XALLOC_INLINE
|
||||
# define XALLOC_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if ! defined __clang__ && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
# define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
|
||||
#else
|
||||
# define _GL_ATTRIBUTE_ALLOC_SIZE(args)
|
||||
#endif
|
||||
|
||||
/* This function is always triggered when memory is exhausted.
|
||||
It must be defined by the application, either explicitly
|
||||
or by using gnulib's xalloc-die module. This is the
|
||||
function to call when one wants the program to die because of a
|
||||
memory allocation failure. */
|
||||
extern _Noreturn void xalloc_die (void);
|
||||
|
||||
void *xmalloc (size_t s)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
|
||||
void *xzalloc (size_t s)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
|
||||
void *xcalloc (size_t n, size_t s)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
|
||||
void *xrealloc (void *p, size_t s)
|
||||
_GL_ATTRIBUTE_ALLOC_SIZE ((2));
|
||||
void *x2realloc (void *p, size_t *pn);
|
||||
void *xmemdup (void const *p, size_t s)
|
||||
_GL_ATTRIBUTE_ALLOC_SIZE ((2));
|
||||
char *xstrdup (char const *str)
|
||||
_GL_ATTRIBUTE_MALLOC;
|
||||
|
||||
/* In the following macros, T must be an elementary or structure/union or
|
||||
typedef'ed type, or a pointer to such a type. To apply one of the
|
||||
following macros to a function pointer or array type, you need to typedef
|
||||
it first and use the typedef name. */
|
||||
|
||||
/* Allocate an object of type T dynamically, with error checking. */
|
||||
/* extern t *XMALLOC (typename t); */
|
||||
#define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
|
||||
|
||||
/* Allocate memory for N elements of type T, with error checking. */
|
||||
/* extern t *XNMALLOC (size_t n, typename t); */
|
||||
#define XNMALLOC(n, t) \
|
||||
((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
|
||||
|
||||
/* Allocate an object of type T dynamically, with error checking,
|
||||
and zero it. */
|
||||
/* extern t *XZALLOC (typename t); */
|
||||
#define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
|
||||
|
||||
/* Allocate memory for N elements of type T, with error checking,
|
||||
and zero it. */
|
||||
/* extern t *XCALLOC (size_t n, typename t); */
|
||||
#define XCALLOC(n, t) \
|
||||
((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
|
||||
|
||||
|
||||
/* Allocate an array of N objects, each with S bytes of memory,
|
||||
dynamically, with error checking. S must be nonzero. */
|
||||
|
||||
XALLOC_INLINE void *xnmalloc (size_t n, size_t s)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
|
||||
XALLOC_INLINE void *
|
||||
xnmalloc (size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
return xmalloc (n * s);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to an array of N
|
||||
objects each of S bytes, with error checking. S must be nonzero. */
|
||||
|
||||
XALLOC_INLINE void *xnrealloc (void *p, size_t n, size_t s)
|
||||
_GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
|
||||
XALLOC_INLINE void *
|
||||
xnrealloc (void *p, size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN such objects;
|
||||
otherwise, reallocate P so that it contains more than *PN objects
|
||||
each of S bytes. S must be nonzero. Set *PN to the new number of
|
||||
objects, and return the pointer to the new block. *PN is never set
|
||||
to zero, and the returned pointer is never null.
|
||||
|
||||
Repeated reallocations are guaranteed to make progress, either by
|
||||
allocating an initial block with a nonzero size, or by allocating a
|
||||
larger block.
|
||||
|
||||
In the following implementation, nonzero sizes are increased by a
|
||||
factor of approximately 1.5 so that repeated reallocations have
|
||||
O(N) overall cost rather than O(N**2) cost, but the
|
||||
specification for this function does not guarantee that rate.
|
||||
|
||||
Here is an example of use:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
p = x2nrealloc (p, &allocated, sizeof *p);
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
This causes x2nrealloc to allocate a block of some nonzero size the
|
||||
first time it is called.
|
||||
|
||||
To have finer-grained control over the initial size, set *PN to a
|
||||
nonzero value before calling this function with P == NULL. For
|
||||
example:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
size_t allocated1 = 1000;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
{
|
||||
p = x2nrealloc (p, &allocated1, sizeof *p);
|
||||
allocated = allocated1;
|
||||
}
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
XALLOC_INLINE void *
|
||||
x2nrealloc (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
size_t n = *pn;
|
||||
|
||||
if (! p)
|
||||
{
|
||||
if (! n)
|
||||
{
|
||||
/* The approximate size to use for initial small allocation
|
||||
requests, when the invoking code specifies an old size of
|
||||
zero. This is the largest "small" request for the GNU C
|
||||
library malloc. */
|
||||
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
|
||||
|
||||
n = DEFAULT_MXFAST / s;
|
||||
n += !n;
|
||||
}
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set N = floor (1.5 * N) + 1 so that progress is made even if N == 0.
|
||||
Check for overflow, so that N * S stays in both ptrdiff_t and
|
||||
size_t range. The check may be slightly conservative, but an
|
||||
exact check isn't worth the trouble. */
|
||||
if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s
|
||||
<= n)
|
||||
xalloc_die ();
|
||||
n += n / 2 + 1;
|
||||
}
|
||||
|
||||
*pn = n;
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
|
||||
except it returns char *. */
|
||||
|
||||
XALLOC_INLINE char *xcharalloc (size_t n)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
|
||||
XALLOC_INLINE char *
|
||||
xcharalloc (size_t n)
|
||||
{
|
||||
return XNMALLOC (n, char);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
/* C++ does not allow conversions from void * to other pointer types
|
||||
without a cast. Use templates to work around the problem when
|
||||
possible. */
|
||||
|
||||
template <typename T> inline T *
|
||||
xrealloc (T *p, size_t s)
|
||||
{
|
||||
return (T *) xrealloc ((void *) p, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
xnrealloc (T *p, size_t n, size_t s)
|
||||
{
|
||||
return (T *) xnrealloc ((void *) p, n, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
x2realloc (T *p, size_t *pn)
|
||||
{
|
||||
return (T *) x2realloc ((void *) p, pn);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
x2nrealloc (T *p, size_t *pn, size_t s)
|
||||
{
|
||||
return (T *) x2nrealloc ((void *) p, pn, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
xmemdup (T const *p, size_t s)
|
||||
{
|
||||
return (T *) xmemdup ((void const *) p, s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
_GL_INLINE_HEADER_END
|
||||
|
||||
#endif /* !XALLOC_H_ */
|
41
third_party/make/xconcat-filename.c
vendored
41
third_party/make/xconcat-filename.c
vendored
|
@ -1,41 +0,0 @@
|
|||
/* Construct a full filename from a directory and a relative filename.
|
||||
Copyright (C) 2001-2004, 2006-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3 of the License, or any
|
||||
later version.
|
||||
|
||||
This program 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/>. */
|
||||
|
||||
/* Written by Bruno Haible <haible@clisp.cons.org>. */
|
||||
|
||||
#include "third_party/make/config.h"
|
||||
|
||||
/* Specification. */
|
||||
#include "third_party/make/concat-filename.h"
|
||||
|
||||
#include "third_party/make/xalloc.h"
|
||||
|
||||
/* Concatenate a directory filename, a relative filename and an optional
|
||||
suffix. The directory may end with the directory separator. The second
|
||||
argument may not start with the directory separator (it is relative).
|
||||
Return a freshly allocated filename. */
|
||||
char *
|
||||
xconcatenated_filename (const char *directory, const char *filename,
|
||||
const char *suffix)
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = concatenated_filename (directory, filename, suffix);
|
||||
if (result == NULL)
|
||||
xalloc_die ();
|
||||
|
||||
return result;
|
||||
}
|
122
third_party/make/xmalloc.c
vendored
122
third_party/make/xmalloc.c
vendored
|
@ -1,122 +0,0 @@
|
|||
/* xmalloc.c -- malloc with out of memory checking
|
||||
|
||||
Copyright (C) 1990-2000, 2002-2006, 2008-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/make/config.h"
|
||||
|
||||
#define XALLOC_INLINE _GL_EXTERN_INLINE
|
||||
|
||||
#include "third_party/make/xalloc.h"
|
||||
|
||||
|
||||
/* 1 if calloc is known to be compatible with GNU calloc. This
|
||||
matters if we are not also using the calloc module, which defines
|
||||
HAVE_CALLOC_GNU and supports the GNU API even on non-GNU platforms. */
|
||||
#if defined HAVE_CALLOC_GNU || (defined __GLIBC__ && !defined __UCLIBC__)
|
||||
enum { HAVE_GNU_CALLOC = 1 };
|
||||
#else
|
||||
enum { HAVE_GNU_CALLOC = 0 };
|
||||
#endif
|
||||
|
||||
/* Allocate N bytes of memory dynamically, with error checking. */
|
||||
|
||||
void *
|
||||
xmalloc (size_t n)
|
||||
{
|
||||
void *p = malloc (n);
|
||||
if (!p && n != 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to N bytes,
|
||||
with error checking. */
|
||||
|
||||
void *
|
||||
xrealloc (void *p, size_t n)
|
||||
{
|
||||
if (!n && p)
|
||||
{
|
||||
/* The GNU and C99 realloc behaviors disagree here. Act like
|
||||
GNU, even if the underlying realloc is C99. */
|
||||
free (p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = realloc (p, n);
|
||||
if (!p && n)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN bytes; otherwise,
|
||||
reallocate P so that it contains more than *PN bytes. *PN must be
|
||||
nonzero unless P is null. Set *PN to the new block's size, and
|
||||
return the pointer to the new block. *PN is never set to zero, and
|
||||
the returned pointer is never null. */
|
||||
|
||||
void *
|
||||
x2realloc (void *p, size_t *pn)
|
||||
{
|
||||
return x2nrealloc (p, pn, 1);
|
||||
}
|
||||
|
||||
/* Allocate N bytes of zeroed memory dynamically, with error checking.
|
||||
There's no need for xnzalloc (N, S), since it would be equivalent
|
||||
to xcalloc (N, S). */
|
||||
|
||||
void *
|
||||
xzalloc (size_t n)
|
||||
{
|
||||
return xcalloc (n, 1);
|
||||
}
|
||||
|
||||
/* Allocate zeroed memory for N elements of S bytes, with error
|
||||
checking. S must be nonzero. */
|
||||
|
||||
void *
|
||||
xcalloc (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
/* Test for overflow, since objects with size greater than
|
||||
PTRDIFF_MAX cause pointer subtraction to go awry. Omit size-zero
|
||||
tests if HAVE_GNU_CALLOC, since GNU calloc never returns NULL if
|
||||
successful. */
|
||||
if (xalloc_oversized (n, s)
|
||||
|| (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Clone an object P of size S, with error checking. There's no need
|
||||
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
|
||||
need for an arithmetic overflow check. */
|
||||
|
||||
void *
|
||||
xmemdup (void const *p, size_t s)
|
||||
{
|
||||
return memcpy (xmalloc (s), p, s);
|
||||
}
|
||||
|
||||
/* Clone STRING. */
|
||||
|
||||
char *
|
||||
xstrdup (char const *string)
|
||||
{
|
||||
return xmemdup (string, strlen (string) + 1);
|
||||
}
|
Loading…
Reference in a new issue