Inital Commit
This commit is contained in:
commit
e4fae03d28
21
AUTHORS
Normal file
21
AUTHORS
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- mode: rec -*-
|
||||||
|
|
||||||
|
# This file contains the names of the people that contributed with
|
||||||
|
# code and/or documentation to GNU recutils.
|
||||||
|
|
||||||
|
Name: Jose E. Marchesi
|
||||||
|
Email: jemarch@gnu.org
|
||||||
|
|
||||||
|
Name: Ralf Wildenhues
|
||||||
|
Email: Ralf.Wildenhues@gmx.de
|
||||||
|
|
||||||
|
Name: Daiki Ueno
|
||||||
|
Email: ueno@unixuser.org
|
||||||
|
|
||||||
|
Name: John Darrington
|
||||||
|
Email: john@darrington.wattle.id.au
|
||||||
|
|
||||||
|
Name: Michał Masłowski
|
||||||
|
Email: mtjm@mtjm.eu
|
||||||
|
|
||||||
|
# End of AUTHORS
|
||||||
674
COPYING
Normal file
674
COPYING
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
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>.
|
||||||
127
GNUmakefile
Normal file
127
GNUmakefile
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# Having a separate GNUmakefile lets me 'include' the dynamically
|
||||||
|
# generated rules created via cfg.mk (package-local configuration)
|
||||||
|
# as well as maint.mk (generic maintainer rules).
|
||||||
|
# This makefile is used only if you run GNU Make.
|
||||||
|
# It is necessary if you want to build targets usually of interest
|
||||||
|
# only to the maintainer.
|
||||||
|
|
||||||
|
# Copyright (C) 2001, 2003, 2006-2022 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/>.
|
||||||
|
|
||||||
|
# If the user runs GNU make but has not yet run ./configure,
|
||||||
|
# give them a diagnostic.
|
||||||
|
_gl-Makefile := $(wildcard [M]akefile)
|
||||||
|
ifneq ($(_gl-Makefile),)
|
||||||
|
|
||||||
|
# Make tar archive easier to reproduce.
|
||||||
|
export TAR_OPTIONS = --owner=0 --group=0 --numeric-owner
|
||||||
|
|
||||||
|
# Allow the user to add to this in the Makefile.
|
||||||
|
ALL_RECURSIVE_TARGETS =
|
||||||
|
|
||||||
|
include Makefile
|
||||||
|
|
||||||
|
# Some projects override e.g., _autoreconf here.
|
||||||
|
-include $(srcdir)/cfg.mk
|
||||||
|
|
||||||
|
# Allow cfg.mk to override these.
|
||||||
|
_build-aux ?= build-aux
|
||||||
|
_autoreconf ?= autoreconf -v
|
||||||
|
|
||||||
|
include $(srcdir)/maint.mk
|
||||||
|
|
||||||
|
# Ensure that $(VERSION) is up to date for dist-related targets, but not
|
||||||
|
# for others: rerunning autoreconf and recompiling everything isn't cheap.
|
||||||
|
_have-git-version-gen := \
|
||||||
|
$(shell test -f $(srcdir)/$(_build-aux)/git-version-gen && echo yes)
|
||||||
|
ifeq ($(_have-git-version-gen)0,yes$(MAKELEVEL))
|
||||||
|
_is-dist-target ?= $(filter-out %clean, \
|
||||||
|
$(filter maintainer-% dist% alpha beta stable,$(MAKECMDGOALS)))
|
||||||
|
_is-install-target ?= $(filter-out %check, $(filter install%,$(MAKECMDGOALS)))
|
||||||
|
ifneq (,$(_is-dist-target)$(_is-install-target))
|
||||||
|
_curr-ver := $(shell cd $(srcdir) \
|
||||||
|
&& $(_build-aux)/git-version-gen \
|
||||||
|
.tarball-version \
|
||||||
|
$(git-version-gen-tag-sed-script))
|
||||||
|
ifneq ($(_curr-ver),$(VERSION))
|
||||||
|
ifeq ($(_curr-ver),UNKNOWN)
|
||||||
|
$(info WARNING: unable to verify if $(VERSION) is the correct version)
|
||||||
|
else
|
||||||
|
ifneq (,$(_is-install-target))
|
||||||
|
# GNU Coding Standards state that 'make install' should not cause
|
||||||
|
# recompilation after 'make all'. But as long as changing the version
|
||||||
|
# string alters config.h, the cost of having 'make all' always have an
|
||||||
|
# up-to-date version is prohibitive. So, as a compromise, we merely
|
||||||
|
# warn when installing a version string that is out of date; the user
|
||||||
|
# should run 'autoreconf' (or something like 'make distcheck') to
|
||||||
|
# fix the version, 'make all' to propagate it, then 'make install'.
|
||||||
|
$(info WARNING: version string $(VERSION) is out of date;)
|
||||||
|
$(info run '$(MAKE) _version' to fix it)
|
||||||
|
else
|
||||||
|
$(info INFO: running autoreconf for new version string: $(_curr-ver))
|
||||||
|
GNUmakefile: _version
|
||||||
|
touch GNUmakefile
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: _version
|
||||||
|
_version:
|
||||||
|
cd $(srcdir) && rm -rf autom4te.cache .version && $(_autoreconf)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) Makefile
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := abort-due-to-no-makefile
|
||||||
|
srcdir = .
|
||||||
|
|
||||||
|
# The package can override .DEFAULT_GOAL to run actions like autoreconf.
|
||||||
|
-include ./cfg.mk
|
||||||
|
|
||||||
|
# Allow cfg.mk to override these.
|
||||||
|
_build-aux ?= build-aux
|
||||||
|
_autoreconf ?= autoreconf -v
|
||||||
|
|
||||||
|
include ./maint.mk
|
||||||
|
|
||||||
|
ifeq ($(.DEFAULT_GOAL),abort-due-to-no-makefile)
|
||||||
|
$(MAKECMDGOALS): abort-due-to-no-makefile
|
||||||
|
endif
|
||||||
|
|
||||||
|
abort-due-to-no-makefile:
|
||||||
|
@echo There seems to be no Makefile in this directory. 1>&2
|
||||||
|
@echo "You must run ./configure before running '$(MAKE)'." 1>&2
|
||||||
|
@exit 1
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Tell version 3.79 and up of GNU make to not build goals in this
|
||||||
|
# directory in parallel, in case someone tries to build multiple
|
||||||
|
# targets, and one of them can cause a recursive target to be invoked.
|
||||||
|
|
||||||
|
# Only set this if Automake doesn't provide it.
|
||||||
|
AM_RECURSIVE_TARGETS ?= $(RECURSIVE_TARGETS:-recursive=) \
|
||||||
|
$(RECURSIVE_CLEAN_TARGETS:-recursive=) \
|
||||||
|
dist distcheck tags ctags
|
||||||
|
|
||||||
|
ALL_RECURSIVE_TARGETS += $(AM_RECURSIVE_TARGETS)
|
||||||
|
|
||||||
|
ifneq ($(word 2, $(MAKECMDGOALS)), )
|
||||||
|
ifneq ($(filter $(ALL_RECURSIVE_TARGETS), $(MAKECMDGOALS)), )
|
||||||
|
.NOTPARALLEL:
|
||||||
|
endif
|
||||||
|
endif
|
||||||
368
INSTALL
Normal file
368
INSTALL
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
|
||||||
|
Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. This file is offered as-is,
|
||||||
|
without warranty of any kind.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
Briefly, the shell command './configure && make && make install'
|
||||||
|
should configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the 'README' file for
|
||||||
|
instructions specific to this package. Some packages provide this
|
||||||
|
'INSTALL' file but do not implement all of the features documented
|
||||||
|
below. The lack of an optional feature in a given package is not
|
||||||
|
necessarily a bug. More recommendations for GNU packages can be found
|
||||||
|
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||||
|
|
||||||
|
The 'configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a 'Makefile' in each directory of the package.
|
||||||
|
It may also create one or more '.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script 'config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file 'config.log' containing compiler output (useful mainly for
|
||||||
|
debugging 'configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called 'config.cache' and
|
||||||
|
enabled with '--cache-file=config.cache' or simply '-C') that saves the
|
||||||
|
results of its tests to speed up reconfiguring. Caching is disabled by
|
||||||
|
default to prevent problems with accidental use of stale cache files.
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how 'configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the 'README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point 'config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file 'configure.ac' (or 'configure.in') is used to create
|
||||||
|
'configure' by a program called 'autoconf'. You need 'configure.ac' if
|
||||||
|
you want to change it or regenerate 'configure' using a newer version of
|
||||||
|
'autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. 'cd' to the directory containing the package's source code and type
|
||||||
|
'./configure' to configure the package for your system.
|
||||||
|
|
||||||
|
Running 'configure' might take a while. While running, it prints
|
||||||
|
some messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type 'make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type 'make check' to run any self-tests that come with
|
||||||
|
the package, generally using the just-built uninstalled binaries.
|
||||||
|
|
||||||
|
4. Type 'make install' to install the programs and any data files and
|
||||||
|
documentation. When installing into a prefix owned by root, it is
|
||||||
|
recommended that the package be configured and built as a regular
|
||||||
|
user, and only the 'make install' phase executed with root
|
||||||
|
privileges.
|
||||||
|
|
||||||
|
5. Optionally, type 'make installcheck' to repeat any self-tests, but
|
||||||
|
this time using the binaries in their final installed location.
|
||||||
|
This target does not install anything. Running this target as a
|
||||||
|
regular user, particularly if the prior 'make install' required
|
||||||
|
root privileges, verifies that the installation completed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
6. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing 'make clean'. To also remove the
|
||||||
|
files that 'configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type 'make distclean'. There is
|
||||||
|
also a 'make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
7. Often, you can also type 'make uninstall' to remove the installed
|
||||||
|
files again. In practice, not all packages have tested that
|
||||||
|
uninstallation works correctly, even though it is required by the
|
||||||
|
GNU Coding Standards.
|
||||||
|
|
||||||
|
8. Some packages, particularly those that use Automake, provide 'make
|
||||||
|
distcheck', which can by used by developers to test that all other
|
||||||
|
targets like 'make install' and 'make uninstall' work correctly.
|
||||||
|
This target is generally not run by end users.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Some systems require unusual options for compilation or linking that
|
||||||
|
the 'configure' script does not know about. Run './configure --help'
|
||||||
|
for details on some of the pertinent environment variables.
|
||||||
|
|
||||||
|
You can give 'configure' initial values for configuration parameters
|
||||||
|
by setting variables in the command line or in the environment. Here is
|
||||||
|
an example:
|
||||||
|
|
||||||
|
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||||
|
|
||||||
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can compile the package for more than one kind of computer at the
|
||||||
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you can use GNU 'make'. 'cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the 'configure' script. 'configure' automatically checks for the source
|
||||||
|
code in the directory that 'configure' is in and in '..'. This is known
|
||||||
|
as a "VPATH" build.
|
||||||
|
|
||||||
|
With a non-GNU 'make', it is safer to compile the package for one
|
||||||
|
architecture at a time in the source code directory. After you have
|
||||||
|
installed the package for one architecture, use 'make distclean' before
|
||||||
|
reconfiguring for another architecture.
|
||||||
|
|
||||||
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
|
executables that work on multiple system types--known as "fat" or
|
||||||
|
"universal" binaries--by specifying multiple '-arch' options to the
|
||||||
|
compiler but only a single '-arch' option to the preprocessor. Like
|
||||||
|
this:
|
||||||
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the 'lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, 'make install' installs the package's commands under
|
||||||
|
'/usr/local/bin', include files under '/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than '/usr/local' by giving
|
||||||
|
'configure' the option '--prefix=PREFIX', where PREFIX must be an
|
||||||
|
absolute file name.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like '--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run 'configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them. In general, the default
|
||||||
|
for these options is expressed in terms of '${prefix}', so that
|
||||||
|
specifying just '--prefix' will affect all of the other directory
|
||||||
|
specifications that were not explicitly provided.
|
||||||
|
|
||||||
|
The most portable way to affect installation locations is to pass the
|
||||||
|
correct locations to 'configure'; however, many packages provide one or
|
||||||
|
both of the following shortcuts of passing variable assignments to the
|
||||||
|
'make install' command line to change installation locations without
|
||||||
|
having to reconfigure or recompile.
|
||||||
|
|
||||||
|
The first method involves providing an override variable for each
|
||||||
|
affected directory. For example, 'make install
|
||||||
|
prefix=/alternate/directory' will choose an alternate location for all
|
||||||
|
directory configuration variables that were expressed in terms of
|
||||||
|
'${prefix}'. Any directories that were specified during 'configure',
|
||||||
|
but not in terms of '${prefix}', must each be overridden at install time
|
||||||
|
for the entire installation to be relocated. The approach of makefile
|
||||||
|
variable overrides for each directory variable is required by the GNU
|
||||||
|
Coding Standards, and ideally causes no recompilation. However, some
|
||||||
|
platforms have known limitations with the semantics of shared libraries
|
||||||
|
that end up requiring recompilation when using this method, particularly
|
||||||
|
noticeable in packages that use GNU Libtool.
|
||||||
|
|
||||||
|
The second method involves providing the 'DESTDIR' variable. For
|
||||||
|
example, 'make install DESTDIR=/alternate/directory' will prepend
|
||||||
|
'/alternate/directory' before all installation names. The approach of
|
||||||
|
'DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||||
|
does not work on platforms that have drive letters. On the other hand,
|
||||||
|
it does better at avoiding recompilation issues, and works well even
|
||||||
|
when some directory options were not specified in terms of '${prefix}'
|
||||||
|
at 'configure' time.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving 'configure' the
|
||||||
|
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Some packages pay attention to '--enable-FEATURE' options to
|
||||||
|
'configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like 'gnu-as' or 'x' (for the X Window System). The
|
||||||
|
'README' should mention any '--enable-' and '--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, 'configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the 'configure' options '--x-includes=DIR' and
|
||||||
|
'--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Some packages offer the ability to configure how verbose the
|
||||||
|
execution of 'make' will be. For these packages, running './configure
|
||||||
|
--enable-silent-rules' sets the default to minimal output, which can be
|
||||||
|
overridden with 'make V=1'; while running './configure
|
||||||
|
--disable-silent-rules' sets the default to verbose, which can be
|
||||||
|
overridden with 'make V=0'.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
|
||||||
|
is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
HP-UX 'make' updates targets which have the same timestamps as their
|
||||||
|
prerequisites, which makes it generally unusable when shipped generated
|
||||||
|
files such as 'configure' are involved. Use GNU 'make' instead.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
|
||||||
|
workaround. If GNU CC is not installed, it is therefore recommended to
|
||||||
|
try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
|
||||||
|
directory contains several dysfunctional programs; working variants of
|
||||||
|
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
|
||||||
|
in your 'PATH', put it _after_ '/usr/bin'.
|
||||||
|
|
||||||
|
On Haiku, software installed for all users goes in '/boot/common',
|
||||||
|
not '/usr/local'. It is recommended to use the following options:
|
||||||
|
|
||||||
|
./configure --prefix=/boot/common
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features 'configure' cannot figure out
|
||||||
|
automatically, but needs to determine by the type of machine the package
|
||||||
|
will run on. Usually, assuming the package is built to be run on the
|
||||||
|
_same_ architectures, 'configure' can figure that out, but if it prints
|
||||||
|
a message saying it cannot guess the machine type, give it the
|
||||||
|
'--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as 'sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS
|
||||||
|
KERNEL-OS
|
||||||
|
|
||||||
|
See the file 'config.sub' for the possible values of each field. If
|
||||||
|
'config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option '--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with '--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for 'configure' scripts to share,
|
||||||
|
you can create a site shell script called 'config.site' that gives
|
||||||
|
default values for variables like 'CC', 'cache_file', and 'prefix'.
|
||||||
|
'configure' looks for 'PREFIX/share/config.site' if it exists, then
|
||||||
|
'PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
'CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all 'configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to 'configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the 'configure' command line, using 'VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified 'gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
|
||||||
|
Autoconf limitation. Until the limitation is lifted, you can use this
|
||||||
|
workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
'configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
'configure' recognizes the following options to control how it
|
||||||
|
operates.
|
||||||
|
|
||||||
|
'--help'
|
||||||
|
'-h'
|
||||||
|
Print a summary of all of the options to 'configure', and exit.
|
||||||
|
|
||||||
|
'--help=short'
|
||||||
|
'--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
'configure', and exit. The 'short' variant lists options used only
|
||||||
|
in the top level, while the 'recursive' variant lists options also
|
||||||
|
present in any nested packages.
|
||||||
|
|
||||||
|
'--version'
|
||||||
|
'-V'
|
||||||
|
Print the version of Autoconf used to generate the 'configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
'--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally 'config.cache'. FILE defaults to '/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
'--config-cache'
|
||||||
|
'-C'
|
||||||
|
Alias for '--cache-file=config.cache'.
|
||||||
|
|
||||||
|
'--quiet'
|
||||||
|
'--silent'
|
||||||
|
'-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to '/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
'--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
'configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
'--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *note Installation Names:: for
|
||||||
|
more details, including other options available for fine-tuning the
|
||||||
|
installation locations.
|
||||||
|
|
||||||
|
'--no-create'
|
||||||
|
'-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
'configure' also accepts some other, not widely useful, options. Run
|
||||||
|
'configure --help' for more details.
|
||||||
27
Makefile.am
Normal file
27
Makefile.am
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Top-level Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2020, 2022
|
||||||
|
# Jose E. Marchesi
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
SUBDIRS = lib libcsv src utils bash doc po man torture etc
|
||||||
|
|
||||||
|
perf:
|
||||||
|
$(MAKE) -C torture/utils perf
|
||||||
|
|
||||||
|
.PHONY: perf
|
||||||
|
|
||||||
|
# End of Makefile.am
|
||||||
2320
Makefile.in
Normal file
2320
Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
213
NEWS
Normal file
213
NEWS
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
This NEWS file records noteworthy changes, very tersely.
|
||||||
|
See the manual for detailed information.
|
||||||
|
|
||||||
|
Copyright 2010-2022 Jose E. Marchesi.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Version 1.9 (16 April 2022)
|
||||||
|
* Utilities:
|
||||||
|
. Fix bug preventing recins and recset to work when /tmp is
|
||||||
|
in a different mount point.
|
||||||
|
. Fix a segfault that occured when csv2rec was presented with
|
||||||
|
invalid data.
|
||||||
|
. Fix long option name for -j/--join.
|
||||||
|
* Format:
|
||||||
|
. New special field %singular to mark fields whose contents
|
||||||
|
must be unique in the containing record set.
|
||||||
|
* librec:
|
||||||
|
. Fix a segmentation fault when there are blank characters before
|
||||||
|
the list of fields in %type fields.
|
||||||
|
* Documentation:
|
||||||
|
. New manual chapter discussing the ob-rec.el major mode.
|
||||||
|
. Do not claim that recins creates non-existent files.
|
||||||
|
* Other fixes:
|
||||||
|
. CVE-2021-46019
|
||||||
|
. CVE-2021-46022
|
||||||
|
. CVE-2021-46022
|
||||||
|
. gnulib updated.
|
||||||
|
|
||||||
|
Version 1.8 (3 January 2019)
|
||||||
|
* Utilities:
|
||||||
|
. Fix the build of readrec with recent bash headers.
|
||||||
|
* librec:
|
||||||
|
. Fix evaluation of sexes containing #NAME expressions.
|
||||||
|
. Make numeric results from aggregated functions signed.
|
||||||
|
* readred:
|
||||||
|
. readrec --help now shows the help message and returns,
|
||||||
|
instead of waiting for input.
|
||||||
|
* Emacs mode:
|
||||||
|
. rec-mode.el now supports case-insensitive searches.
|
||||||
|
. rec-mode.el now defines it's own faces.
|
||||||
|
. ob-rec.el was switched to lexical binding to satisfy later
|
||||||
|
org-mode versions.
|
||||||
|
* It is now possible to run the testsuite in parallel.
|
||||||
|
* Other fixes:
|
||||||
|
. gnulib updated.
|
||||||
|
. GNU/Hurd build fixed.
|
||||||
|
. Aggregate functions now work properly in Aarch64 and powerpc.
|
||||||
|
|
||||||
|
Version 1.7 (25 March 2014)
|
||||||
|
* Utilities:
|
||||||
|
. rec2csv now supports a -d option to change the delimiter
|
||||||
|
character in CSV files.
|
||||||
|
. It is now possible to specify several recfiles in the
|
||||||
|
command line containing anonymous records.
|
||||||
|
* Format:
|
||||||
|
. Support for restricting the fields that can appear in records
|
||||||
|
with the new %allowed special field.
|
||||||
|
. If a tab separates a field name and a field value is now
|
||||||
|
ignored and not considered part of the field value.
|
||||||
|
* librec:
|
||||||
|
. The current version of the library is now 1.
|
||||||
|
* Emacs mode:
|
||||||
|
. It now possible to jump several records while navigating
|
||||||
|
using a prefix argument to the next/previous commands.
|
||||||
|
* Documentation:
|
||||||
|
. The examples in the manual have been improved, and well as many
|
||||||
|
other aspects: formatting, English, etc. Special thanks to Karl
|
||||||
|
Berry for pointing out the problems and suggesting solutions.
|
||||||
|
* Internal cleanup and code factorization.
|
||||||
|
* Many, many, many bug fixes :D
|
||||||
|
|
||||||
|
Version 1.6 (03 November 2013)
|
||||||
|
* Utilities:
|
||||||
|
. Support for joins and foreign keys.
|
||||||
|
. Grouping records by one or more fields.
|
||||||
|
. Sorting recors by several fields.
|
||||||
|
. Specifying rewrite rules in field expressions.
|
||||||
|
. Writing field values in rows.
|
||||||
|
. Dot-notation in selection expressions.
|
||||||
|
. Support for the >= and <= operators in selection expressions.
|
||||||
|
. Aggregated functions: sum, min, max, avg.
|
||||||
|
. New bash loadable builtin `readrec'.
|
||||||
|
* Format:
|
||||||
|
. New UUID field type.
|
||||||
|
. User provided arbitrary constraints with %constraint.
|
||||||
|
. Pre-defined constants MIN and MAX can now be used in ranges.
|
||||||
|
* librec:
|
||||||
|
. New high-level API: rec_db_query, rec_db_insert, rec_db_delete and
|
||||||
|
rec_db_set.
|
||||||
|
. Documentation in the rec.h header file extended and improved.
|
||||||
|
* Emacs mode:
|
||||||
|
. Texinfo manual describing the usage of rec-mode.
|
||||||
|
. Support for a mode hook.
|
||||||
|
. Comments are now supported in records.
|
||||||
|
. add-change-log-entry in a recfile now does the right thing.
|
||||||
|
. Commands for copying/killing fields and records.
|
||||||
|
. Support for undo in navigation mode.
|
||||||
|
. Field folding.
|
||||||
|
. Editing methods for the several field types.
|
||||||
|
. Statistics.
|
||||||
|
* Documentation:
|
||||||
|
. The user manual has been restructured and expanded.
|
||||||
|
* Internal cleanup and code factorization.
|
||||||
|
* Many, many, many bug fixes :D
|
||||||
|
|
||||||
|
Version 1.5 (13 January 2012)
|
||||||
|
* The utilities will now ask interactively for a password if it was
|
||||||
|
not provided with the -s command line option. This avoids security
|
||||||
|
problems related to shell history files.
|
||||||
|
* Support for octal and hexadecimal numbers has been added. They can
|
||||||
|
be used in both the records and selection expressions.
|
||||||
|
* It is now possible to select a given number of random records in
|
||||||
|
many of the utilities using the -m command line option.
|
||||||
|
* The -n option now accepts a list of indexes, supporting ranges.
|
||||||
|
* The new -U (uniq) option for recsel removes duplicated fields in the
|
||||||
|
output records.
|
||||||
|
* The new -q (quick) option allows to quickly search for the desired
|
||||||
|
record without having to provide a complete selection expression.
|
||||||
|
* Auto generated fields are now considered integers by default. This
|
||||||
|
avoids repetitive patterns in record descriptors involving %auto and
|
||||||
|
%type.
|
||||||
|
* Tab characters are now allowed in blank lines betwwen records.
|
||||||
|
* The API in rec.h is now better documented with comments, and
|
||||||
|
improved.
|
||||||
|
* recfix now exits with an error status if there is a parse error in
|
||||||
|
some input file.
|
||||||
|
* The usage of the internal data structures has been _vastly_
|
||||||
|
improved, resulting in a much faster operation.
|
||||||
|
* Internal cleanup and code factorization.
|
||||||
|
* Many, many, many bug fixes :D
|
||||||
|
|
||||||
|
Version 1.4 (03 November 2011)
|
||||||
|
* Support for encryption with the new %confidential special field.
|
||||||
|
* Support for named types with the new %typedef special field.
|
||||||
|
* Support for sorting with the new %sort special field.
|
||||||
|
* Recutils support for org-babel is now included in the distribution
|
||||||
|
as ob-rec.el. It allows to read rec data into org documents in both
|
||||||
|
raw and table formats.
|
||||||
|
* It is now possible to use double quotes for delimiting string
|
||||||
|
literals in selection expressions, as well as single quotes.
|
||||||
|
Unescapted newline characters are also supported.
|
||||||
|
* The manual has been vastly improved.
|
||||||
|
* recfix now supports several operations: check, sort, encrypt and
|
||||||
|
decrypt.
|
||||||
|
* recins now generates parseable locale independent dates when
|
||||||
|
generating time-stamps in auto-fields.
|
||||||
|
* Lots of bug fixes.
|
||||||
|
|
||||||
|
Version 1.3 (11 February 2011)
|
||||||
|
* A quite bad (and embarrassing) bug introduced in 1.2 has been
|
||||||
|
fixed. The bug was causing recins, recdel and recset to report
|
||||||
|
random integrity failures, due to a uninitialized variable.
|
||||||
|
* New special field %size, that allows to define constraints in the
|
||||||
|
size of record sets.
|
||||||
|
* Several fixes in the user manual.
|
||||||
|
* Little portability issue that prevented one of the tests to compile
|
||||||
|
in macos x has been fixed.
|
||||||
|
* Translations updates.
|
||||||
|
|
||||||
|
Version 1.2 (4 February 2011)
|
||||||
|
* New utility rec2csv, to export rec data to csv files.
|
||||||
|
* Support for auto-incremented fields and timestamps with the new
|
||||||
|
%auto field in record descriptors.
|
||||||
|
* Support for comments in enum type descriptions.
|
||||||
|
* recset now supports a new "set or add field" operation, implementing
|
||||||
|
the common case of setting the value of a field in case it exists,
|
||||||
|
or else add it to the record.
|
||||||
|
* The flavor of regular expressions accepted in both selection
|
||||||
|
expressions and type descriptions is now documented in the user
|
||||||
|
manual.
|
||||||
|
* Translations for German, Finnish, Swedish and Dutch.
|
||||||
|
* recdel now performs an integrity check before to complete the
|
||||||
|
deletion.
|
||||||
|
* The utilities no longer "expand" the contents of remote descriptors
|
||||||
|
in the local ones.
|
||||||
|
* recset and recins no longer destroy the permissions of the rec file
|
||||||
|
that is being modified.
|
||||||
|
* Many fixes in the documentation.
|
||||||
|
* Lots of bug fixes.
|
||||||
|
|
||||||
|
Version 1.1 (24 December 2010)
|
||||||
|
* New utility recfmt, to format records based on templates.
|
||||||
|
* Improvements in selection expressions:
|
||||||
|
. Support ranges in field subscripts.
|
||||||
|
. New date operators: before (<<), after (>>) and sametime (==).
|
||||||
|
. New ternary conditional operator (?:).
|
||||||
|
. New string concatenation operator (&).
|
||||||
|
* libcsv is now embedded in the source distribution, so it is no
|
||||||
|
longer required to have it installed to build csv2rec.
|
||||||
|
* Portability problems fixed. The programs have been tested in the
|
||||||
|
following systems:
|
||||||
|
. GNU/Linux
|
||||||
|
. FreeBSD 6.4
|
||||||
|
. MacOS X
|
||||||
|
. mingw32
|
||||||
|
. Solaris 8
|
||||||
|
. AIX 5.1
|
||||||
|
. HP-UX 11.00
|
||||||
|
. IRIX 6.5
|
||||||
|
. Tru64 (OSF/1 5.1)
|
||||||
|
. Cygwin 1.7
|
||||||
|
* Lots of bug fixes.
|
||||||
|
|
||||||
|
Version 1.0 (3 December 2010)
|
||||||
|
* Initial release.
|
||||||
|
. User manual.
|
||||||
|
. Library (librec).
|
||||||
|
. Utilities: recinf, recsel, recins, recdel, recset, recfix, csv2rec,
|
||||||
|
mdb2rec.
|
||||||
|
. Experimental Emacs mode (rec-mode.el).
|
||||||
56
README
Normal file
56
README
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
This is the README file for the GNU recutils distribution.
|
||||||
|
The GNU recutils are a set of libraries and utilities supporting the
|
||||||
|
Rec format: a human-readable, text-based format to store little to
|
||||||
|
medium sized databases.
|
||||||
|
|
||||||
|
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
|
2002, 2004, 2005, 2006, 2010, 2020, 2022 Free Software Foundation,
|
||||||
|
Inc.
|
||||||
|
Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
|
||||||
|
2020, 2022 Jose E. Marchesi
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
See the files ./INSTALL* for building and installation instructions.
|
||||||
|
|
||||||
|
Primary distribution point: ftp://ftp.gnu.org/gnu/recutils/
|
||||||
|
automatic redirection: http://ftpmirror.gnu.org/recutils
|
||||||
|
list of mirrors for manual selection: http://www.gnu.org/prep/ftp.html
|
||||||
|
|
||||||
|
Home page: http://www.gnu.org/software/recutils/
|
||||||
|
|
||||||
|
Mailing list: bug-recutils@gnu.org
|
||||||
|
- please use this list for all discussion: bug reports, enhancements, etc.
|
||||||
|
- archived at: http://lists.gnu.org/pipermail/bug-recutils
|
||||||
|
- anyone is welcome to join the list; to do so, visit
|
||||||
|
http://lists.gnu.org/mailman/listinfo/bug-recutils
|
||||||
|
- there is no corresponding newsgroup.
|
||||||
|
|
||||||
|
Bug reports:
|
||||||
|
Please include enough information for the maintainers to reproduce the
|
||||||
|
problem. Gnerally speaking, that means:
|
||||||
|
- the contents of any input files necessary to reproduce the bug
|
||||||
|
and command line invocations of the program(s) involved (crucial!).
|
||||||
|
- a description of the problem and any samples of the erroneous output.
|
||||||
|
- the version number of the program(s) involved (use --version).
|
||||||
|
- hardware, operating system, and compiler versions (uname -a).
|
||||||
|
- unusual options you gave to configure, if any (see config.status).
|
||||||
|
- anything else that you think would be helpful.
|
||||||
|
|
||||||
|
Patches are most welcome; if possible, please make them with diff -c and
|
||||||
|
include ChangeLog entries.
|
||||||
|
|
||||||
|
See README-dev for information on the development environment -- any
|
||||||
|
interested parties are welcome. If you're a programmer and wish to
|
||||||
|
contribute, this should get you started. If you're not a programmer,
|
||||||
|
your help in writing test cases, checking the documentation against the
|
||||||
|
implementation, translating the program strings to other languages,
|
||||||
|
etc., would still be very much appreciated.
|
||||||
|
|
||||||
|
GNU Recutils is free software. See the file COPYING for copying conditions.
|
||||||
|
|
||||||
|
For any copyright year range specified as YYYY-ZZZZ in this package
|
||||||
|
note that the range specifies every single year in that closed
|
||||||
|
interval.
|
||||||
17
README.md
Normal file
17
README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# town-recutils
|
||||||
|
|
||||||
|
This source code is GNU Recutils version 1.9 from the GNU mirrors.
|
||||||
|
With minimal patching to make it build on Debian Trixe.
|
||||||
|
|
||||||
|
The patch set is a slight tweak to the Fedora recutils-c99 patch,
|
||||||
|
by Florian Weimer. Which has been pending upstream review for three years.
|
||||||
|
|
||||||
|
This repository is intended to provide access to
|
||||||
|
Complete Corresponding Source, for members if tilde.town.
|
||||||
|
|
||||||
|
Accordingly i will only make commits in this repo, when
|
||||||
|
tilde.town's needs require changes to be made.
|
||||||
|
|
||||||
|
In other words
|
||||||
|
|
||||||
|
This is not a fork!
|
||||||
1452
aclocal.m4
vendored
Normal file
1452
aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
bash/Makefile.am
Normal file
41
bash/Makefile.am
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# bash/Makefile.am
|
||||||
|
# GNU recutils
|
||||||
|
|
||||||
|
# Copyright (C) 2013, 2014, 2015, 2016, 2017, 2018, 2020, 2022 Jose E.
|
||||||
|
# Marchesi
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
if BASH_BUILTINS
|
||||||
|
|
||||||
|
COMMON_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \
|
||||||
|
-I$(top_srcdir)/src -DHAVE_CONFIG_H \
|
||||||
|
-I$(BASH_HEADERS) -I$(BASH_HEADERS)/lib -I$(BASH_HEADERS)/builtins \
|
||||||
|
-I$(BASH_HEADERS)/include
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = readrec.la testrec.la
|
||||||
|
|
||||||
|
AM_CPPFLAGS = $(COMMON_CPPFLAGS)
|
||||||
|
|
||||||
|
readrec_la_LDFLAGS = -module
|
||||||
|
readrec_la_LIBADD = $(top_builddir)/src/librec.la
|
||||||
|
readrec_la_SOURCES = readrec.c
|
||||||
|
|
||||||
|
testrec_la_LDFLAGS = -module
|
||||||
|
testrec_la_LIBADD = $(top_builddir)/src/librec.la
|
||||||
|
testrec_la_SOURCES = testrec.c
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# End of Makefile.am
|
||||||
2187
bash/Makefile.in
Normal file
2187
bash/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
158
bash/readrec.c
Normal file
158
bash/readrec.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/* -*- mode: C -*-
|
||||||
|
*
|
||||||
|
* File: readrec.c
|
||||||
|
* Date: Fri Aug 23 18:38:08 2013
|
||||||
|
*
|
||||||
|
* GNU recutils - readrec bash loadable builtin.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (C) 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2022
|
||||||
|
* Jose E. Marchesi */
|
||||||
|
|
||||||
|
/* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <bash/config.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <rec.h>
|
||||||
|
|
||||||
|
#include "builtins.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "builtins/bashgetopt.h"
|
||||||
|
|
||||||
|
/* The function implementing the builtin. It uses internal_getopt to
|
||||||
|
parse options. It is the same as getopt(3), but it takes a pointer
|
||||||
|
to a WORD_LIST.
|
||||||
|
|
||||||
|
If the builtin takes no options, call no_options(list) before doing
|
||||||
|
anything else. If it returns a non-zero value, your builtin should
|
||||||
|
immediately return EX_USAGE.
|
||||||
|
|
||||||
|
A builtin command returns EXECUTION_SUCCESS for success and
|
||||||
|
EXECUTION_FAILURE to indicate failure. */
|
||||||
|
int
|
||||||
|
readrec_builtin (WORD_LIST *list)
|
||||||
|
{
|
||||||
|
SHELL_VAR *var;
|
||||||
|
rec_parser_t parser;
|
||||||
|
rec_record_t record;
|
||||||
|
|
||||||
|
if (no_options (list) != 0)
|
||||||
|
return EX_USAGE;
|
||||||
|
|
||||||
|
/* Create a librec parser to operate on the standard input and try
|
||||||
|
to read a record. If there is a parse error then report it and
|
||||||
|
fail. */
|
||||||
|
|
||||||
|
parser = rec_parser_new (stdin, "stdin");
|
||||||
|
if (!parser)
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
|
||||||
|
if (!rec_parse_record (parser, &record))
|
||||||
|
{
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t record_str_size = 0;
|
||||||
|
char *record_str = NULL;
|
||||||
|
char *record_str_dequoted = NULL;
|
||||||
|
rec_writer_t writer = rec_writer_new_str (&record_str, &record_str_size);
|
||||||
|
|
||||||
|
if (!writer || !rec_write_record (writer, record))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
rec_writer_destroy (writer);
|
||||||
|
|
||||||
|
/* Set the REPLY_REC environment variable to the read record. */
|
||||||
|
record_str_dequoted = dequote_string (record_str);
|
||||||
|
var = bind_variable ("REPLY_REC", record_str_dequoted, 0);
|
||||||
|
VUNSETATTR (var, att_invisible);
|
||||||
|
xfree (record_str_dequoted);
|
||||||
|
|
||||||
|
/* Set the environment variables for the fields. */
|
||||||
|
{
|
||||||
|
rec_field_t field = NULL;
|
||||||
|
rec_mset_iterator_t iter = rec_mset_iterator (rec_record_mset (record));
|
||||||
|
|
||||||
|
// rec_record_reset_marks (record);
|
||||||
|
while (rec_mset_iterator_next (&iter, MSET_FIELD, (const void **) &field, NULL))
|
||||||
|
{
|
||||||
|
char *var_name = rec_field_name (field);
|
||||||
|
size_t num_fields = rec_record_get_num_fields_by_name (record, var_name);
|
||||||
|
|
||||||
|
// if (rec_record_field_mark (record, field))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
#if defined ARRAY_VARS
|
||||||
|
if (num_fields > 1)
|
||||||
|
{
|
||||||
|
/* In case several fields share the same field name, create
|
||||||
|
an array variable containing all the values. */
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < num_fields; i++)
|
||||||
|
{
|
||||||
|
// rec_record_mark_field (record, field, true);
|
||||||
|
field = rec_record_get_field_by_name (record, var_name, i);
|
||||||
|
var = bind_array_variable (var_name, i, rec_field_value (field), 0);
|
||||||
|
VUNSETATTR (var, att_invisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bind a normal variable. */
|
||||||
|
char *var_value = rec_field_value (field);
|
||||||
|
var = bind_variable (var_name, var_value, 0);
|
||||||
|
VUNSETATTR (var, att_invisible);
|
||||||
|
}
|
||||||
|
#endif /* ARRAY_VARS */
|
||||||
|
}
|
||||||
|
rec_mset_iterator_free (&iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXECUTION_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An array of strings forming the `long' documentation for the builtin,
|
||||||
|
which is printed by `help xxx'. It must end with a NULL. By convention,
|
||||||
|
the first line is a short description. */
|
||||||
|
char *readrec_doc[] = {
|
||||||
|
"Read a recutils record from the standard input.",
|
||||||
|
"",
|
||||||
|
"The read record is stored in the REPLY_REC variable. Additional variables",
|
||||||
|
"are set named after the fields in the record.",
|
||||||
|
"",
|
||||||
|
"Exit Status:",
|
||||||
|
"The return code is zero, unless end-of-file is encountered.",
|
||||||
|
(char *) NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The standard structure describing a builtin command. bash keeps an
|
||||||
|
array of these structures. The flags must include BUILTIN_ENABLED
|
||||||
|
so the builtin can be used. */
|
||||||
|
struct builtin readrec_struct = {
|
||||||
|
"readrec", /* builtin name */
|
||||||
|
readrec_builtin, /* function implementing the builtin */
|
||||||
|
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||||
|
readrec_doc, /* array of long documentation strings. */
|
||||||
|
"readrec", /* usage synopsis; becomes short_doc */
|
||||||
|
0 /* reserved for internal use */
|
||||||
|
};
|
||||||
135
bash/testrec.c
Normal file
135
bash/testrec.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/* -*- mode: C -*- Time-stamp: "2019-01-03 09:44:20 jemarch"
|
||||||
|
*
|
||||||
|
* File: testrec.c
|
||||||
|
* Date: Fri Aug 23 21:41:00 2013
|
||||||
|
*
|
||||||
|
* GNU recutils - testrec bash loadable builtin.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (C) 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2022
|
||||||
|
* Jose E. Marchesi */
|
||||||
|
|
||||||
|
/* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <bash/config.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <rec.h>
|
||||||
|
|
||||||
|
#include "builtins.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "builtins/bashgetopt.h"
|
||||||
|
|
||||||
|
/* The function implementing the builtin. It uses internal_getopt to
|
||||||
|
parse options. It is the same as getopt(3), but it takes a pointer
|
||||||
|
to a WORD_LIST.
|
||||||
|
|
||||||
|
If the builtin takes no options, call no_options(list) before doing
|
||||||
|
anything else. If it returns a non-zero value, your builtin should
|
||||||
|
immediately return EX_USAGE.
|
||||||
|
|
||||||
|
A builtin command returns EXECUTION_SUCCESS for success and
|
||||||
|
EXECUTION_FAILURE to indicate failure. */
|
||||||
|
int
|
||||||
|
testrec_builtin (WORD_LIST *list)
|
||||||
|
{
|
||||||
|
int res = EXECUTION_SUCCESS;
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
SHELL_VAR *var;
|
||||||
|
rec_record_t record;
|
||||||
|
rec_parser_t parser;
|
||||||
|
char *record_str, *sex_str;
|
||||||
|
|
||||||
|
/* Get arguments and verify them. */
|
||||||
|
|
||||||
|
argv = make_builtin_argv (list, &argc);
|
||||||
|
if ((argc != 3)
|
||||||
|
|| ((strcmp (argv[0], "[%") == 0) && ((strlen (argv[2]) == 2) && ((argv[2][0] != '%') || (argv[2][1] != ']')))))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Usage: [%% SEX %%]\n");
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sex_str = argv[1];
|
||||||
|
|
||||||
|
/* Get the record to operate on from the REPLY_REC environment
|
||||||
|
variable. */
|
||||||
|
var = find_variable ("REPLY_REC");
|
||||||
|
if (!var)
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
|
||||||
|
record_str = get_variable_value (var);
|
||||||
|
parser = rec_parser_new_str (record_str, "REPLY_REC");
|
||||||
|
if (!parser || !rec_parse_record (parser, &record))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "testrec: error: invalid record in REPLY_REC\n");
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply the selection expression. */
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
rec_sex_t sex = rec_sex_new (false);
|
||||||
|
if (!sex)
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
|
||||||
|
if (!rec_sex_compile (sex, sex_str))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "testrec: error: wrong selection expression\n");
|
||||||
|
return EXECUTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = rec_sex_eval (sex, record, &status) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
|
||||||
|
rec_sex_destroy (sex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup. */
|
||||||
|
rec_record_destroy (record);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An array of strings forming the `long' documentation for the builtin,
|
||||||
|
which is printed by `help xxx'. It must end with a NULL. By convention,
|
||||||
|
the first line is a short description. */
|
||||||
|
char *testrec_doc[] = {
|
||||||
|
"Evaluate a selection expression on the record stored in REPLY_REC.",
|
||||||
|
"",
|
||||||
|
"Evaluates a given selection expression on the record stored in the\n\
|
||||||
|
REPLY_REC variable, if any.\n\
|
||||||
|
\n\
|
||||||
|
Exit Status:\n\
|
||||||
|
The return code is zero if the selection expression evaluates to\n\
|
||||||
|
true, -1 otherwise.\n",
|
||||||
|
(char *) NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The standard structure describing a builtin command. bash keeps an
|
||||||
|
array of these structures. The flags must include BUILTIN_ENABLED
|
||||||
|
so the builtin can be used. */
|
||||||
|
struct builtin testrec_struct = {
|
||||||
|
"[%", /* builtin name */
|
||||||
|
testrec_builtin, /* function implementing the builtin */
|
||||||
|
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||||
|
testrec_doc, /* array of long documentation strings. */
|
||||||
|
"testrec", /* usage synopsis; becomes short_doc */
|
||||||
|
0 /* reserved for internal use */
|
||||||
|
};
|
||||||
596
build-aux/announce-gen
Executable file
596
build-aux/announce-gen
Executable file
@ -0,0 +1,596 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#! -*-perl-*-
|
||||||
|
|
||||||
|
# Generate a release announcement message.
|
||||||
|
|
||||||
|
# Copyright (C) 2002-2022 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 Jim Meyering
|
||||||
|
|
||||||
|
# This is a prologue that allows to run a perl script as an executable
|
||||||
|
# on systems that are compliant to a POSIX version before POSIX:2017.
|
||||||
|
# On such systems, the usual invocation of an executable through execlp()
|
||||||
|
# or execvp() fails with ENOEXEC if it is a script that does not start
|
||||||
|
# with a #! line. The script interpreter mentioned in the #! line has
|
||||||
|
# to be /bin/sh, because on GuixSD systems that is the only program that
|
||||||
|
# has a fixed file name. The second line is essential for perl and is
|
||||||
|
# also useful for editing this file in Emacs. The next two lines below
|
||||||
|
# are valid code in both sh and perl. When executed by sh, they re-execute
|
||||||
|
# the script through the perl program found in $PATH. The '-x' option
|
||||||
|
# is essential as well; without it, perl would re-execute the script
|
||||||
|
# through /bin/sh. When executed by perl, the next two lines are a no-op.
|
||||||
|
eval 'exec perl -wSx "$0" "$@"'
|
||||||
|
if 0;
|
||||||
|
|
||||||
|
my $VERSION = '2022-03-14 10:08'; # UTC
|
||||||
|
# The definition above must lie within the first 8 lines in order
|
||||||
|
# for the Emacs time-stamp write hook (at end) to update it.
|
||||||
|
# If you change this file with Emacs, please let the write hook
|
||||||
|
# do its job. Otherwise, update this string manually.
|
||||||
|
|
||||||
|
my $copyright_year = '2022';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Getopt::Long;
|
||||||
|
use POSIX qw(strftime);
|
||||||
|
|
||||||
|
(my $ME = $0) =~ s|.*/||;
|
||||||
|
|
||||||
|
my %valid_release_types = map {$_ => 1} qw (alpha beta stable);
|
||||||
|
my @archive_suffixes = qw (tar.gz tar.bz2 tar.lz tar.lzma tar.xz);
|
||||||
|
my $srcdir = '.';
|
||||||
|
|
||||||
|
sub usage ($)
|
||||||
|
{
|
||||||
|
my ($exit_code) = @_;
|
||||||
|
my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
|
||||||
|
if ($exit_code != 0)
|
||||||
|
{
|
||||||
|
print $STREAM "Try '$ME --help' for more information.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my @types = sort keys %valid_release_types;
|
||||||
|
print $STREAM <<EOF;
|
||||||
|
Usage: $ME [OPTIONS]
|
||||||
|
Generate an announcement message. Run this from builddir.
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
|
||||||
|
These options must be specified:
|
||||||
|
|
||||||
|
--release-type=TYPE TYPE must be one of @types
|
||||||
|
--package-name=PACKAGE_NAME
|
||||||
|
--previous-version=VER
|
||||||
|
--current-version=VER
|
||||||
|
--gpg-key-id=ID The GnuPG ID of the key used to sign the tarballs
|
||||||
|
--url-directory=URL_DIR
|
||||||
|
|
||||||
|
The following are optional:
|
||||||
|
|
||||||
|
--news=NEWS_FILE include the NEWS section about this release
|
||||||
|
from this NEWS_FILE; accumulates.
|
||||||
|
--srcdir=DIR where to find the NEWS_FILEs (default: $srcdir)
|
||||||
|
--bootstrap-tools=TOOL_LIST a comma-separated list of tools, e.g.,
|
||||||
|
autoconf,automake,bison,gnulib
|
||||||
|
--gnulib-version=VERSION report VERSION as the gnulib version, where
|
||||||
|
VERSION is the result of running git describe
|
||||||
|
in the gnulib source directory.
|
||||||
|
required if gnulib is in TOOL_LIST.
|
||||||
|
--gpg-key-email=EMAIL The email address of the key used to
|
||||||
|
sign the tarballs
|
||||||
|
--gpg-keyring-url=URL URL pointing to keyring containing the key used
|
||||||
|
to sign the tarballs
|
||||||
|
--no-print-checksums do not emit SHA1 or SHA256 checksums
|
||||||
|
--archive-suffix=SUF add SUF to the list of archive suffixes
|
||||||
|
--mail-headers=HEADERS a space-separated list of mail headers, e.g.,
|
||||||
|
To: x\@example.com Cc: y-announce\@example.com,...
|
||||||
|
|
||||||
|
--help display this help and exit
|
||||||
|
--version output version information and exit
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
exit $exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
=item C<%size> = C<sizes (@file)>
|
||||||
|
|
||||||
|
Compute the sizes of the C<@file> and return them as a hash. Return
|
||||||
|
C<undef> if one of the computation failed.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sizes (@)
|
||||||
|
{
|
||||||
|
my (@file) = @_;
|
||||||
|
|
||||||
|
my $fail = 0;
|
||||||
|
my %res;
|
||||||
|
foreach my $f (@file)
|
||||||
|
{
|
||||||
|
my $cmd = "du -h $f";
|
||||||
|
my $t = `$cmd`;
|
||||||
|
# FIXME-someday: give a better diagnostic, a la $PROCESS_STATUS
|
||||||
|
$@
|
||||||
|
and (warn "command failed: '$cmd'\n"), $fail = 1;
|
||||||
|
chomp $t;
|
||||||
|
$t =~ s/^\s*([\d.]+[MkK]).*/${1}B/;
|
||||||
|
$res{$f} = $t;
|
||||||
|
}
|
||||||
|
return $fail ? undef : %res;
|
||||||
|
}
|
||||||
|
|
||||||
|
=item C<print_locations ($title, \@url, \%size, @file)
|
||||||
|
|
||||||
|
Print a section C<$title> dedicated to the list of <@file>, which
|
||||||
|
sizes are stored in C<%size>, and which are available from the C<@url>.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub print_locations ($\@\%@)
|
||||||
|
{
|
||||||
|
my ($title, $url, $size, @file) = @_;
|
||||||
|
print "Here are the $title:\n";
|
||||||
|
foreach my $url (@{$url})
|
||||||
|
{
|
||||||
|
for my $file (@file)
|
||||||
|
{
|
||||||
|
print " $url/$file";
|
||||||
|
print " (", $$size{$file}, ")"
|
||||||
|
if exists $$size{$file};
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
=item C<print_checksums (@file)
|
||||||
|
|
||||||
|
Print the SHA1 and SHA256 signature section for each C<@file>.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub print_checksums (@)
|
||||||
|
{
|
||||||
|
my (@file) = @_;
|
||||||
|
|
||||||
|
print "Here are the SHA1 and SHA256 checksums:\n";
|
||||||
|
print "\n";
|
||||||
|
|
||||||
|
use Digest::file qw(digest_file_hex digest_file_base64);
|
||||||
|
|
||||||
|
foreach my $f (@file)
|
||||||
|
{
|
||||||
|
print digest_file_hex($f, "SHA-1"), " $f\n";
|
||||||
|
print digest_file_base64($f, "SHA-256"), " $f\n";
|
||||||
|
}
|
||||||
|
print "\nThe SHA256 checksum is base64 encoded, instead of the\n";
|
||||||
|
print "hexadecimal encoding that most checksum tools default to.\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
=item C<print_news_deltas ($news_file, $prev_version, $curr_version)
|
||||||
|
|
||||||
|
Print the section of the NEWS file C<$news_file> addressing changes
|
||||||
|
between versions C<$prev_version> and C<$curr_version>.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub print_news_deltas ($$$)
|
||||||
|
{
|
||||||
|
my ($news_file, $prev_version, $curr_version) = @_;
|
||||||
|
|
||||||
|
my $news_name = $news_file;
|
||||||
|
$news_name =~ s|^\Q$srcdir\E/||;
|
||||||
|
|
||||||
|
print "\n$news_name\n\n";
|
||||||
|
|
||||||
|
# Print all lines from $news_file, starting with the first one
|
||||||
|
# that mentions $curr_version up to but not including
|
||||||
|
# the first occurrence of $prev_version.
|
||||||
|
my $in_items;
|
||||||
|
|
||||||
|
my $re_prefix = qr/(?:\* )?(?:Noteworthy c|Major c|C)(?i:hanges)/;
|
||||||
|
|
||||||
|
my $found_news;
|
||||||
|
open NEWS, '<', $news_file
|
||||||
|
or die "$ME: $news_file: cannot open for reading: $!\n";
|
||||||
|
while (defined (my $line = <NEWS>))
|
||||||
|
{
|
||||||
|
if ( ! $in_items)
|
||||||
|
{
|
||||||
|
# Match lines like these:
|
||||||
|
# * Major changes in release 5.0.1:
|
||||||
|
# * Noteworthy changes in release 6.6 (2006-11-22) [stable]
|
||||||
|
$line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$curr_version\E(?:[^\d.]|$)/o
|
||||||
|
or next;
|
||||||
|
$in_items = 1;
|
||||||
|
print $line;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# This regexp must not match version numbers in NEWS items.
|
||||||
|
# For example, they might well say "introduced in 4.5.5",
|
||||||
|
# and we don't want that to match.
|
||||||
|
$line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$prev_version\E(?:[^\d.]|$)/o
|
||||||
|
and last;
|
||||||
|
print $line;
|
||||||
|
$line =~ /\S/
|
||||||
|
and $found_news = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close NEWS;
|
||||||
|
|
||||||
|
$in_items
|
||||||
|
or die "$ME: $news_file: no matching lines for '$curr_version'\n";
|
||||||
|
$found_news
|
||||||
|
or die "$ME: $news_file: no news item found for '$curr_version'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub print_changelog_deltas ($$)
|
||||||
|
{
|
||||||
|
my ($package_name, $prev_version) = @_;
|
||||||
|
|
||||||
|
# Print new ChangeLog entries.
|
||||||
|
|
||||||
|
# First find all CVS-controlled ChangeLog files.
|
||||||
|
use File::Find;
|
||||||
|
my @changelog;
|
||||||
|
find ({wanted => sub {$_ eq 'ChangeLog' && -d 'CVS'
|
||||||
|
and push @changelog, $File::Find::name}},
|
||||||
|
'.');
|
||||||
|
|
||||||
|
# If there are no ChangeLog files, we're done.
|
||||||
|
@changelog
|
||||||
|
or return;
|
||||||
|
my %changelog = map {$_ => 1} @changelog;
|
||||||
|
|
||||||
|
# Reorder the list of files so that if there are ChangeLog
|
||||||
|
# files in the specified directories, they're listed first,
|
||||||
|
# in this order:
|
||||||
|
my @dir = qw ( . src lib m4 config doc );
|
||||||
|
|
||||||
|
# A typical @changelog array might look like this:
|
||||||
|
# ./ChangeLog
|
||||||
|
# ./po/ChangeLog
|
||||||
|
# ./m4/ChangeLog
|
||||||
|
# ./lib/ChangeLog
|
||||||
|
# ./doc/ChangeLog
|
||||||
|
# ./config/ChangeLog
|
||||||
|
my @reordered;
|
||||||
|
foreach my $d (@dir)
|
||||||
|
{
|
||||||
|
my $dot_slash = $d eq '.' ? $d : "./$d";
|
||||||
|
my $target = "$dot_slash/ChangeLog";
|
||||||
|
delete $changelog{$target}
|
||||||
|
and push @reordered, $target;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Append any remaining ChangeLog files.
|
||||||
|
push @reordered, sort keys %changelog;
|
||||||
|
|
||||||
|
# Remove leading './'.
|
||||||
|
@reordered = map { s!^\./!!; $_ } @reordered;
|
||||||
|
|
||||||
|
print "\nChangeLog entries:\n\n";
|
||||||
|
# print join ("\n", @reordered), "\n";
|
||||||
|
|
||||||
|
$prev_version =~ s/\./_/g;
|
||||||
|
my $prev_cvs_tag = "\U$package_name\E-$prev_version";
|
||||||
|
|
||||||
|
my $cmd = "cvs -n diff -u -r$prev_cvs_tag -rHEAD @reordered";
|
||||||
|
open DIFF, '-|', $cmd
|
||||||
|
or die "$ME: cannot run '$cmd': $!\n";
|
||||||
|
# Print two types of lines, making minor changes:
|
||||||
|
# Lines starting with '+++ ', e.g.,
|
||||||
|
# +++ ChangeLog 22 Feb 2003 16:52:51 -0000 1.247
|
||||||
|
# and those starting with '+'.
|
||||||
|
# Don't print the others.
|
||||||
|
my $prev_printed_line_empty = 1;
|
||||||
|
while (defined (my $line = <DIFF>))
|
||||||
|
{
|
||||||
|
if ($line =~ /^\+\+\+ /)
|
||||||
|
{
|
||||||
|
my $separator = "*"x70 ."\n";
|
||||||
|
$line =~ s///;
|
||||||
|
$line =~ s/\s.*//;
|
||||||
|
$prev_printed_line_empty
|
||||||
|
or print "\n";
|
||||||
|
print $separator, $line, $separator;
|
||||||
|
}
|
||||||
|
elsif ($line =~ /^\+/)
|
||||||
|
{
|
||||||
|
$line =~ s///;
|
||||||
|
print $line;
|
||||||
|
$prev_printed_line_empty = ($line =~ /^$/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close DIFF;
|
||||||
|
|
||||||
|
# The exit code should be 1.
|
||||||
|
# Allow in case there are no modified ChangeLog entries.
|
||||||
|
$? == 256 || $? == 128
|
||||||
|
or warn "warning: '$cmd' had unexpected exit code or signal ($?)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_tool_versions ($$)
|
||||||
|
{
|
||||||
|
my ($tool_list, $gnulib_version) = @_;
|
||||||
|
@$tool_list
|
||||||
|
or return ();
|
||||||
|
|
||||||
|
my $fail;
|
||||||
|
my @tool_version_pair;
|
||||||
|
foreach my $t (@$tool_list)
|
||||||
|
{
|
||||||
|
if ($t eq 'gnulib')
|
||||||
|
{
|
||||||
|
push @tool_version_pair, ucfirst $t . ' ' . $gnulib_version;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
# Assume that the last "word" on the first line of
|
||||||
|
# 'tool --version' output is the version string.
|
||||||
|
my ($first_line, undef) = split ("\n", `$t --version`);
|
||||||
|
if ($first_line =~ /.* (\d[\w.-]+)$/)
|
||||||
|
{
|
||||||
|
$t = ucfirst $t;
|
||||||
|
push @tool_version_pair, "$t $1";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defined $first_line
|
||||||
|
and $first_line = '';
|
||||||
|
warn "$t: unexpected --version output\n:$first_line";
|
||||||
|
$fail = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$fail
|
||||||
|
and exit 1;
|
||||||
|
|
||||||
|
return @tool_version_pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# Use the C locale so that, for instance, "du" does not
|
||||||
|
# print "1,2" instead of "1.2", which would confuse our regexps.
|
||||||
|
$ENV{LC_ALL} = "C";
|
||||||
|
|
||||||
|
my $mail_headers;
|
||||||
|
my $release_type;
|
||||||
|
my $package_name;
|
||||||
|
my $prev_version;
|
||||||
|
my $curr_version;
|
||||||
|
my $gpg_key_id;
|
||||||
|
my @url_dir_list;
|
||||||
|
my @news_file;
|
||||||
|
my $bootstrap_tools;
|
||||||
|
my $gnulib_version;
|
||||||
|
my $print_checksums_p = 1;
|
||||||
|
my $gpg_key_email;
|
||||||
|
my $gpg_keyring_url;
|
||||||
|
|
||||||
|
# Reformat the warnings before displaying them.
|
||||||
|
local $SIG{__WARN__} = sub
|
||||||
|
{
|
||||||
|
my ($msg) = @_;
|
||||||
|
# Warnings from GetOptions.
|
||||||
|
$msg =~ s/Option (\w)/option --$1/;
|
||||||
|
warn "$ME: $msg";
|
||||||
|
};
|
||||||
|
|
||||||
|
GetOptions
|
||||||
|
(
|
||||||
|
'mail-headers=s' => \$mail_headers,
|
||||||
|
'release-type=s' => \$release_type,
|
||||||
|
'package-name=s' => \$package_name,
|
||||||
|
'previous-version=s' => \$prev_version,
|
||||||
|
'current-version=s' => \$curr_version,
|
||||||
|
'gpg-key-id=s' => \$gpg_key_id,
|
||||||
|
'gpg-key-email=s' => \$gpg_key_email,
|
||||||
|
'gpg-keyring-url=s' => \$gpg_keyring_url,
|
||||||
|
'url-directory=s' => \@url_dir_list,
|
||||||
|
'news=s' => \@news_file,
|
||||||
|
'srcdir=s' => \$srcdir,
|
||||||
|
'bootstrap-tools=s' => \$bootstrap_tools,
|
||||||
|
'gnulib-version=s' => \$gnulib_version,
|
||||||
|
'print-checksums!' => \$print_checksums_p,
|
||||||
|
'archive-suffix=s' => \@archive_suffixes,
|
||||||
|
|
||||||
|
help => sub { usage 0 },
|
||||||
|
version =>
|
||||||
|
sub
|
||||||
|
{
|
||||||
|
print "$ME version $VERSION\n";
|
||||||
|
print "Copyright (C) $copyright_year Free Software Foundation, Inc.\n";
|
||||||
|
print "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n"
|
||||||
|
. "This is free software: you are free to change and redistribute it.\n"
|
||||||
|
. "There is NO WARRANTY, to the extent permitted by law.\n";
|
||||||
|
print "\n";
|
||||||
|
my $author = "Jim Meyering";
|
||||||
|
print "Written by $author.\n";
|
||||||
|
exit
|
||||||
|
},
|
||||||
|
) or usage 1;
|
||||||
|
|
||||||
|
my $fail = 0;
|
||||||
|
# Ensure that each required option is specified.
|
||||||
|
$release_type
|
||||||
|
or (warn "release type not specified\n"), $fail = 1;
|
||||||
|
$package_name
|
||||||
|
or (warn "package name not specified\n"), $fail = 1;
|
||||||
|
$prev_version
|
||||||
|
or (warn "previous version string not specified\n"), $fail = 1;
|
||||||
|
$curr_version
|
||||||
|
or (warn "current version string not specified\n"), $fail = 1;
|
||||||
|
$gpg_key_id
|
||||||
|
or (warn "GnuPG key ID not specified\n"), $fail = 1;
|
||||||
|
@url_dir_list
|
||||||
|
or (warn "URL directory name(s) not specified\n"), $fail = 1;
|
||||||
|
|
||||||
|
my @tool_list = split ',', $bootstrap_tools
|
||||||
|
if $bootstrap_tools;
|
||||||
|
|
||||||
|
grep (/^gnulib$/, @tool_list) ^ defined $gnulib_version
|
||||||
|
and (warn "when specifying gnulib as a tool, you must also specify\n"
|
||||||
|
. "--gnulib-version=V, where V is the result of running git describe\n"
|
||||||
|
. "in the gnulib source directory.\n"), $fail = 1;
|
||||||
|
|
||||||
|
!$release_type || exists $valid_release_types{$release_type}
|
||||||
|
or (warn "'$release_type': invalid release type\n"), $fail = 1;
|
||||||
|
|
||||||
|
@ARGV
|
||||||
|
and (warn "too many arguments:\n", join ("\n", @ARGV), "\n"),
|
||||||
|
$fail = 1;
|
||||||
|
$fail
|
||||||
|
and usage 1;
|
||||||
|
|
||||||
|
my $my_distdir = "$package_name-$curr_version";
|
||||||
|
|
||||||
|
my $xd = "$package_name-$prev_version-$curr_version.xdelta";
|
||||||
|
|
||||||
|
my @candidates = map { "$my_distdir.$_" } @archive_suffixes;
|
||||||
|
my @tarballs = grep {-f $_} @candidates;
|
||||||
|
|
||||||
|
@tarballs
|
||||||
|
or die "$ME: none of " . join(', ', @candidates) . " were found\n";
|
||||||
|
my @sizable = @tarballs;
|
||||||
|
-f $xd
|
||||||
|
and push @sizable, $xd;
|
||||||
|
my %size = sizes (@sizable);
|
||||||
|
%size
|
||||||
|
or exit 1;
|
||||||
|
|
||||||
|
my $headers = '';
|
||||||
|
if (defined $mail_headers)
|
||||||
|
{
|
||||||
|
($headers = $mail_headers) =~ s/\s+(\S+:)/\n$1/g;
|
||||||
|
$headers .= "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# The markup is escaped as <\# so that when this script is sent by
|
||||||
|
# mail (or part of a diff), Gnus is not triggered.
|
||||||
|
print <<EOF;
|
||||||
|
|
||||||
|
${headers}Subject: $my_distdir released [$release_type]
|
||||||
|
|
||||||
|
<\#secure method=pgpmime mode=sign>
|
||||||
|
|
||||||
|
FIXME: put comments here
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if (@url_dir_list == 1 && @tarballs == 1)
|
||||||
|
{
|
||||||
|
# When there's only one tarball and one URL, use a more concise form.
|
||||||
|
my $m = "$url_dir_list[0]/$tarballs[0]";
|
||||||
|
print "Here are the compressed sources and a GPG detached signature[*]:\n"
|
||||||
|
. " $m\n"
|
||||||
|
. " $m.sig\n\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_locations ("compressed sources", @url_dir_list, %size, @tarballs);
|
||||||
|
-f $xd
|
||||||
|
and print_locations ("xdelta diffs (useful? if so, "
|
||||||
|
. "please tell bug-gnulib\@gnu.org)",
|
||||||
|
@url_dir_list, %size, $xd);
|
||||||
|
my @sig_files = map { "$_.sig" } @tarballs;
|
||||||
|
print_locations ("GPG detached signatures[*]", @url_dir_list, %size,
|
||||||
|
@sig_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($url_dir_list[0] =~ "gnu\.org")
|
||||||
|
{
|
||||||
|
print "Use a mirror for higher download bandwidth:\n";
|
||||||
|
if (@tarballs == 1 && $url_dir_list[0] =~ m!https://ftp\.gnu\.org/gnu/!)
|
||||||
|
{
|
||||||
|
(my $m = "$url_dir_list[0]/$tarballs[0]")
|
||||||
|
=~ s!https://ftp\.gnu\.org/gnu/!https://ftpmirror\.gnu\.org/!;
|
||||||
|
print " $m\n"
|
||||||
|
. " $m.sig\n\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print " https://www.gnu.org/order/ftp.html\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$print_checksums_p
|
||||||
|
and print_checksums (@sizable);
|
||||||
|
|
||||||
|
print <<EOF;
|
||||||
|
[*] Use a .sig file to verify that the corresponding file (without the
|
||||||
|
.sig suffix) is intact. First, be sure to download both the .sig file
|
||||||
|
and the corresponding tarball. Then, run a command like this:
|
||||||
|
|
||||||
|
gpg --verify $tarballs[0].sig
|
||||||
|
|
||||||
|
If that command fails because you don't have the required public key,
|
||||||
|
or that public key has expired, try the following commands to update
|
||||||
|
or refresh it, and then rerun the 'gpg --verify' command.
|
||||||
|
EOF
|
||||||
|
if ($gpg_key_email) {
|
||||||
|
print <<EOF;
|
||||||
|
|
||||||
|
gpg --locate-external-key $gpg_key_email
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
print <<EOF;
|
||||||
|
|
||||||
|
gpg --recv-keys $gpg_key_id
|
||||||
|
EOF
|
||||||
|
if ($gpg_keyring_url) {
|
||||||
|
print <<EOF;
|
||||||
|
|
||||||
|
wget -q -O- '$gpg_keyring_url' | gpg --import -
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
my @tool_versions = get_tool_versions (\@tool_list, $gnulib_version);
|
||||||
|
@tool_versions
|
||||||
|
and print "\nThis release was bootstrapped with the following tools:",
|
||||||
|
join ('', map {"\n $_"} @tool_versions), "\n";
|
||||||
|
|
||||||
|
print_news_deltas ($_, $prev_version, $curr_version)
|
||||||
|
foreach @news_file;
|
||||||
|
|
||||||
|
$release_type eq 'stable'
|
||||||
|
or print_changelog_deltas ($package_name, $prev_version);
|
||||||
|
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
### Setup "GNU" style for perl-mode and cperl-mode.
|
||||||
|
## Local Variables:
|
||||||
|
## mode: perl
|
||||||
|
## perl-indent-level: 2
|
||||||
|
## perl-continued-statement-offset: 2
|
||||||
|
## perl-continued-brace-offset: 0
|
||||||
|
## perl-brace-offset: 0
|
||||||
|
## perl-brace-imaginary-offset: 0
|
||||||
|
## perl-label-offset: -2
|
||||||
|
## perl-extra-newline-before-brace: t
|
||||||
|
## perl-merge-trailing-else: nil
|
||||||
|
## eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
## time-stamp-line-limit: 50
|
||||||
|
## time-stamp-start: "my $VERSION = '"
|
||||||
|
## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
|
||||||
|
## time-stamp-time-zone: "UTC0"
|
||||||
|
## time-stamp-end: "'; # UTC"
|
||||||
|
## End:
|
||||||
348
build-aux/compile
Executable file
348
build-aux/compile
Executable file
@ -0,0 +1,348 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||||
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
|
#
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
|
||||||
|
# We need space, tab and new line, in precisely that order. Quoting is
|
||||||
|
# there to prevent tools from complaining about whitespace usage.
|
||||||
|
IFS=" "" $nl"
|
||||||
|
|
||||||
|
file_conv=
|
||||||
|
|
||||||
|
# func_file_conv build_file lazy
|
||||||
|
# Convert a $build file to $host form and store it in $file
|
||||||
|
# Currently only supports Windows hosts. If the determined conversion
|
||||||
|
# type is listed in (the comma separated) LAZY, no conversion will
|
||||||
|
# take place.
|
||||||
|
func_file_conv ()
|
||||||
|
{
|
||||||
|
file=$1
|
||||||
|
case $file in
|
||||||
|
/ | /[!/]*) # absolute file, and not a UNC file
|
||||||
|
if test -z "$file_conv"; then
|
||||||
|
# lazily determine how to convert abs files
|
||||||
|
case `uname -s` in
|
||||||
|
MINGW*)
|
||||||
|
file_conv=mingw
|
||||||
|
;;
|
||||||
|
CYGWIN* | MSYS*)
|
||||||
|
file_conv=cygwin
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
file_conv=wine
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case $file_conv/,$2, in
|
||||||
|
*,$file_conv,*)
|
||||||
|
;;
|
||||||
|
mingw/*)
|
||||||
|
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||||
|
;;
|
||||||
|
cygwin/* | msys/*)
|
||||||
|
file=`cygpath -m "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
wine/*)
|
||||||
|
file=`winepath -w "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashL linkdir
|
||||||
|
# Make cl look for libraries in LINKDIR
|
||||||
|
func_cl_dashL ()
|
||||||
|
{
|
||||||
|
func_file_conv "$1"
|
||||||
|
if test -z "$lib_path"; then
|
||||||
|
lib_path=$file
|
||||||
|
else
|
||||||
|
lib_path="$lib_path;$file"
|
||||||
|
fi
|
||||||
|
linker_opts="$linker_opts -LIBPATH:$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashl library
|
||||||
|
# Do a library search-path lookup for cl
|
||||||
|
func_cl_dashl ()
|
||||||
|
{
|
||||||
|
lib=$1
|
||||||
|
found=no
|
||||||
|
save_IFS=$IFS
|
||||||
|
IFS=';'
|
||||||
|
for dir in $lib_path $LIB
|
||||||
|
do
|
||||||
|
IFS=$save_IFS
|
||||||
|
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.dll.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/$lib.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/lib$lib.a"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/lib$lib.a
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$save_IFS
|
||||||
|
|
||||||
|
if test "$found" != yes; then
|
||||||
|
lib=$lib.lib
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_wrapper cl arg...
|
||||||
|
# Adjust compile command to suit cl
|
||||||
|
func_cl_wrapper ()
|
||||||
|
{
|
||||||
|
# Assume a capable shell
|
||||||
|
lib_path=
|
||||||
|
shared=:
|
||||||
|
linker_opts=
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.[oO][bB][jJ])
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fo"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fe"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-I)
|
||||||
|
eat=1
|
||||||
|
func_file_conv "$2" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-I*)
|
||||||
|
func_file_conv "${1#-I}" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashl "$2"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l*)
|
||||||
|
func_cl_dashl "${1#-l}"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-L)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashL "$2"
|
||||||
|
;;
|
||||||
|
-L*)
|
||||||
|
func_cl_dashL "${1#-L}"
|
||||||
|
;;
|
||||||
|
-static)
|
||||||
|
shared=false
|
||||||
|
;;
|
||||||
|
-Wl,*)
|
||||||
|
arg=${1#-Wl,}
|
||||||
|
save_ifs="$IFS"; IFS=','
|
||||||
|
for flag in $arg; do
|
||||||
|
IFS="$save_ifs"
|
||||||
|
linker_opts="$linker_opts $flag"
|
||||||
|
done
|
||||||
|
IFS="$save_ifs"
|
||||||
|
;;
|
||||||
|
-Xlinker)
|
||||||
|
eat=1
|
||||||
|
linker_opts="$linker_opts $2"
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||||
|
func_file_conv "$1"
|
||||||
|
set x "$@" -Tp"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||||
|
func_file_conv "$1" mingw
|
||||||
|
set x "$@" "$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if test -n "$linker_opts"; then
|
||||||
|
linker_opts="-link$linker_opts"
|
||||||
|
fi
|
||||||
|
exec "$@" $linker_opts
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
eat=
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||||
|
arguments, and rename the output as expected.
|
||||||
|
|
||||||
|
If you are trying to build a whole package this is not the
|
||||||
|
right script to run: please start by reading the file 'INSTALL'.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "compile $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||||
|
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||||
|
func_cl_wrapper "$@" # Doesn't return...
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ofile=
|
||||||
|
cfile=
|
||||||
|
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
# So we strip '-o arg' only if arg is an object.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.obj)
|
||||||
|
ofile=$2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" -o "$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*.c)
|
||||||
|
cfile=$1
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -z "$ofile" || test -z "$cfile"; then
|
||||||
|
# If no '-o' option was seen then we might have been invoked from a
|
||||||
|
# pattern rule where we don't need one. That is ok -- this is a
|
||||||
|
# normal compilation that the losing compiler can handle. If no
|
||||||
|
# '.c' file was seen then we are probably linking. That is also
|
||||||
|
# ok.
|
||||||
|
exec "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Name of file we expect compiler to create.
|
||||||
|
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||||
|
|
||||||
|
# Create the lock directory.
|
||||||
|
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||||
|
# that we are using for the .o file. Also, base the name on the expected
|
||||||
|
# object file name, since that is what matters with a parallel build.
|
||||||
|
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||||
|
while true; do
|
||||||
|
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
# FIXME: race condition here if user kills between mkdir and trap.
|
||||||
|
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||||
|
|
||||||
|
# Run the compile.
|
||||||
|
"$@"
|
||||||
|
ret=$?
|
||||||
|
|
||||||
|
if test -f "$cofile"; then
|
||||||
|
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||||
|
elif test -f "${cofile}bj"; then
|
||||||
|
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rmdir "$lockdir"
|
||||||
|
exit $ret
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
1754
build-aux/config.guess
vendored
Executable file
1754
build-aux/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
684
build-aux/config.rpath
Executable file
684
build-aux/config.rpath
Executable file
@ -0,0 +1,684 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Output a system dependent set of variables, describing how to set the
|
||||||
|
# run time search path of shared libraries in an executable.
|
||||||
|
#
|
||||||
|
# Copyright 1996-2022 Free Software Foundation, Inc.
|
||||||
|
# Taken from GNU libtool, 2001
|
||||||
|
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
#
|
||||||
|
# The first argument passed to this file is the canonical host specification,
|
||||||
|
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
|
||||||
|
# or
|
||||||
|
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||||
|
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
|
||||||
|
# should be set by the caller.
|
||||||
|
#
|
||||||
|
# The set of defined variables is at the end of this script.
|
||||||
|
|
||||||
|
# Known limitations:
|
||||||
|
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
|
||||||
|
# than 256 bytes, otherwise the compiler driver will dump core. The only
|
||||||
|
# known workaround is to choose shorter directory names for the build
|
||||||
|
# directory and/or the installation directory.
|
||||||
|
|
||||||
|
# All known linkers require a '.a' archive for static linking (except MSVC,
|
||||||
|
# which needs '.lib').
|
||||||
|
libext=a
|
||||||
|
shrext=.so
|
||||||
|
|
||||||
|
host="$1"
|
||||||
|
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
|
||||||
|
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
|
||||||
|
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_CC_BASENAME.
|
||||||
|
|
||||||
|
for cc_temp in $CC""; do
|
||||||
|
case $cc_temp in
|
||||||
|
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
|
||||||
|
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
|
||||||
|
\-*) ;;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_COMPILER_PIC.
|
||||||
|
|
||||||
|
wl=
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
wl='-Wl,'
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
aix*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
mingw* | cygwin* | pw32* | os2* | cegcc*)
|
||||||
|
;;
|
||||||
|
hpux9* | hpux10* | hpux11*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
linux* | k*bsd*-gnu | kopensolaris*-gnu)
|
||||||
|
case $cc_basename in
|
||||||
|
ecc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
icc* | ifort*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
lf95*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
nagfor*)
|
||||||
|
wl='-Wl,-Wl,,'
|
||||||
|
;;
|
||||||
|
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
ccc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
xl* | bgxl* | bgf* | mpixl*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
como)
|
||||||
|
wl='-lopt='
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case `$CC -V 2>&1 | sed 5q` in
|
||||||
|
*Sun\ F* | *Sun*Fortran*)
|
||||||
|
wl=
|
||||||
|
;;
|
||||||
|
*Sun\ C*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
;;
|
||||||
|
*nto* | *qnx*)
|
||||||
|
;;
|
||||||
|
osf3* | osf4* | osf5*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
rdos*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
case $cc_basename in
|
||||||
|
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
|
||||||
|
wl='-Qoption ld '
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
wl='-Qoption ld '
|
||||||
|
;;
|
||||||
|
sysv4 | sysv4.2uw2* | sysv4.3*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
;;
|
||||||
|
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
unicos*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
|
||||||
|
|
||||||
|
hardcode_libdir_flag_spec=
|
||||||
|
hardcode_libdir_separator=
|
||||||
|
hardcode_direct=no
|
||||||
|
hardcode_minus_L=no
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
# FIXME: the MSVC++ port hasn't been tested in a loooong time
|
||||||
|
# When not using gcc, we currently assume that we are using
|
||||||
|
# Microsoft Visual C++.
|
||||||
|
if test "$GCC" != yes; then
|
||||||
|
with_gnu_ld=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
interix*)
|
||||||
|
# we just hope/assume this is gcc and not c89 (= MSVC++)
|
||||||
|
with_gnu_ld=yes
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
with_gnu_ld=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ld_shlibs=yes
|
||||||
|
if test "$with_gnu_ld" = yes; then
|
||||||
|
# Set some defaults for GNU ld with shared library support. These
|
||||||
|
# are reset later if shared libraries are not supported. Putting them
|
||||||
|
# here allows them to be overridden if necessary.
|
||||||
|
# Unlike libtool, we use -rpath here, not --rpath, since the documented
|
||||||
|
# option of GNU ld is called -rpath, not --rpath.
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
case "$host_os" in
|
||||||
|
aix[3-9]*)
|
||||||
|
# On AIX/PPC, the GNU linker is very broken
|
||||||
|
if test "$host_cpu" != ia64; then
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
case "$host_cpu" in
|
||||||
|
powerpc)
|
||||||
|
;;
|
||||||
|
m68k)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
beos*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||||
|
# no search path for DLLs.
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
haiku*)
|
||||||
|
;;
|
||||||
|
interix[3-9]*)
|
||||||
|
hardcode_direct=no
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
;;
|
||||||
|
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
|
||||||
|
ld_shlibs=no
|
||||||
|
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
|
||||||
|
case `$LD -v 2>&1` in
|
||||||
|
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if test "$ld_shlibs" = no; then
|
||||||
|
hardcode_libdir_flag_spec=
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
aix3*)
|
||||||
|
# Note: this linker hardcodes the directories in LIBPATH if there
|
||||||
|
# are no directories specified by -L.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
# Neither direct hardcoding nor static linking is supported with a
|
||||||
|
# broken collect2.
|
||||||
|
hardcode_direct=unsupported
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
aix[4-9]*)
|
||||||
|
if test "$host_cpu" = ia64; then
|
||||||
|
# On IA64, the linker does run time linking by default, so we don't
|
||||||
|
# have to do anything special.
|
||||||
|
aix_use_runtimelinking=no
|
||||||
|
else
|
||||||
|
aix_use_runtimelinking=no
|
||||||
|
# Test if we are trying to use run time linking or normal
|
||||||
|
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
|
||||||
|
# need to do runtime linking.
|
||||||
|
case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
|
||||||
|
for ld_flag in $LDFLAGS; do
|
||||||
|
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
|
||||||
|
aix_use_runtimelinking=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_libdir_separator=':'
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
case $host_os in aix4.[012]|aix4.[012].*)
|
||||||
|
collect2name=`${CC} -print-prog-name=collect2`
|
||||||
|
if test -f "$collect2name" && \
|
||||||
|
strings "$collect2name" | grep resolve_lib_name >/dev/null
|
||||||
|
then
|
||||||
|
# We have reworked collect2
|
||||||
|
:
|
||||||
|
else
|
||||||
|
# We have old collect2
|
||||||
|
hardcode_direct=unsupported
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_libdir_separator=
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
# Begin _LT_AC_SYS_LIBPATH_AIX.
|
||||||
|
echo 'int main () { return 0; }' > conftest.c
|
||||||
|
${CC} ${LDFLAGS} conftest.c -o conftest
|
||||||
|
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||||
|
}'`
|
||||||
|
if test -z "$aix_libpath"; then
|
||||||
|
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||||
|
}'`
|
||||||
|
fi
|
||||||
|
if test -z "$aix_libpath"; then
|
||||||
|
aix_libpath="/usr/lib:/lib"
|
||||||
|
fi
|
||||||
|
rm -f conftest.c conftest
|
||||||
|
# End _LT_AC_SYS_LIBPATH_AIX.
|
||||||
|
if test "$aix_use_runtimelinking" = yes; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||||
|
else
|
||||||
|
if test "$host_cpu" = ia64; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
|
||||||
|
else
|
||||||
|
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
case "$host_cpu" in
|
||||||
|
powerpc)
|
||||||
|
;;
|
||||||
|
m68k)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
bsdi[45]*)
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
# When not using gcc, we currently assume that we are using
|
||||||
|
# Microsoft Visual C++.
|
||||||
|
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||||
|
# no search path for DLLs.
|
||||||
|
hardcode_libdir_flag_spec=' '
|
||||||
|
libext=lib
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody*)
|
||||||
|
hardcode_direct=no
|
||||||
|
if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
dgux*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
;;
|
||||||
|
freebsd2.[01]*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
freebsd* | dragonfly* | midnightbsd*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
hpux9*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
hardcode_direct=yes
|
||||||
|
# hardcode_minus_L: Not really in the search PATH,
|
||||||
|
# but as the default location of the library.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
hpux10*)
|
||||||
|
if test "$with_gnu_ld" = no; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
hardcode_direct=yes
|
||||||
|
# hardcode_minus_L: Not really in the search PATH,
|
||||||
|
# but as the default location of the library.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
hpux11*)
|
||||||
|
if test "$with_gnu_ld" = no; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
case $host_cpu in
|
||||||
|
hppa*64*|ia64*)
|
||||||
|
hardcode_direct=no
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
# hardcode_minus_L: Not really in the search PATH,
|
||||||
|
# but as the default location of the library.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
*nto* | *qnx*)
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
if test -f /usr/libexec/ld.so; then
|
||||||
|
hardcode_direct=yes
|
||||||
|
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
os2*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
osf3*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
osf4* | osf5*)
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
else
|
||||||
|
# Both cc and cxx compiler support -rpath directly
|
||||||
|
hardcode_libdir_flag_spec='-rpath $libdir'
|
||||||
|
fi
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
sysv4)
|
||||||
|
case $host_vendor in
|
||||||
|
sni)
|
||||||
|
hardcode_direct=yes # is this really true???
|
||||||
|
;;
|
||||||
|
siemens)
|
||||||
|
hardcode_direct=no
|
||||||
|
;;
|
||||||
|
motorola)
|
||||||
|
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sysv4.3*)
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
if test -d /usr/nec; then
|
||||||
|
ld_shlibs=yes
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6*)
|
||||||
|
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
|
||||||
|
hardcode_libdir_separator=':'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check dynamic linker characteristics
|
||||||
|
# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
|
||||||
|
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
|
||||||
|
# only about the one the linker finds when passed -lNAME. This is the last
|
||||||
|
# element of library_names_spec in libtool.m4, or possibly two of them if the
|
||||||
|
# linker has special search rules.
|
||||||
|
library_names_spec= # the last element of library_names_spec in libtool.m4
|
||||||
|
libname_spec='lib$name'
|
||||||
|
case "$host_os" in
|
||||||
|
aix3*)
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
aix[4-9]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
case "$host_cpu" in
|
||||||
|
powerpc*)
|
||||||
|
library_names_spec='$libname$shrext' ;;
|
||||||
|
m68k)
|
||||||
|
library_names_spec='$libname.a' ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
beos*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
bsdi[45]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
shrext=.dll
|
||||||
|
library_names_spec='$libname.dll.a $libname.lib'
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody*)
|
||||||
|
shrext=.dylib
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
dgux*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
freebsd[23].*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
freebsd* | dragonfly* | midnightbsd*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
gnu*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
haiku*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
hpux9* | hpux10* | hpux11*)
|
||||||
|
case $host_cpu in
|
||||||
|
ia64*)
|
||||||
|
shrext=.so
|
||||||
|
;;
|
||||||
|
hppa*64*)
|
||||||
|
shrext=.sl
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
shrext=.sl
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
interix[3-9]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
case "$host_os" in
|
||||||
|
irix5* | nonstopux*)
|
||||||
|
libsuff= shlibsuff=
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case $LD in
|
||||||
|
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
|
||||||
|
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
|
||||||
|
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
|
||||||
|
*) libsuff= shlibsuff= ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
linux*oldld* | linux*aout* | linux*coff*)
|
||||||
|
;;
|
||||||
|
linux* | k*bsd*-gnu | kopensolaris*-gnu)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
knetbsd*-gnu)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
*nto* | *qnx*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
os2*)
|
||||||
|
libname_spec='$name'
|
||||||
|
shrext=.dll
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
osf3* | osf4* | osf5*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
rdos*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
sysv4 | sysv4.3*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
tpf*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
|
||||||
|
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
|
||||||
|
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
|
||||||
|
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
|
||||||
|
|
||||||
|
# How to pass a linker flag through the compiler.
|
||||||
|
wl="$escaped_wl"
|
||||||
|
|
||||||
|
# Static library suffix (normally "a").
|
||||||
|
libext="$libext"
|
||||||
|
|
||||||
|
# Shared library suffix (normally "so").
|
||||||
|
shlibext="$shlibext"
|
||||||
|
|
||||||
|
# Format of library name prefix.
|
||||||
|
libname_spec="$escaped_libname_spec"
|
||||||
|
|
||||||
|
# Library names that the linker finds when passed -lNAME.
|
||||||
|
library_names_spec="$escaped_library_names_spec"
|
||||||
|
|
||||||
|
# Flag to hardcode \$libdir into a binary during linking.
|
||||||
|
# This must work even if \$libdir does not exist.
|
||||||
|
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
|
||||||
|
|
||||||
|
# Whether we need a single -rpath flag with a separated argument.
|
||||||
|
hardcode_libdir_separator="$hardcode_libdir_separator"
|
||||||
|
|
||||||
|
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
|
||||||
|
# resulting binary.
|
||||||
|
hardcode_direct="$hardcode_direct"
|
||||||
|
|
||||||
|
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
|
||||||
|
# resulting binary.
|
||||||
|
hardcode_minus_L="$hardcode_minus_L"
|
||||||
|
|
||||||
|
EOF
|
||||||
1890
build-aux/config.sub
vendored
Executable file
1890
build-aux/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
790
build-aux/depcomp
Executable file
790
build-aux/depcomp
Executable file
@ -0,0 +1,790 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# depcomp - compile a program generating dependencies as side-effects
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2022 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||||
|
as side-effects.
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
depmode Dependency tracking mode.
|
||||||
|
source Source file read by 'PROGRAMS ARGS'.
|
||||||
|
object Object file output by 'PROGRAMS ARGS'.
|
||||||
|
DEPDIR directory where to store dependencies.
|
||||||
|
depfile Dependency file to output.
|
||||||
|
tmpdepfile Temporary file to use when outputting dependencies.
|
||||||
|
libtool Whether libtool is used (yes/no).
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "depcomp $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Get the directory component of the given path, and save it in the
|
||||||
|
# global variables '$dir'. Note that this directory component will
|
||||||
|
# be either empty or ending with a '/' character. This is deliberate.
|
||||||
|
set_dir_from ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||||
|
*) dir=;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the suffix-stripped basename of the given path, and save it the
|
||||||
|
# global variable '$base'.
|
||||||
|
set_base_from ()
|
||||||
|
{
|
||||||
|
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||||
|
}
|
||||||
|
|
||||||
|
# If no dependency file was actually created by the compiler invocation,
|
||||||
|
# we still have to create a dummy depfile, to avoid errors with the
|
||||||
|
# Makefile "include basename.Plo" scheme.
|
||||||
|
make_dummy_depfile ()
|
||||||
|
{
|
||||||
|
echo "#dummy" > "$depfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Factor out some common post-processing of the generated depfile.
|
||||||
|
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||||
|
aix_post_process_depfile ()
|
||||||
|
{
|
||||||
|
# If the compiler actually managed to produce a dependency file,
|
||||||
|
# post-process it.
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
# Each line is of the form 'foo.o: dependency.h'.
|
||||||
|
# Do two passes, one to just change these to
|
||||||
|
# $object: dependency.h
|
||||||
|
# and one to simply output
|
||||||
|
# dependency.h:
|
||||||
|
# which is needed to avoid the deleted-header problem.
|
||||||
|
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||||
|
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||||
|
} > "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# A tabulation character.
|
||||||
|
tab=' '
|
||||||
|
# A newline character.
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
# Character ranges might be problematic outside the C locale.
|
||||||
|
# These definitions help.
|
||||||
|
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||||
|
lower=abcdefghijklmnopqrstuvwxyz
|
||||||
|
alpha=${upper}${lower}
|
||||||
|
|
||||||
|
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||||
|
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||||
|
depfile=${depfile-`echo "$object" |
|
||||||
|
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||||
|
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||||
|
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
|
||||||
|
# Avoid interferences from the environment.
|
||||||
|
gccflag= dashmflag=
|
||||||
|
|
||||||
|
# Some modes work just like other modes, but use different flags. We
|
||||||
|
# parameterize here, but still list the modes in the big case below,
|
||||||
|
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||||
|
# here, because this file can only contain one case statement.
|
||||||
|
if test "$depmode" = hp; then
|
||||||
|
# HP compiler uses -M and no extra arg.
|
||||||
|
gccflag=-M
|
||||||
|
depmode=gcc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = dashXmstdout; then
|
||||||
|
# This is just like dashmstdout with a different argument.
|
||||||
|
dashmflag=-xM
|
||||||
|
depmode=dashmstdout
|
||||||
|
fi
|
||||||
|
|
||||||
|
cygpath_u="cygpath -u -f -"
|
||||||
|
if test "$depmode" = msvcmsys; then
|
||||||
|
# This is just like msvisualcpp but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u='sed s,\\\\,/,g'
|
||||||
|
depmode=msvisualcpp
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = msvc7msys; then
|
||||||
|
# This is just like msvc7 but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u='sed s,\\\\,/,g'
|
||||||
|
depmode=msvc7
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = xlc; then
|
||||||
|
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||||
|
gccflag=-qmakedep=gcc,-MF
|
||||||
|
depmode=gcc
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$depmode" in
|
||||||
|
gcc3)
|
||||||
|
## gcc 3 implements dependency tracking that does exactly what
|
||||||
|
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||||
|
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||||
|
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||||
|
## the command line argument order; so add the flags where they
|
||||||
|
## appear in depend2.am. Note that the slowdown incurred here
|
||||||
|
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||||
|
*) set fnord "$@" "$arg" ;;
|
||||||
|
esac
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
done
|
||||||
|
"$@"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
mv "$tmpdepfile" "$depfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
gcc)
|
||||||
|
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||||
|
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||||
|
## (see the conditional assignment to $gccflag above).
|
||||||
|
## There are various ways to get dependency output from gcc. Here's
|
||||||
|
## why we pick this rather obscure method:
|
||||||
|
## - Don't want to use -MD because we'd like the dependencies to end
|
||||||
|
## up in a subdir. Having to rename by hand is ugly.
|
||||||
|
## (We might end up doing this anyway to support other compilers.)
|
||||||
|
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||||
|
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||||
|
## supported by the other compilers which use the 'gcc' depmode.
|
||||||
|
## - Using -M directly means running the compiler twice (even worse
|
||||||
|
## than renaming).
|
||||||
|
if test -z "$gccflag"; then
|
||||||
|
gccflag=-MD,
|
||||||
|
fi
|
||||||
|
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# The second -e expression handles DOS-style file names with drive
|
||||||
|
# letters.
|
||||||
|
sed -e 's/^[^:]*: / /' \
|
||||||
|
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||||
|
## This next piece of magic avoids the "deleted header file" problem.
|
||||||
|
## The problem is that when a header file which appears in a .P file
|
||||||
|
## is deleted, the dependency causes make to die (because there is
|
||||||
|
## typically no way to rebuild the header). We avoid this by adding
|
||||||
|
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||||
|
## this for us directly.
|
||||||
|
## Some versions of gcc put a space before the ':'. On the theory
|
||||||
|
## that the space means something, we add a space to the output as
|
||||||
|
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||||
|
## to the object. Take care to not repeat it in the output.
|
||||||
|
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||||
|
## correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
sgi)
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||||
|
else
|
||||||
|
"$@" -MDupdate "$tmpdepfile"
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
|
||||||
|
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# Clip off the initial element (the dependent). Don't try to be
|
||||||
|
# clever and replace this with sed code, as IRIX sed won't handle
|
||||||
|
# lines with more than a fixed number of characters (4096 in
|
||||||
|
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||||
|
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||||
|
# dependency line.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||||
|
| tr "$nl" ' ' >> "$depfile"
|
||||||
|
echo >> "$depfile"
|
||||||
|
# The second pass generates a dummy entry for each header file.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||||
|
>> "$depfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
xlc)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
aix)
|
||||||
|
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||||
|
# in a .u file. In older versions, this file always lives in the
|
||||||
|
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||||
|
# start of each line; $object doesn't have directory information.
|
||||||
|
# Version 6 uses the directory in both cases.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$base.u
|
||||||
|
tmpdepfile3=$dir.libs/$base.u
|
||||||
|
"$@" -Wc,-M
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$dir$base.u
|
||||||
|
tmpdepfile3=$dir$base.u
|
||||||
|
"$@" -M
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
aix_post_process_depfile
|
||||||
|
;;
|
||||||
|
|
||||||
|
tcc)
|
||||||
|
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||||
|
# FIXME: That version still under development at the moment of writing.
|
||||||
|
# Make that this statement remains true also for stable, released
|
||||||
|
# versions.
|
||||||
|
# It will wrap lines (doesn't matter whether long or short) with a
|
||||||
|
# trailing '\', as in:
|
||||||
|
#
|
||||||
|
# foo.o : \
|
||||||
|
# foo.c \
|
||||||
|
# foo.h \
|
||||||
|
#
|
||||||
|
# It will put a trailing '\' even on the last line, and will use leading
|
||||||
|
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||||
|
# "Emit spaces for -MD").
|
||||||
|
"$@" -MD -MF "$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||||
|
# We have to change lines of the first kind to '$object: \'.
|
||||||
|
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||||
|
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||||
|
# dummy dependency, to avoid the deleted-header problem.
|
||||||
|
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
## The order of this option in the case statement is important, since the
|
||||||
|
## shell code in configure will try each of these formats in the order
|
||||||
|
## listed in this file. A plain '-MD' option would be understood by many
|
||||||
|
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||||
|
pgcc)
|
||||||
|
# Portland's C compiler understands '-MD'.
|
||||||
|
# Will always output deps to 'file.d' where file is the root name of the
|
||||||
|
# source file under compilation, even if file resides in a subdirectory.
|
||||||
|
# The object file name does not affect the name of the '.d' file.
|
||||||
|
# pgcc 10.2 will output
|
||||||
|
# foo.o: sub/foo.c sub/foo.h
|
||||||
|
# and will wrap long lines using '\' :
|
||||||
|
# foo.o: sub/foo.c ... \
|
||||||
|
# sub/foo.h ... \
|
||||||
|
# ...
|
||||||
|
set_dir_from "$object"
|
||||||
|
# Use the source, not the object, to determine the base name, since
|
||||||
|
# that's sadly what pgcc will do too.
|
||||||
|
set_base_from "$source"
|
||||||
|
tmpdepfile=$base.d
|
||||||
|
|
||||||
|
# For projects that build the same source file twice into different object
|
||||||
|
# files, the pgcc approach of using the *source* file root name can cause
|
||||||
|
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||||
|
# the same $tmpdepfile.
|
||||||
|
lockdir=$base.d-lock
|
||||||
|
trap "
|
||||||
|
echo '$0: caught signal, cleaning up...' >&2
|
||||||
|
rmdir '$lockdir'
|
||||||
|
exit 1
|
||||||
|
" 1 2 13 15
|
||||||
|
numtries=100
|
||||||
|
i=$numtries
|
||||||
|
while test $i -gt 0; do
|
||||||
|
# mkdir is a portable test-and-set.
|
||||||
|
if mkdir "$lockdir" 2>/dev/null; then
|
||||||
|
# This process acquired the lock.
|
||||||
|
"$@" -MD
|
||||||
|
stat=$?
|
||||||
|
# Release the lock.
|
||||||
|
rmdir "$lockdir"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
# If the lock is being held by a different process, wait
|
||||||
|
# until the winning process is done or we timeout.
|
||||||
|
while test -d "$lockdir" && test $i -gt 0; do
|
||||||
|
sleep 1
|
||||||
|
i=`expr $i - 1`
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
i=`expr $i - 1`
|
||||||
|
done
|
||||||
|
trap - 1 2 13 15
|
||||||
|
if test $i -le 0; then
|
||||||
|
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||||
|
echo "$0: check lockdir '$lockdir'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
# Each line is of the form `foo.o: dependent.h',
|
||||||
|
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||||
|
# Do two passes, one to just change these to
|
||||||
|
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||||
|
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp2)
|
||||||
|
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||||
|
# compilers, which have integrated preprocessors. The correct option
|
||||||
|
# to use with these is +Maked; it writes dependencies to a file named
|
||||||
|
# 'foo.d', which lands next to the object file, wherever that
|
||||||
|
# happens to be.
|
||||||
|
# Much of this is similar to the tru64 case; see comments there.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir.libs/$base.d
|
||||||
|
"$@" -Wc,+Maked
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
"$@" +Maked
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||||
|
# Add 'dependent.h:' lines.
|
||||||
|
sed -ne '2,${
|
||||||
|
s/^ *//
|
||||||
|
s/ \\*$//
|
||||||
|
s/$/:/
|
||||||
|
p
|
||||||
|
}' "$tmpdepfile" >> "$depfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||||
|
;;
|
||||||
|
|
||||||
|
tru64)
|
||||||
|
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||||
|
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||||
|
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||||
|
# dependencies in 'foo.d' instead, so we check for that too.
|
||||||
|
# Subdirectories are respected.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||||
|
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||||
|
# in $dir$base.o.d. We have to check for both files, because
|
||||||
|
# one of the two compilations can be disabled. We should prefer
|
||||||
|
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||||
|
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||||
|
# the former would cause a distcleancheck panic.
|
||||||
|
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||||
|
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||||
|
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||||
|
"$@" -Wc,-MD
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
tmpdepfile3=$dir$base.d
|
||||||
|
"$@" -MD
|
||||||
|
fi
|
||||||
|
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
# Same post-processing that is required for AIX mode.
|
||||||
|
aix_post_process_depfile
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvc7)
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
showIncludes=-Wc,-showIncludes
|
||||||
|
else
|
||||||
|
showIncludes=-showIncludes
|
||||||
|
fi
|
||||||
|
"$@" $showIncludes > "$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# The first sed program below extracts the file names and escapes
|
||||||
|
# backslashes for cygpath. The second sed program outputs the file
|
||||||
|
# name when reading, but also accumulates all include files in the
|
||||||
|
# hold buffer in order to output them again at the end. This only
|
||||||
|
# works with sed implementations that can handle large buffers.
|
||||||
|
sed < "$tmpdepfile" -n '
|
||||||
|
/^Note: including file: *\(.*\)/ {
|
||||||
|
s//\1/
|
||||||
|
s/\\/\\\\/g
|
||||||
|
p
|
||||||
|
}' | $cygpath_u | sort -u | sed -n '
|
||||||
|
s/ /\\ /g
|
||||||
|
s/\(.*\)/'"$tab"'\1 \\/p
|
||||||
|
s/.\(.*\) \\/\1:/
|
||||||
|
H
|
||||||
|
$ {
|
||||||
|
s/.*/'"$tab"'/
|
||||||
|
G
|
||||||
|
p
|
||||||
|
}' >> "$depfile"
|
||||||
|
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvc7msys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
#nosideeffect)
|
||||||
|
# This comment above is used by automake to tell side-effect
|
||||||
|
# dependency tracking mechanisms from slower ones.
|
||||||
|
|
||||||
|
dashmstdout)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout, regardless of -o.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove '-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
test -z "$dashmflag" && dashmflag=-M
|
||||||
|
# Require at least two characters before searching for ':'
|
||||||
|
# in the target name. This is to cope with DOS-style filenames:
|
||||||
|
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||||
|
"$@" $dashmflag |
|
||||||
|
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
cat < "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
dashXmstdout)
|
||||||
|
# This case only exists to satisfy depend.m4. It is never actually
|
||||||
|
# run, as this mode is specially recognized in the preamble.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
makedepend)
|
||||||
|
"$@" || exit $?
|
||||||
|
# Remove any Libtool call
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
# X makedepend
|
||||||
|
shift
|
||||||
|
cleared=no eat=no
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $cleared in
|
||||||
|
no)
|
||||||
|
set ""; shift
|
||||||
|
cleared=yes ;;
|
||||||
|
esac
|
||||||
|
if test $eat = yes; then
|
||||||
|
eat=no
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$arg" in
|
||||||
|
-D*|-I*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
# Strip any option that makedepend may not understand. Remove
|
||||||
|
# the object too, otherwise makedepend will parse it as a source file.
|
||||||
|
-arch)
|
||||||
|
eat=yes ;;
|
||||||
|
-*|$object)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||||
|
touch "$tmpdepfile"
|
||||||
|
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||||
|
rm -f "$depfile"
|
||||||
|
# makedepend may prepend the VPATH from the source file name to the object.
|
||||||
|
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||||
|
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
sed '1,2d' "$tmpdepfile" \
|
||||||
|
| tr ' ' "$nl" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||||
|
;;
|
||||||
|
|
||||||
|
cpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove '-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
"$@" -E \
|
||||||
|
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
cat < "$tmpdepfile" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvisualcpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case "$arg" in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||||
|
set fnord "$@"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
"$@" -E 2>/dev/null |
|
||||||
|
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||||
|
echo "$tab" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvcmsys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
none)
|
||||||
|
exec "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown depmode $depmode" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
510
build-aux/gendocs.sh
Executable file
510
build-aux/gendocs.sh
Executable file
@ -0,0 +1,510 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
# gendocs.sh -- generate a GNU manual in many formats. This script is
|
||||||
|
# mentioned in maintain.texi. See the help message below for usage details.
|
||||||
|
|
||||||
|
scriptversion=2022-01-01.00
|
||||||
|
|
||||||
|
# Copyright 2003-2022 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/>.
|
||||||
|
#
|
||||||
|
# Original author: Mohit Agarwal.
|
||||||
|
# Send bug reports and any other correspondence to bug-gnulib@gnu.org.
|
||||||
|
#
|
||||||
|
# The latest version of this script, and the companion template, is
|
||||||
|
# available from the Gnulib repository:
|
||||||
|
#
|
||||||
|
# https://git.savannah.gnu.org/cgit/gnulib.git/tree/build-aux/gendocs.sh
|
||||||
|
# https://git.savannah.gnu.org/cgit/gnulib.git/tree/doc/gendocs_template
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# - image importing was only implemented for HTML generated by
|
||||||
|
# makeinfo. But it should be simple enough to adjust.
|
||||||
|
# - images are not imported in the source tarball. All the needed
|
||||||
|
# formats (PDF, PNG, etc.) should be included.
|
||||||
|
|
||||||
|
prog=`basename "$0"`
|
||||||
|
srcdir=`pwd`
|
||||||
|
|
||||||
|
scripturl="https://git.savannah.gnu.org/cgit/gnulib.git/plain/build-aux/gendocs.sh"
|
||||||
|
templateurl="https://git.savannah.gnu.org/cgit/gnulib.git/plain/doc/gendocs_template"
|
||||||
|
|
||||||
|
: ${SETLANG="env LANG= LC_MESSAGES= LC_ALL= LANGUAGE="}
|
||||||
|
: ${MAKEINFO="makeinfo"}
|
||||||
|
: ${TEXI2DVI="texi2dvi"}
|
||||||
|
: ${DOCBOOK2HTML="docbook2html"}
|
||||||
|
: ${DOCBOOK2PDF="docbook2pdf"}
|
||||||
|
: ${DOCBOOK2TXT="docbook2txt"}
|
||||||
|
: ${GENDOCS_TEMPLATE_DIR="."}
|
||||||
|
: ${PERL='perl'}
|
||||||
|
: ${TEXI2HTML="texi2html"}
|
||||||
|
unset CDPATH
|
||||||
|
unset use_texi2html
|
||||||
|
|
||||||
|
MANUAL_TITLE=
|
||||||
|
PACKAGE=
|
||||||
|
EMAIL=webmasters@gnu.org # please override with --email
|
||||||
|
commonarg= # passed to all makeinfo/texi2html invcations.
|
||||||
|
dirargs= # passed to all tools (-I dir).
|
||||||
|
dirs= # -I directories.
|
||||||
|
htmlarg="--css-ref=https://www.gnu.org/software/gnulib/manual.css -c TOP_NODE_UP_URL=/manual"
|
||||||
|
default_htmlarg=true
|
||||||
|
infoarg=--no-split
|
||||||
|
generate_ascii=true
|
||||||
|
generate_html=true
|
||||||
|
generate_info=true
|
||||||
|
generate_tex=true
|
||||||
|
outdir=manual
|
||||||
|
source_extra=
|
||||||
|
split=node
|
||||||
|
srcfile=
|
||||||
|
texarg="-t @finalout"
|
||||||
|
|
||||||
|
version="gendocs.sh $scriptversion
|
||||||
|
|
||||||
|
Copyright 2022 Free Software Foundation, Inc.
|
||||||
|
There is NO warranty. You may redistribute this software
|
||||||
|
under the terms of the GNU General Public License.
|
||||||
|
For more information about these matters, see the files named COPYING."
|
||||||
|
|
||||||
|
usage="Usage: $prog [OPTION]... PACKAGE MANUAL-TITLE
|
||||||
|
|
||||||
|
Generate output in various formats from PACKAGE.texinfo (or .texi or
|
||||||
|
.txi) source. See the GNU Maintainers document for a more extensive
|
||||||
|
discussion:
|
||||||
|
https://www.gnu.org/prep/maintain_toc.html
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--email ADR use ADR as contact in generated web pages; always give this.
|
||||||
|
|
||||||
|
-s SRCFILE read Texinfo from SRCFILE, instead of PACKAGE.{texinfo|texi|txi}
|
||||||
|
-o OUTDIR write files into OUTDIR, instead of manual/.
|
||||||
|
-I DIR append DIR to the Texinfo search path.
|
||||||
|
--common ARG pass ARG in all invocations.
|
||||||
|
--html ARG pass ARG to makeinfo or texi2html for HTML targets,
|
||||||
|
instead of '$htmlarg'.
|
||||||
|
--info ARG pass ARG to makeinfo for Info, instead of --no-split.
|
||||||
|
--no-ascii skip generating the plain text output.
|
||||||
|
--no-html skip generating the html output.
|
||||||
|
--no-info skip generating the info output.
|
||||||
|
--no-tex skip generating the dvi and pdf output.
|
||||||
|
--source ARG include ARG in tar archive of sources.
|
||||||
|
--split HOW make split HTML by node, section, chapter; default node.
|
||||||
|
--tex ARG pass ARG to texi2dvi for DVI and PDF, instead of -t @finalout.
|
||||||
|
|
||||||
|
--texi2html use texi2html to make HTML target, with all split versions.
|
||||||
|
--docbook convert through DocBook too (xml, txt, html, pdf).
|
||||||
|
|
||||||
|
--help display this help and exit successfully.
|
||||||
|
--version display version information and exit successfully.
|
||||||
|
|
||||||
|
Simple example: $prog --email bug-gnu-emacs@gnu.org emacs \"GNU Emacs Manual\"
|
||||||
|
|
||||||
|
Typical sequence:
|
||||||
|
cd PACKAGESOURCE/doc
|
||||||
|
wget \"$scripturl\"
|
||||||
|
wget \"$templateurl\"
|
||||||
|
$prog --email BUGLIST MANUAL \"GNU MANUAL - One-line description\"
|
||||||
|
|
||||||
|
Output will be in a new subdirectory \"manual\" (by default;
|
||||||
|
use -o OUTDIR to override). Move all the new files into your web CVS
|
||||||
|
tree, as explained in the Web Pages node of maintain.texi.
|
||||||
|
|
||||||
|
Please use the --email ADDRESS option so your own bug-reporting
|
||||||
|
address will be used in the generated HTML pages.
|
||||||
|
|
||||||
|
MANUAL-TITLE is included as part of the HTML <title> of the overall
|
||||||
|
manual/index.html file. It should include the name of the package being
|
||||||
|
documented. manual/index.html is created by substitution from the file
|
||||||
|
$GENDOCS_TEMPLATE_DIR/gendocs_template. (Feel free to modify the
|
||||||
|
generic template for your own purposes.)
|
||||||
|
|
||||||
|
If you have several manuals, you'll need to run this script several
|
||||||
|
times with different MANUAL values, specifying a different output
|
||||||
|
directory with -o each time. Then write (by hand) an overall index.html
|
||||||
|
with links to them all.
|
||||||
|
|
||||||
|
If a manual's Texinfo sources are spread across several directories,
|
||||||
|
first copy or symlink all Texinfo sources into a single directory.
|
||||||
|
(Part of the script's work is to make a tar.gz of the sources.)
|
||||||
|
|
||||||
|
As implied above, by default monolithic Info files are generated.
|
||||||
|
If you want split Info, or other Info options, use --info to override.
|
||||||
|
|
||||||
|
You can set the environment variables MAKEINFO, TEXI2DVI, TEXI2HTML,
|
||||||
|
and PERL to control the programs that get executed, and
|
||||||
|
GENDOCS_TEMPLATE_DIR to control where the gendocs_template file is
|
||||||
|
looked for. With --docbook, the environment variables DOCBOOK2HTML,
|
||||||
|
DOCBOOK2PDF, and DOCBOOK2TXT are also consulted.
|
||||||
|
|
||||||
|
By default, makeinfo and texi2dvi are run in the default (English)
|
||||||
|
locale, since that's the language of most Texinfo manuals. If you
|
||||||
|
happen to have a non-English manual and non-English web site, see the
|
||||||
|
SETLANG setting in the source.
|
||||||
|
|
||||||
|
Email bug reports or enhancement requests to bug-gnulib@gnu.org.
|
||||||
|
"
|
||||||
|
|
||||||
|
while test $# -gt 0; do
|
||||||
|
case $1 in
|
||||||
|
-s) shift; srcfile=$1;;
|
||||||
|
-o) shift; outdir=$1;;
|
||||||
|
-I) shift; dirargs="$dirargs -I '$1'"; dirs="$dirs $1";;
|
||||||
|
--common) shift; commonarg=$1;;
|
||||||
|
--docbook) docbook=yes;;
|
||||||
|
--email) shift; EMAIL=$1;;
|
||||||
|
--html) shift; default_htmlarg=false; htmlarg=$1;;
|
||||||
|
--info) shift; infoarg=$1;;
|
||||||
|
--no-ascii) generate_ascii=false;;
|
||||||
|
--no-html) generate_ascii=false;;
|
||||||
|
--no-info) generate_info=false;;
|
||||||
|
--no-tex) generate_tex=false;;
|
||||||
|
--source) shift; source_extra=$1;;
|
||||||
|
--split) shift; split=$1;;
|
||||||
|
--tex) shift; texarg=$1;;
|
||||||
|
--texi2html) use_texi2html=1;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit 0;;
|
||||||
|
--version) echo "$version"; exit 0;;
|
||||||
|
-*)
|
||||||
|
echo "$0: Unknown option \`$1'." >&2
|
||||||
|
echo "$0: Try \`--help' for more information." >&2
|
||||||
|
exit 1;;
|
||||||
|
*)
|
||||||
|
if test -z "$PACKAGE"; then
|
||||||
|
PACKAGE=$1
|
||||||
|
elif test -z "$MANUAL_TITLE"; then
|
||||||
|
MANUAL_TITLE=$1
|
||||||
|
else
|
||||||
|
echo "$0: extra non-option argument \`$1'." >&2
|
||||||
|
exit 1
|
||||||
|
fi;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# makeinfo uses the dirargs, but texi2dvi doesn't.
|
||||||
|
commonarg=" $dirargs $commonarg"
|
||||||
|
|
||||||
|
# For most of the following, the base name is just $PACKAGE
|
||||||
|
base=$PACKAGE
|
||||||
|
|
||||||
|
if $default_htmlarg && test -n "$use_texi2html"; then
|
||||||
|
# The legacy texi2html doesn't support TOP_NODE_UP_URL
|
||||||
|
htmlarg="--css-ref=https://www.gnu.org/software/gnulib/manual.css"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$srcfile"; then
|
||||||
|
# but here, we use the basename of $srcfile
|
||||||
|
base=`basename "$srcfile"`
|
||||||
|
case $base in
|
||||||
|
*.txi|*.texi|*.texinfo) base=`echo "$base"|sed 's/\.[texinfo]*$//'`;;
|
||||||
|
esac
|
||||||
|
PACKAGE=$base
|
||||||
|
elif test -s "$srcdir/$PACKAGE.texinfo"; then
|
||||||
|
srcfile=$srcdir/$PACKAGE.texinfo
|
||||||
|
elif test -s "$srcdir/$PACKAGE.texi"; then
|
||||||
|
srcfile=$srcdir/$PACKAGE.texi
|
||||||
|
elif test -s "$srcdir/$PACKAGE.txi"; then
|
||||||
|
srcfile=$srcdir/$PACKAGE.txi
|
||||||
|
else
|
||||||
|
echo "$0: cannot find .texinfo or .texi or .txi for $PACKAGE in $srcdir." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test ! -r $GENDOCS_TEMPLATE_DIR/gendocs_template; then
|
||||||
|
echo "$0: cannot read $GENDOCS_TEMPLATE_DIR/gendocs_template." >&2
|
||||||
|
echo "$0: it is available from $templateurl." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to return size of $1 in something resembling kilobytes.
|
||||||
|
calcsize()
|
||||||
|
{
|
||||||
|
size=`ls -ksl $1 | awk '{print $1}'`
|
||||||
|
echo $size
|
||||||
|
}
|
||||||
|
|
||||||
|
# copy_images OUTDIR HTML-FILE...
|
||||||
|
# -------------------------------
|
||||||
|
# Copy all the images needed by the HTML-FILEs into OUTDIR.
|
||||||
|
# Look for them in . and the -I directories; this is simpler than what
|
||||||
|
# makeinfo supports with -I, but hopefully it will suffice.
|
||||||
|
copy_images()
|
||||||
|
{
|
||||||
|
local odir
|
||||||
|
odir=$1
|
||||||
|
shift
|
||||||
|
$PERL -n -e "
|
||||||
|
BEGIN {
|
||||||
|
\$me = '$prog';
|
||||||
|
\$odir = '$odir';
|
||||||
|
@dirs = qw(. $dirs);
|
||||||
|
}
|
||||||
|
" -e '
|
||||||
|
/<img src="(.*?)"/g && ++$need{$1};
|
||||||
|
|
||||||
|
END {
|
||||||
|
#print "$me: @{[keys %need]}\n"; # for debugging, show images found.
|
||||||
|
FILE: for my $f (keys %need) {
|
||||||
|
for my $d (@dirs) {
|
||||||
|
if (-f "$d/$f") {
|
||||||
|
use File::Basename;
|
||||||
|
my $dest = dirname ("$odir/$f");
|
||||||
|
#
|
||||||
|
use File::Path;
|
||||||
|
-d $dest || mkpath ($dest)
|
||||||
|
|| die "$me: cannot mkdir $dest: $!\n";
|
||||||
|
#
|
||||||
|
use File::Copy;
|
||||||
|
copy ("$d/$f", $dest)
|
||||||
|
|| die "$me: cannot copy $d/$f to $dest: $!\n";
|
||||||
|
next FILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die "$me: $ARGV: cannot find image $f\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' -- "$@" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
case $outdir in
|
||||||
|
/*) abs_outdir=$outdir;;
|
||||||
|
*) abs_outdir=$srcdir/$outdir;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "Making output for $srcfile"
|
||||||
|
echo " in `pwd`"
|
||||||
|
mkdir -p "$outdir/"
|
||||||
|
|
||||||
|
#
|
||||||
|
if $generate_info; then
|
||||||
|
cmd="$SETLANG $MAKEINFO -o $PACKAGE.info $commonarg $infoarg \"$srcfile\""
|
||||||
|
echo "Generating info... ($cmd)"
|
||||||
|
rm -f $PACKAGE.info* # get rid of any strays
|
||||||
|
eval "$cmd"
|
||||||
|
tar czf "$outdir/$PACKAGE.info.tar.gz" $PACKAGE.info*
|
||||||
|
ls -l "$outdir/$PACKAGE.info.tar.gz"
|
||||||
|
info_tgz_size=`calcsize "$outdir/$PACKAGE.info.tar.gz"`
|
||||||
|
# do not mv the info files, there's no point in having them available
|
||||||
|
# separately on the web.
|
||||||
|
fi # end info
|
||||||
|
|
||||||
|
#
|
||||||
|
if $generate_tex; then
|
||||||
|
cmd="$SETLANG $TEXI2DVI $dirargs $texarg \"$srcfile\""
|
||||||
|
printf "\nGenerating dvi... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
# compress/finish dvi:
|
||||||
|
gzip -f -9 $PACKAGE.dvi
|
||||||
|
dvi_gz_size=`calcsize $PACKAGE.dvi.gz`
|
||||||
|
mv $PACKAGE.dvi.gz "$outdir/"
|
||||||
|
ls -l "$outdir/$PACKAGE.dvi.gz"
|
||||||
|
|
||||||
|
cmd="$SETLANG $TEXI2DVI --pdf $dirargs $texarg \"$srcfile\""
|
||||||
|
printf "\nGenerating pdf... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
pdf_size=`calcsize $PACKAGE.pdf`
|
||||||
|
mv $PACKAGE.pdf "$outdir/"
|
||||||
|
ls -l "$outdir/$PACKAGE.pdf"
|
||||||
|
fi # end tex (dvi + pdf)
|
||||||
|
|
||||||
|
#
|
||||||
|
if $generate_ascii; then
|
||||||
|
opt="-o $PACKAGE.txt --no-split --no-headers $commonarg"
|
||||||
|
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
|
||||||
|
printf "\nGenerating ascii... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
ascii_size=`calcsize $PACKAGE.txt`
|
||||||
|
gzip -f -9 -c $PACKAGE.txt >"$outdir/$PACKAGE.txt.gz"
|
||||||
|
ascii_gz_size=`calcsize "$outdir/$PACKAGE.txt.gz"`
|
||||||
|
mv $PACKAGE.txt "$outdir/"
|
||||||
|
ls -l "$outdir/$PACKAGE.txt" "$outdir/$PACKAGE.txt.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
if $generate_html; then
|
||||||
|
# Split HTML at level $1. Used for texi2html.
|
||||||
|
html_split()
|
||||||
|
{
|
||||||
|
opt="--split=$1 --node-files $commonarg $htmlarg"
|
||||||
|
cmd="$SETLANG $TEXI2HTML --output $PACKAGE.html $opt \"$srcfile\""
|
||||||
|
printf "\nGenerating html by $1... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
split_html_dir=$PACKAGE.html
|
||||||
|
(
|
||||||
|
cd ${split_html_dir} || exit 1
|
||||||
|
ln -sf ${PACKAGE}.html index.html
|
||||||
|
tar -czf "$abs_outdir/${PACKAGE}.html_$1.tar.gz" -- *.html
|
||||||
|
)
|
||||||
|
eval html_$1_tgz_size=`calcsize "$outdir/${PACKAGE}.html_$1.tar.gz"`
|
||||||
|
rm -f "$outdir"/html_$1/*.html
|
||||||
|
mkdir -p "$outdir/html_$1/"
|
||||||
|
mv ${split_html_dir}/*.html "$outdir/html_$1/"
|
||||||
|
rmdir ${split_html_dir}
|
||||||
|
}
|
||||||
|
|
||||||
|
if test -z "$use_texi2html"; then
|
||||||
|
opt="--no-split --html -o $PACKAGE.html $commonarg $htmlarg"
|
||||||
|
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
|
||||||
|
printf "\nGenerating monolithic html... ($cmd)\n"
|
||||||
|
rm -rf $PACKAGE.html # in case a directory is left over
|
||||||
|
eval "$cmd"
|
||||||
|
html_mono_size=`calcsize $PACKAGE.html`
|
||||||
|
gzip -f -9 -c $PACKAGE.html >"$outdir/$PACKAGE.html.gz"
|
||||||
|
html_mono_gz_size=`calcsize "$outdir/$PACKAGE.html.gz"`
|
||||||
|
copy_images "$outdir/" $PACKAGE.html
|
||||||
|
mv $PACKAGE.html "$outdir/"
|
||||||
|
ls -l "$outdir/$PACKAGE.html" "$outdir/$PACKAGE.html.gz"
|
||||||
|
|
||||||
|
# Before Texinfo 5.0, makeinfo did not accept a --split=HOW option,
|
||||||
|
# it just always split by node. So if we're splitting by node anyway,
|
||||||
|
# leave it out.
|
||||||
|
if test "x$split" = xnode; then
|
||||||
|
split_arg=
|
||||||
|
else
|
||||||
|
split_arg=--split=$split
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
opt="--html -o $PACKAGE.html $split_arg $commonarg $htmlarg"
|
||||||
|
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
|
||||||
|
printf "\nGenerating html by $split... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
split_html_dir=$PACKAGE.html
|
||||||
|
copy_images $split_html_dir/ $split_html_dir/*.html
|
||||||
|
(
|
||||||
|
cd $split_html_dir || exit 1
|
||||||
|
tar -czf "$abs_outdir/$PACKAGE.html_$split.tar.gz" -- *
|
||||||
|
)
|
||||||
|
eval \
|
||||||
|
html_${split}_tgz_size=`calcsize "$outdir/$PACKAGE.html_$split.tar.gz"`
|
||||||
|
rm -rf "$outdir/html_$split/"
|
||||||
|
mv $split_html_dir "$outdir/html_$split/"
|
||||||
|
du -s "$outdir/html_$split/"
|
||||||
|
ls -l "$outdir/$PACKAGE.html_$split.tar.gz"
|
||||||
|
|
||||||
|
else # use texi2html:
|
||||||
|
opt="--output $PACKAGE.html $commonarg $htmlarg"
|
||||||
|
cmd="$SETLANG $TEXI2HTML $opt \"$srcfile\""
|
||||||
|
printf "\nGenerating monolithic html with texi2html... ($cmd)\n"
|
||||||
|
rm -rf $PACKAGE.html # in case a directory is left over
|
||||||
|
eval "$cmd"
|
||||||
|
html_mono_size=`calcsize $PACKAGE.html`
|
||||||
|
gzip -f -9 -c $PACKAGE.html >"$outdir/$PACKAGE.html.gz"
|
||||||
|
html_mono_gz_size=`calcsize "$outdir/$PACKAGE.html.gz"`
|
||||||
|
mv $PACKAGE.html "$outdir/"
|
||||||
|
|
||||||
|
html_split node
|
||||||
|
html_split chapter
|
||||||
|
html_split section
|
||||||
|
fi
|
||||||
|
fi # end html
|
||||||
|
|
||||||
|
#
|
||||||
|
printf "\nMaking .tar.gz for sources...\n"
|
||||||
|
d=`dirname $srcfile`
|
||||||
|
(
|
||||||
|
cd "$d"
|
||||||
|
srcfiles=`ls -d *.texinfo *.texi *.txi *.eps $source_extra 2>/dev/null` || true
|
||||||
|
tar czfh "$abs_outdir/$PACKAGE.texi.tar.gz" $srcfiles
|
||||||
|
ls -l "$abs_outdir/$PACKAGE.texi.tar.gz"
|
||||||
|
)
|
||||||
|
texi_tgz_size=`calcsize "$outdir/$PACKAGE.texi.tar.gz"`
|
||||||
|
|
||||||
|
#
|
||||||
|
# Do everything again through docbook.
|
||||||
|
if test -n "$docbook"; then
|
||||||
|
opt="-o - --docbook $commonarg"
|
||||||
|
cmd="$SETLANG $MAKEINFO $opt \"$srcfile\" >${srcdir}/$PACKAGE-db.xml"
|
||||||
|
printf "\nGenerating docbook XML... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
docbook_xml_size=`calcsize $PACKAGE-db.xml`
|
||||||
|
gzip -f -9 -c $PACKAGE-db.xml >"$outdir/$PACKAGE-db.xml.gz"
|
||||||
|
docbook_xml_gz_size=`calcsize "$outdir/$PACKAGE-db.xml.gz"`
|
||||||
|
mv $PACKAGE-db.xml "$outdir/"
|
||||||
|
|
||||||
|
split_html_db_dir=html_node_db
|
||||||
|
opt="$commonarg -o $split_html_db_dir"
|
||||||
|
cmd="$DOCBOOK2HTML $opt \"${outdir}/$PACKAGE-db.xml\""
|
||||||
|
printf "\nGenerating docbook HTML... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
(
|
||||||
|
cd ${split_html_db_dir} || exit 1
|
||||||
|
tar -czf "$abs_outdir/${PACKAGE}.html_node_db.tar.gz" -- *.html
|
||||||
|
)
|
||||||
|
html_node_db_tgz_size=`calcsize "$outdir/${PACKAGE}.html_node_db.tar.gz"`
|
||||||
|
rm -f "$outdir"/html_node_db/*.html
|
||||||
|
mkdir -p "$outdir/html_node_db"
|
||||||
|
mv ${split_html_db_dir}/*.html "$outdir/html_node_db/"
|
||||||
|
rmdir ${split_html_db_dir}
|
||||||
|
|
||||||
|
cmd="$DOCBOOK2TXT \"${outdir}/$PACKAGE-db.xml\""
|
||||||
|
printf "\nGenerating docbook ASCII... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
docbook_ascii_size=`calcsize $PACKAGE-db.txt`
|
||||||
|
mv $PACKAGE-db.txt "$outdir/"
|
||||||
|
|
||||||
|
cmd="$DOCBOOK2PDF \"${outdir}/$PACKAGE-db.xml\""
|
||||||
|
printf "\nGenerating docbook PDF... ($cmd)\n"
|
||||||
|
eval "$cmd"
|
||||||
|
docbook_pdf_size=`calcsize $PACKAGE-db.pdf`
|
||||||
|
mv $PACKAGE-db.pdf "$outdir/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
printf "\nMaking index.html for $PACKAGE...\n"
|
||||||
|
if test -z "$use_texi2html"; then
|
||||||
|
CONDS="/%%IF *HTML_SECTION%%/,/%%ENDIF *HTML_SECTION%%/d;\
|
||||||
|
/%%IF *HTML_CHAPTER%%/,/%%ENDIF *HTML_CHAPTER%%/d"
|
||||||
|
else
|
||||||
|
# should take account of --split here.
|
||||||
|
CONDS="/%%ENDIF.*%%/d;/%%IF *HTML_SECTION%%/d;/%%IF *HTML_CHAPTER%%/d"
|
||||||
|
fi
|
||||||
|
|
||||||
|
curdate=`$SETLANG date '+%B %d, %Y'`
|
||||||
|
sed \
|
||||||
|
-e "s!%%TITLE%%!$MANUAL_TITLE!g" \
|
||||||
|
-e "s!%%EMAIL%%!$EMAIL!g" \
|
||||||
|
-e "s!%%PACKAGE%%!$PACKAGE!g" \
|
||||||
|
-e "s!%%DATE%%!$curdate!g" \
|
||||||
|
-e "s!%%HTML_MONO_SIZE%%!$html_mono_size!g" \
|
||||||
|
-e "s!%%HTML_MONO_GZ_SIZE%%!$html_mono_gz_size!g" \
|
||||||
|
-e "s!%%HTML_NODE_TGZ_SIZE%%!$html_node_tgz_size!g" \
|
||||||
|
-e "s!%%HTML_SECTION_TGZ_SIZE%%!$html_section_tgz_size!g" \
|
||||||
|
-e "s!%%HTML_CHAPTER_TGZ_SIZE%%!$html_chapter_tgz_size!g" \
|
||||||
|
-e "s!%%INFO_TGZ_SIZE%%!$info_tgz_size!g" \
|
||||||
|
-e "s!%%DVI_GZ_SIZE%%!$dvi_gz_size!g" \
|
||||||
|
-e "s!%%PDF_SIZE%%!$pdf_size!g" \
|
||||||
|
-e "s!%%ASCII_SIZE%%!$ascii_size!g" \
|
||||||
|
-e "s!%%ASCII_GZ_SIZE%%!$ascii_gz_size!g" \
|
||||||
|
-e "s!%%TEXI_TGZ_SIZE%%!$texi_tgz_size!g" \
|
||||||
|
-e "s!%%DOCBOOK_HTML_NODE_TGZ_SIZE%%!$html_node_db_tgz_size!g" \
|
||||||
|
-e "s!%%DOCBOOK_ASCII_SIZE%%!$docbook_ascii_size!g" \
|
||||||
|
-e "s!%%DOCBOOK_PDF_SIZE%%!$docbook_pdf_size!g" \
|
||||||
|
-e "s!%%DOCBOOK_XML_SIZE%%!$docbook_xml_size!g" \
|
||||||
|
-e "s!%%DOCBOOK_XML_GZ_SIZE%%!$docbook_xml_gz_size!g" \
|
||||||
|
-e "s,%%SCRIPTURL%%,$scripturl,g" \
|
||||||
|
-e "s!%%SCRIPTNAME%%!$prog!g" \
|
||||||
|
-e "$CONDS" \
|
||||||
|
$GENDOCS_TEMPLATE_DIR/gendocs_template >"$outdir/index.html"
|
||||||
|
|
||||||
|
echo "Done, see $outdir/ subdirectory for new files."
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-end: "$"
|
||||||
|
# End:
|
||||||
480
build-aux/gnupload
Executable file
480
build-aux/gnupload
Executable file
@ -0,0 +1,480 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Sign files and upload them.
|
||||||
|
|
||||||
|
scriptversion=2022-01-27.18; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 2004-2022 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 2, 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/>.
|
||||||
|
|
||||||
|
# Originally written by Alexandre Duret-Lutz <adl@gnu.org>.
|
||||||
|
# The master copy of this file is maintained in the gnulib Git repository.
|
||||||
|
# Please send bug reports and feature requests to bug-gnulib@gnu.org.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
GPG=gpg
|
||||||
|
# Choose the proper version of gpg, so as to avoid a
|
||||||
|
# "gpg-agent is not available in this session" error
|
||||||
|
# when gpg-agent is version 2 but gpg is still version 1.
|
||||||
|
# FIXME-2020: remove, once all major distros ship gpg version 2 as /usr/bin/gpg
|
||||||
|
gpg_agent_version=`(gpg-agent --version) 2>/dev/null | sed -e '2,$d' -e 's/^[^0-9]*//'`
|
||||||
|
case "$gpg_agent_version" in
|
||||||
|
2.*)
|
||||||
|
gpg_version=`(gpg --version) 2>/dev/null | sed -e '2,$d' -e 's/^[^0-9]*//'`
|
||||||
|
case "$gpg_version" in
|
||||||
|
1.*)
|
||||||
|
if (type gpg2) >/dev/null 2>/dev/null; then
|
||||||
|
# gpg2 is present.
|
||||||
|
GPG=gpg2
|
||||||
|
else
|
||||||
|
# gpg2 is missing. Ubuntu users should install the package 'gnupg2'.
|
||||||
|
echo "WARNING: Using 'gpg', which is too old. You should install 'gpg2'." 1>&2
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
GPG="${GPG} --batch --no-tty"
|
||||||
|
conffile=.gnuploadrc
|
||||||
|
to=
|
||||||
|
dry_run=false
|
||||||
|
replace=
|
||||||
|
symlink_files=
|
||||||
|
delete_files=
|
||||||
|
delete_symlinks=
|
||||||
|
collect_var=
|
||||||
|
dbg=
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
|
||||||
|
usage="Usage: $0 [OPTION]... [CMD] FILE... [[CMD] FILE...]
|
||||||
|
|
||||||
|
Sign all FILES, and process them at the destinations specified with --to.
|
||||||
|
If CMD is not given, it defaults to uploading. See examples below.
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
--delete delete FILES from destination
|
||||||
|
--symlink create symbolic links
|
||||||
|
--rmsymlink remove symbolic links
|
||||||
|
-- treat the remaining arguments as files to upload
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--to DEST specify a destination DEST for FILES
|
||||||
|
(multiple --to options are allowed)
|
||||||
|
--user NAME sign with key NAME
|
||||||
|
--replace allow replacements of existing files
|
||||||
|
--symlink-regex[=EXPR] use sed script EXPR to compute symbolic link names
|
||||||
|
-n, --dry-run do nothing, show what would have been done
|
||||||
|
(including the constructed directive file)
|
||||||
|
--version output version information and exit
|
||||||
|
-h, --help print this help text and exit
|
||||||
|
|
||||||
|
If --symlink-regex is given without EXPR, then the link target name
|
||||||
|
is created by replacing the version information with '-latest', e.g.:
|
||||||
|
foo-1.3.4.tar.gz -> foo-latest.tar.gz
|
||||||
|
|
||||||
|
Recognized destinations are:
|
||||||
|
alpha.gnu.org:DIRECTORY
|
||||||
|
savannah.gnu.org:DIRECTORY
|
||||||
|
savannah.nongnu.org:DIRECTORY
|
||||||
|
ftp.gnu.org:DIRECTORY
|
||||||
|
build directive files and upload files by FTP
|
||||||
|
download.gnu.org.ua:{alpha|ftp}/DIRECTORY
|
||||||
|
build directive files and upload files by SFTP
|
||||||
|
[user@]host:DIRECTORY upload files with scp
|
||||||
|
|
||||||
|
Options and commands are applied in order. If the file $conffile exists
|
||||||
|
in the current working directory, its contents are prepended to the
|
||||||
|
actual command line options. Use this to keep your defaults. Comments
|
||||||
|
(#) and empty lines in $conffile are allowed.
|
||||||
|
|
||||||
|
<https://www.gnu.org/prep/maintain/html_node/Automated-FTP-Uploads.html>
|
||||||
|
gives some further background.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
1. Upload foobar-1.0.tar.gz to ftp.gnu.org:
|
||||||
|
gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz
|
||||||
|
|
||||||
|
2. Upload foobar-1.0.tar.gz and foobar-1.0.tar.xz to ftp.gnu.org:
|
||||||
|
gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz foobar-1.0.tar.xz
|
||||||
|
|
||||||
|
3. Same as above, and also create symbolic links to foobar-latest.tar.*:
|
||||||
|
gnupload --to ftp.gnu.org:foobar \\
|
||||||
|
--symlink-regex \\
|
||||||
|
foobar-1.0.tar.gz foobar-1.0.tar.xz
|
||||||
|
|
||||||
|
4. Create a symbolic link foobar-latest.tar.gz -> foobar-1.0.tar.gz
|
||||||
|
and likewise for the corresponding .sig file:
|
||||||
|
gnupload --to ftp.gnu.org:foobar \\
|
||||||
|
--symlink foobar-1.0.tar.gz foobar-latest.tar.gz \\
|
||||||
|
foobar-1.0.tar.gz.sig foobar-latest.tar.gz.sig
|
||||||
|
or (equivalent):
|
||||||
|
gnupload --to ftp.gnu.org:foobar \\
|
||||||
|
--symlink foobar-1.0.tar.gz foobar-latest.tar.gz \\
|
||||||
|
--symlink foobar-1.0.tar.gz.sig foobar-latest.tar.gz.sig
|
||||||
|
|
||||||
|
5. Upload foobar-0.9.90.tar.gz to two sites:
|
||||||
|
gnupload --to alpha.gnu.org:foobar \\
|
||||||
|
--to sources.redhat.com:~ftp/pub/foobar \\
|
||||||
|
foobar-0.9.90.tar.gz
|
||||||
|
|
||||||
|
6. Delete oopsbar-0.9.91.tar.gz and upload foobar-0.9.91.tar.gz
|
||||||
|
(the -- terminates the list of files to delete):
|
||||||
|
gnupload --to alpha.gnu.org:foobar \\
|
||||||
|
--to sources.redhat.com:~ftp/pub/foobar \\
|
||||||
|
--delete oopsbar-0.9.91.tar.gz \\
|
||||||
|
-- foobar-0.9.91.tar.gz
|
||||||
|
|
||||||
|
gnupload executes a program ncftpput to do the transfers; if you don't
|
||||||
|
happen to have an ncftp package installed, the ncftpput-ftp script in
|
||||||
|
the build-aux/ directory of the gnulib package
|
||||||
|
(https://savannah.gnu.org/projects/gnulib) may serve as a replacement.
|
||||||
|
|
||||||
|
Send patches and bug reports to <bug-gnulib@gnu.org>."
|
||||||
|
|
||||||
|
copyright_year=`echo "$scriptversion" | sed -e 's/[^0-9].*//'`
|
||||||
|
copyright="Copyright (C) ${copyright_year} Free Software Foundation, Inc.
|
||||||
|
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl.html>.
|
||||||
|
This is free software: you are free to change and redistribute it.
|
||||||
|
There is NO WARRANTY, to the extent permitted by law."
|
||||||
|
|
||||||
|
# Read local configuration file
|
||||||
|
if test -r "$conffile"; then
|
||||||
|
echo "$0: Reading configuration file $conffile"
|
||||||
|
conf=`sed 's/#.*$//;/^$/d' "$conffile" | tr "\015$nl" ' '`
|
||||||
|
eval set x "$conf \"\$@\""
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
while test -n "$1"; do
|
||||||
|
case $1 in
|
||||||
|
-*)
|
||||||
|
collect_var=
|
||||||
|
case $1 in
|
||||||
|
-h | --help)
|
||||||
|
echo "$usage"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
--to)
|
||||||
|
if test -z "$2"; then
|
||||||
|
echo "$0: Missing argument for --to" 1>&2
|
||||||
|
exit 1
|
||||||
|
elif echo "$2" | grep 'ftp-upload\.gnu\.org' >/dev/null; then
|
||||||
|
echo "$0: Use ftp.gnu.org:PKGNAME or alpha.gnu.org:PKGNAME" >&2
|
||||||
|
echo "$0: for the destination, not ftp-upload.gnu.org (which" >&2
|
||||||
|
echo "$0: is used for direct ftp uploads, not with gnupload)." >&2
|
||||||
|
echo "$0: See --help and its examples if need be." >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
to="$to $2"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--user)
|
||||||
|
if test -z "$2"; then
|
||||||
|
echo "$0: Missing argument for --user" 1>&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
GPG="$GPG --local-user $2"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--delete)
|
||||||
|
collect_var=delete_files
|
||||||
|
;;
|
||||||
|
--replace)
|
||||||
|
replace="replace: true"
|
||||||
|
;;
|
||||||
|
--rmsymlink)
|
||||||
|
collect_var=delete_symlinks
|
||||||
|
;;
|
||||||
|
--symlink-regex=*)
|
||||||
|
symlink_expr=`expr "$1" : '[^=]*=\(.*\)'`
|
||||||
|
;;
|
||||||
|
--symlink-regex)
|
||||||
|
symlink_expr='s|-[0-9][0-9\.]*\(-[0-9][0-9]*\)\{0,1\}\.|-latest.|'
|
||||||
|
;;
|
||||||
|
--symlink)
|
||||||
|
collect_var=symlink_files
|
||||||
|
;;
|
||||||
|
-n | --dry-run)
|
||||||
|
dry_run=:
|
||||||
|
;;
|
||||||
|
--version)
|
||||||
|
echo "gnupload $scriptversion"
|
||||||
|
echo "$copyright"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
echo "$0: Unknown option '$1', try '$0 --help'" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if test -z "$collect_var"; then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
eval "$collect_var=\"\$$collect_var $1\""
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
dprint()
|
||||||
|
{
|
||||||
|
echo "Running $* ..."
|
||||||
|
}
|
||||||
|
|
||||||
|
if $dry_run; then
|
||||||
|
dbg=dprint
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$to"; then
|
||||||
|
echo "$0: Missing destination sites" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$symlink_files"; then
|
||||||
|
x=`echo "$symlink_files" | sed 's/[^ ]//g;s/ //g'`
|
||||||
|
if test -n "$x"; then
|
||||||
|
echo "$0: Odd number of symlink arguments" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# = 0; then
|
||||||
|
if test -z "${symlink_files}${delete_files}${delete_symlinks}"; then
|
||||||
|
echo "$0: No file to upload" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Make sure all files exist. We don't want to ask
|
||||||
|
# for the passphrase if the script will fail.
|
||||||
|
for file
|
||||||
|
do
|
||||||
|
if test ! -f $file; then
|
||||||
|
echo "$0: Cannot find '$file'" 1>&2
|
||||||
|
exit 1
|
||||||
|
elif test -n "$symlink_expr"; then
|
||||||
|
linkname=`echo $file | sed "$symlink_expr"`
|
||||||
|
if test -z "$linkname"; then
|
||||||
|
echo "$0: symlink expression produces empty results" >&2
|
||||||
|
exit 1
|
||||||
|
elif test "$linkname" = $file; then
|
||||||
|
echo "$0: symlink expression does not alter file name" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure passphrase is not exported in the environment.
|
||||||
|
unset passphrase
|
||||||
|
unset passphrase_fd_0
|
||||||
|
GNUPGHOME=${GNUPGHOME:-$HOME/.gnupg}
|
||||||
|
|
||||||
|
# Reset PATH to be sure that echo is a built-in. We will later use
|
||||||
|
# 'echo $passphrase' to output the passphrase, so it is important that
|
||||||
|
# it is a built-in (third-party programs tend to appear in 'ps'
|
||||||
|
# listings with their arguments...).
|
||||||
|
# Remember this script runs with 'set -e', so if echo is not built-in
|
||||||
|
# it will exit now.
|
||||||
|
if $dry_run || grep -q "^use-agent" $GNUPGHOME/gpg.conf; then :; else
|
||||||
|
PATH=/empty echo -n "Enter GPG passphrase: "
|
||||||
|
stty -echo
|
||||||
|
read -r passphrase
|
||||||
|
stty echo
|
||||||
|
echo
|
||||||
|
passphrase_fd_0="--passphrase-fd 0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -ne 0; then
|
||||||
|
for file
|
||||||
|
do
|
||||||
|
echo "Signing $file ..."
|
||||||
|
rm -f $file.sig
|
||||||
|
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 -ba -o $file.sig $file
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# mkdirective DESTDIR BASE FILE STMT
|
||||||
|
# Arguments: See upload, below
|
||||||
|
mkdirective ()
|
||||||
|
{
|
||||||
|
stmt="$4"
|
||||||
|
if test -n "$3"; then
|
||||||
|
stmt="
|
||||||
|
filename: $3$stmt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >${2}.directive<<EOF
|
||||||
|
version: 1.2
|
||||||
|
directory: $1
|
||||||
|
comment: gnupload v. $scriptversion$stmt
|
||||||
|
EOF
|
||||||
|
if $dry_run; then
|
||||||
|
echo "File ${2}.directive:"
|
||||||
|
cat ${2}.directive
|
||||||
|
echo "File ${2}.directive:" | sed 's/./-/g'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mksymlink ()
|
||||||
|
{
|
||||||
|
while test $# -ne 0
|
||||||
|
do
|
||||||
|
echo "symlink: $1 $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# upload DEST DESTDIR BASE FILE STMT FILES
|
||||||
|
# Arguments:
|
||||||
|
# DEST Destination site;
|
||||||
|
# DESTDIR Destination directory;
|
||||||
|
# BASE Base name for the directive file;
|
||||||
|
# FILE Name of the file to distribute (may be empty);
|
||||||
|
# STMT Additional statements for the directive file;
|
||||||
|
# FILES List of files to upload.
|
||||||
|
upload ()
|
||||||
|
{
|
||||||
|
dest=$1
|
||||||
|
destdir=$2
|
||||||
|
base=$3
|
||||||
|
file=$4
|
||||||
|
stmt=$5
|
||||||
|
files=$6
|
||||||
|
|
||||||
|
rm -f $base.directive $base.directive.asc
|
||||||
|
case $dest in
|
||||||
|
alpha.gnu.org:*)
|
||||||
|
mkdirective "$destdir" "$base" "$file" "$stmt"
|
||||||
|
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
|
||||||
|
$dbg ncftpput ftp-upload.gnu.org /incoming/alpha $files $base.directive.asc
|
||||||
|
;;
|
||||||
|
ftp.gnu.org:*)
|
||||||
|
mkdirective "$destdir" "$base" "$file" "$stmt"
|
||||||
|
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
|
||||||
|
$dbg ncftpput ftp-upload.gnu.org /incoming/ftp $files $base.directive.asc
|
||||||
|
;;
|
||||||
|
savannah.gnu.org:*)
|
||||||
|
if test -z "$files"; then
|
||||||
|
echo "$0: warning: standalone directives not applicable for $dest" >&2
|
||||||
|
fi
|
||||||
|
$dbg ncftpput savannah.gnu.org /incoming/savannah/$destdir $files
|
||||||
|
;;
|
||||||
|
savannah.nongnu.org:*)
|
||||||
|
if test -z "$files"; then
|
||||||
|
echo "$0: warning: standalone directives not applicable for $dest" >&2
|
||||||
|
fi
|
||||||
|
$dbg ncftpput savannah.nongnu.org /incoming/savannah/$destdir $files
|
||||||
|
;;
|
||||||
|
download.gnu.org.ua:alpha/*|download.gnu.org.ua:ftp/*)
|
||||||
|
destdir_p1=`echo "$destdir" | sed 's,^[^/]*/,,'`
|
||||||
|
destdir_topdir=`echo "$destdir" | sed 's,/.*,,'`
|
||||||
|
mkdirective "$destdir_p1" "$base" "$file" "$stmt"
|
||||||
|
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
|
||||||
|
for f in $files $base.directive.asc
|
||||||
|
do
|
||||||
|
echo put $f
|
||||||
|
done | $dbg sftp -b - puszcza.gnu.org.ua:/incoming/$destdir_topdir
|
||||||
|
;;
|
||||||
|
/*)
|
||||||
|
dest_host=`echo "$dest" | sed 's,:.*,,'`
|
||||||
|
mkdirective "$destdir" "$base" "$file" "$stmt"
|
||||||
|
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
|
||||||
|
$dbg cp $files $base.directive.asc $dest_host
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if test -z "$files"; then
|
||||||
|
echo "$0: warning: standalone directives not applicable for $dest" >&2
|
||||||
|
fi
|
||||||
|
$dbg scp $files $dest
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
rm -f $base.directive $base.directive.asc
|
||||||
|
}
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Process any standalone directives
|
||||||
|
stmt=
|
||||||
|
if test -n "$symlink_files"; then
|
||||||
|
stmt="$stmt
|
||||||
|
`mksymlink $symlink_files`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for file in $delete_files
|
||||||
|
do
|
||||||
|
stmt="$stmt
|
||||||
|
archive: $file"
|
||||||
|
done
|
||||||
|
|
||||||
|
for file in $delete_symlinks
|
||||||
|
do
|
||||||
|
stmt="$stmt
|
||||||
|
rmsymlink: $file"
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$stmt"; then
|
||||||
|
for dest in $to
|
||||||
|
do
|
||||||
|
destdir=`echo $dest | sed 's/[^:]*://'`
|
||||||
|
upload "$dest" "$destdir" "`hostname`-$$" "" "$stmt"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process actual uploads
|
||||||
|
for dest in $to
|
||||||
|
do
|
||||||
|
for file
|
||||||
|
do
|
||||||
|
echo "Uploading $file to $dest ..."
|
||||||
|
stmt=
|
||||||
|
#
|
||||||
|
# allowing file replacement is all or nothing.
|
||||||
|
if test -n "$replace"; then stmt="$stmt
|
||||||
|
$replace"
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
files="$file $file.sig"
|
||||||
|
destdir=`echo $dest | sed 's/[^:]*://'`
|
||||||
|
if test -n "$symlink_expr"; then
|
||||||
|
linkname=`echo $file | sed "$symlink_expr"`
|
||||||
|
stmt="$stmt
|
||||||
|
symlink: $file $linkname
|
||||||
|
symlink: $file.sig $linkname.sig"
|
||||||
|
fi
|
||||||
|
upload "$dest" "$destdir" "$file" "$file" "$stmt" "$files"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
541
build-aux/install-sh
Executable file
541
build-aux/install-sh
Executable file
@ -0,0 +1,541 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
|
scriptversion=2020-11-14.01; # UTC
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
|
#
|
||||||
|
# Copyright (C) 1994 X Consortium
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# 'make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch.
|
||||||
|
|
||||||
|
tab=' '
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
IFS=" $tab$nl"
|
||||||
|
|
||||||
|
# Set DOITPROG to "echo" to test this script.
|
||||||
|
|
||||||
|
doit=${DOITPROG-}
|
||||||
|
doit_exec=${doit:-exec}
|
||||||
|
|
||||||
|
# Put in absolute file names if you don't have them in your path;
|
||||||
|
# or use environment vars.
|
||||||
|
|
||||||
|
chgrpprog=${CHGRPPROG-chgrp}
|
||||||
|
chmodprog=${CHMODPROG-chmod}
|
||||||
|
chownprog=${CHOWNPROG-chown}
|
||||||
|
cmpprog=${CMPPROG-cmp}
|
||||||
|
cpprog=${CPPROG-cp}
|
||||||
|
mkdirprog=${MKDIRPROG-mkdir}
|
||||||
|
mvprog=${MVPROG-mv}
|
||||||
|
rmprog=${RMPROG-rm}
|
||||||
|
stripprog=${STRIPPROG-strip}
|
||||||
|
|
||||||
|
posix_mkdir=
|
||||||
|
|
||||||
|
# Desired mode of installed file.
|
||||||
|
mode=0755
|
||||||
|
|
||||||
|
# Create dirs (including intermediate dirs) using mode 755.
|
||||||
|
# This is like GNU 'install' as of coreutils 8.32 (2020).
|
||||||
|
mkdir_umask=22
|
||||||
|
|
||||||
|
backupsuffix=
|
||||||
|
chgrpcmd=
|
||||||
|
chmodcmd=$chmodprog
|
||||||
|
chowncmd=
|
||||||
|
mvcmd=$mvprog
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
stripcmd=
|
||||||
|
|
||||||
|
src=
|
||||||
|
dst=
|
||||||
|
dir_arg=
|
||||||
|
dst_arg=
|
||||||
|
|
||||||
|
copy_on_change=false
|
||||||
|
is_target_a_directory=possibly
|
||||||
|
|
||||||
|
usage="\
|
||||||
|
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||||
|
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||||
|
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||||
|
or: $0 [OPTION]... -d DIRECTORIES...
|
||||||
|
|
||||||
|
In the 1st form, copy SRCFILE to DSTFILE.
|
||||||
|
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||||
|
In the 4th, create DIRECTORIES.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
|
-c (ignored)
|
||||||
|
-C install only if different (preserve data modification time)
|
||||||
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrpprog installed files to GROUP.
|
||||||
|
-m MODE $chmodprog installed files to MODE.
|
||||||
|
-o USER $chownprog installed files to USER.
|
||||||
|
-p pass -p to $cpprog.
|
||||||
|
-s $stripprog installed files.
|
||||||
|
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
|
||||||
|
-t DIRECTORY install into DIRECTORY.
|
||||||
|
-T report an error if DSTFILE is a directory.
|
||||||
|
|
||||||
|
Environment variables override the default commands:
|
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||||
|
RMPROG STRIPPROG
|
||||||
|
|
||||||
|
By default, rm is invoked with -f; when overridden with RMPROG,
|
||||||
|
it's up to you to specify -f if you want it.
|
||||||
|
|
||||||
|
If -S is not specified, no backups are attempted.
|
||||||
|
|
||||||
|
Email bug reports to bug-automake@gnu.org.
|
||||||
|
Automake home page: https://www.gnu.org/software/automake/
|
||||||
|
"
|
||||||
|
|
||||||
|
while test $# -ne 0; do
|
||||||
|
case $1 in
|
||||||
|
-c) ;;
|
||||||
|
|
||||||
|
-C) copy_on_change=true;;
|
||||||
|
|
||||||
|
-d) dir_arg=true;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;;
|
||||||
|
|
||||||
|
-m) mode=$2
|
||||||
|
case $mode in
|
||||||
|
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||||
|
echo "$0: invalid mode: $mode" >&2
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-p) cpprog="$cpprog -p";;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog;;
|
||||||
|
|
||||||
|
-S) backupsuffix="$2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-t)
|
||||||
|
is_target_a_directory=always
|
||||||
|
dst_arg=$2
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-T) is_target_a_directory=never;;
|
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit $?;;
|
||||||
|
|
||||||
|
--) shift
|
||||||
|
break;;
|
||||||
|
|
||||||
|
-*) echo "$0: invalid option: $1" >&2
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# We allow the use of options -d and -T together, by making -d
|
||||||
|
# take the precedence; this is for compatibility with GNU install.
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
echo "$0: target directory not allowed when installing a directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||||
|
# When -d is used, all remaining arguments are directories to create.
|
||||||
|
# When -t is used, the destination is already specified.
|
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
# $@ is not empty: it contains at least $arg.
|
||||||
|
set fnord "$@" "$dst_arg"
|
||||||
|
shift # fnord
|
||||||
|
fi
|
||||||
|
shift # arg
|
||||||
|
dst_arg=$arg
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
echo "$0: no input file specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# It's OK to call 'install-sh -d' without argument.
|
||||||
|
# This can happen when creating conditional directories.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||||
|
if test ! -d "$dst_arg"; then
|
||||||
|
echo "$0: $dst_arg: Is not a directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
do_exit='(exit $ret); exit $ret'
|
||||||
|
trap "ret=129; $do_exit" 1
|
||||||
|
trap "ret=130; $do_exit" 2
|
||||||
|
trap "ret=141; $do_exit" 13
|
||||||
|
trap "ret=143; $do_exit" 15
|
||||||
|
|
||||||
|
# Set umask so as not to create temps with too-generous modes.
|
||||||
|
# However, 'strip' requires both read and write access to temps.
|
||||||
|
case $mode in
|
||||||
|
# Optimize common cases.
|
||||||
|
*644) cp_umask=133;;
|
||||||
|
*755) cp_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw='% 200'
|
||||||
|
fi
|
||||||
|
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||||
|
*)
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw=,u+rw
|
||||||
|
fi
|
||||||
|
cp_umask=$mode$u_plus_rw;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
for src
|
||||||
|
do
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $src in
|
||||||
|
-* | [=\(\)!]) src=./$src;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
dst=$src
|
||||||
|
dstdir=$dst
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
# Don't chown directories that already exist.
|
||||||
|
if test $dstdir_status = 0; then
|
||||||
|
chowncmd=""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
|
||||||
|
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dst_arg"; then
|
||||||
|
echo "$0: no destination specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dst=$dst_arg
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename.
|
||||||
|
if test -d "$dst"; then
|
||||||
|
if test "$is_target_a_directory" = never; then
|
||||||
|
echo "$0: $dst_arg: Is a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dstdir=$dst
|
||||||
|
dstbase=`basename "$src"`
|
||||||
|
case $dst in
|
||||||
|
*/) dst=$dst$dstbase;;
|
||||||
|
*) dst=$dst/$dstbase;;
|
||||||
|
esac
|
||||||
|
dstdir_status=0
|
||||||
|
else
|
||||||
|
dstdir=`dirname "$dst"`
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
*/) dstdirslash=$dstdir;;
|
||||||
|
*) dstdirslash=$dstdir/;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
obsolete_mkdir_used=false
|
||||||
|
|
||||||
|
if test $dstdir_status != 0; then
|
||||||
|
case $posix_mkdir in
|
||||||
|
'')
|
||||||
|
# With -d, create the new directory with the user-specified mode.
|
||||||
|
# Otherwise, rely on $mkdir_umask.
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
mkdir_mode=-m$mode
|
||||||
|
else
|
||||||
|
mkdir_mode=
|
||||||
|
fi
|
||||||
|
|
||||||
|
posix_mkdir=false
|
||||||
|
# The $RANDOM variable is not portable (e.g., dash). Use it
|
||||||
|
# here however when possible just to lower collision chance.
|
||||||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||||
|
|
||||||
|
trap '
|
||||||
|
ret=$?
|
||||||
|
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
|
||||||
|
exit $ret
|
||||||
|
' 0
|
||||||
|
|
||||||
|
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||||
|
# directly in world-writeable /tmp, make sure that the '$tmpdir'
|
||||||
|
# directory is successfully created first before we actually test
|
||||||
|
# 'mkdir -p'.
|
||||||
|
if (umask $mkdir_umask &&
|
||||||
|
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
if test -z "$dir_arg" || {
|
||||||
|
# Check for POSIX incompatibilities with -m.
|
||||||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
|
# other-writable bit of parent directory when it shouldn't.
|
||||||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
|
test_tmpdir="$tmpdir/a"
|
||||||
|
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||||
|
case $ls_ld_tmpdir in
|
||||||
|
d????-?r-*) different_mode=700;;
|
||||||
|
d????-?--*) different_mode=755;;
|
||||||
|
*) false;;
|
||||||
|
esac &&
|
||||||
|
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||||
|
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
then posix_mkdir=:
|
||||||
|
fi
|
||||||
|
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||||
|
else
|
||||||
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||||||
|
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||||
|
fi
|
||||||
|
trap '' 0;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if
|
||||||
|
$posix_mkdir && (
|
||||||
|
umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||||
|
)
|
||||||
|
then :
|
||||||
|
else
|
||||||
|
|
||||||
|
# mkdir does not conform to POSIX,
|
||||||
|
# or it failed possibly due to a race condition. Create the
|
||||||
|
# directory the slow way, step by step, checking for races as we go.
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
/*) prefix='/';;
|
||||||
|
[-=\(\)!]*) prefix='./';;
|
||||||
|
*) prefix='';;
|
||||||
|
esac
|
||||||
|
|
||||||
|
oIFS=$IFS
|
||||||
|
IFS=/
|
||||||
|
set -f
|
||||||
|
set fnord $dstdir
|
||||||
|
shift
|
||||||
|
set +f
|
||||||
|
IFS=$oIFS
|
||||||
|
|
||||||
|
prefixes=
|
||||||
|
|
||||||
|
for d
|
||||||
|
do
|
||||||
|
test X"$d" = X && continue
|
||||||
|
|
||||||
|
prefix=$prefix$d
|
||||||
|
if test -d "$prefix"; then
|
||||||
|
prefixes=
|
||||||
|
else
|
||||||
|
if $posix_mkdir; then
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
test -d "$prefix" || exit 1
|
||||||
|
else
|
||||||
|
case $prefix in
|
||||||
|
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||||
|
*) qprefix=$prefix;;
|
||||||
|
esac
|
||||||
|
prefixes="$prefixes '$qprefix'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
prefix=$prefix/
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$prefixes"; then
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||||
|
test -d "$dstdir" || exit 1
|
||||||
|
obsolete_mkdir_used=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||||
|
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||||
|
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||||
|
else
|
||||||
|
|
||||||
|
# Make a couple of temp file names in the proper directory.
|
||||||
|
dsttmp=${dstdirslash}_inst.$$_
|
||||||
|
rmtmp=${dstdirslash}_rm.$$_
|
||||||
|
|
||||||
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
|
|
||||||
|
# Copy the file name to the temp name.
|
||||||
|
(umask $cp_umask &&
|
||||||
|
{ test -z "$stripcmd" || {
|
||||||
|
# Create $dsttmp read-write so that cp doesn't create it read-only,
|
||||||
|
# which would cause strip to fail.
|
||||||
|
if test -z "$doit"; then
|
||||||
|
: >"$dsttmp" # No need to fork-exec 'touch'.
|
||||||
|
else
|
||||||
|
$doit touch "$dsttmp"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
$doit_exec $cpprog "$src" "$dsttmp") &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||||
|
|
||||||
|
# If -C, don't bother to copy if it wouldn't change the file.
|
||||||
|
if $copy_on_change &&
|
||||||
|
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||||
|
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||||
|
set -f &&
|
||||||
|
set X $old && old=:$2:$4:$5:$6 &&
|
||||||
|
set X $new && new=:$2:$4:$5:$6 &&
|
||||||
|
set +f &&
|
||||||
|
test "$old" = "$new" &&
|
||||||
|
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
rm -f "$dsttmp"
|
||||||
|
else
|
||||||
|
# If $backupsuffix is set, and the file being installed
|
||||||
|
# already exists, attempt a backup. Don't worry if it fails,
|
||||||
|
# e.g., if mv doesn't support -f.
|
||||||
|
if test -n "$backupsuffix" && test -f "$dst"; then
|
||||||
|
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Rename the file to the real destination.
|
||||||
|
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||||
|
|
||||||
|
# The rename failed, perhaps because mv can't rename something else
|
||||||
|
# to itself, or perhaps because mv is so ancient that it does not
|
||||||
|
# support -f.
|
||||||
|
{
|
||||||
|
# Now remove or move aside any old file at destination location.
|
||||||
|
# We try this two ways since rm can't unlink itself on some
|
||||||
|
# systems and the destination file might be busy for other
|
||||||
|
# reasons. In this case, the final cleanup might fail but the new
|
||||||
|
# file should still install successfully.
|
||||||
|
{
|
||||||
|
test ! -f "$dst" ||
|
||||||
|
$doit $rmcmd "$dst" 2>/dev/null ||
|
||||||
|
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||||
|
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
|
||||||
|
} ||
|
||||||
|
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||||
|
(exit 1); exit 1
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dst"
|
||||||
|
}
|
||||||
|
fi || exit 1
|
||||||
|
|
||||||
|
trap '' 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
11156
build-aux/ltmain.sh
Normal file
11156
build-aux/ltmain.sh
Normal file
File diff suppressed because it is too large
Load Diff
228
build-aux/mdate-sh
Executable file
228
build-aux/mdate-sh
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Get modification time of a file or directory and pretty-print it.
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1995-2022 Free Software Foundation, Inc.
|
||||||
|
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
|
||||||
|
#
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
|
||||||
|
emulate sh
|
||||||
|
NULLCMD=:
|
||||||
|
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
|
||||||
|
# is contrary to our usage. Disable this feature.
|
||||||
|
alias -g '${1+"$@"}'='"$@"'
|
||||||
|
setopt NO_GLOB_SUBST
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No file. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: mdate-sh [--help] [--version] FILE
|
||||||
|
|
||||||
|
Pretty-print the modification day of FILE, in the format:
|
||||||
|
1 January 1970
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "mdate-sh $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
error ()
|
||||||
|
{
|
||||||
|
echo "$0: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Prevent date giving response in another language.
|
||||||
|
LANG=C
|
||||||
|
export LANG
|
||||||
|
LC_ALL=C
|
||||||
|
export LC_ALL
|
||||||
|
LC_TIME=C
|
||||||
|
export LC_TIME
|
||||||
|
|
||||||
|
# Use UTC to get reproducible result.
|
||||||
|
TZ=UTC0
|
||||||
|
export TZ
|
||||||
|
|
||||||
|
# GNU ls changes its time format in response to the TIME_STYLE
|
||||||
|
# variable. Since we cannot assume 'unset' works, revert this
|
||||||
|
# variable to its documented default.
|
||||||
|
if test "${TIME_STYLE+set}" = set; then
|
||||||
|
TIME_STYLE=posix-long-iso
|
||||||
|
export TIME_STYLE
|
||||||
|
fi
|
||||||
|
|
||||||
|
save_arg1=$1
|
||||||
|
|
||||||
|
# Find out how to get the extended ls output of a file or directory.
|
||||||
|
if ls -L /dev/null 1>/dev/null 2>&1; then
|
||||||
|
ls_command='ls -L -l -d'
|
||||||
|
else
|
||||||
|
ls_command='ls -l -d'
|
||||||
|
fi
|
||||||
|
# Avoid user/group names that might have spaces, when possible.
|
||||||
|
if ls -n /dev/null 1>/dev/null 2>&1; then
|
||||||
|
ls_command="$ls_command -n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A 'ls -l' line looks as follows on OS/2.
|
||||||
|
# drwxrwx--- 0 Aug 11 2001 foo
|
||||||
|
# This differs from Unix, which adds ownership information.
|
||||||
|
# drwxrwx--- 2 root root 4096 Aug 11 2001 foo
|
||||||
|
#
|
||||||
|
# To find the date, we split the line on spaces and iterate on words
|
||||||
|
# until we find a month. This cannot work with files whose owner is a
|
||||||
|
# user named "Jan", or "Feb", etc. However, it's unlikely that '/'
|
||||||
|
# will be owned by a user whose name is a month. So we first look at
|
||||||
|
# the extended ls output of the root directory to decide how many
|
||||||
|
# words should be skipped to get the date.
|
||||||
|
|
||||||
|
# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
|
||||||
|
set x`$ls_command /`
|
||||||
|
|
||||||
|
# Find which argument is the month.
|
||||||
|
month=
|
||||||
|
command=
|
||||||
|
until test $month
|
||||||
|
do
|
||||||
|
test $# -gt 0 || error "failed parsing '$ls_command /' output"
|
||||||
|
shift
|
||||||
|
# Add another shift to the command.
|
||||||
|
command="$command shift;"
|
||||||
|
case $1 in
|
||||||
|
Jan) month=January; nummonth=1;;
|
||||||
|
Feb) month=February; nummonth=2;;
|
||||||
|
Mar) month=March; nummonth=3;;
|
||||||
|
Apr) month=April; nummonth=4;;
|
||||||
|
May) month=May; nummonth=5;;
|
||||||
|
Jun) month=June; nummonth=6;;
|
||||||
|
Jul) month=July; nummonth=7;;
|
||||||
|
Aug) month=August; nummonth=8;;
|
||||||
|
Sep) month=September; nummonth=9;;
|
||||||
|
Oct) month=October; nummonth=10;;
|
||||||
|
Nov) month=November; nummonth=11;;
|
||||||
|
Dec) month=December; nummonth=12;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
test -n "$month" || error "failed parsing '$ls_command /' output"
|
||||||
|
|
||||||
|
# Get the extended ls output of the file or directory.
|
||||||
|
set dummy x`eval "$ls_command \"\\\$save_arg1\""`
|
||||||
|
|
||||||
|
# Remove all preceding arguments
|
||||||
|
eval $command
|
||||||
|
|
||||||
|
# Because of the dummy argument above, month is in $2.
|
||||||
|
#
|
||||||
|
# On a POSIX system, we should have
|
||||||
|
#
|
||||||
|
# $# = 5
|
||||||
|
# $1 = file size
|
||||||
|
# $2 = month
|
||||||
|
# $3 = day
|
||||||
|
# $4 = year or time
|
||||||
|
# $5 = filename
|
||||||
|
#
|
||||||
|
# On Darwin 7.7.0 and 7.6.0, we have
|
||||||
|
#
|
||||||
|
# $# = 4
|
||||||
|
# $1 = day
|
||||||
|
# $2 = month
|
||||||
|
# $3 = year or time
|
||||||
|
# $4 = filename
|
||||||
|
|
||||||
|
# Get the month.
|
||||||
|
case $2 in
|
||||||
|
Jan) month=January; nummonth=1;;
|
||||||
|
Feb) month=February; nummonth=2;;
|
||||||
|
Mar) month=March; nummonth=3;;
|
||||||
|
Apr) month=April; nummonth=4;;
|
||||||
|
May) month=May; nummonth=5;;
|
||||||
|
Jun) month=June; nummonth=6;;
|
||||||
|
Jul) month=July; nummonth=7;;
|
||||||
|
Aug) month=August; nummonth=8;;
|
||||||
|
Sep) month=September; nummonth=9;;
|
||||||
|
Oct) month=October; nummonth=10;;
|
||||||
|
Nov) month=November; nummonth=11;;
|
||||||
|
Dec) month=December; nummonth=12;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case $3 in
|
||||||
|
???*) day=$1;;
|
||||||
|
*) day=$3; shift;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Here we have to deal with the problem that the ls output gives either
|
||||||
|
# the time of day or the year.
|
||||||
|
case $3 in
|
||||||
|
*:*) set `date`; eval year=\$$#
|
||||||
|
case $2 in
|
||||||
|
Jan) nummonthtod=1;;
|
||||||
|
Feb) nummonthtod=2;;
|
||||||
|
Mar) nummonthtod=3;;
|
||||||
|
Apr) nummonthtod=4;;
|
||||||
|
May) nummonthtod=5;;
|
||||||
|
Jun) nummonthtod=6;;
|
||||||
|
Jul) nummonthtod=7;;
|
||||||
|
Aug) nummonthtod=8;;
|
||||||
|
Sep) nummonthtod=9;;
|
||||||
|
Oct) nummonthtod=10;;
|
||||||
|
Nov) nummonthtod=11;;
|
||||||
|
Dec) nummonthtod=12;;
|
||||||
|
esac
|
||||||
|
# For the first six month of the year the time notation can also
|
||||||
|
# be used for files modified in the last year.
|
||||||
|
if (expr $nummonth \> $nummonthtod) > /dev/null;
|
||||||
|
then
|
||||||
|
year=`expr $year - 1`
|
||||||
|
fi;;
|
||||||
|
*) year=$3;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# The result.
|
||||||
|
echo $day $month $year
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
215
build-aux/missing
Executable file
215
build-aux/missing
Executable file
@ -0,0 +1,215 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Common wrapper for a few potentially missing GNU programs.
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||||
|
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
|
||||||
|
--is-lightweight)
|
||||||
|
# Used by our autoconf macros to check whether the available missing
|
||||||
|
# script is modern enough.
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--run)
|
||||||
|
# Back-compat with the calling convention used by older automake.
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
|
||||||
|
-h|--h|--he|--hel|--help)
|
||||||
|
echo "\
|
||||||
|
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||||
|
|
||||||
|
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||||
|
to PROGRAM being missing or too old.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help display this help and exit
|
||||||
|
-v, --version output version information and exit
|
||||||
|
|
||||||
|
Supported PROGRAM values:
|
||||||
|
aclocal autoconf autoheader autom4te automake makeinfo
|
||||||
|
bison yacc flex lex help2man
|
||||||
|
|
||||||
|
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||||
|
'g' are ignored when checking the name.
|
||||||
|
|
||||||
|
Send bug reports to <bug-automake@gnu.org>."
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||||
|
echo "missing $scriptversion (GNU Automake)"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
echo 1>&2 "$0: unknown '$1' option"
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Run the given program, remember its exit status.
|
||||||
|
"$@"; st=$?
|
||||||
|
|
||||||
|
# If it succeeded, we are done.
|
||||||
|
test $st -eq 0 && exit 0
|
||||||
|
|
||||||
|
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||||
|
# passed; such an option is passed most likely to detect whether the
|
||||||
|
# program is present and works.
|
||||||
|
case $2 in --version|--help) exit $st;; esac
|
||||||
|
|
||||||
|
# Exit code 63 means version mismatch. This often happens when the user
|
||||||
|
# tries to use an ancient version of a tool on a file that requires a
|
||||||
|
# minimum version.
|
||||||
|
if test $st -eq 63; then
|
||||||
|
msg="probably too old"
|
||||||
|
elif test $st -eq 127; then
|
||||||
|
# Program was missing.
|
||||||
|
msg="missing on your system"
|
||||||
|
else
|
||||||
|
# Program was found and executed, but failed. Give up.
|
||||||
|
exit $st
|
||||||
|
fi
|
||||||
|
|
||||||
|
perl_URL=https://www.perl.org/
|
||||||
|
flex_URL=https://github.com/westes/flex
|
||||||
|
gnu_software_URL=https://www.gnu.org/software
|
||||||
|
|
||||||
|
program_details ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
aclocal|automake)
|
||||||
|
echo "The '$1' program is part of the GNU Automake package:"
|
||||||
|
echo "<$gnu_software_URL/automake>"
|
||||||
|
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/autoconf>"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
autoconf|autom4te|autoheader)
|
||||||
|
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||||
|
echo "<$gnu_software_URL/autoconf/>"
|
||||||
|
echo "It also requires GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice ()
|
||||||
|
{
|
||||||
|
# Normalize program name to check for.
|
||||||
|
normalized_program=`echo "$1" | sed '
|
||||||
|
s/^gnu-//; t
|
||||||
|
s/^gnu//; t
|
||||||
|
s/^g//; t'`
|
||||||
|
|
||||||
|
printf '%s\n' "'$1' is $msg."
|
||||||
|
|
||||||
|
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||||
|
case $normalized_program in
|
||||||
|
autoconf*)
|
||||||
|
echo "You should only need it if you modified 'configure.ac',"
|
||||||
|
echo "or m4 files included by it."
|
||||||
|
program_details 'autoconf'
|
||||||
|
;;
|
||||||
|
autoheader*)
|
||||||
|
echo "You should only need it if you modified 'acconfig.h' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'autoheader'
|
||||||
|
;;
|
||||||
|
automake*)
|
||||||
|
echo "You should only need it if you modified 'Makefile.am' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'automake'
|
||||||
|
;;
|
||||||
|
aclocal*)
|
||||||
|
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'aclocal'
|
||||||
|
;;
|
||||||
|
autom4te*)
|
||||||
|
echo "You might have modified some maintainer files that require"
|
||||||
|
echo "the 'autom4te' program to be rebuilt."
|
||||||
|
program_details 'autom4te'
|
||||||
|
;;
|
||||||
|
bison*|yacc*)
|
||||||
|
echo "You should only need it if you modified a '.y' file."
|
||||||
|
echo "You may want to install the GNU Bison package:"
|
||||||
|
echo "<$gnu_software_URL/bison/>"
|
||||||
|
;;
|
||||||
|
lex*|flex*)
|
||||||
|
echo "You should only need it if you modified a '.l' file."
|
||||||
|
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||||
|
echo "<$flex_URL>"
|
||||||
|
;;
|
||||||
|
help2man*)
|
||||||
|
echo "You should only need it if you modified a dependency" \
|
||||||
|
"of a man page."
|
||||||
|
echo "You may want to install the GNU Help2man package:"
|
||||||
|
echo "<$gnu_software_URL/help2man/>"
|
||||||
|
;;
|
||||||
|
makeinfo*)
|
||||||
|
echo "You should only need it if you modified a '.texi' file, or"
|
||||||
|
echo "any other file indirectly affecting the aspect of the manual."
|
||||||
|
echo "You might want to install the Texinfo package:"
|
||||||
|
echo "<$gnu_software_URL/texinfo/>"
|
||||||
|
echo "The spurious makeinfo call might also be the consequence of"
|
||||||
|
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||||
|
echo "want to install GNU make:"
|
||||||
|
echo "<$gnu_software_URL/make/>"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "You might have modified some files without having the proper"
|
||||||
|
echo "tools for further handling them. Check the 'README' file, it"
|
||||||
|
echo "often tells you about the needed prerequisites for installing"
|
||||||
|
echo "this package. You may also peek at any GNU archive site, in"
|
||||||
|
echo "case some other package contains this missing '$1' program."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||||
|
-e '2,$s/^/ /' >&2
|
||||||
|
|
||||||
|
# Propagate the correct exit status (expected to be 127 for a program
|
||||||
|
# not found, 63 for a program that failed due to version mismatch).
|
||||||
|
exit $st
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
153
build-aux/test-driver
Executable file
153
build-aux/test-driver
Executable file
@ -0,0 +1,153 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# test-driver - basic testsuite driver script.
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 2011-2021 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
# Make unconditional expansion of undefined variables an error. This
|
||||||
|
# helps a lot in preventing typo-related bugs.
|
||||||
|
set -u
|
||||||
|
|
||||||
|
usage_error ()
|
||||||
|
{
|
||||||
|
echo "$0: $*" >&2
|
||||||
|
print_usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
print_usage ()
|
||||||
|
{
|
||||||
|
cat <<END
|
||||||
|
Usage:
|
||||||
|
test-driver --test-name NAME --log-file PATH --trs-file PATH
|
||||||
|
[--expect-failure {yes|no}] [--color-tests {yes|no}]
|
||||||
|
[--enable-hard-errors {yes|no}] [--]
|
||||||
|
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
|
||||||
|
|
||||||
|
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
|
||||||
|
See the GNU Automake documentation for information.
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
test_name= # Used for reporting.
|
||||||
|
log_file= # Where to save the output of the test script.
|
||||||
|
trs_file= # Where to save the metadata of the test run.
|
||||||
|
expect_failure=no
|
||||||
|
color_tests=no
|
||||||
|
enable_hard_errors=yes
|
||||||
|
while test $# -gt 0; do
|
||||||
|
case $1 in
|
||||||
|
--help) print_usage; exit $?;;
|
||||||
|
--version) echo "test-driver $scriptversion"; exit $?;;
|
||||||
|
--test-name) test_name=$2; shift;;
|
||||||
|
--log-file) log_file=$2; shift;;
|
||||||
|
--trs-file) trs_file=$2; shift;;
|
||||||
|
--color-tests) color_tests=$2; shift;;
|
||||||
|
--expect-failure) expect_failure=$2; shift;;
|
||||||
|
--enable-hard-errors) enable_hard_errors=$2; shift;;
|
||||||
|
--) shift; break;;
|
||||||
|
-*) usage_error "invalid option: '$1'";;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
missing_opts=
|
||||||
|
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
|
||||||
|
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
|
||||||
|
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
|
||||||
|
if test x"$missing_opts" != x; then
|
||||||
|
usage_error "the following mandatory options are missing:$missing_opts"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
usage_error "missing argument"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $color_tests = yes; then
|
||||||
|
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
|
||||||
|
red='[0;31m' # Red.
|
||||||
|
grn='[0;32m' # Green.
|
||||||
|
lgn='[1;32m' # Light green.
|
||||||
|
blu='[1;34m' # Blue.
|
||||||
|
mgn='[0;35m' # Magenta.
|
||||||
|
std='[m' # No color.
|
||||||
|
else
|
||||||
|
red= grn= lgn= blu= mgn= std=
|
||||||
|
fi
|
||||||
|
|
||||||
|
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
|
||||||
|
trap "st=129; $do_exit" 1
|
||||||
|
trap "st=130; $do_exit" 2
|
||||||
|
trap "st=141; $do_exit" 13
|
||||||
|
trap "st=143; $do_exit" 15
|
||||||
|
|
||||||
|
# Test script is run here. We create the file first, then append to it,
|
||||||
|
# to ameliorate tests themselves also writing to the log file. Our tests
|
||||||
|
# don't, but others can (automake bug#35762).
|
||||||
|
: >"$log_file"
|
||||||
|
"$@" >>"$log_file" 2>&1
|
||||||
|
estatus=$?
|
||||||
|
|
||||||
|
if test $enable_hard_errors = no && test $estatus -eq 99; then
|
||||||
|
tweaked_estatus=1
|
||||||
|
else
|
||||||
|
tweaked_estatus=$estatus
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $tweaked_estatus:$expect_failure in
|
||||||
|
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
|
||||||
|
0:*) col=$grn res=PASS recheck=no gcopy=no;;
|
||||||
|
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
|
||||||
|
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
|
||||||
|
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
|
||||||
|
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Report the test outcome and exit status in the logs, so that one can
|
||||||
|
# know whether the test passed or failed simply by looking at the '.log'
|
||||||
|
# file, without the need of also peaking into the corresponding '.trs'
|
||||||
|
# file (automake bug#11814).
|
||||||
|
echo "$res $test_name (exit status: $estatus)" >>"$log_file"
|
||||||
|
|
||||||
|
# Report outcome to console.
|
||||||
|
echo "${col}${res}${std}: $test_name"
|
||||||
|
|
||||||
|
# Register the test result, and other relevant metadata.
|
||||||
|
echo ":test-result: $res" > $trs_file
|
||||||
|
echo ":global-test-result: $res" >> $trs_file
|
||||||
|
echo ":recheck: $recheck" >> $trs_file
|
||||||
|
echo ":copy-in-global-log: $gcopy" >> $trs_file
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
11592
build-aux/texinfo.tex
Normal file
11592
build-aux/texinfo.tex
Normal file
File diff suppressed because it is too large
Load Diff
302
build-aux/update-copyright
Executable file
302
build-aux/update-copyright
Executable file
@ -0,0 +1,302 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#! -*-perl-*-
|
||||||
|
|
||||||
|
# Update an FSF copyright year list to include the current year.
|
||||||
|
|
||||||
|
# Copyright (C) 2009-2022 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 Jim Meyering and Joel E. Denny
|
||||||
|
|
||||||
|
# This script updates an FSF copyright year list to include the current year.
|
||||||
|
# Usage: update-copyright [FILE...]
|
||||||
|
#
|
||||||
|
# The arguments to this script should be names of files that contain
|
||||||
|
# copyright statements to be updated. The copyright holder's name
|
||||||
|
# defaults to "Free Software Foundation, Inc." but may be changed to
|
||||||
|
# any other name by using the "UPDATE_COPYRIGHT_HOLDER" environment
|
||||||
|
# variable.
|
||||||
|
#
|
||||||
|
# For example, you might wish to use the update-copyright target rule
|
||||||
|
# in maint.mk from gnulib's maintainer-makefile module.
|
||||||
|
#
|
||||||
|
# Iff a copyright statement is recognized in a file and the final
|
||||||
|
# year is not the current year, then the statement is updated for the
|
||||||
|
# new year and it is reformatted to:
|
||||||
|
#
|
||||||
|
# 1. Fit within 72 columns.
|
||||||
|
# 2. Convert 2-digit years to 4-digit years by prepending "19".
|
||||||
|
# 3. Expand copyright year intervals. (See "Environment variables"
|
||||||
|
# below.)
|
||||||
|
#
|
||||||
|
# A warning is printed for every file for which no copyright
|
||||||
|
# statement is recognized.
|
||||||
|
#
|
||||||
|
# Each file's copyright statement must be formatted correctly in
|
||||||
|
# order to be recognized. For example, each of these is fine:
|
||||||
|
#
|
||||||
|
# Copyright @copyright{} 1990-2005, 2007-2009 Free Software
|
||||||
|
# Foundation, Inc.
|
||||||
|
#
|
||||||
|
# # Copyright (C) 1990-2005, 2007-2009 Free Software
|
||||||
|
# # Foundation, Inc.
|
||||||
|
#
|
||||||
|
# /*
|
||||||
|
# * Copyright © 90,2005,2007-2009
|
||||||
|
# * Free Software Foundation, Inc.
|
||||||
|
# */
|
||||||
|
#
|
||||||
|
# However, the following format is not recognized because the line
|
||||||
|
# prefix changes after the first line:
|
||||||
|
#
|
||||||
|
# ## Copyright (C) 1990-2005, 2007-2009 Free Software
|
||||||
|
# # Foundation, Inc.
|
||||||
|
#
|
||||||
|
# However, any correctly formatted copyright statement following
|
||||||
|
# a non-matching copyright statements would be recognized.
|
||||||
|
#
|
||||||
|
# The exact conditions that a file's copyright statement must meet
|
||||||
|
# to be recognized are:
|
||||||
|
#
|
||||||
|
# 1. It is the first copyright statement that meets all of the
|
||||||
|
# following conditions. Subsequent copyright statements are
|
||||||
|
# ignored.
|
||||||
|
# 2. Its format is "Copyright (C)", then a list of copyright years,
|
||||||
|
# and then the name of the copyright holder.
|
||||||
|
# 3. The "(C)" takes one of the following forms or is omitted
|
||||||
|
# entirely:
|
||||||
|
#
|
||||||
|
# A. (C)
|
||||||
|
# B. (c)
|
||||||
|
# C. @copyright{}
|
||||||
|
# D. ©
|
||||||
|
# E. ©
|
||||||
|
#
|
||||||
|
# 4. The "Copyright" appears at the beginning of a line, except that it
|
||||||
|
# may be prefixed by any sequence (e.g., a comment) of no more than
|
||||||
|
# 5 characters -- including white space.
|
||||||
|
# 5. Iff such a prefix is present, the same prefix appears at the
|
||||||
|
# beginning of each remaining line within the FSF copyright
|
||||||
|
# statement. There is one exception in order to support C-style
|
||||||
|
# comments: if the first line's prefix contains nothing but
|
||||||
|
# whitespace surrounding a "/*", then the prefix for all subsequent
|
||||||
|
# lines is the same as the first line's prefix except with each of
|
||||||
|
# "/" and possibly "*" replaced by a " ". The replacement of "*"
|
||||||
|
# by " " is consistent throughout all subsequent lines.
|
||||||
|
# 6. Blank lines, even if preceded by the prefix, do not appear
|
||||||
|
# within the FSF copyright statement.
|
||||||
|
# 7. Each copyright year is 2 or 4 digits, and years are separated by
|
||||||
|
# commas, "-", or "--". Whitespace may appear after commas.
|
||||||
|
#
|
||||||
|
# Environment variables:
|
||||||
|
#
|
||||||
|
# 1. If UPDATE_COPYRIGHT_FORCE=1, a recognized FSF copyright statement
|
||||||
|
# is reformatted even if it does not need updating for the new
|
||||||
|
# year. If unset or set to 0, only updated FSF copyright
|
||||||
|
# statements are reformatted.
|
||||||
|
# 2. If UPDATE_COPYRIGHT_USE_INTERVALS=1, every series of consecutive
|
||||||
|
# copyright years (such as 90, 1991, 1992-2007, 2008) in a
|
||||||
|
# reformatted FSF copyright statement is collapsed to a single
|
||||||
|
# interval (such as 1990-2008). If unset or set to 0, all existing
|
||||||
|
# copyright year intervals in a reformatted FSF copyright statement
|
||||||
|
# are expanded instead.
|
||||||
|
# If UPDATE_COPYRIGHT_USE_INTERVALS=2, convert a sequence with gaps
|
||||||
|
# to the minimal containing range. For example, convert
|
||||||
|
# 2000, 2004-2007, 2009 to 2000-2009.
|
||||||
|
# 3. For testing purposes, you can set the assumed current year in
|
||||||
|
# UPDATE_COPYRIGHT_YEAR.
|
||||||
|
# 4. The default maximum line length for a copyright line is 72.
|
||||||
|
# Set UPDATE_COPYRIGHT_MAX_LINE_LENGTH to use a different length.
|
||||||
|
# 5. Set UPDATE_COPYRIGHT_HOLDER if the copyright holder is other
|
||||||
|
# than "Free Software Foundation, Inc.".
|
||||||
|
|
||||||
|
# This is a prologue that allows to run a perl script as an executable
|
||||||
|
# on systems that are compliant to a POSIX version before POSIX:2017.
|
||||||
|
# On such systems, the usual invocation of an executable through execlp()
|
||||||
|
# or execvp() fails with ENOEXEC if it is a script that does not start
|
||||||
|
# with a #! line. The script interpreter mentioned in the #! line has
|
||||||
|
# to be /bin/sh, because on GuixSD systems that is the only program that
|
||||||
|
# has a fixed file name. The second line is essential for perl and is
|
||||||
|
# also useful for editing this file in Emacs. The next two lines below
|
||||||
|
# are valid code in both sh and perl. When executed by sh, they re-execute
|
||||||
|
# the script through the perl program found in $PATH. The '-x' option
|
||||||
|
# is essential as well; without it, perl would re-execute the script
|
||||||
|
# through /bin/sh. When executed by perl, the next two lines are a no-op.
|
||||||
|
eval 'exec perl -wSx -0777 -pi "$0" "$@"'
|
||||||
|
if 0;
|
||||||
|
|
||||||
|
my $VERSION = '2020-04-04.15:07'; # UTC
|
||||||
|
# The definition above must lie within the first 8 lines in order
|
||||||
|
# for the Emacs time-stamp write hook (at end) to update it.
|
||||||
|
# If you change this file with Emacs, please let the write hook
|
||||||
|
# do its job. Otherwise, update this string manually.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my $copyright_re = 'Copyright';
|
||||||
|
my $circle_c_re = '(?:\([cC]\)|@copyright\{}|\\\\\(co|©|©)';
|
||||||
|
my $holder = $ENV{UPDATE_COPYRIGHT_HOLDER};
|
||||||
|
$holder ||= 'Free Software Foundation, Inc.';
|
||||||
|
my $prefix_max = 5;
|
||||||
|
my $margin = $ENV{UPDATE_COPYRIGHT_MAX_LINE_LENGTH};
|
||||||
|
!$margin || $margin !~ m/^\d+$/
|
||||||
|
and $margin = 72;
|
||||||
|
|
||||||
|
my $tab_width = 8;
|
||||||
|
|
||||||
|
my $this_year = $ENV{UPDATE_COPYRIGHT_YEAR};
|
||||||
|
if (!$this_year || $this_year !~ m/^\d{4}$/)
|
||||||
|
{
|
||||||
|
my ($sec, $min, $hour, $mday, $month, $year) = localtime (time ());
|
||||||
|
$this_year = $year + 1900;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unless the file consistently uses "\r\n" as the EOL, use "\n" instead.
|
||||||
|
my $eol = /(?:^|[^\r])\n/ ? "\n" : "\r\n";
|
||||||
|
|
||||||
|
my $leading;
|
||||||
|
my $prefix;
|
||||||
|
my $ws_re;
|
||||||
|
my $stmt_re;
|
||||||
|
while (/(^|\n)(.{0,$prefix_max})$copyright_re/g)
|
||||||
|
{
|
||||||
|
$leading = "$1$2";
|
||||||
|
$prefix = $2;
|
||||||
|
if ($prefix =~ /^(\s*\/)\*(\s*)$/)
|
||||||
|
{
|
||||||
|
$prefix =~ s,/, ,;
|
||||||
|
my $prefix_ws = $prefix;
|
||||||
|
$prefix_ws =~ s/\*/ /; # Only whitespace.
|
||||||
|
if (/\G(?:[^*\n]|\*[^\/\n])*\*?\n$prefix_ws/)
|
||||||
|
{
|
||||||
|
$prefix = $prefix_ws;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ws_re = '[ \t\r\f]'; # \s without \n
|
||||||
|
$ws_re =
|
||||||
|
"(?:$ws_re*(?:$ws_re|\\n" . quotemeta($prefix) . ")$ws_re*)";
|
||||||
|
my $holder_re = $holder;
|
||||||
|
$holder_re =~ s/\s/$ws_re/g;
|
||||||
|
my $stmt_remainder_re =
|
||||||
|
"(?:$ws_re$circle_c_re)?"
|
||||||
|
. "$ws_re(?:(?:\\d\\d)?\\d\\d(?:,$ws_re?|--?))*"
|
||||||
|
. "((?:\\d\\d)?\\d\\d)$ws_re$holder_re";
|
||||||
|
if (/\G$stmt_remainder_re/)
|
||||||
|
{
|
||||||
|
$stmt_re =
|
||||||
|
quotemeta($leading) . "($copyright_re$stmt_remainder_re)";
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defined $stmt_re)
|
||||||
|
{
|
||||||
|
/$stmt_re/ or die; # Should never die.
|
||||||
|
my $stmt = $1;
|
||||||
|
my $final_year_orig = $2;
|
||||||
|
|
||||||
|
# Handle two-digit year numbers like "98" and "99".
|
||||||
|
my $final_year = $final_year_orig;
|
||||||
|
$final_year <= 99
|
||||||
|
and $final_year += 1900;
|
||||||
|
|
||||||
|
if ($final_year != $this_year)
|
||||||
|
{
|
||||||
|
# Update the year.
|
||||||
|
$stmt =~ s/\b$final_year_orig\b/$final_year, $this_year/;
|
||||||
|
}
|
||||||
|
if ($final_year != $this_year || $ENV{'UPDATE_COPYRIGHT_FORCE'})
|
||||||
|
{
|
||||||
|
# Normalize all whitespace including newline-prefix sequences.
|
||||||
|
$stmt =~ s/$ws_re/ /g;
|
||||||
|
|
||||||
|
# Put spaces after commas.
|
||||||
|
$stmt =~ s/, ?/, /g;
|
||||||
|
|
||||||
|
# Convert 2-digit to 4-digit years.
|
||||||
|
$stmt =~ s/(\b\d\d\b)/19$1/g;
|
||||||
|
|
||||||
|
# Make the use of intervals consistent.
|
||||||
|
if (!$ENV{UPDATE_COPYRIGHT_USE_INTERVALS})
|
||||||
|
{
|
||||||
|
$stmt =~ s/(\d{4})--?(\d{4})/join(', ', $1..$2)/eg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my $ndash = $ARGV =~ /\.tex(i(nfo)?)?$/ ? "--" : "-";
|
||||||
|
|
||||||
|
$stmt =~
|
||||||
|
s/
|
||||||
|
(\d{4})
|
||||||
|
(?:
|
||||||
|
(,\ |--?)
|
||||||
|
((??{
|
||||||
|
if ($2 ne ', ') { '\d{4}'; }
|
||||||
|
elsif (!$3) { $1 + 1; }
|
||||||
|
else { $3 + 1; }
|
||||||
|
}))
|
||||||
|
)+
|
||||||
|
/$1$ndash$3/gx;
|
||||||
|
|
||||||
|
# When it's 2, emit a single range encompassing all year numbers.
|
||||||
|
$ENV{UPDATE_COPYRIGHT_USE_INTERVALS} == 2
|
||||||
|
and $stmt =~ s/\b(\d{4})\b.*\b(\d{4})\b/$1$ndash$2/;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Format within margin.
|
||||||
|
my $stmt_wrapped;
|
||||||
|
my $text_margin = $margin - length($prefix);
|
||||||
|
if ($prefix =~ /^(\t+)/)
|
||||||
|
{
|
||||||
|
$text_margin -= length($1) * ($tab_width - 1);
|
||||||
|
}
|
||||||
|
while (length $stmt)
|
||||||
|
{
|
||||||
|
if (($stmt =~ s/^(.{1,$text_margin})(?: |$)//)
|
||||||
|
|| ($stmt =~ s/^([\S]+)(?: |$)//))
|
||||||
|
{
|
||||||
|
my $line = $1;
|
||||||
|
$stmt_wrapped .= $stmt_wrapped ? "$eol$prefix" : $leading;
|
||||||
|
$stmt_wrapped .= $line;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# Should be unreachable, but we don't want an infinite
|
||||||
|
# loop if it can be reached.
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Replace the old copyright statement.
|
||||||
|
s/$stmt_re/$stmt_wrapped/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print STDERR "$ARGV: warning: copyright statement not found\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hey Emacs!
|
||||||
|
# Local variables:
|
||||||
|
# coding: utf-8
|
||||||
|
# mode: perl
|
||||||
|
# indent-tabs-mode: nil
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-line-limit: 200
|
||||||
|
# time-stamp-start: "my $VERSION = '"
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H:%02M"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "'; # UTC"
|
||||||
|
# End:
|
||||||
240
build-aux/useless-if-before-free
Executable file
240
build-aux/useless-if-before-free
Executable file
@ -0,0 +1,240 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#! -*-perl-*-
|
||||||
|
|
||||||
|
# Detect instances of "if (p) free (p);".
|
||||||
|
# Likewise "if (p != 0)", "if (0 != p)", or with NULL; and with braces.
|
||||||
|
|
||||||
|
# Copyright (C) 2008-2022 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 Jim Meyering
|
||||||
|
|
||||||
|
# This is a prologue that allows to run a perl script as an executable
|
||||||
|
# on systems that are compliant to a POSIX version before POSIX:2017.
|
||||||
|
# On such systems, the usual invocation of an executable through execlp()
|
||||||
|
# or execvp() fails with ENOEXEC if it is a script that does not start
|
||||||
|
# with a #! line. The script interpreter mentioned in the #! line has
|
||||||
|
# to be /bin/sh, because on GuixSD systems that is the only program that
|
||||||
|
# has a fixed file name. The second line is essential for perl and is
|
||||||
|
# also useful for editing this file in Emacs. The next two lines below
|
||||||
|
# are valid code in both sh and perl. When executed by sh, they re-execute
|
||||||
|
# the script through the perl program found in $PATH. The '-x' option
|
||||||
|
# is essential as well; without it, perl would re-execute the script
|
||||||
|
# through /bin/sh. When executed by perl, the next two lines are a no-op.
|
||||||
|
eval 'exec perl -wSx "$0" "$@"'
|
||||||
|
if 0;
|
||||||
|
|
||||||
|
my $VERSION = '2022-01-27 18:51'; # UTC
|
||||||
|
# The definition above must lie within the first 8 lines in order
|
||||||
|
# for the Emacs time-stamp write hook (at end) to update it.
|
||||||
|
# If you change this file with Emacs, please let the write hook
|
||||||
|
# do its job. Otherwise, update this string manually.
|
||||||
|
|
||||||
|
my $copyright_year = '2022';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
(my $ME = $0) =~ s|.*/||;
|
||||||
|
|
||||||
|
# use File::Coda; # https://meyering.net/code/Coda/
|
||||||
|
END {
|
||||||
|
defined fileno STDOUT or return;
|
||||||
|
close STDOUT and return;
|
||||||
|
warn "$ME: failed to close standard output: $!\n";
|
||||||
|
$? ||= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub usage ($)
|
||||||
|
{
|
||||||
|
my ($exit_code) = @_;
|
||||||
|
my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
|
||||||
|
if ($exit_code != 0)
|
||||||
|
{
|
||||||
|
print $STREAM "Try '$ME --help' for more information.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print $STREAM <<EOF;
|
||||||
|
Usage: $ME [OPTIONS] FILE...
|
||||||
|
|
||||||
|
Detect any instance in FILE of a useless "if" test before a free call, e.g.,
|
||||||
|
"if (p) free (p);". Any such test may be safely removed without affecting
|
||||||
|
the semantics of the C code in FILE. Use --name=FOO --name=BAR to also
|
||||||
|
detect free-like functions named FOO and BAR.
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
|
||||||
|
--list print only the name of each matching FILE (\\0-terminated)
|
||||||
|
--name=N add name N to the list of \'free\'-like functions to detect;
|
||||||
|
may be repeated
|
||||||
|
|
||||||
|
--help display this help and exit
|
||||||
|
--version output version information and exit
|
||||||
|
|
||||||
|
Exit status:
|
||||||
|
|
||||||
|
0 one or more matches
|
||||||
|
1 no match
|
||||||
|
2 an error
|
||||||
|
|
||||||
|
EXAMPLE:
|
||||||
|
|
||||||
|
For example, this command prints all removable "if" tests before "free"
|
||||||
|
and "kfree" calls in the linux kernel sources:
|
||||||
|
|
||||||
|
git ls-files -z |xargs -0 $ME --name=kfree
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
exit $exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_NULL ($)
|
||||||
|
{
|
||||||
|
my ($expr) = @_;
|
||||||
|
return ($expr eq 'NULL' || $expr eq '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
sub EXIT_MATCH {0}
|
||||||
|
sub EXIT_NO_MATCH {1}
|
||||||
|
sub EXIT_ERROR {2}
|
||||||
|
my $err = EXIT_NO_MATCH;
|
||||||
|
|
||||||
|
my $list;
|
||||||
|
my @name = qw(free);
|
||||||
|
GetOptions
|
||||||
|
(
|
||||||
|
help => sub { usage 0 },
|
||||||
|
version =>
|
||||||
|
sub
|
||||||
|
{
|
||||||
|
print "$ME version $VERSION\n";
|
||||||
|
print "Copyright (C) $copyright_year Free Software Foundation, Inc.\n";
|
||||||
|
print "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n"
|
||||||
|
. "This is free software: you are free to change and redistribute it.\n"
|
||||||
|
. "There is NO WARRANTY, to the extent permitted by law.\n";
|
||||||
|
print "\n";
|
||||||
|
my $author = "Jim Meyering";
|
||||||
|
print "Written by $author.\n";
|
||||||
|
exit
|
||||||
|
},
|
||||||
|
list => \$list,
|
||||||
|
'name=s@' => \@name,
|
||||||
|
) or usage 1;
|
||||||
|
|
||||||
|
# Make sure we have the right number of non-option arguments.
|
||||||
|
# Always tell the user why we fail.
|
||||||
|
@ARGV < 1
|
||||||
|
and (warn "$ME: missing FILE argument\n"), usage EXIT_ERROR;
|
||||||
|
|
||||||
|
my $or = join '|', @name;
|
||||||
|
my $regexp = qr/(?:$or)/;
|
||||||
|
|
||||||
|
# Set the input record separator.
|
||||||
|
# Note: this makes it impractical to print line numbers.
|
||||||
|
$/ = '"';
|
||||||
|
|
||||||
|
my $found_match = 0;
|
||||||
|
FILE:
|
||||||
|
foreach my $file (@ARGV)
|
||||||
|
{
|
||||||
|
open FH, '<', $file
|
||||||
|
or (warn "$ME: can't open '$file' for reading: $!\n"),
|
||||||
|
$err = EXIT_ERROR, next;
|
||||||
|
while (defined (my $line = <FH>))
|
||||||
|
{
|
||||||
|
# Skip non-matching lines early to save time
|
||||||
|
$line =~ /\bif\b/
|
||||||
|
or next;
|
||||||
|
while ($line =~
|
||||||
|
/\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*([^)]+?))?\s*\)
|
||||||
|
# 1 2 3
|
||||||
|
(?: \s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;|
|
||||||
|
\s*\{\s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;\s*\}))/sxg)
|
||||||
|
{
|
||||||
|
my $all = $1;
|
||||||
|
my ($lhs, $rhs) = ($2, $3);
|
||||||
|
my ($free_opnd, $braced_free_opnd) = ($4, $5);
|
||||||
|
my $non_NULL;
|
||||||
|
if (!defined $rhs) { $non_NULL = $lhs }
|
||||||
|
elsif (is_NULL $rhs) { $non_NULL = $lhs }
|
||||||
|
elsif (is_NULL $lhs) { $non_NULL = $rhs }
|
||||||
|
else { next }
|
||||||
|
|
||||||
|
# Compare the non-NULL part of the "if" expression and the
|
||||||
|
# free'd expression, without regard to white space.
|
||||||
|
$non_NULL =~ tr/ \t//d;
|
||||||
|
my $e2 = defined $free_opnd ? $free_opnd : $braced_free_opnd;
|
||||||
|
$e2 =~ tr/ \t//d;
|
||||||
|
if ($non_NULL eq $e2)
|
||||||
|
{
|
||||||
|
$found_match = 1;
|
||||||
|
$list
|
||||||
|
and (print "$file\0"), next FILE;
|
||||||
|
print "$file: $all\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
{
|
||||||
|
close FH;
|
||||||
|
}
|
||||||
|
|
||||||
|
$found_match && $err == EXIT_NO_MATCH
|
||||||
|
and $err = EXIT_MATCH;
|
||||||
|
|
||||||
|
exit $err;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $foo = <<'EOF';
|
||||||
|
# The above is to *find* them.
|
||||||
|
# This adjusts them, removing the unnecessary "if (p)" part.
|
||||||
|
|
||||||
|
# FIXME: do something like this as an option (doesn't do braces):
|
||||||
|
free=xfree
|
||||||
|
git grep -l -z "$free *(" \
|
||||||
|
| xargs -0 useless-if-before-free -l --name="$free" \
|
||||||
|
| xargs -0 perl -0x3b -pi -e \
|
||||||
|
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
|
||||||
|
|
||||||
|
# Use the following to remove redundant uses of kfree inside braces.
|
||||||
|
# Note that -0777 puts perl in slurp-whole-file mode;
|
||||||
|
# but we have plenty of memory, these days...
|
||||||
|
free=kfree
|
||||||
|
git grep -l -z "$free *(" \
|
||||||
|
| xargs -0 useless-if-before-free -l --name="$free" \
|
||||||
|
| xargs -0 perl -0777 -pi -e \
|
||||||
|
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
|
||||||
|
|
||||||
|
Be careful that the result of the above transformation is valid.
|
||||||
|
If the matched string is followed by "else", then obviously, it won't be.
|
||||||
|
|
||||||
|
When modifying files, refuse to process anything other than a regular file.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
## Local Variables:
|
||||||
|
## mode: perl
|
||||||
|
## indent-tabs-mode: nil
|
||||||
|
## eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
## time-stamp-line-limit: 50
|
||||||
|
## time-stamp-start: "my $VERSION = '"
|
||||||
|
## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
|
||||||
|
## time-stamp-time-zone: "UTC0"
|
||||||
|
## time-stamp-end: "'; # UTC"
|
||||||
|
## End:
|
||||||
113
build-aux/vc-list-files
Executable file
113
build-aux/vc-list-files
Executable file
@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# List version-controlled file names.
|
||||||
|
|
||||||
|
# Print a version string.
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 2006-2022 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/>.
|
||||||
|
|
||||||
|
|
||||||
|
# List the specified version-controlled files.
|
||||||
|
# With no argument, list them all. With a single DIRECTORY argument,
|
||||||
|
# list the version-controlled files in that directory.
|
||||||
|
|
||||||
|
# If there's an argument, it must be a single, "."-relative directory name.
|
||||||
|
# cvsu is part of the cvsutils package: https://www.red-bean.com/cvsutils/
|
||||||
|
|
||||||
|
postprocess=
|
||||||
|
case $1 in
|
||||||
|
--help) cat <<EOF
|
||||||
|
Usage: $0 [-C SRCDIR] [DIR...]
|
||||||
|
|
||||||
|
Output a list of version-controlled files in DIR (default .), relative to
|
||||||
|
SRCDIR (default .). SRCDIR must be the top directory of a checkout.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--help print this help, then exit
|
||||||
|
--version print version number, then exit
|
||||||
|
-C SRCDIR change directory to SRCDIR before generating list
|
||||||
|
|
||||||
|
Report bugs and patches to <bug-gnulib@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit ;;
|
||||||
|
|
||||||
|
--version)
|
||||||
|
year=`echo "$scriptversion" | sed 's/[^0-9].*//'`
|
||||||
|
cat <<EOF
|
||||||
|
vc-list-files $scriptversion
|
||||||
|
Copyright (C) $year Free Software Foundation, Inc,
|
||||||
|
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
|
||||||
|
This is free software: you are free to change and redistribute it.
|
||||||
|
There is NO WARRANTY, to the extent permitted by law.
|
||||||
|
EOF
|
||||||
|
exit ;;
|
||||||
|
|
||||||
|
-C)
|
||||||
|
test "$2" = . || postprocess="| sed 's|^|$2/|'"
|
||||||
|
cd "$2" || exit 1
|
||||||
|
shift; shift ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
test $# = 0 && set .
|
||||||
|
|
||||||
|
for dir
|
||||||
|
do
|
||||||
|
if test -d .git || test -f .git; then
|
||||||
|
test "x$dir" = x. \
|
||||||
|
&& dir= sed_esc= \
|
||||||
|
|| { dir="$dir/"; sed_esc=`echo "$dir"|env sed 's,\([\\/]\),\\\\\1,g'`; }
|
||||||
|
# Ignore git symlinks - either they point into the tree, in which case
|
||||||
|
# we don't need to visit the target twice, or they point somewhere
|
||||||
|
# else (often into a submodule), in which case the content does not
|
||||||
|
# belong to this package.
|
||||||
|
eval exec git ls-tree -r 'HEAD:"$dir"' \
|
||||||
|
\| sed -n '"s/^100[^ ]*./$sed_esc/p"' $postprocess
|
||||||
|
elif test -d .hg; then
|
||||||
|
eval exec hg locate '"$dir/*"' $postprocess
|
||||||
|
elif test -d .bzr; then
|
||||||
|
test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
|
||||||
|
eval exec bzr ls -R --versioned '"$dir"' $postprocess
|
||||||
|
elif test -d CVS; then
|
||||||
|
test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
|
||||||
|
if test -x build-aux/cvsu; then
|
||||||
|
eval build-aux/cvsu --find --types=AFGM '"$dir"' $postprocess
|
||||||
|
elif (cvsu --help) >/dev/null 2>&1; then
|
||||||
|
eval cvsu --find --types=AFGM '"$dir"' $postprocess
|
||||||
|
else
|
||||||
|
eval awk -F/ \''{ \
|
||||||
|
if (!$1 && $3 !~ /^-/) { \
|
||||||
|
f=FILENAME; \
|
||||||
|
if (f ~ /CVS\/Entries$/) \
|
||||||
|
f = substr(f, 1, length(f)-11); \
|
||||||
|
print f $2; \
|
||||||
|
}}'\'' \
|
||||||
|
`find "$dir" -name Entries -print` /dev/null' $postprocess
|
||||||
|
fi
|
||||||
|
elif test -d .svn; then
|
||||||
|
eval exec svn list -R '"$dir"' $postprocess
|
||||||
|
else
|
||||||
|
echo "$0: Failed to determine type of version control used in `pwd`" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
247
build-aux/ylwrap
Executable file
247
build-aux/ylwrap
Executable file
@ -0,0 +1,247 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# ylwrap - wrapper for lex/yacc invocations.
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
|
#
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
get_dirname ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
|
||||||
|
# Otherwise, we want the empty string (not ".").
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# guard FILE
|
||||||
|
# ----------
|
||||||
|
# The CPP macro used to guard inclusion of FILE.
|
||||||
|
guard ()
|
||||||
|
{
|
||||||
|
printf '%s\n' "$1" \
|
||||||
|
| sed \
|
||||||
|
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
|
||||||
|
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
|
||||||
|
-e 's/__*/_/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
# quote_for_sed [STRING]
|
||||||
|
# ----------------------
|
||||||
|
# Return STRING (or stdin) quoted to be used as a sed pattern.
|
||||||
|
quote_for_sed ()
|
||||||
|
{
|
||||||
|
case $# in
|
||||||
|
0) cat;;
|
||||||
|
1) printf '%s\n' "$1";;
|
||||||
|
esac \
|
||||||
|
| sed -e 's|[][\\.*]|\\&|g'
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
'')
|
||||||
|
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
--basedir)
|
||||||
|
basedir=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
|
||||||
|
|
||||||
|
Wrapper for lex/yacc invocations, renaming files as desired.
|
||||||
|
|
||||||
|
INPUT is the input file
|
||||||
|
OUTPUT is one file PROG generates
|
||||||
|
DESIRED is the file we actually want instead of OUTPUT
|
||||||
|
PROGRAM is program to run
|
||||||
|
ARGS are passed to PROG
|
||||||
|
|
||||||
|
Any number of OUTPUT,DESIRED pairs may be used.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v|--v*)
|
||||||
|
echo "ylwrap $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
# The input.
|
||||||
|
input=$1
|
||||||
|
shift
|
||||||
|
# We'll later need for a correct munging of "#line" directives.
|
||||||
|
input_sub_rx=`get_dirname "$input" | quote_for_sed`
|
||||||
|
case $input in
|
||||||
|
[\\/]* | ?:[\\/]*)
|
||||||
|
# Absolute path; do nothing.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Relative path. Make it absolute.
|
||||||
|
input=`pwd`/$input
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
input_rx=`get_dirname "$input" | quote_for_sed`
|
||||||
|
|
||||||
|
# Since DOS filename conventions don't allow two dots,
|
||||||
|
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
|
||||||
|
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
|
||||||
|
y_tab_nodot=false
|
||||||
|
if test -f y_tab.c || test -f y_tab.h; then
|
||||||
|
y_tab_nodot=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The parser itself, the first file, is the destination of the .y.c
|
||||||
|
# rule in the Makefile.
|
||||||
|
parser=$1
|
||||||
|
|
||||||
|
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
|
||||||
|
# instance, we rename #include "y.tab.h" into #include "parse.h"
|
||||||
|
# during the conversion from y.tab.c to parse.c.
|
||||||
|
sed_fix_filenames=
|
||||||
|
|
||||||
|
# Also rename header guards, as Bison 2.7 for instance uses its header
|
||||||
|
# guard in its implementation file.
|
||||||
|
sed_fix_header_guards=
|
||||||
|
|
||||||
|
while test $# -ne 0; do
|
||||||
|
if test x"$1" = x"--"; then
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
from=$1
|
||||||
|
# Handle y_tab.c and y_tab.h output by DOS
|
||||||
|
if $y_tab_nodot; then
|
||||||
|
case $from in
|
||||||
|
"y.tab.c") from=y_tab.c;;
|
||||||
|
"y.tab.h") from=y_tab.h;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
to=$1
|
||||||
|
shift
|
||||||
|
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
|
||||||
|
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
|
||||||
|
done
|
||||||
|
|
||||||
|
# The program to run.
|
||||||
|
prog=$1
|
||||||
|
shift
|
||||||
|
# Make any relative path in $prog absolute.
|
||||||
|
case $prog in
|
||||||
|
[\\/]* | ?:[\\/]*) ;;
|
||||||
|
*[\\/]*) prog=`pwd`/$prog ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
dirname=ylwrap$$
|
||||||
|
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
|
||||||
|
trap "ret=129; $do_exit" 1
|
||||||
|
trap "ret=130; $do_exit" 2
|
||||||
|
trap "ret=141; $do_exit" 13
|
||||||
|
trap "ret=143; $do_exit" 15
|
||||||
|
mkdir $dirname || exit 1
|
||||||
|
|
||||||
|
cd $dirname
|
||||||
|
|
||||||
|
case $# in
|
||||||
|
0) "$prog" "$input" ;;
|
||||||
|
*) "$prog" "$@" "$input" ;;
|
||||||
|
esac
|
||||||
|
ret=$?
|
||||||
|
|
||||||
|
if test $ret -eq 0; then
|
||||||
|
for from in *
|
||||||
|
do
|
||||||
|
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
|
||||||
|
if test -f "$from"; then
|
||||||
|
# If $2 is an absolute path name, then just use that,
|
||||||
|
# otherwise prepend '../'.
|
||||||
|
case $to in
|
||||||
|
[\\/]* | ?:[\\/]*) target=$to;;
|
||||||
|
*) target=../$to;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Do not overwrite unchanged header files to avoid useless
|
||||||
|
# recompilations. Always update the parser itself: it is the
|
||||||
|
# destination of the .y.c rule in the Makefile. Divert the
|
||||||
|
# output of all other files to a temporary file so we can
|
||||||
|
# compare them to existing versions.
|
||||||
|
if test $from != $parser; then
|
||||||
|
realtarget=$target
|
||||||
|
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Munge "#line" or "#" directives. Don't let the resulting
|
||||||
|
# debug information point at an absolute srcdir. Use the real
|
||||||
|
# output file name, not yy.lex.c for instance. Adjust the
|
||||||
|
# include guards too.
|
||||||
|
sed -e "/^#/!b" \
|
||||||
|
-e "s|$input_rx|$input_sub_rx|" \
|
||||||
|
-e "$sed_fix_filenames" \
|
||||||
|
-e "$sed_fix_header_guards" \
|
||||||
|
"$from" >"$target" || ret=$?
|
||||||
|
|
||||||
|
# Check whether files must be updated.
|
||||||
|
if test "$from" != "$parser"; then
|
||||||
|
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
|
||||||
|
echo "$to is unchanged"
|
||||||
|
rm -f "$target"
|
||||||
|
else
|
||||||
|
echo "updating $to"
|
||||||
|
mv -f "$target" "$realtarget"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# A missing file is only an error for the parser. This is a
|
||||||
|
# blatant hack to let us support using "yacc -d". If -d is not
|
||||||
|
# specified, don't fail when the header file is "missing".
|
||||||
|
if test "$from" = "$parser"; then
|
||||||
|
ret=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove the directory.
|
||||||
|
cd ..
|
||||||
|
rm -rf $dirname
|
||||||
|
|
||||||
|
exit $ret
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
247
configure.ac
Normal file
247
configure.ac
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
dnl configure.ac for GNU rec
|
||||||
|
dnl
|
||||||
|
dnl Please process this file with autoconf to get a 'configure'
|
||||||
|
dnl script.
|
||||||
|
|
||||||
|
dnl Copyright (C) 2009-2022 Jose E. Marchesi
|
||||||
|
|
||||||
|
dnl This program is free software: you can redistribute it and/or modify
|
||||||
|
dnl it under the terms of the GNU General Public License as published by
|
||||||
|
dnl the Free Software Foundation, either version 3 of the License, or
|
||||||
|
dnl (at your option) any later version.
|
||||||
|
dnl
|
||||||
|
dnl This program is distributed in the hope that it will be useful,
|
||||||
|
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
dnl GNU General Public License for more details.
|
||||||
|
dnl
|
||||||
|
dnl You should have received a copy of the GNU General Public License
|
||||||
|
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
AC_INIT([GNU recutils], [1.9], [bug-recutils@gnu.org])
|
||||||
|
|
||||||
|
dnl Must come before AM_INIT_AUTOMAKE
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AM_INIT_AUTOMAKE([subdir-objects])
|
||||||
|
AC_CONFIG_HEADERS(src/config.h)
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
|
dnl Autobuild
|
||||||
|
AB_INIT
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
gl_EARLY
|
||||||
|
|
||||||
|
LT_INIT
|
||||||
|
AC_PROG_CC_C99
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
|
||||||
|
dnl Both lex and yacc are required to generate the lexer/parser source
|
||||||
|
dnl files.
|
||||||
|
|
||||||
|
: ${LEX='flex'}
|
||||||
|
: ${LEXLIB='-lfl'}
|
||||||
|
: ${LEX_OUTPUT_ROOT='lex.yy'}
|
||||||
|
AC_ARG_VAR([LEX], [The flex implementation to use.])
|
||||||
|
AC_ARG_VAR([LEXLIB], [Options for linking with the flex runtime library.])
|
||||||
|
AC_ARG_VAR([LEX_OUTPUT_ROOT], [Base of the file name that the lexer generates.])
|
||||||
|
|
||||||
|
gl_BISON
|
||||||
|
|
||||||
|
dnl System
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
canonical=$host
|
||||||
|
|
||||||
|
gl_INIT
|
||||||
|
|
||||||
|
# GNU help2man creates man pages from --help output; in many cases, this
|
||||||
|
# is sufficient, and obviates the need to maintain man pages separately.
|
||||||
|
# However, this means invoking executables, which we generally cannot do
|
||||||
|
# when cross-compiling, so we test to avoid that (the variable
|
||||||
|
# "cross_compiling" is set by AC_PROG_CC).
|
||||||
|
if test $cross_compiling = no; then
|
||||||
|
AM_MISSING_PROG(HELP2MAN, help2man)
|
||||||
|
else
|
||||||
|
HELP2MAN=:
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Seach for headers
|
||||||
|
AC_CHECK_HEADERS([malloc.h string.h])
|
||||||
|
|
||||||
|
dnl Search for data types
|
||||||
|
AC_CHECK_TYPE(size_t, unsigned)
|
||||||
|
AC_CHECK_TYPE(off_t, long)
|
||||||
|
|
||||||
|
dnl Search for functions
|
||||||
|
AC_FUNC_FSEEKO
|
||||||
|
|
||||||
|
dnl Search for required libraries
|
||||||
|
|
||||||
|
have_check=no
|
||||||
|
PKG_CHECK_MODULES([CHECK], [check],
|
||||||
|
[have_check=yes], [have_check=no])
|
||||||
|
AM_CONDITIONAL([CHECK], [test "x$have_check" != "xno"])
|
||||||
|
AC_SUBST([CHECK_CFLAGS])
|
||||||
|
AC_SUBST([CHECK_LIBS])
|
||||||
|
|
||||||
|
have_curl=no
|
||||||
|
AC_CHECK_LIB([curl],[curl_global_init],[have_curl=yes],)
|
||||||
|
if test "x$have_curl" = "xyes"; then
|
||||||
|
CURLLIBS=-lcurl
|
||||||
|
fi
|
||||||
|
AC_SUBST([CURLLIBS])
|
||||||
|
|
||||||
|
have_uuid=no
|
||||||
|
AC_CHECK_LIB([uuid],[uuid_generate],[have_uuid=yes],)
|
||||||
|
if test "x$have_uuid" = "xyes"; then
|
||||||
|
UUIDLIBS=-luuid
|
||||||
|
fi
|
||||||
|
AC_SUBST([UUIDLIBS])
|
||||||
|
AC_SUBST([have_uuid])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([encryption],
|
||||||
|
AS_HELP_STRING([--enable-encryption],
|
||||||
|
[Compile recutils with encryption support (default is YES)]),
|
||||||
|
[crypt_enabled=$enableval], [crypt_enabled=yes])
|
||||||
|
|
||||||
|
crypt_support=no
|
||||||
|
if test "x$crypt_enabled" = "xyes"; then
|
||||||
|
|
||||||
|
AC_LIB_HAVE_LINKFLAGS([gcrypt],[gpg-error],[#include <gpg-error.h>])
|
||||||
|
crypt_support=$HAVE_LIBGCRYPT
|
||||||
|
|
||||||
|
if test "x$crypt_support" = "xyes"; then
|
||||||
|
AC_DEFINE([REC_CRYPT_SUPPORT],[1],[Compile encryption support])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL([CRYPT], [test "x$crypt_support" = "xyes"])
|
||||||
|
AC_SUBST([crypt_support])
|
||||||
|
|
||||||
|
have_glib=no
|
||||||
|
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.0.0],
|
||||||
|
[have_glib=yes], [have_glib=no])
|
||||||
|
|
||||||
|
have_mdb=no
|
||||||
|
AC_CHECK_LIB([mdb],[mdb_init],[have_mdb=yes],)
|
||||||
|
if test "x$have_mdb" = "xyes"; then
|
||||||
|
MDBLIBS=-lmdb
|
||||||
|
|
||||||
|
OLD_CFLAGS=$CFLAGS
|
||||||
|
CFLAGS="$CFLAGS $pkg_cv_GLIB_CFLAGS"
|
||||||
|
mdb_uses_sdatetime=no
|
||||||
|
AC_CHECK_DECL([MDB_SDATETIME],[mdb_uses_sdatetime=yes],,[#include <glib.h>
|
||||||
|
#include <mdbtools.h>])
|
||||||
|
CFLAGS=$OLD_CFLAGS
|
||||||
|
|
||||||
|
if test "x$mdb_uses_sdatetime" = "xyes"; then
|
||||||
|
MDB_DATETIME="MDB_SDATETIME"
|
||||||
|
else
|
||||||
|
MDB_DATETIME="MDB_DATETIME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST([MDB_DATETIME])
|
||||||
|
fi
|
||||||
|
AC_SUBST([MDBLIBS])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([COMPILE_MDB2REC],
|
||||||
|
[test "x$have_glib" = "xyes" && test "x$have_mdb" = "xyes"])
|
||||||
|
AM_CONDITIONAL([REMOTE_DESCRIPTORS], [test "x$have_curl" = "xyes"])
|
||||||
|
AM_CONDITIONAL([UUID_TYPE], [test "x$have_uuid" = "xyes"])
|
||||||
|
|
||||||
|
dnl Bash builtins
|
||||||
|
|
||||||
|
dnl It would be much better to use AC_CHECK_HEADER([bash/config.h]) instead
|
||||||
|
dnl of a fixed value like /usr/include/bash, but then it would be difficult
|
||||||
|
dnl to set a proper search path for the preprocessor, since the bash
|
||||||
|
dnl headers which are needed to compile loadable builtins are not
|
||||||
|
dnl very well designed.
|
||||||
|
|
||||||
|
BASH_HEADERS=/usr/include/bash
|
||||||
|
AC_ARG_WITH([bash-headers],
|
||||||
|
AS_HELP_STRING([--with-bash-headers],
|
||||||
|
[location of the bash header files (default is /usr/include/bash)]),
|
||||||
|
[BASH_HEADERS=$withval],)
|
||||||
|
|
||||||
|
if test -f ${BASH_HEADERS}/config.h; then
|
||||||
|
AC_SUBST([BASH_HEADERS])
|
||||||
|
bash_headers_available=yes
|
||||||
|
else
|
||||||
|
bash_headers_available=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([bash-builtins],
|
||||||
|
AS_HELP_STRING([--enable-bash-builtins],
|
||||||
|
[Build the recutils bash builtins (default is YES)]),
|
||||||
|
[bash_builtins_enabled=$enableval], [bash_builtins_enabled=yes])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([BASH_BUILTINS],
|
||||||
|
[test "x$bash_headers_available" = "xyes" && test "x$bash_builtins_enabled" = "xyes"])
|
||||||
|
|
||||||
|
dnl Platform-based compilation options
|
||||||
|
compile_w32_system=no
|
||||||
|
case "${host}" in
|
||||||
|
*-mingw32*)
|
||||||
|
compile_w32_system=yes
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
dnl i18n with gettext
|
||||||
|
AM_GNU_GETTEXT_VERSION([0.19.8])
|
||||||
|
AM_GNU_GETTEXT([external])
|
||||||
|
|
||||||
|
dnl gcov compilation
|
||||||
|
AC_ARG_ENABLE([coverage],
|
||||||
|
AS_HELP_STRING([--enable-coverage],
|
||||||
|
[Compile the library with code coverage support (default is NO)]),
|
||||||
|
[use_gcov=$enableval], [use_gcov=no])
|
||||||
|
AM_CONDITIONAL([USE_COVERAGE], [test "x$use_gcov" = "xyes"])
|
||||||
|
|
||||||
|
dnl Generate output files
|
||||||
|
AC_CONFIG_FILES(Makefile
|
||||||
|
lib/Makefile
|
||||||
|
libcsv/Makefile
|
||||||
|
src/Makefile
|
||||||
|
utils/Makefile
|
||||||
|
bash/Makefile
|
||||||
|
doc/Makefile
|
||||||
|
po/Makefile.in
|
||||||
|
torture/Makefile
|
||||||
|
torture/utils/Makefile
|
||||||
|
torture/utils/config.sh
|
||||||
|
man/Makefile
|
||||||
|
etc/Makefile)
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
dnl Report warnings
|
||||||
|
|
||||||
|
if test "x$have_check" = "xno"; then
|
||||||
|
echo "warning: libcheck was not found in the system."
|
||||||
|
echo "warning: unit tests wont be compiled and executed upon make check."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$have_mdb" = "xno"; then
|
||||||
|
echo "warning: libmdb was not found in the system."
|
||||||
|
echo "warning: the mdb2rec utility won't get built."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$have_glib" = "xno"; then
|
||||||
|
echo "warning: glib was not found in the system."
|
||||||
|
echo "warning: the mdb2rec utility won't get built."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$crypt_support" = "xno"; then
|
||||||
|
echo "warning: building recutils without encryption support."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$have_uuid" = "xno"; then
|
||||||
|
echo "warning: building recutils without support for uuid types."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$bash_headers_available" = "xno" || test "x$bash_builtins_enabled" = "xno"; then
|
||||||
|
echo "warning: not building the recutils bash builtins."
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl End of configure.ac
|
||||||
23
doc/Makefile.am
Normal file
23
doc/Makefile.am
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# doc/Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
|
||||||
|
# 2018, 2019, 2020, 2022 Jose E. Marchesi
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
|
||||||
|
info_TEXINFOS = recutils.texi
|
||||||
|
recutils_TEXINFOS = parse-datetime.texi fdl.texi
|
||||||
|
|
||||||
|
# End of Makefile.am
|
||||||
2281
doc/Makefile.in
Normal file
2281
doc/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
507
doc/fdl.texi
Normal file
507
doc/fdl.texi
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
@c The GNU Free Documentation License.
|
||||||
|
@center Version 1.3, 3 November 2008
|
||||||
|
|
||||||
|
@c This file is intended to be included within another document,
|
||||||
|
@c hence no sectioning command or @node.
|
||||||
|
|
||||||
|
@display
|
||||||
|
Copyright @copyright{} 2000, 2001, 2002, 2007, 2008, 2020, 2022 Free
|
||||||
|
Software Foundation, Inc.
|
||||||
|
@uref{http://fsf.org/}
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
@end display
|
||||||
|
|
||||||
|
@enumerate 0
|
||||||
|
@item
|
||||||
|
PREAMBLE
|
||||||
|
|
||||||
|
The purpose of this License is to make a manual, textbook, or other
|
||||||
|
functional and useful document @dfn{free} in the sense of freedom: to
|
||||||
|
assure everyone the effective freedom to copy and redistribute it,
|
||||||
|
with or without modifying it, either commercially or noncommercially.
|
||||||
|
Secondarily, this License preserves for the author and publisher a way
|
||||||
|
to get credit for their work, while not being considered responsible
|
||||||
|
for modifications made by others.
|
||||||
|
|
||||||
|
This License is a kind of ``copyleft'', which means that derivative
|
||||||
|
works of the document must themselves be free in the same sense. It
|
||||||
|
complements the GNU General Public License, which is a copyleft
|
||||||
|
license designed for free software.
|
||||||
|
|
||||||
|
We have designed this License in order to use it for manuals for free
|
||||||
|
software, because free software needs free documentation: a free
|
||||||
|
program should come with manuals providing the same freedoms that the
|
||||||
|
software does. But this License is not limited to software manuals;
|
||||||
|
it can be used for any textual work, regardless of subject matter or
|
||||||
|
whether it is published as a printed book. We recommend this License
|
||||||
|
principally for works whose purpose is instruction or reference.
|
||||||
|
|
||||||
|
@item
|
||||||
|
APPLICABILITY AND DEFINITIONS
|
||||||
|
|
||||||
|
This License applies to any manual or other work, in any medium, that
|
||||||
|
contains a notice placed by the copyright holder saying it can be
|
||||||
|
distributed under the terms of this License. Such a notice grants a
|
||||||
|
world-wide, royalty-free license, unlimited in duration, to use that
|
||||||
|
work under the conditions stated herein. The ``Document'', below,
|
||||||
|
refers to any such manual or work. Any member of the public is a
|
||||||
|
licensee, and is addressed as ``you''. You accept the license if you
|
||||||
|
copy, modify or distribute the work in a way requiring permission
|
||||||
|
under copyright law.
|
||||||
|
|
||||||
|
A ``Modified Version'' of the Document means any work containing the
|
||||||
|
Document or a portion of it, either copied verbatim, or with
|
||||||
|
modifications and/or translated into another language.
|
||||||
|
|
||||||
|
A ``Secondary Section'' is a named appendix or a front-matter section
|
||||||
|
of the Document that deals exclusively with the relationship of the
|
||||||
|
publishers or authors of the Document to the Document's overall
|
||||||
|
subject (or to related matters) and contains nothing that could fall
|
||||||
|
directly within that overall subject. (Thus, if the Document is in
|
||||||
|
part a textbook of mathematics, a Secondary Section may not explain
|
||||||
|
any mathematics.) The relationship could be a matter of historical
|
||||||
|
connection with the subject or with related matters, or of legal,
|
||||||
|
commercial, philosophical, ethical or political position regarding
|
||||||
|
them.
|
||||||
|
|
||||||
|
The ``Invariant Sections'' are certain Secondary Sections whose titles
|
||||||
|
are designated, as being those of Invariant Sections, in the notice
|
||||||
|
that says that the Document is released under this License. If a
|
||||||
|
section does not fit the above definition of Secondary then it is not
|
||||||
|
allowed to be designated as Invariant. The Document may contain zero
|
||||||
|
Invariant Sections. If the Document does not identify any Invariant
|
||||||
|
Sections then there are none.
|
||||||
|
|
||||||
|
The ``Cover Texts'' are certain short passages of text that are listed,
|
||||||
|
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||||
|
the Document is released under this License. A Front-Cover Text may
|
||||||
|
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||||||
|
|
||||||
|
A ``Transparent'' copy of the Document means a machine-readable copy,
|
||||||
|
represented in a format whose specification is available to the
|
||||||
|
general public, that is suitable for revising the document
|
||||||
|
straightforwardly with generic text editors or (for images composed of
|
||||||
|
pixels) generic paint programs or (for drawings) some widely available
|
||||||
|
drawing editor, and that is suitable for input to text formatters or
|
||||||
|
for automatic translation to a variety of formats suitable for input
|
||||||
|
to text formatters. A copy made in an otherwise Transparent file
|
||||||
|
format whose markup, or absence of markup, has been arranged to thwart
|
||||||
|
or discourage subsequent modification by readers is not Transparent.
|
||||||
|
An image format is not Transparent if used for any substantial amount
|
||||||
|
of text. A copy that is not ``Transparent'' is called ``Opaque''.
|
||||||
|
|
||||||
|
Examples of suitable formats for Transparent copies include plain
|
||||||
|
ASCII without markup, Texinfo input format, La@TeX{} input
|
||||||
|
format, SGML or XML using a publicly available
|
||||||
|
DTD, and standard-conforming simple HTML,
|
||||||
|
PostScript or PDF designed for human modification. Examples
|
||||||
|
of transparent image formats include PNG, XCF and
|
||||||
|
JPG. Opaque formats include proprietary formats that can be
|
||||||
|
read and edited only by proprietary word processors, SGML or
|
||||||
|
XML for which the DTD and/or processing tools are
|
||||||
|
not generally available, and the machine-generated HTML,
|
||||||
|
PostScript or PDF produced by some word processors for
|
||||||
|
output purposes only.
|
||||||
|
|
||||||
|
The ``Title Page'' means, for a printed book, the title page itself,
|
||||||
|
plus such following pages as are needed to hold, legibly, the material
|
||||||
|
this License requires to appear in the title page. For works in
|
||||||
|
formats which do not have any title page as such, ``Title Page'' means
|
||||||
|
the text near the most prominent appearance of the work's title,
|
||||||
|
preceding the beginning of the body of the text.
|
||||||
|
|
||||||
|
The ``publisher'' means any person or entity that distributes copies
|
||||||
|
of the Document to the public.
|
||||||
|
|
||||||
|
A section ``Entitled XYZ'' means a named subunit of the Document whose
|
||||||
|
title either is precisely XYZ or contains XYZ in parentheses following
|
||||||
|
text that translates XYZ in another language. (Here XYZ stands for a
|
||||||
|
specific section name mentioned below, such as ``Acknowledgements'',
|
||||||
|
``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
|
||||||
|
of such a section when you modify the Document means that it remains a
|
||||||
|
section ``Entitled XYZ'' according to this definition.
|
||||||
|
|
||||||
|
The Document may include Warranty Disclaimers next to the notice which
|
||||||
|
states that this License applies to the Document. These Warranty
|
||||||
|
Disclaimers are considered to be included by reference in this
|
||||||
|
License, but only as regards disclaiming warranties: any other
|
||||||
|
implication that these Warranty Disclaimers may have is void and has
|
||||||
|
no effect on the meaning of this License.
|
||||||
|
|
||||||
|
@item
|
||||||
|
VERBATIM COPYING
|
||||||
|
|
||||||
|
You may copy and distribute the Document in any medium, either
|
||||||
|
commercially or noncommercially, provided that this License, the
|
||||||
|
copyright notices, and the license notice saying this License applies
|
||||||
|
to the Document are reproduced in all copies, and that you add no other
|
||||||
|
conditions whatsoever to those of this License. You may not use
|
||||||
|
technical measures to obstruct or control the reading or further
|
||||||
|
copying of the copies you make or distribute. However, you may accept
|
||||||
|
compensation in exchange for copies. If you distribute a large enough
|
||||||
|
number of copies you must also follow the conditions in section 3.
|
||||||
|
|
||||||
|
You may also lend copies, under the same conditions stated above, and
|
||||||
|
you may publicly display copies.
|
||||||
|
|
||||||
|
@item
|
||||||
|
COPYING IN QUANTITY
|
||||||
|
|
||||||
|
If you publish printed copies (or copies in media that commonly have
|
||||||
|
printed covers) of the Document, numbering more than 100, and the
|
||||||
|
Document's license notice requires Cover Texts, you must enclose the
|
||||||
|
copies in covers that carry, clearly and legibly, all these Cover
|
||||||
|
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||||
|
the back cover. Both covers must also clearly and legibly identify
|
||||||
|
you as the publisher of these copies. The front cover must present
|
||||||
|
the full title with all words of the title equally prominent and
|
||||||
|
visible. You may add other material on the covers in addition.
|
||||||
|
Copying with changes limited to the covers, as long as they preserve
|
||||||
|
the title of the Document and satisfy these conditions, can be treated
|
||||||
|
as verbatim copying in other respects.
|
||||||
|
|
||||||
|
If the required texts for either cover are too voluminous to fit
|
||||||
|
legibly, you should put the first ones listed (as many as fit
|
||||||
|
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||||
|
pages.
|
||||||
|
|
||||||
|
If you publish or distribute Opaque copies of the Document numbering
|
||||||
|
more than 100, you must either include a machine-readable Transparent
|
||||||
|
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||||
|
a computer-network location from which the general network-using
|
||||||
|
public has access to download using public-standard network protocols
|
||||||
|
a complete Transparent copy of the Document, free of added material.
|
||||||
|
If you use the latter option, you must take reasonably prudent steps,
|
||||||
|
when you begin distribution of Opaque copies in quantity, to ensure
|
||||||
|
that this Transparent copy will remain thus accessible at the stated
|
||||||
|
location until at least one year after the last time you distribute an
|
||||||
|
Opaque copy (directly or through your agents or retailers) of that
|
||||||
|
edition to the public.
|
||||||
|
|
||||||
|
It is requested, but not required, that you contact the authors of the
|
||||||
|
Document well before redistributing any large number of copies, to give
|
||||||
|
them a chance to provide you with an updated version of the Document.
|
||||||
|
|
||||||
|
@item
|
||||||
|
MODIFICATIONS
|
||||||
|
|
||||||
|
You may copy and distribute a Modified Version of the Document under
|
||||||
|
the conditions of sections 2 and 3 above, provided that you release
|
||||||
|
the Modified Version under precisely this License, with the Modified
|
||||||
|
Version filling the role of the Document, thus licensing distribution
|
||||||
|
and modification of the Modified Version to whoever possesses a copy
|
||||||
|
of it. In addition, you must do these things in the Modified Version:
|
||||||
|
|
||||||
|
@enumerate A
|
||||||
|
@item
|
||||||
|
Use in the Title Page (and on the covers, if any) a title distinct
|
||||||
|
from that of the Document, and from those of previous versions
|
||||||
|
(which should, if there were any, be listed in the History section
|
||||||
|
of the Document). You may use the same title as a previous version
|
||||||
|
if the original publisher of that version gives permission.
|
||||||
|
|
||||||
|
@item
|
||||||
|
List on the Title Page, as authors, one or more persons or entities
|
||||||
|
responsible for authorship of the modifications in the Modified
|
||||||
|
Version, together with at least five of the principal authors of the
|
||||||
|
Document (all of its principal authors, if it has fewer than five),
|
||||||
|
unless they release you from this requirement.
|
||||||
|
|
||||||
|
@item
|
||||||
|
State on the Title page the name of the publisher of the
|
||||||
|
Modified Version, as the publisher.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Preserve all the copyright notices of the Document.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Add an appropriate copyright notice for your modifications
|
||||||
|
adjacent to the other copyright notices.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Include, immediately after the copyright notices, a license notice
|
||||||
|
giving the public permission to use the Modified Version under the
|
||||||
|
terms of this License, in the form shown in the Addendum below.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Preserve in that license notice the full lists of Invariant Sections
|
||||||
|
and required Cover Texts given in the Document's license notice.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Include an unaltered copy of this License.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Preserve the section Entitled ``History'', Preserve its Title, and add
|
||||||
|
to it an item stating at least the title, year, new authors, and
|
||||||
|
publisher of the Modified Version as given on the Title Page. If
|
||||||
|
there is no section Entitled ``History'' in the Document, create one
|
||||||
|
stating the title, year, authors, and publisher of the Document as
|
||||||
|
given on its Title Page, then add an item describing the Modified
|
||||||
|
Version as stated in the previous sentence.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Preserve the network location, if any, given in the Document for
|
||||||
|
public access to a Transparent copy of the Document, and likewise
|
||||||
|
the network locations given in the Document for previous versions
|
||||||
|
it was based on. These may be placed in the ``History'' section.
|
||||||
|
You may omit a network location for a work that was published at
|
||||||
|
least four years before the Document itself, or if the original
|
||||||
|
publisher of the version it refers to gives permission.
|
||||||
|
|
||||||
|
@item
|
||||||
|
For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
|
||||||
|
the Title of the section, and preserve in the section all the
|
||||||
|
substance and tone of each of the contributor acknowledgements and/or
|
||||||
|
dedications given therein.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Preserve all the Invariant Sections of the Document,
|
||||||
|
unaltered in their text and in their titles. Section numbers
|
||||||
|
or the equivalent are not considered part of the section titles.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Delete any section Entitled ``Endorsements''. Such a section
|
||||||
|
may not be included in the Modified Version.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Do not retitle any existing section to be Entitled ``Endorsements'' or
|
||||||
|
to conflict in title with any Invariant Section.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Preserve any Warranty Disclaimers.
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
If the Modified Version includes new front-matter sections or
|
||||||
|
appendices that qualify as Secondary Sections and contain no material
|
||||||
|
copied from the Document, you may at your option designate some or all
|
||||||
|
of these sections as invariant. To do this, add their titles to the
|
||||||
|
list of Invariant Sections in the Modified Version's license notice.
|
||||||
|
These titles must be distinct from any other section titles.
|
||||||
|
|
||||||
|
You may add a section Entitled ``Endorsements'', provided it contains
|
||||||
|
nothing but endorsements of your Modified Version by various
|
||||||
|
parties---for example, statements of peer review or that the text has
|
||||||
|
been approved by an organization as the authoritative definition of a
|
||||||
|
standard.
|
||||||
|
|
||||||
|
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||||
|
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||||
|
of Cover Texts in the Modified Version. Only one passage of
|
||||||
|
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||||
|
through arrangements made by) any one entity. If the Document already
|
||||||
|
includes a cover text for the same cover, previously added by you or
|
||||||
|
by arrangement made by the same entity you are acting on behalf of,
|
||||||
|
you may not add another; but you may replace the old one, on explicit
|
||||||
|
permission from the previous publisher that added the old one.
|
||||||
|
|
||||||
|
The author(s) and publisher(s) of the Document do not by this License
|
||||||
|
give permission to use their names for publicity for or to assert or
|
||||||
|
imply endorsement of any Modified Version.
|
||||||
|
|
||||||
|
@item
|
||||||
|
COMBINING DOCUMENTS
|
||||||
|
|
||||||
|
You may combine the Document with other documents released under this
|
||||||
|
License, under the terms defined in section 4 above for modified
|
||||||
|
versions, provided that you include in the combination all of the
|
||||||
|
Invariant Sections of all of the original documents, unmodified, and
|
||||||
|
list them all as Invariant Sections of your combined work in its
|
||||||
|
license notice, and that you preserve all their Warranty Disclaimers.
|
||||||
|
|
||||||
|
The combined work need only contain one copy of this License, and
|
||||||
|
multiple identical Invariant Sections may be replaced with a single
|
||||||
|
copy. If there are multiple Invariant Sections with the same name but
|
||||||
|
different contents, make the title of each such section unique by
|
||||||
|
adding at the end of it, in parentheses, the name of the original
|
||||||
|
author or publisher of that section if known, or else a unique number.
|
||||||
|
Make the same adjustment to the section titles in the list of
|
||||||
|
Invariant Sections in the license notice of the combined work.
|
||||||
|
|
||||||
|
In the combination, you must combine any sections Entitled ``History''
|
||||||
|
in the various original documents, forming one section Entitled
|
||||||
|
``History''; likewise combine any sections Entitled ``Acknowledgements'',
|
||||||
|
and any sections Entitled ``Dedications''. You must delete all
|
||||||
|
sections Entitled ``Endorsements.''
|
||||||
|
|
||||||
|
@item
|
||||||
|
COLLECTIONS OF DOCUMENTS
|
||||||
|
|
||||||
|
You may make a collection consisting of the Document and other documents
|
||||||
|
released under this License, and replace the individual copies of this
|
||||||
|
License in the various documents with a single copy that is included in
|
||||||
|
the collection, provided that you follow the rules of this License for
|
||||||
|
verbatim copying of each of the documents in all other respects.
|
||||||
|
|
||||||
|
You may extract a single document from such a collection, and distribute
|
||||||
|
it individually under this License, provided you insert a copy of this
|
||||||
|
License into the extracted document, and follow this License in all
|
||||||
|
other respects regarding verbatim copying of that document.
|
||||||
|
|
||||||
|
@item
|
||||||
|
AGGREGATION WITH INDEPENDENT WORKS
|
||||||
|
|
||||||
|
A compilation of the Document or its derivatives with other separate
|
||||||
|
and independent documents or works, in or on a volume of a storage or
|
||||||
|
distribution medium, is called an ``aggregate'' if the copyright
|
||||||
|
resulting from the compilation is not used to limit the legal rights
|
||||||
|
of the compilation's users beyond what the individual works permit.
|
||||||
|
When the Document is included in an aggregate, this License does not
|
||||||
|
apply to the other works in the aggregate which are not themselves
|
||||||
|
derivative works of the Document.
|
||||||
|
|
||||||
|
If the Cover Text requirement of section 3 is applicable to these
|
||||||
|
copies of the Document, then if the Document is less than one half of
|
||||||
|
the entire aggregate, the Document's Cover Texts may be placed on
|
||||||
|
covers that bracket the Document within the aggregate, or the
|
||||||
|
electronic equivalent of covers if the Document is in electronic form.
|
||||||
|
Otherwise they must appear on printed covers that bracket the whole
|
||||||
|
aggregate.
|
||||||
|
|
||||||
|
@item
|
||||||
|
TRANSLATION
|
||||||
|
|
||||||
|
Translation is considered a kind of modification, so you may
|
||||||
|
distribute translations of the Document under the terms of section 4.
|
||||||
|
Replacing Invariant Sections with translations requires special
|
||||||
|
permission from their copyright holders, but you may include
|
||||||
|
translations of some or all Invariant Sections in addition to the
|
||||||
|
original versions of these Invariant Sections. You may include a
|
||||||
|
translation of this License, and all the license notices in the
|
||||||
|
Document, and any Warranty Disclaimers, provided that you also include
|
||||||
|
the original English version of this License and the original versions
|
||||||
|
of those notices and disclaimers. In case of a disagreement between
|
||||||
|
the translation and the original version of this License or a notice
|
||||||
|
or disclaimer, the original version will prevail.
|
||||||
|
|
||||||
|
If a section in the Document is Entitled ``Acknowledgements'',
|
||||||
|
``Dedications'', or ``History'', the requirement (section 4) to Preserve
|
||||||
|
its Title (section 1) will typically require changing the actual
|
||||||
|
title.
|
||||||
|
|
||||||
|
@item
|
||||||
|
TERMINATION
|
||||||
|
|
||||||
|
You may not copy, modify, sublicense, or distribute the Document
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense, or distribute it is void, and
|
||||||
|
will automatically terminate your rights under this License.
|
||||||
|
|
||||||
|
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, receipt of a copy of some or all of the same material does
|
||||||
|
not give you any rights to use it.
|
||||||
|
|
||||||
|
@item
|
||||||
|
FUTURE REVISIONS OF THIS LICENSE
|
||||||
|
|
||||||
|
The Free Software Foundation may publish new, revised versions
|
||||||
|
of the GNU Free Documentation 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. See
|
||||||
|
@uref{http://www.gnu.org/copyleft/}.
|
||||||
|
|
||||||
|
Each version of the License is given a distinguishing version number.
|
||||||
|
If the Document specifies that a particular numbered version of this
|
||||||
|
License ``or any later version'' applies to it, you have the option of
|
||||||
|
following the terms and conditions either of that specified version or
|
||||||
|
of any later version that has been published (not as a draft) by the
|
||||||
|
Free Software Foundation. If the Document does not specify a version
|
||||||
|
number of this License, you may choose any version ever published (not
|
||||||
|
as a draft) by the Free Software Foundation. If the Document
|
||||||
|
specifies that a proxy can decide which future versions of this
|
||||||
|
License can be used, that proxy's public statement of acceptance of a
|
||||||
|
version permanently authorizes you to choose that version for the
|
||||||
|
Document.
|
||||||
|
|
||||||
|
@item
|
||||||
|
RELICENSING
|
||||||
|
|
||||||
|
``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any
|
||||||
|
World Wide Web server that publishes copyrightable works and also
|
||||||
|
provides prominent facilities for anybody to edit those works. A
|
||||||
|
public wiki that anybody can edit is an example of such a server. A
|
||||||
|
``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the
|
||||||
|
site means any set of copyrightable works thus published on the MMC
|
||||||
|
site.
|
||||||
|
|
||||||
|
``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0
|
||||||
|
license published by Creative Commons Corporation, a not-for-profit
|
||||||
|
corporation with a principal place of business in San Francisco,
|
||||||
|
California, as well as future copyleft versions of that license
|
||||||
|
published by that same organization.
|
||||||
|
|
||||||
|
``Incorporate'' means to publish or republish a Document, in whole or
|
||||||
|
in part, as part of another Document.
|
||||||
|
|
||||||
|
An MMC is ``eligible for relicensing'' if it is licensed under this
|
||||||
|
License, and if all works that were first published under this License
|
||||||
|
somewhere other than this MMC, and subsequently incorporated in whole
|
||||||
|
or in part into the MMC, (1) had no cover texts or invariant sections,
|
||||||
|
and (2) were thus incorporated prior to November 1, 2008.
|
||||||
|
|
||||||
|
The operator of an MMC Site may republish an MMC contained in the site
|
||||||
|
under CC-BY-SA on the same site at any time before August 1, 2009,
|
||||||
|
provided the MMC is eligible for relicensing.
|
||||||
|
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
@page
|
||||||
|
@heading ADDENDUM: How to use this License for your documents
|
||||||
|
|
||||||
|
To use this License in a document you have written, include a copy of
|
||||||
|
the License in the document and put the following copyright and
|
||||||
|
license notices just after the title page:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
@group
|
||||||
|
Copyright (C) @var{year} @var{your name}.
|
||||||
|
Permission is granted to copy, distribute and/or modify this document
|
||||||
|
under the terms of the GNU Free Documentation License, Version 1.3
|
||||||
|
or any later version published by the Free Software Foundation;
|
||||||
|
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
|
||||||
|
Texts. A copy of the license is included in the section entitled ``GNU
|
||||||
|
Free Documentation License''.
|
||||||
|
@end group
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||||||
|
replace the ``with@dots{}Texts.'' line with this:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
@group
|
||||||
|
with the Invariant Sections being @var{list their titles}, with
|
||||||
|
the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
|
||||||
|
being @var{list}.
|
||||||
|
@end group
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
If you have Invariant Sections without Cover Texts, or some other
|
||||||
|
combination of the three, merge those two alternatives to suit the
|
||||||
|
situation.
|
||||||
|
|
||||||
|
If your document contains nontrivial examples of program code, we
|
||||||
|
recommend releasing these examples in parallel under your choice of
|
||||||
|
free software license, such as the GNU General Public License,
|
||||||
|
to permit their use in free software.
|
||||||
|
|
||||||
|
@c Local Variables:
|
||||||
|
@c ispell-local-pdict: "ispell-dict"
|
||||||
|
@c End:
|
||||||
|
|
||||||
594
doc/parse-datetime.texi
Normal file
594
doc/parse-datetime.texi
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
@c GNU date syntax documentation
|
||||||
|
|
||||||
|
@c Copyright (C) 1994--2006, 2009--2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
@c Permission is granted to copy, distribute and/or modify this document
|
||||||
|
@c under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||||
|
@c any later version published by the Free Software Foundation; with no
|
||||||
|
@c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
|
||||||
|
@c copy of the license is at <https://www.gnu.org/licenses/fdl-1.3.en.html>.
|
||||||
|
|
||||||
|
@node Date input formats
|
||||||
|
@chapter Date input formats
|
||||||
|
|
||||||
|
@cindex date input formats
|
||||||
|
@findex parse_datetime
|
||||||
|
|
||||||
|
First, a quote:
|
||||||
|
|
||||||
|
@quotation
|
||||||
|
Our units of temporal measurement, from seconds on up to months, are so
|
||||||
|
complicated, asymmetrical and disjunctive so as to make coherent mental
|
||||||
|
reckoning in time all but impossible. Indeed, had some tyrannical god
|
||||||
|
contrived to enslave our minds to time, to make it all but impossible
|
||||||
|
for us to escape subjection to sodden routines and unpleasant surprises,
|
||||||
|
he could hardly have done better than handing down our present system.
|
||||||
|
It is like a set of trapezoidal building blocks, with no vertical or
|
||||||
|
horizontal surfaces, like a language in which the simplest thought
|
||||||
|
demands ornate constructions, useless particles and lengthy
|
||||||
|
circumlocutions. Unlike the more successful patterns of language and
|
||||||
|
science, which enable us to face experience boldly or at least
|
||||||
|
level-headedly, our system of temporal calculation silently and
|
||||||
|
persistently encourages our terror of time.
|
||||||
|
|
||||||
|
@dots{} It is as though architects had to measure length in feet, width
|
||||||
|
in meters and height in ells; as though basic instruction manuals
|
||||||
|
demanded a knowledge of five different languages. It is no wonder then
|
||||||
|
that we often look into our own immediate past or future, last Tuesday
|
||||||
|
or a week from Sunday, with feelings of helpless confusion. @dots{}
|
||||||
|
|
||||||
|
---Robert Grudin, @cite{Time and the Art of Living}.
|
||||||
|
@end quotation
|
||||||
|
|
||||||
|
This section describes the textual date representations that GNU
|
||||||
|
programs accept. These are the strings you, as a user, can supply as
|
||||||
|
arguments to the various programs. The C interface (via the
|
||||||
|
@code{parse_datetime} function) is not described here.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* General date syntax:: Common rules
|
||||||
|
* Calendar date items:: 21 Jul 2020
|
||||||
|
* Time of day items:: 9:20pm
|
||||||
|
* Time zone items:: UTC, -0700, +0900, @dots{}
|
||||||
|
* Combined date and time of day items:: 2020-07-21T20:02:00,000000-0400
|
||||||
|
* Day of week items:: Monday and others
|
||||||
|
* Relative items in date strings:: next tuesday, 2 years ago
|
||||||
|
* Pure numbers in date strings:: 20200721, 1440
|
||||||
|
* Seconds since the Epoch:: @@1595289600
|
||||||
|
* Specifying time zone rules:: TZ="America/New_York", TZ="UTC0"
|
||||||
|
* Authors of parse_datetime:: Bellovin, Eggert, Salz, Berets, et al.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node General date syntax
|
||||||
|
@section General date syntax
|
||||||
|
|
||||||
|
@cindex general date syntax
|
||||||
|
|
||||||
|
@cindex items in date strings
|
||||||
|
A @dfn{date} is a string, possibly empty, containing many items
|
||||||
|
separated by whitespace. The whitespace may be omitted when no
|
||||||
|
ambiguity arises. The empty string means the beginning of today (i.e.,
|
||||||
|
midnight). Order of the items is immaterial. A date string may contain
|
||||||
|
many flavors of items:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item calendar date items
|
||||||
|
@item time of day items
|
||||||
|
@item time zone items
|
||||||
|
@item combined date and time of day items
|
||||||
|
@item day of the week items
|
||||||
|
@item relative items
|
||||||
|
@item pure numbers.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@noindent We describe each of these item types in turn, below.
|
||||||
|
|
||||||
|
@cindex numbers, written-out
|
||||||
|
@cindex ordinal numbers
|
||||||
|
@findex first @r{in date strings}
|
||||||
|
@findex next @r{in date strings}
|
||||||
|
@findex last @r{in date strings}
|
||||||
|
A few ordinal numbers may be written out in words in some contexts. This is
|
||||||
|
most useful for specifying day of the week items or relative items (see
|
||||||
|
below). Among the most commonly used ordinal numbers, the word
|
||||||
|
@samp{last} stands for @math{-1}, @samp{this} stands for 0, and
|
||||||
|
@samp{first} and @samp{next} both stand for 1. Because the word
|
||||||
|
@samp{second} stands for the unit of time there is no way to write the
|
||||||
|
ordinal number 2, but for convenience @samp{third} stands for 3,
|
||||||
|
@samp{fourth} for 4, @samp{fifth} for 5,
|
||||||
|
@samp{sixth} for 6, @samp{seventh} for 7, @samp{eighth} for 8,
|
||||||
|
@samp{ninth} for 9, @samp{tenth} for 10, @samp{eleventh} for 11 and
|
||||||
|
@samp{twelfth} for 12.
|
||||||
|
|
||||||
|
@cindex months, written-out
|
||||||
|
When a month is written this way, it is still considered to be written
|
||||||
|
numerically, instead of being ``spelled in full''; this changes the
|
||||||
|
allowed strings.
|
||||||
|
|
||||||
|
@cindex language, in dates
|
||||||
|
In the current implementation, only English is supported for words and
|
||||||
|
abbreviations like @samp{AM}, @samp{DST}, @samp{EST}, @samp{first},
|
||||||
|
@samp{January}, @samp{Sunday}, @samp{tomorrow}, and @samp{year}.
|
||||||
|
|
||||||
|
@cindex language, in dates
|
||||||
|
@cindex time zone item
|
||||||
|
The output of the @command{date} command
|
||||||
|
is not always acceptable as a date string,
|
||||||
|
not only because of the language problem, but also because there is no
|
||||||
|
standard meaning for time zone items like @samp{IST}@. When using
|
||||||
|
@command{date} to generate a date string intended to be parsed later,
|
||||||
|
specify a date format that is independent of language and that does not
|
||||||
|
use time zone items other than @samp{UTC} and @samp{Z}@. Here are some
|
||||||
|
ways to do this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ LC_ALL=C TZ=UTC0 date
|
||||||
|
Tue Jul 21 23:00:37 UTC 2020
|
||||||
|
$ TZ=UTC0 date +'%Y-%m-%d %H:%M:%SZ'
|
||||||
|
2020-07-21 23:00:37Z
|
||||||
|
$ date --rfc-3339=ns # --rfc-3339 is a GNU extension.
|
||||||
|
2020-07-21 19:00:37.692722128-04:00
|
||||||
|
$ date --rfc-2822 # a GNU extension
|
||||||
|
Tue, 21 Jul 2020 19:00:37 -0400
|
||||||
|
$ date +'%Y-%m-%d %H:%M:%S %z' # %z is a GNU extension.
|
||||||
|
2020-07-21 19:00:37 -0400
|
||||||
|
$ date +'@@%s.%N' # %s and %N are GNU extensions.
|
||||||
|
@@1595372437.692722128
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@cindex case, ignored in dates
|
||||||
|
@cindex comments, in dates
|
||||||
|
Alphabetic case is completely ignored in dates. Comments may be introduced
|
||||||
|
between round parentheses, as long as included parentheses are properly
|
||||||
|
nested. Hyphens not followed by a digit are currently ignored. Leading
|
||||||
|
zeros on numbers are ignored.
|
||||||
|
|
||||||
|
@cindex leap seconds
|
||||||
|
Invalid dates like @samp{2019-02-29} or times like @samp{24:00} are
|
||||||
|
rejected. In the typical case of a host that does not support leap
|
||||||
|
seconds, a time like @samp{23:59:60} is rejected even if it
|
||||||
|
corresponds to a valid leap second.
|
||||||
|
|
||||||
|
|
||||||
|
@node Calendar date items
|
||||||
|
@section Calendar date items
|
||||||
|
|
||||||
|
@cindex calendar date item
|
||||||
|
|
||||||
|
A @dfn{calendar date item} specifies a day of the year. It is
|
||||||
|
specified differently, depending on whether the month is specified
|
||||||
|
numerically or literally. All these strings specify the same calendar date:
|
||||||
|
|
||||||
|
@example
|
||||||
|
2020-07-20 # ISO 8601.
|
||||||
|
20-7-20 # Assume 19xx for 69 through 99,
|
||||||
|
# 20xx for 00 through 68 (not recommended).
|
||||||
|
7/20/2020 # Common U.S. writing.
|
||||||
|
20 July 2020
|
||||||
|
20 Jul 2020 # Three-letter abbreviations always allowed.
|
||||||
|
Jul 20, 2020
|
||||||
|
20-jul-2020
|
||||||
|
20jul2020
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The year can also be omitted. In this case, the last specified year is
|
||||||
|
used, or the current year if none. For example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
7/20
|
||||||
|
jul 20
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Here are the rules.
|
||||||
|
|
||||||
|
@cindex ISO 8601 date format
|
||||||
|
@cindex date format, ISO 8601
|
||||||
|
For numeric months, the ISO 8601 format
|
||||||
|
@samp{@var{year}-@var{month}-@var{day}} is allowed, where @var{year} is
|
||||||
|
any positive number, @var{month} is a number between 01 and 12, and
|
||||||
|
@var{day} is a number between 01 and 31. A leading zero must be present
|
||||||
|
if a number is less than ten. If @var{year} is 68 or smaller, then 2000
|
||||||
|
is added to it; otherwise, if @var{year} is less than 100,
|
||||||
|
then 1900 is added to it. The construct
|
||||||
|
@samp{@var{month}/@var{day}/@var{year}}, popular in the United States,
|
||||||
|
is accepted. Also @samp{@var{month}/@var{day}}, omitting the year.
|
||||||
|
|
||||||
|
@cindex month names in date strings
|
||||||
|
@cindex abbreviations for months
|
||||||
|
Literal months may be spelled out in full: @samp{January},
|
||||||
|
@samp{February}, @samp{March}, @samp{April}, @samp{May}, @samp{June},
|
||||||
|
@samp{July}, @samp{August}, @samp{September}, @samp{October},
|
||||||
|
@samp{November} or @samp{December}. Literal months may be abbreviated
|
||||||
|
to their first three letters, possibly followed by an abbreviating dot.
|
||||||
|
It is also permitted to write @samp{Sept} instead of @samp{September}.
|
||||||
|
|
||||||
|
When months are written literally, the calendar date may be given as any
|
||||||
|
of the following:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@var{day} @var{month} @var{year}
|
||||||
|
@var{day} @var{month}
|
||||||
|
@var{month} @var{day} @var{year}
|
||||||
|
@var{day}-@var{month}-@var{year}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Or, omitting the year:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@var{month} @var{day}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
|
||||||
|
@node Time of day items
|
||||||
|
@section Time of day items
|
||||||
|
|
||||||
|
@cindex time of day item
|
||||||
|
|
||||||
|
A @dfn{time of day item} in date strings specifies the time on a given
|
||||||
|
day. Here are some examples, all of which represent the same time:
|
||||||
|
|
||||||
|
@example
|
||||||
|
20:02:00.000000
|
||||||
|
20:02
|
||||||
|
8:02pm
|
||||||
|
20:02-0500 # In EST (U.S. Eastern Standard Time).
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@cindex leap seconds
|
||||||
|
More generally, the time of day may be given as
|
||||||
|
@samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is
|
||||||
|
a number between 0 and 23, @var{minute} is a number between 0 and
|
||||||
|
59, and @var{second} is a number between 0 and 59 possibly followed by
|
||||||
|
@samp{.} or @samp{,} and a fraction containing one or more digits.
|
||||||
|
Alternatively,
|
||||||
|
@samp{:@var{second}} can be omitted, in which case it is taken to
|
||||||
|
be zero. On the rare hosts that support leap seconds, @var{second}
|
||||||
|
may be 60.
|
||||||
|
|
||||||
|
@findex am @r{in date strings}
|
||||||
|
@findex pm @r{in date strings}
|
||||||
|
@findex midnight @r{in date strings}
|
||||||
|
@findex noon @r{in date strings}
|
||||||
|
If the time is followed by @samp{am} or @samp{pm} (or @samp{a.m.}
|
||||||
|
or @samp{p.m.}), @var{hour} is restricted to run from 1 to 12, and
|
||||||
|
@samp{:@var{minute}} may be omitted (taken to be zero). @samp{am}
|
||||||
|
indicates the first half of the day, @samp{pm} indicates the second
|
||||||
|
half of the day. In this notation, 12 is the predecessor of 1:
|
||||||
|
midnight is @samp{12am} while noon is @samp{12pm}.
|
||||||
|
(This is the zero-oriented interpretation of @samp{12am} and @samp{12pm},
|
||||||
|
as opposed to the old tradition derived from Latin
|
||||||
|
which uses @samp{12m} for noon and @samp{12pm} for midnight.)
|
||||||
|
|
||||||
|
@cindex time zone correction
|
||||||
|
@cindex minutes, time zone correction by
|
||||||
|
The time may alternatively be followed by a time zone correction,
|
||||||
|
expressed as @samp{@var{s}@var{hh}@var{mm}}, where @var{s} is @samp{+}
|
||||||
|
or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number
|
||||||
|
of zone minutes.
|
||||||
|
The zone minutes term, @var{mm}, may be omitted, in which case
|
||||||
|
the one- or two-digit correction is interpreted as a number of hours.
|
||||||
|
You can also separate @var{hh} from @var{mm} with a colon.
|
||||||
|
When a time zone correction is given this way, it
|
||||||
|
forces interpretation of the time relative to
|
||||||
|
Coordinated Universal Time (UTC), overriding any previous
|
||||||
|
specification for the time zone or the local time zone. For example,
|
||||||
|
@samp{+0530} and @samp{+05:30} both stand for the time zone 5.5 hours
|
||||||
|
ahead of UTC (e.g., India).
|
||||||
|
This is the best way to
|
||||||
|
specify a time zone correction by fractional parts of an hour.
|
||||||
|
The maximum zone correction is 24 hours.
|
||||||
|
|
||||||
|
Either @samp{am}/@samp{pm} or a time zone correction may be specified,
|
||||||
|
but not both.
|
||||||
|
|
||||||
|
|
||||||
|
@node Time zone items
|
||||||
|
@section Time zone items
|
||||||
|
|
||||||
|
@cindex time zone item
|
||||||
|
|
||||||
|
A @dfn{time zone item} specifies an international time zone, indicated
|
||||||
|
by a small set of letters, e.g., @samp{UTC} or @samp{Z}
|
||||||
|
for Coordinated Universal
|
||||||
|
Time. Any included periods are ignored. By following a
|
||||||
|
non-daylight-saving time zone by the string @samp{DST} in a separate
|
||||||
|
word (that is, separated by some white space), the corresponding
|
||||||
|
daylight saving time zone may be specified.
|
||||||
|
Alternatively, a non-daylight-saving time zone can be followed by a
|
||||||
|
time zone correction, to add the two values. This is normally done
|
||||||
|
only for @samp{UTC}; for example, @samp{UTC+05:30} is equivalent to
|
||||||
|
@samp{+05:30}.
|
||||||
|
|
||||||
|
Time zone items other than @samp{UTC} and @samp{Z}
|
||||||
|
are obsolescent and are not recommended, because they
|
||||||
|
are ambiguous; for example, @samp{EST} has a different meaning in
|
||||||
|
Australia than in the United States, and @samp{A} has different
|
||||||
|
meaning as a military time zone than as an obsolescent
|
||||||
|
RFC 822 time zone. Instead, it's better to use
|
||||||
|
unambiguous numeric time zone corrections like @samp{-0500}, as
|
||||||
|
described in the previous section.
|
||||||
|
|
||||||
|
If neither a time zone item nor a time zone correction is supplied,
|
||||||
|
timestamps are interpreted using the rules of the default time zone
|
||||||
|
(@pxref{Specifying time zone rules}).
|
||||||
|
|
||||||
|
|
||||||
|
@node Combined date and time of day items
|
||||||
|
@section Combined date and time of day items
|
||||||
|
|
||||||
|
@cindex combined date and time of day item
|
||||||
|
@cindex ISO 8601 date and time of day format
|
||||||
|
@cindex date and time of day format, ISO 8601
|
||||||
|
|
||||||
|
The ISO 8601 date and time of day extended format consists of an ISO
|
||||||
|
8601 date, a @samp{T} character separator, and an ISO 8601 time of
|
||||||
|
day. This format is also recognized if the @samp{T} is replaced by a
|
||||||
|
space.
|
||||||
|
|
||||||
|
In this format, the time of day should use 24-hour notation.
|
||||||
|
Fractional seconds are allowed, with either comma or period preceding
|
||||||
|
the fraction. ISO 8601 fractional minutes and hours are not
|
||||||
|
supported. Typically, hosts support nanosecond timestamp resolution;
|
||||||
|
excess precision is silently discarded.
|
||||||
|
|
||||||
|
Here are some examples:
|
||||||
|
|
||||||
|
@example
|
||||||
|
2012-09-24T20:02:00.052-05:00
|
||||||
|
2012-12-31T23:59:59,999999999+11:00
|
||||||
|
1970-01-01 00:00Z
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@node Day of week items
|
||||||
|
@section Day of week items
|
||||||
|
|
||||||
|
@cindex day of week item
|
||||||
|
|
||||||
|
The explicit mention of a day of the week will forward the date
|
||||||
|
(only if necessary) to reach that day of the week in the future.
|
||||||
|
|
||||||
|
Days of the week may be spelled out in full: @samp{Sunday},
|
||||||
|
@samp{Monday}, @samp{Tuesday}, @samp{Wednesday}, @samp{Thursday},
|
||||||
|
@samp{Friday} or @samp{Saturday}. Days may be abbreviated to their
|
||||||
|
first three letters, optionally followed by a period. The special
|
||||||
|
abbreviations @samp{Tues} for @samp{Tuesday}, @samp{Wednes} for
|
||||||
|
@samp{Wednesday} and @samp{Thur} or @samp{Thurs} for @samp{Thursday} are
|
||||||
|
also allowed.
|
||||||
|
|
||||||
|
@findex next @var{day}
|
||||||
|
@findex last @var{day}
|
||||||
|
A number may precede a day of the week item to move forward
|
||||||
|
supplementary weeks. It is best used in expression like @samp{third
|
||||||
|
monday}. In this context, @samp{last @var{day}} or @samp{next
|
||||||
|
@var{day}} is also acceptable; they move one week before or after
|
||||||
|
the day that @var{day} by itself would represent.
|
||||||
|
|
||||||
|
A comma following a day of the week item is ignored.
|
||||||
|
|
||||||
|
|
||||||
|
@node Relative items in date strings
|
||||||
|
@section Relative items in date strings
|
||||||
|
|
||||||
|
@cindex relative items in date strings
|
||||||
|
@cindex displacement of dates
|
||||||
|
|
||||||
|
@dfn{Relative items} adjust a date (or the current date if none) forward
|
||||||
|
or backward. The effects of relative items accumulate. Here are some
|
||||||
|
examples:
|
||||||
|
|
||||||
|
@example
|
||||||
|
1 year
|
||||||
|
1 year ago
|
||||||
|
3 years
|
||||||
|
2 days
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@findex year @r{in date strings}
|
||||||
|
@findex month @r{in date strings}
|
||||||
|
@findex fortnight @r{in date strings}
|
||||||
|
@findex week @r{in date strings}
|
||||||
|
@findex day @r{in date strings}
|
||||||
|
@findex hour @r{in date strings}
|
||||||
|
@findex minute @r{in date strings}
|
||||||
|
The unit of time displacement may be selected by the string @samp{year}
|
||||||
|
or @samp{month} for moving by whole years or months. These are fuzzy
|
||||||
|
units, as years and months are not all of equal duration. More precise
|
||||||
|
units are @samp{fortnight} which is worth 14 days, @samp{week} worth 7
|
||||||
|
days, @samp{day} worth 24 hours, @samp{hour} worth 60 minutes,
|
||||||
|
@samp{minute} or @samp{min} worth 60 seconds, and @samp{second} or
|
||||||
|
@samp{sec} worth one second. An @samp{s} suffix on these units is
|
||||||
|
accepted and ignored.
|
||||||
|
|
||||||
|
@findex ago @r{in date strings}
|
||||||
|
The unit of time may be preceded by a multiplier, given as an optionally
|
||||||
|
signed number. Unsigned numbers are taken as positively signed. No
|
||||||
|
number at all implies 1 for a multiplier. Following a relative item by
|
||||||
|
the string @samp{ago} is equivalent to preceding the unit by a
|
||||||
|
multiplier with value @math{-1}.
|
||||||
|
|
||||||
|
@findex day @r{in date strings}
|
||||||
|
@findex tomorrow @r{in date strings}
|
||||||
|
@findex yesterday @r{in date strings}
|
||||||
|
The string @samp{tomorrow} is worth one day in the future (equivalent
|
||||||
|
to @samp{day}), the string @samp{yesterday} is worth
|
||||||
|
one day in the past (equivalent to @samp{day ago}).
|
||||||
|
|
||||||
|
@findex now @r{in date strings}
|
||||||
|
@findex today @r{in date strings}
|
||||||
|
@findex this @r{in date strings}
|
||||||
|
The strings @samp{now} or @samp{today} are relative items corresponding
|
||||||
|
to zero-valued time displacement, these strings come from the fact
|
||||||
|
a zero-valued time displacement represents the current time when not
|
||||||
|
otherwise changed by previous items. They may be used to stress other
|
||||||
|
items, like in @samp{12:00 today}. The string @samp{this} also has
|
||||||
|
the meaning of a zero-valued time displacement, but is preferred in
|
||||||
|
date strings like @samp{this thursday}.
|
||||||
|
|
||||||
|
When a relative item causes the resulting date to cross a boundary
|
||||||
|
where the clocks were adjusted, typically for daylight saving time,
|
||||||
|
the resulting date and time are adjusted accordingly.
|
||||||
|
|
||||||
|
The fuzz in units can cause problems with relative items. For
|
||||||
|
example, @samp{2020-07-31 -1 month} might evaluate to 2020-07-01,
|
||||||
|
because 2020-06-31 is an invalid date. To determine the previous
|
||||||
|
month more reliably, you can ask for the month before the 15th of the
|
||||||
|
current month. For example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ date -R
|
||||||
|
Thu, 31 Jul 2020 13:02:39 -0400
|
||||||
|
$ date --date='-1 month' +'Last month was %B?'
|
||||||
|
Last month was July?
|
||||||
|
$ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
|
||||||
|
Last month was June!
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Also, take care when manipulating dates around clock changes such as
|
||||||
|
daylight saving leaps. In a few cases these have added or subtracted
|
||||||
|
as much as 24 hours from the clock, so it is often wise to adopt
|
||||||
|
universal time by setting the @env{TZ} environment variable to
|
||||||
|
@samp{UTC0} before embarking on calendrical calculations.
|
||||||
|
|
||||||
|
@node Pure numbers in date strings
|
||||||
|
@section Pure numbers in date strings
|
||||||
|
|
||||||
|
@cindex pure numbers in date strings
|
||||||
|
|
||||||
|
The precise interpretation of a pure decimal number depends
|
||||||
|
on the context in the date string.
|
||||||
|
|
||||||
|
If the decimal number is of the form @var{yyyy}@var{mm}@var{dd} and no
|
||||||
|
other calendar date item (@pxref{Calendar date items}) appears before it
|
||||||
|
in the date string, then @var{yyyy} is read as the year, @var{mm} as the
|
||||||
|
month number and @var{dd} as the day of the month, for the specified
|
||||||
|
calendar date.
|
||||||
|
|
||||||
|
If the decimal number is of the form @var{hh}@var{mm} and no other time
|
||||||
|
of day item appears before it in the date string, then @var{hh} is read
|
||||||
|
as the hour of the day and @var{mm} as the minute of the hour, for the
|
||||||
|
specified time of day. @var{mm} can also be omitted.
|
||||||
|
|
||||||
|
If both a calendar date and a time of day appear to the left of a number
|
||||||
|
in the date string, but no relative item, then the number overrides the
|
||||||
|
year.
|
||||||
|
|
||||||
|
|
||||||
|
@node Seconds since the Epoch
|
||||||
|
@section Seconds since the Epoch
|
||||||
|
|
||||||
|
If you precede a number with @samp{@@}, it represents an internal
|
||||||
|
timestamp as a count of seconds. The number can contain an internal
|
||||||
|
decimal point (either @samp{.} or @samp{,}); any excess precision not
|
||||||
|
supported by the internal representation is truncated toward minus
|
||||||
|
infinity. Such a number cannot be combined with any other date
|
||||||
|
item, as it specifies a complete timestamp.
|
||||||
|
|
||||||
|
@cindex beginning of time, for POSIX
|
||||||
|
@cindex Epoch, for POSIX
|
||||||
|
Internally, computer times are represented as a count of seconds since
|
||||||
|
an Epoch---a well-defined point of time. On GNU and
|
||||||
|
POSIX systems, the Epoch is 1970-01-01 00:00:00 UTC, so
|
||||||
|
@samp{@@0} represents this time, @samp{@@1} represents 1970-01-01
|
||||||
|
00:00:01 UTC, and so forth. GNU and most other
|
||||||
|
POSIX-compliant systems support such times as an extension
|
||||||
|
to POSIX, using negative counts, so that @samp{@@-1}
|
||||||
|
represents 1969-12-31 23:59:59 UTC.
|
||||||
|
|
||||||
|
Most modern systems count seconds with 64-bit two's-complement integers
|
||||||
|
of seconds with nanosecond subcounts, which is a range that includes
|
||||||
|
the known lifetime of the universe with nanosecond resolution.
|
||||||
|
Some obsolescent systems count seconds with 32-bit two's-complement
|
||||||
|
integers and can represent times from 1901-12-13 20:45:52 through
|
||||||
|
2038-01-19 03:14:07 UTC@. A few systems sport other time ranges.
|
||||||
|
|
||||||
|
@cindex leap seconds
|
||||||
|
On most hosts, these counts ignore the presence of leap seconds.
|
||||||
|
For example, on most hosts @samp{@@1483228799} represents 2016-12-31
|
||||||
|
23:59:59 UTC, @samp{@@1483228800} represents 2017-01-01 00:00:00
|
||||||
|
UTC, and there is no way to represent the intervening leap second
|
||||||
|
2016-12-31 23:59:60 UTC.
|
||||||
|
|
||||||
|
@node Specifying time zone rules
|
||||||
|
@section Specifying time zone rules
|
||||||
|
|
||||||
|
@vindex TZ
|
||||||
|
Normally, dates are interpreted using the rules of the current time
|
||||||
|
zone, which in turn are specified by the @env{TZ} environment
|
||||||
|
variable, or by a system default if @env{TZ} is not set. To specify a
|
||||||
|
different set of default time zone rules that apply just to one date,
|
||||||
|
start the date with a string of the form @samp{TZ="@var{rule}"}. The
|
||||||
|
two quote characters (@samp{"}) must be present in the date, and any
|
||||||
|
quotes or backslashes within @var{rule} must be escaped by a
|
||||||
|
backslash.
|
||||||
|
|
||||||
|
For example, with the GNU @command{date} command you can
|
||||||
|
answer the question ``What time is it in New York when a Paris clock
|
||||||
|
shows 6:30am on October 31, 2019?'' by using a date beginning with
|
||||||
|
@samp{TZ="Europe/Paris"} as shown in the following shell transcript:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ export TZ="America/New_York"
|
||||||
|
$ date --date='TZ="Europe/Paris" 2019-10-31 06:30'
|
||||||
|
Sun Oct 31 01:30:00 EDT 2019
|
||||||
|
@end example
|
||||||
|
|
||||||
|
In this example, the @option{--date} operand begins with its own
|
||||||
|
@env{TZ} setting, so the rest of that operand is processed according
|
||||||
|
to @samp{Europe/Paris} rules, treating the string @samp{2019-10-31
|
||||||
|
06:30} as if it were in Paris. However, since the output of the
|
||||||
|
@command{date} command is processed according to the overall time zone
|
||||||
|
rules, it uses New York time. (Paris was normally six hours ahead of
|
||||||
|
New York in 2019, but this example refers to a brief Halloween period
|
||||||
|
when the gap was five hours.)
|
||||||
|
|
||||||
|
A @env{TZ} value is a rule that typically names a location in the
|
||||||
|
@uref{https://www.iana.org/time-zones, @samp{tz} database}.
|
||||||
|
A recent catalog of location names appears in the
|
||||||
|
@uref{https://twiki.org/cgi-bin/xtra/tzdatepick.html, TWiki Date and Time
|
||||||
|
Gateway}. A few non-GNU hosts require a colon before a
|
||||||
|
location name in a @env{TZ} setting, e.g.,
|
||||||
|
@samp{TZ=":America/New_York"}.
|
||||||
|
|
||||||
|
The @samp{tz} database includes a wide variety of locations ranging
|
||||||
|
from @samp{Arctic/Longyearbyen} to @samp{Antarctica/South_Pole}, but
|
||||||
|
if you are at sea and have your own private time zone, or if you are
|
||||||
|
using a non-GNU host that does not support the @samp{tz}
|
||||||
|
database, you may need to use a POSIX rule instead. Simple
|
||||||
|
POSIX rules like @samp{UTC0} specify a time zone without
|
||||||
|
daylight saving time; other rules can specify simple daylight saving
|
||||||
|
regimes. @xref{TZ Variable,, Specifying the Time Zone with @code{TZ},
|
||||||
|
libc, The GNU C Library}.
|
||||||
|
|
||||||
|
@node Authors of parse_datetime
|
||||||
|
@section Authors of @code{parse_datetime}
|
||||||
|
@c the anchor keeps the old node name, to try to avoid breaking links
|
||||||
|
@anchor{Authors of get_date}
|
||||||
|
|
||||||
|
@cindex authors of @code{parse_datetime}
|
||||||
|
|
||||||
|
@cindex Bellovin, Steven M.
|
||||||
|
@cindex Salz, Rich
|
||||||
|
@cindex Berets, Jim
|
||||||
|
@cindex MacKenzie, David
|
||||||
|
@cindex Meyering, Jim
|
||||||
|
@cindex Eggert, Paul
|
||||||
|
@code{parse_datetime} started life as @code{getdate}, as originally
|
||||||
|
implemented by Steven M. Bellovin
|
||||||
|
(@email{smb@@research.att.com}) while at the University of North Carolina
|
||||||
|
at Chapel Hill. The code was later tweaked by a couple of people on
|
||||||
|
Usenet, then completely overhauled by Rich $alz (@email{rsalz@@bbn.com})
|
||||||
|
and Jim Berets (@email{jberets@@bbn.com}) in August, 1990. Various
|
||||||
|
revisions for the GNU system were made by David MacKenzie, Jim Meyering,
|
||||||
|
Paul Eggert and others, including renaming it to @code{get_date} to
|
||||||
|
avoid a conflict with the alternative Posix function @code{getdate},
|
||||||
|
and a later rename to @code{parse_datetime}. The Posix function
|
||||||
|
@code{getdate} can parse more locale-specific dates using
|
||||||
|
@code{strptime}, but relies on an environment variable and external
|
||||||
|
file, and lacks the thread-safety of @code{parse_datetime}.
|
||||||
|
|
||||||
|
@cindex Pinard, F.
|
||||||
|
@cindex Berry, K.
|
||||||
|
This chapter was originally produced by Fran@,{c}ois Pinard
|
||||||
|
(@email{pinard@@iro.umontreal.ca}) from the @file{parse_datetime.y} source code,
|
||||||
|
and then edited by K. Berry (@email{kb@@cs.umb.edu}).
|
||||||
6313
doc/recutils.info
Normal file
6313
doc/recutils.info
Normal file
File diff suppressed because it is too large
Load Diff
5735
doc/recutils.texi
Normal file
5735
doc/recutils.texi
Normal file
File diff suppressed because it is too large
Load Diff
4
doc/stamp-vti
Normal file
4
doc/stamp-vti
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@set UPDATED 16 April 2022
|
||||||
|
@set UPDATED-MONTH April 2022
|
||||||
|
@set EDITION 1.9
|
||||||
|
@set VERSION 1.9
|
||||||
9153
doc/texinfo.tex
Normal file
9153
doc/texinfo.tex
Normal file
File diff suppressed because it is too large
Load Diff
4
doc/version.texi
Normal file
4
doc/version.texi
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@set UPDATED 16 April 2022
|
||||||
|
@set UPDATED-MONTH April 2022
|
||||||
|
@set EDITION 1.9
|
||||||
|
@set VERSION 1.9
|
||||||
37
etc/FSD.rec
Normal file
37
etc/FSD.rec
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# FSD.rec - Record descriptor for FSD entries
|
||||||
|
#
|
||||||
|
# This file contains the record descriptor for entries in the Free
|
||||||
|
# Software Directory.
|
||||||
|
#
|
||||||
|
# The canonical location of this file is
|
||||||
|
# http://www.jemarch.net/downloads/FSD.rec
|
||||||
|
|
||||||
|
# Copyright (C) 2010, 2020, 2022 Jose E. Marchesi
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
%rec: FSD_Entry
|
||||||
|
%mandatory: Title
|
||||||
|
%type: Title line
|
||||||
|
%type: GNU bool
|
||||||
|
%type: MaturityLevel enum
|
||||||
|
+ Undefined Planning PreAlpha Alpha Beta
|
||||||
|
+ Production Mature Orphaned
|
||||||
|
%type: License enum
|
||||||
|
+ GPLv2 GPLv2PLUS GPLv3 GPLv3PLUS
|
||||||
|
+ GFDLv21PLUS
|
||||||
|
%type: InterfaceStyle enum
|
||||||
|
+ CommandLine Console Daemon XWindow Web Email
|
||||||
|
|
||||||
|
# End of FSD.rec
|
||||||
22
etc/Makefile.am
Normal file
22
etc/Makefile.am
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Makefile.am for etc/
|
||||||
|
|
||||||
|
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
|
||||||
|
# 2019, 2020, 2022 Jose E. Marchesi
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
etcdir=$(pkgdatadir)/etc
|
||||||
|
dist_etc_DATA = FSD.rec
|
||||||
|
|
||||||
|
# End of Makefile.am
|
||||||
1999
etc/Makefile.in
Normal file
1999
etc/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
4366
lib/Makefile.am
Normal file
4366
lib/Makefile.am
Normal file
File diff suppressed because it is too large
Load Diff
7548
lib/Makefile.in
Normal file
7548
lib/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
45
lib/_Noreturn.h
Normal file
45
lib/_Noreturn.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* A C macro for declaring that a function does not return.
|
||||||
|
Copyright (C) 2011-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program 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 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 _Noreturn
|
||||||
|
# if (defined __cplusplus \
|
||||||
|
&& ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
|
||||||
|
|| (defined _MSC_VER && 1900 <= _MSC_VER)) \
|
||||||
|
&& 0)
|
||||||
|
/* [[noreturn]] is not practically usable, because with it the syntax
|
||||||
|
extern _Noreturn void func (...);
|
||||||
|
would not be valid; such a declaration would only be valid with 'extern'
|
||||||
|
and '_Noreturn' swapped, or without the 'extern' keyword. However, some
|
||||||
|
AIX system header files and several gnulib header files use precisely
|
||||||
|
this syntax with 'extern'. */
|
||||||
|
# define _Noreturn [[noreturn]]
|
||||||
|
# elif ((!defined __cplusplus || defined __clang__) \
|
||||||
|
&& (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|
||||||
|
|| (!defined __STRICT_ANSI__ \
|
||||||
|
&& (4 < __GNUC__ + (7 <= __GNUC_MINOR__) \
|
||||||
|
|| (defined __apple_build_version__ \
|
||||||
|
? 6000000 <= __apple_build_version__ \
|
||||||
|
: 3 < __clang_major__ + (5 <= __clang_minor__))))))
|
||||||
|
/* _Noreturn works as-is. */
|
||||||
|
# elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \
|
||||||
|
|| 0x5110 <= __SUNPRO_C)
|
||||||
|
# define _Noreturn __attribute__ ((__noreturn__))
|
||||||
|
# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
|
||||||
|
# define _Noreturn __declspec (noreturn)
|
||||||
|
# else
|
||||||
|
# define _Noreturn
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
31
lib/access.c
Normal file
31
lib/access.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* Test the access rights of a file.
|
||||||
|
Copyright (C) 2019-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
access (const char *file, int mode)
|
||||||
|
{
|
||||||
|
if ((mode & X_OK) != 0)
|
||||||
|
mode = (mode & ~X_OK) | R_OK;
|
||||||
|
return _access (file, mode);
|
||||||
|
}
|
||||||
52
lib/acl-errno-valid.c
Normal file
52
lib/acl-errno-valid.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Test whether ACLs are well supported on this system.
|
||||||
|
|
||||||
|
Copyright 2013-2022 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. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <acl.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* Return true if errno value ERRNUM indicates that ACLs are well
|
||||||
|
supported on this system. ERRNUM should be an errno value obtained
|
||||||
|
after an ACL-related system call fails. */
|
||||||
|
bool
|
||||||
|
acl_errno_valid (int errnum)
|
||||||
|
{
|
||||||
|
/* Recognize some common errors such as from an NFS mount that does
|
||||||
|
not support ACLs, even when local drives do. */
|
||||||
|
switch (errnum)
|
||||||
|
{
|
||||||
|
case EBUSY: return false;
|
||||||
|
case EINVAL: return false;
|
||||||
|
#if defined __APPLE__ && defined __MACH__
|
||||||
|
case ENOENT: return false;
|
||||||
|
#endif
|
||||||
|
case ENOSYS: return false;
|
||||||
|
|
||||||
|
#if defined ENOTSUP && ENOTSUP != EOPNOTSUPP
|
||||||
|
# if ENOTSUP != ENOSYS /* Needed for the MS-Windows port of GNU Emacs. */
|
||||||
|
case ENOTSUP: return false;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case EOPNOTSUPP: return false;
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
507
lib/acl-internal.c
Normal file
507
lib/acl-internal.c
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
Copyright (C) 2002-2003, 2005-2022 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, Andreas Grünbacher, and Bruno Haible. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "acl.h"
|
||||||
|
|
||||||
|
#include "acl-internal.h"
|
||||||
|
|
||||||
|
#if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
|
||||||
|
Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial. */
|
||||||
|
int
|
||||||
|
acl_extended_nontrivial (acl_t acl)
|
||||||
|
{
|
||||||
|
/* acl is non-trivial if it is non-empty. */
|
||||||
|
return (acl_entries (acl) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# else /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
|
||||||
|
Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
|
||||||
|
Return -1 and set errno upon failure to determine it. */
|
||||||
|
int
|
||||||
|
acl_access_nontrivial (acl_t acl)
|
||||||
|
{
|
||||||
|
/* acl is non-trivial if it has some entries other than for "user::",
|
||||||
|
"group::", and "other::". Normally these three should be present
|
||||||
|
at least, allowing us to write
|
||||||
|
return (3 < acl_entries (acl));
|
||||||
|
but the following code is more robust. */
|
||||||
|
# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Cygwin >= 2.5 */
|
||||||
|
|
||||||
|
acl_entry_t ace;
|
||||||
|
int got_one;
|
||||||
|
|
||||||
|
for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
|
||||||
|
got_one > 0;
|
||||||
|
got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
|
||||||
|
{
|
||||||
|
acl_tag_t tag;
|
||||||
|
if (acl_get_tag_type (ace, &tag) < 0)
|
||||||
|
return -1;
|
||||||
|
if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return got_one;
|
||||||
|
|
||||||
|
# elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */
|
||||||
|
/* Don't use acl_get_entry: it is undocumented. */
|
||||||
|
|
||||||
|
int count = acl->acl_cnt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
acl_entry_t ace = &acl->acl_entry[i];
|
||||||
|
acl_tag_t tag = ace->ae_tag;
|
||||||
|
|
||||||
|
if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ
|
||||||
|
|| tag == ACL_OTHER_OBJ))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
# elif HAVE_ACL_FREE_TEXT /* Tru64 */
|
||||||
|
/* Don't use acl_get_entry: it takes only one argument and does not work. */
|
||||||
|
|
||||||
|
int count = acl->acl_num;
|
||||||
|
acl_entry_t ace;
|
||||||
|
|
||||||
|
for (ace = acl->acl_first; count > 0; ace = ace->next, count--)
|
||||||
|
{
|
||||||
|
acl_tag_t tag;
|
||||||
|
acl_perm_t perm;
|
||||||
|
|
||||||
|
tag = ace->entry->acl_type;
|
||||||
|
if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
perm = ace->entry->acl_perm;
|
||||||
|
/* On Tru64, perm can also contain non-standard bits such as
|
||||||
|
PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */
|
||||||
|
if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
acl_default_nontrivial (acl_t acl)
|
||||||
|
{
|
||||||
|
/* acl is non-trivial if it is non-empty. */
|
||||||
|
return (acl_entries (acl) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
|
||||||
|
|
||||||
|
/* Test an ACL retrieved with GETACL.
|
||||||
|
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
acl_nontrivial (int count, aclent_t *entries)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
aclent_t *ace = &entries[i];
|
||||||
|
|
||||||
|
/* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
|
||||||
|
If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
|
||||||
|
We don't need to check ace->a_id in these cases. */
|
||||||
|
if (!(ace->a_type == USER_OBJ
|
||||||
|
|| ace->a_type == GROUP_OBJ
|
||||||
|
|| ace->a_type == OTHER_OBJ
|
||||||
|
/* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry
|
||||||
|
sometimes. */
|
||||||
|
|| ace->a_type == CLASS_OBJ))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef ACE_GETACL
|
||||||
|
|
||||||
|
/* A shortcut for a bitmask. */
|
||||||
|
# define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA)
|
||||||
|
|
||||||
|
/* Test an ACL retrieved with ACE_GETACL.
|
||||||
|
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
acl_ace_nontrivial (int count, ace_t *entries)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* The flags in the ace_t structure changed in a binary incompatible way
|
||||||
|
when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
|
||||||
|
How to distinguish the two conventions at runtime?
|
||||||
|
In the old convention, usually three ACEs have a_flags = ACE_OWNER /
|
||||||
|
ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new
|
||||||
|
convention, these values are not used. */
|
||||||
|
int old_convention = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
|
||||||
|
{
|
||||||
|
old_convention = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_convention)
|
||||||
|
/* Running on Solaris 10. */
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ace_t *ace = &entries[i];
|
||||||
|
|
||||||
|
/* Note:
|
||||||
|
If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat().
|
||||||
|
If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat().
|
||||||
|
We don't need to check ace->a_who in these cases. */
|
||||||
|
if (!(ace->a_type == OLD_ALLOW
|
||||||
|
&& (ace->a_flags == OLD_ACE_OWNER
|
||||||
|
|| ace->a_flags == OLD_ACE_GROUP
|
||||||
|
|| ace->a_flags == OLD_ACE_OTHER)))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Running on Solaris 10 (newer version) or Solaris 11. */
|
||||||
|
unsigned int access_masks[6] =
|
||||||
|
{
|
||||||
|
0, /* owner@ deny */
|
||||||
|
0, /* owner@ allow */
|
||||||
|
0, /* group@ deny */
|
||||||
|
0, /* group@ allow */
|
||||||
|
0, /* everyone@ deny */
|
||||||
|
0 /* everyone@ allow */
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ace_t *ace = &entries[i];
|
||||||
|
unsigned int index1;
|
||||||
|
unsigned int index2;
|
||||||
|
|
||||||
|
if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
index1 = 1;
|
||||||
|
else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE)
|
||||||
|
index1 = 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ace->a_flags == NEW_ACE_OWNER)
|
||||||
|
index2 = 0;
|
||||||
|
else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP))
|
||||||
|
index2 = 2;
|
||||||
|
else if (ace->a_flags == NEW_ACE_EVERYONE)
|
||||||
|
index2 = 4;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
access_masks[index1 + index2] |= ace->a_access_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The same bit shouldn't be both allowed and denied. */
|
||||||
|
if (access_masks[0] & access_masks[1])
|
||||||
|
return 1;
|
||||||
|
if (access_masks[2] & access_masks[3])
|
||||||
|
return 1;
|
||||||
|
if (access_masks[4] & access_masks[5])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Check minimum masks. */
|
||||||
|
if ((NEW_ACE_WRITE_NAMED_ATTRS
|
||||||
|
| NEW_ACE_WRITE_ATTRIBUTES
|
||||||
|
| NEW_ACE_WRITE_ACL
|
||||||
|
| NEW_ACE_WRITE_OWNER)
|
||||||
|
& ~ access_masks[1])
|
||||||
|
return 1;
|
||||||
|
access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS
|
||||||
|
| NEW_ACE_WRITE_ATTRIBUTES
|
||||||
|
| NEW_ACE_WRITE_ACL
|
||||||
|
| NEW_ACE_WRITE_OWNER);
|
||||||
|
if ((NEW_ACE_READ_NAMED_ATTRS
|
||||||
|
| NEW_ACE_READ_ATTRIBUTES
|
||||||
|
| NEW_ACE_READ_ACL
|
||||||
|
| NEW_ACE_SYNCHRONIZE)
|
||||||
|
& ~ access_masks[5])
|
||||||
|
return 1;
|
||||||
|
access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS
|
||||||
|
| NEW_ACE_READ_ATTRIBUTES
|
||||||
|
| NEW_ACE_READ_ACL
|
||||||
|
| NEW_ACE_SYNCHRONIZE);
|
||||||
|
|
||||||
|
/* Check the allowed or denied bits. */
|
||||||
|
switch ((access_masks[0] | access_masks[1])
|
||||||
|
& ~(NEW_ACE_READ_NAMED_ATTRS
|
||||||
|
| NEW_ACE_READ_ATTRIBUTES
|
||||||
|
| NEW_ACE_READ_ACL
|
||||||
|
| NEW_ACE_SYNCHRONIZE))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case NEW_ACE_READ_DATA:
|
||||||
|
case NEW_ACE_WRITEA_DATA:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
|
||||||
|
case NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
switch ((access_masks[2] | access_masks[3])
|
||||||
|
& ~(NEW_ACE_READ_NAMED_ATTRS
|
||||||
|
| NEW_ACE_READ_ATTRIBUTES
|
||||||
|
| NEW_ACE_READ_ACL
|
||||||
|
| NEW_ACE_SYNCHRONIZE))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case NEW_ACE_READ_DATA:
|
||||||
|
case NEW_ACE_WRITEA_DATA:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
|
||||||
|
case NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
switch ((access_masks[4] | access_masks[5])
|
||||||
|
& ~(NEW_ACE_WRITE_NAMED_ATTRS
|
||||||
|
| NEW_ACE_WRITE_ATTRIBUTES
|
||||||
|
| NEW_ACE_WRITE_ACL
|
||||||
|
| NEW_ACE_WRITE_OWNER))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case NEW_ACE_READ_DATA:
|
||||||
|
case NEW_ACE_WRITEA_DATA:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
|
||||||
|
case NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
|
||||||
|
case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are
|
||||||
|
either both allowed or both denied. */
|
||||||
|
if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0)
|
||||||
|
!= ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0))
|
||||||
|
return 1;
|
||||||
|
if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0)
|
||||||
|
!= ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0))
|
||||||
|
return 1;
|
||||||
|
if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0)
|
||||||
|
!= ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif USE_ACL && HAVE_GETACL /* HP-UX */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
acl_nontrivial (int count, struct acl_entry *entries)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (count > 3)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
struct acl_entry *ace = &entries[i];
|
||||||
|
|
||||||
|
if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# if HAVE_ACLV_H /* HP-UX >= 11.11 */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
aclv_nontrivial (int count, struct acl *entries)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
struct acl *ace = &entries[i];
|
||||||
|
|
||||||
|
/* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
|
||||||
|
If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
|
||||||
|
We don't need to check ace->a_id in these cases. */
|
||||||
|
if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
|
||||||
|
|| ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
|
||||||
|
|| ace->a_type == CLASS_OBJ
|
||||||
|
|| ace->a_type == OTHER_OBJ))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
acl_nontrivial (struct acl *a)
|
||||||
|
{
|
||||||
|
/* The normal way to iterate through an ACL is like this:
|
||||||
|
struct acl_entry *ace;
|
||||||
|
for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
|
||||||
|
{
|
||||||
|
struct ace_id *aei;
|
||||||
|
switch (ace->ace_type)
|
||||||
|
{
|
||||||
|
case ACC_PERMIT:
|
||||||
|
case ACC_DENY:
|
||||||
|
case ACC_SPECIFY:
|
||||||
|
...;
|
||||||
|
}
|
||||||
|
for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
|
||||||
|
...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return (acl_last (a) != a->acl_ext ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
acl_nfs4_nontrivial (nfs4_acl_int_t *a)
|
||||||
|
{
|
||||||
|
# if 1 /* let's try this first */
|
||||||
|
return (a->aclEntryN > 0 ? 1 : 0);
|
||||||
|
# else
|
||||||
|
int count = a->aclEntryN;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
nfs4_ace_int_t *ace = &a->aclEntry[i];
|
||||||
|
|
||||||
|
if (!((ace->flags & ACE4_ID_SPECIAL) != 0
|
||||||
|
&& (ace->aceWho.special_whoid == ACE4_WHO_OWNER
|
||||||
|
|| ace->aceWho.special_whoid == ACE4_WHO_GROUP
|
||||||
|
|| ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
|
||||||
|
&& ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
|
||||||
|
&& ace->aceFlags == 0
|
||||||
|
&& (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
|
||||||
|
| ACE4_WRITE_DATA | ACE4_ADD_FILE
|
||||||
|
| ACE4_EXECUTE)) == 0))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
|
||||||
|
|
||||||
|
/* Test an ACL retrieved with ACL_GET.
|
||||||
|
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
int
|
||||||
|
acl_nontrivial (int count, struct acl *entries)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
struct acl *ace = &entries[i];
|
||||||
|
|
||||||
|
/* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
|
||||||
|
If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
|
||||||
|
We don't need to check ace->a_id in these cases. */
|
||||||
|
if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
|
||||||
|
|| ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
|
||||||
|
|| ace->a_type == CLASS_OBJ
|
||||||
|
|| ace->a_type == OTHER_OBJ))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
free_permission_context (struct permission_context *ctx)
|
||||||
|
{
|
||||||
|
#if USE_ACL
|
||||||
|
# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
if (ctx->acl)
|
||||||
|
acl_free (ctx->acl);
|
||||||
|
# if !HAVE_ACL_TYPE_EXTENDED
|
||||||
|
if (ctx->default_acl)
|
||||||
|
acl_free (ctx->default_acl);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif defined GETACL /* Solaris, Cygwin < 2.5 */
|
||||||
|
free (ctx->entries);
|
||||||
|
# ifdef ACE_GETACL
|
||||||
|
free (ctx->ace_entries);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_GETACL /* HP-UX */
|
||||||
|
|
||||||
|
# if HAVE_ACLV_H
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_STATACL /* older AIX */
|
||||||
|
|
||||||
|
# elif HAVE_ACLSORT /* NonStop Kernel */
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
302
lib/acl-internal.h
Normal file
302
lib/acl-internal.h
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/* Internal implementation of access control lists. -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
Copyright (C) 2002-2003, 2005-2022 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, Andreas Grünbacher, and Bruno Haible. */
|
||||||
|
|
||||||
|
#include "acl.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* All systems define the ACL related API in <sys/acl.h>. */
|
||||||
|
#if HAVE_SYS_ACL_H
|
||||||
|
# include <sys/acl.h>
|
||||||
|
#endif
|
||||||
|
#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT
|
||||||
|
# define GETACLCNT ACL_CNT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* On Linux and Cygwin >= 2.5, additional ACL related API is available in
|
||||||
|
<acl/libacl.h>. */
|
||||||
|
#ifdef HAVE_ACL_LIBACL_H
|
||||||
|
# include <acl/libacl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* On HP-UX >= 11.11, additional ACL API is available in <aclv.h>. */
|
||||||
|
#if HAVE_ACLV_H
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <aclv.h>
|
||||||
|
/* HP-UX 11.11 lacks these declarations. */
|
||||||
|
extern int acl (char *, int, int, struct acl *);
|
||||||
|
extern int aclsort (int, int, struct acl *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#ifndef MIN
|
||||||
|
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX
|
||||||
|
# define SIZE_MAX ((size_t) -1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_FCHMOD
|
||||||
|
# define HAVE_FCHMOD false
|
||||||
|
# define fchmod(fd, mode) (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _GL_INLINE_HEADER_BEGIN
|
||||||
|
#error "Please include config.h first."
|
||||||
|
#endif
|
||||||
|
_GL_INLINE_HEADER_BEGIN
|
||||||
|
#ifndef ACL_INTERNAL_INLINE
|
||||||
|
# define ACL_INTERNAL_INLINE _GL_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_ACL
|
||||||
|
|
||||||
|
# if HAVE_ACL_GET_FILE
|
||||||
|
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
|
||||||
|
/* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
|
||||||
|
# ifndef MIN_ACL_ENTRIES
|
||||||
|
# define MIN_ACL_ENTRIES 4
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* POSIX 1003.1e (draft 17) */
|
||||||
|
# ifdef HAVE_ACL_GET_FD
|
||||||
|
/* Most platforms have a 1-argument acl_get_fd, only OSF/1 has a 2-argument
|
||||||
|
macro(!). */
|
||||||
|
# if HAVE_ACL_FREE_TEXT /* OSF/1 */
|
||||||
|
ACL_INTERNAL_INLINE acl_t
|
||||||
|
rpl_acl_get_fd (int fd)
|
||||||
|
{
|
||||||
|
return acl_get_fd (fd, ACL_TYPE_ACCESS);
|
||||||
|
}
|
||||||
|
# undef acl_get_fd
|
||||||
|
# define acl_get_fd rpl_acl_get_fd
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define HAVE_ACL_GET_FD false
|
||||||
|
# undef acl_get_fd
|
||||||
|
# define acl_get_fd(fd) (NULL)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* POSIX 1003.1e (draft 17) */
|
||||||
|
# ifdef HAVE_ACL_SET_FD
|
||||||
|
/* Most platforms have a 2-argument acl_set_fd, only OSF/1 has a 3-argument
|
||||||
|
macro(!). */
|
||||||
|
# if HAVE_ACL_FREE_TEXT /* OSF/1 */
|
||||||
|
ACL_INTERNAL_INLINE int
|
||||||
|
rpl_acl_set_fd (int fd, acl_t acl)
|
||||||
|
{
|
||||||
|
return acl_set_fd (fd, ACL_TYPE_ACCESS, acl);
|
||||||
|
}
|
||||||
|
# undef acl_set_fd
|
||||||
|
# define acl_set_fd rpl_acl_set_fd
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define HAVE_ACL_SET_FD false
|
||||||
|
# undef acl_set_fd
|
||||||
|
# define acl_set_fd(fd, acl) (-1)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* POSIX 1003.1e (draft 13) */
|
||||||
|
# if ! HAVE_ACL_FREE_TEXT
|
||||||
|
# define acl_free_text(buf) acl_free (buf)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Linux-specific */
|
||||||
|
/* Cygwin >= 2.5 implements this function, but it returns 1 for all
|
||||||
|
directories, thus is unusable. */
|
||||||
|
# if !defined HAVE_ACL_EXTENDED_FILE || defined __CYGWIN__
|
||||||
|
# undef HAVE_ACL_EXTENDED_FILE
|
||||||
|
# define HAVE_ACL_EXTENDED_FILE false
|
||||||
|
# define acl_extended_file(name) (-1)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if ! defined HAVE_ACL_FROM_MODE && ! defined HAVE_ACL_FROM_TEXT
|
||||||
|
# define acl_from_mode (NULL)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Set to 0 if a file's mode is stored independently from the ACL. */
|
||||||
|
# if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */
|
||||||
|
# define MODE_INSIDE_ACL 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Return the number of entries in ACL.
|
||||||
|
Return -1 and set errno upon failure to determine it. */
|
||||||
|
/* Define a replacement for acl_entries if needed. (Only Linux has it.) */
|
||||||
|
# if !HAVE_ACL_ENTRIES
|
||||||
|
# define acl_entries rpl_acl_entries
|
||||||
|
extern int acl_entries (acl_t);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
|
||||||
|
Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial. */
|
||||||
|
extern int acl_extended_nontrivial (acl_t);
|
||||||
|
# else
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
|
||||||
|
Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
|
||||||
|
Return -1 and set errno upon failure to determine it. */
|
||||||
|
extern int acl_access_nontrivial (acl_t);
|
||||||
|
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_DEFAULT.
|
||||||
|
Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
|
||||||
|
Return -1 and set errno upon failure to determine it. */
|
||||||
|
extern int acl_default_nontrivial (acl_t);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
|
||||||
|
|
||||||
|
/* Set to 0 if a file's mode is stored independently from the ACL. */
|
||||||
|
# if defined __CYGWIN__ /* Cygwin */
|
||||||
|
# define MODE_INSIDE_ACL 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
extern int acl_nontrivial (int count, aclent_t *entries) _GL_ATTRIBUTE_PURE;
|
||||||
|
|
||||||
|
# ifdef ACE_GETACL /* Solaris 10 */
|
||||||
|
|
||||||
|
/* Test an ACL retrieved with ACE_GETACL.
|
||||||
|
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE;
|
||||||
|
|
||||||
|
/* Definitions for when the built executable is executed on Solaris 10
|
||||||
|
(newer version) or Solaris 11. */
|
||||||
|
/* For a_type. */
|
||||||
|
# define OLD_ALLOW 0
|
||||||
|
# define OLD_DENY 1
|
||||||
|
# define NEW_ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */
|
||||||
|
# define NEW_ACE_ACCESS_DENIED_ACE_TYPE 1 /* replaces DENY */
|
||||||
|
/* For a_flags. */
|
||||||
|
# define OLD_ACE_OWNER 0x0100
|
||||||
|
# define OLD_ACE_GROUP 0x0200
|
||||||
|
# define OLD_ACE_OTHER 0x0400
|
||||||
|
# define NEW_ACE_OWNER 0x1000
|
||||||
|
# define NEW_ACE_GROUP 0x2000
|
||||||
|
# define NEW_ACE_IDENTIFIER_GROUP 0x0040
|
||||||
|
# define NEW_ACE_EVERYONE 0x4000
|
||||||
|
/* For a_access_mask. */
|
||||||
|
# define NEW_ACE_READ_DATA 0x001 /* corresponds to 'r' */
|
||||||
|
# define NEW_ACE_WRITE_DATA 0x002 /* corresponds to 'w' */
|
||||||
|
# define NEW_ACE_APPEND_DATA 0x004
|
||||||
|
# define NEW_ACE_READ_NAMED_ATTRS 0x008
|
||||||
|
# define NEW_ACE_WRITE_NAMED_ATTRS 0x010
|
||||||
|
# define NEW_ACE_EXECUTE 0x020
|
||||||
|
# define NEW_ACE_DELETE_CHILD 0x040
|
||||||
|
# define NEW_ACE_READ_ATTRIBUTES 0x080
|
||||||
|
# define NEW_ACE_WRITE_ATTRIBUTES 0x100
|
||||||
|
# define NEW_ACE_DELETE 0x10000
|
||||||
|
# define NEW_ACE_READ_ACL 0x20000
|
||||||
|
# define NEW_ACE_WRITE_ACL 0x40000
|
||||||
|
# define NEW_ACE_WRITE_OWNER 0x80000
|
||||||
|
# define NEW_ACE_SYNCHRONIZE 0x100000
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_GETACL /* HP-UX */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
extern int acl_nontrivial (int count, struct acl_entry *entries);
|
||||||
|
|
||||||
|
# if HAVE_ACLV_H /* HP-UX >= 11.11 */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
extern int aclv_nontrivial (int count, struct acl *entries);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_ACLX_GET && 0 /* AIX */
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
# elif HAVE_STATACL /* older AIX */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
extern int acl_nontrivial (struct acl *a);
|
||||||
|
|
||||||
|
# elif HAVE_ACLSORT /* NonStop Kernel */
|
||||||
|
|
||||||
|
/* Return 1 if the given ACL is non-trivial.
|
||||||
|
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
|
||||||
|
extern int acl_nontrivial (int count, struct acl *entries);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Set to 1 if a file's mode is implicit by the ACL. */
|
||||||
|
# ifndef MODE_INSIDE_ACL
|
||||||
|
# define MODE_INSIDE_ACL 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct permission_context {
|
||||||
|
mode_t mode;
|
||||||
|
#if USE_ACL
|
||||||
|
# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
acl_t acl;
|
||||||
|
# if !HAVE_ACL_TYPE_EXTENDED
|
||||||
|
acl_t default_acl;
|
||||||
|
# endif
|
||||||
|
bool acls_not_supported;
|
||||||
|
|
||||||
|
# elif defined GETACL /* Solaris, Cygwin < 2.5 */
|
||||||
|
int count;
|
||||||
|
aclent_t *entries;
|
||||||
|
# ifdef ACE_GETACL
|
||||||
|
int ace_count;
|
||||||
|
ace_t *ace_entries;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_GETACL /* HP-UX */
|
||||||
|
struct acl_entry entries[NACLENTRIES];
|
||||||
|
int count;
|
||||||
|
# if HAVE_ACLV_H
|
||||||
|
struct acl aclv_entries[NACLVENTRIES];
|
||||||
|
int aclv_count;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif HAVE_STATACL /* older AIX */
|
||||||
|
union { struct acl a; char room[4096]; } u;
|
||||||
|
bool have_u;
|
||||||
|
|
||||||
|
# elif HAVE_ACLSORT /* NonStop Kernel */
|
||||||
|
struct acl entries[NACLENTRIES];
|
||||||
|
int count;
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
int get_permissions (const char *, int, mode_t, struct permission_context *);
|
||||||
|
int set_permissions (struct permission_context *, const char *, int);
|
||||||
|
void free_permission_context (struct permission_context *);
|
||||||
|
|
||||||
|
_GL_INLINE_HEADER_END
|
||||||
35
lib/acl.h
Normal file
35
lib/acl.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* acl.c - access control lists
|
||||||
|
|
||||||
|
Copyright (C) 2002, 2008-2022 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_ACL_H
|
||||||
|
#define _GL_ACL_H 1
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST;
|
||||||
|
int file_has_acl (char const *, struct stat const *);
|
||||||
|
int qset_acl (char const *, int, mode_t);
|
||||||
|
int set_acl (char const *, int, mode_t);
|
||||||
|
int qcopy_acl (char const *, int, char const *, int, mode_t);
|
||||||
|
int copy_acl (char const *, int, char const *, int, mode_t);
|
||||||
|
int chmod_or_fchmod (char const *, int, mode_t);
|
||||||
|
|
||||||
|
#endif
|
||||||
75
lib/acl_entries.c
Normal file
75
lib/acl_entries.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* Return the number of entries in an ACL.
|
||||||
|
|
||||||
|
Copyright (C) 2002-2003, 2005-2022 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 and Andreas Gruenbacher. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "acl-internal.h"
|
||||||
|
|
||||||
|
/* This file assumes POSIX-draft like ACLs
|
||||||
|
(Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5). */
|
||||||
|
|
||||||
|
/* Return the number of entries in ACL.
|
||||||
|
Return -1 and set errno upon failure to determine it. */
|
||||||
|
|
||||||
|
int
|
||||||
|
acl_entries (acl_t acl)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (acl != NULL)
|
||||||
|
{
|
||||||
|
#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X, Cygwin >= 2.5 */
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
/* acl_get_entry returns 0 when it successfully fetches an entry,
|
||||||
|
and -1/EINVAL at the end. */
|
||||||
|
acl_entry_t ace;
|
||||||
|
int got_one;
|
||||||
|
|
||||||
|
for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
|
||||||
|
got_one >= 0;
|
||||||
|
got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
|
||||||
|
count++;
|
||||||
|
# else /* Linux, FreeBSD, Cygwin >= 2.5 */
|
||||||
|
/* acl_get_entry returns 1 when it successfully fetches an entry,
|
||||||
|
and 0 at the end. */
|
||||||
|
acl_entry_t ace;
|
||||||
|
int got_one;
|
||||||
|
|
||||||
|
for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
|
||||||
|
got_one > 0;
|
||||||
|
got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
|
||||||
|
count++;
|
||||||
|
if (got_one < 0)
|
||||||
|
return -1;
|
||||||
|
# endif
|
||||||
|
#else /* IRIX, Tru64 */
|
||||||
|
# if HAVE_ACL_TO_SHORT_TEXT /* IRIX */
|
||||||
|
/* Don't use acl_get_entry: it is undocumented. */
|
||||||
|
count = acl->acl_cnt;
|
||||||
|
# endif
|
||||||
|
# if HAVE_ACL_FREE_TEXT /* Tru64 */
|
||||||
|
/* Don't use acl_get_entry: it takes only one argument and does not
|
||||||
|
work. */
|
||||||
|
count = acl->acl_num;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
52
lib/alignof.h
Normal file
52
lib/alignof.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Determine alignment of types.
|
||||||
|
Copyright (C) 2003-2004, 2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 _ALIGNOF_H
|
||||||
|
#define _ALIGNOF_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* alignof_slot (TYPE)
|
||||||
|
Determine the alignment of a structure slot (field) of a given type,
|
||||||
|
at compile time. Note that the result depends on the ABI.
|
||||||
|
This is the same as alignof (TYPE) and _Alignof (TYPE), defined in
|
||||||
|
<stdalign.h> if __alignof_is_defined is 1.
|
||||||
|
Note: The result cannot be used as a value for an 'enum' constant,
|
||||||
|
due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */
|
||||||
|
#if defined __cplusplus
|
||||||
|
template <class type> struct alignof_helper { char __slot1; type __slot2; };
|
||||||
|
# define alignof_slot(type) offsetof (alignof_helper<type>, __slot2)
|
||||||
|
#else
|
||||||
|
# define alignof_slot(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* alignof_type (TYPE)
|
||||||
|
Determine the good alignment of an object of the given type at compile time.
|
||||||
|
Note that this is not necessarily the same as alignof_slot(type).
|
||||||
|
For example, with GNU C on x86 platforms and with clang on Linux/x86:
|
||||||
|
alignof_type(long long) = 8, but alignof_slot(long long) = 4.
|
||||||
|
And alignof_type(double) = 8, but
|
||||||
|
- when -malign-double is not specified: alignof_slot(double) = 4,
|
||||||
|
- when -malign-double is specified: alignof_slot(double) = 8.
|
||||||
|
Note: The result cannot be used as a value for an 'enum' constant,
|
||||||
|
due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */
|
||||||
|
#if defined __GNUC__ || defined __clang__ || defined __IBM__ALIGNOF__
|
||||||
|
# define alignof_type __alignof__
|
||||||
|
#else
|
||||||
|
# define alignof_type alignof_slot
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ALIGNOF_H */
|
||||||
202
lib/alloca.c
Normal file
202
lib/alloca.c
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/* alloca.c -- allocate automatically reclaimed memory
|
||||||
|
This file is in the public domain. */
|
||||||
|
|
||||||
|
/* (Mostly) portable implementation -- D A Gwyn
|
||||||
|
|
||||||
|
This implementation of the PWB library alloca function,
|
||||||
|
which is used to allocate space off the run-time stack so
|
||||||
|
that it is automatically reclaimed upon procedure exit,
|
||||||
|
was inspired by discussions with J. Q. Johnson of Cornell.
|
||||||
|
J.Otto Tennant <jot@cray.com> contributed the Cray support.
|
||||||
|
|
||||||
|
There are some preprocessor constants that can
|
||||||
|
be defined when compiling for your specific system, for
|
||||||
|
improved efficiency; however, the defaults should be okay.
|
||||||
|
|
||||||
|
The general concept of this implementation is to keep
|
||||||
|
track of all alloca-allocated blocks, and reclaim any
|
||||||
|
that are found to be deeper in the stack than the current
|
||||||
|
invocation. This heuristic does not reclaim storage as
|
||||||
|
soon as it becomes invalid, but it will do so eventually.
|
||||||
|
|
||||||
|
As a special case, alloca(0) reclaims storage without
|
||||||
|
allocating any. It is a good idea to use alloca(0) in
|
||||||
|
your main control loop, etc. to force garbage collection. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <alloca.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef emacs
|
||||||
|
# include "lisp.h"
|
||||||
|
# include "blockinput.h"
|
||||||
|
# ifdef EMACS_FREE
|
||||||
|
# undef free
|
||||||
|
# define free EMACS_FREE
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define memory_full() abort ()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If compiling with GCC or clang, this file is not needed. */
|
||||||
|
#if !(defined __GNUC__ || defined __clang__)
|
||||||
|
|
||||||
|
/* If someone has defined alloca as a macro,
|
||||||
|
there must be some other way alloca is supposed to work. */
|
||||||
|
# ifndef alloca
|
||||||
|
|
||||||
|
# ifdef emacs
|
||||||
|
# ifdef static
|
||||||
|
/* actually, only want this if static is defined as ""
|
||||||
|
-- this is for usg, in which emacs must undefine static
|
||||||
|
in order to make unexec workable
|
||||||
|
*/
|
||||||
|
# ifndef STACK_DIRECTION
|
||||||
|
you
|
||||||
|
lose
|
||||||
|
-- must know STACK_DIRECTION at compile-time
|
||||||
|
/* Using #error here is not wise since this file should work for
|
||||||
|
old and obscure compilers. */
|
||||||
|
# endif /* STACK_DIRECTION undefined */
|
||||||
|
# endif /* static */
|
||||||
|
# endif /* emacs */
|
||||||
|
|
||||||
|
/* Define STACK_DIRECTION if you know the direction of stack
|
||||||
|
growth for your system; otherwise it will be automatically
|
||||||
|
deduced at run-time.
|
||||||
|
|
||||||
|
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||||
|
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||||
|
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||||
|
|
||||||
|
# ifndef STACK_DIRECTION
|
||||||
|
# define STACK_DIRECTION 0 /* Direction unknown. */
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if STACK_DIRECTION != 0
|
||||||
|
|
||||||
|
# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||||
|
|
||||||
|
# else /* STACK_DIRECTION == 0; need run-time code. */
|
||||||
|
|
||||||
|
static int stack_dir; /* 1 or -1 once known. */
|
||||||
|
# define STACK_DIR stack_dir
|
||||||
|
|
||||||
|
static int
|
||||||
|
find_stack_direction (int *addr, int depth)
|
||||||
|
{
|
||||||
|
int dir, dummy = 0;
|
||||||
|
if (! addr)
|
||||||
|
addr = &dummy;
|
||||||
|
*addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
|
||||||
|
dir = depth ? find_stack_direction (addr, depth - 1) : 0;
|
||||||
|
return dir + dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif /* STACK_DIRECTION == 0 */
|
||||||
|
|
||||||
|
/* An "alloca header" is used to:
|
||||||
|
(a) chain together all alloca'ed blocks;
|
||||||
|
(b) keep track of stack depth.
|
||||||
|
|
||||||
|
It is very important that sizeof(header) agree with malloc
|
||||||
|
alignment chunk size. The following default should work okay. */
|
||||||
|
|
||||||
|
# ifndef ALIGN_SIZE
|
||||||
|
# define ALIGN_SIZE sizeof(double)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
typedef union hdr
|
||||||
|
{
|
||||||
|
char align[ALIGN_SIZE]; /* To force sizeof(header). */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
union hdr *next; /* For chaining headers. */
|
||||||
|
char *deep; /* For stack depth measure. */
|
||||||
|
} h;
|
||||||
|
} header;
|
||||||
|
|
||||||
|
static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||||
|
|
||||||
|
/* Return a pointer to at least SIZE bytes of storage,
|
||||||
|
which will be automatically reclaimed upon exit from
|
||||||
|
the procedure that called alloca. Originally, this space
|
||||||
|
was supposed to be taken from the current stack frame of the
|
||||||
|
caller, but that method cannot be made to work for some
|
||||||
|
implementations of C, for example under Gould's UTX/32. */
|
||||||
|
|
||||||
|
void *
|
||||||
|
alloca (size_t size)
|
||||||
|
{
|
||||||
|
auto char probe; /* Probes stack depth: */
|
||||||
|
register char *depth = &probe;
|
||||||
|
|
||||||
|
# if STACK_DIRECTION == 0
|
||||||
|
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||||
|
STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Reclaim garbage, defined as all alloca'd storage that
|
||||||
|
was allocated from deeper in the stack than currently. */
|
||||||
|
|
||||||
|
{
|
||||||
|
register header *hp; /* Traverses linked list. */
|
||||||
|
|
||||||
|
# ifdef emacs
|
||||||
|
BLOCK_INPUT;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
for (hp = last_alloca_header; hp != NULL;)
|
||||||
|
if ((STACK_DIR > 0 && hp->h.deep > depth)
|
||||||
|
|| (STACK_DIR < 0 && hp->h.deep < depth))
|
||||||
|
{
|
||||||
|
register header *np = hp->h.next;
|
||||||
|
|
||||||
|
free (hp); /* Collect garbage. */
|
||||||
|
|
||||||
|
hp = np; /* -> next header. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break; /* Rest are not deeper. */
|
||||||
|
|
||||||
|
last_alloca_header = hp; /* -> last valid storage. */
|
||||||
|
|
||||||
|
# ifdef emacs
|
||||||
|
UNBLOCK_INPUT;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return NULL; /* No allocation required. */
|
||||||
|
|
||||||
|
/* Allocate combined header + user data storage. */
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Address of header. */
|
||||||
|
register header *new;
|
||||||
|
|
||||||
|
size_t combined_size = sizeof (header) + size;
|
||||||
|
if (combined_size < sizeof (header))
|
||||||
|
memory_full ();
|
||||||
|
|
||||||
|
new = malloc (combined_size);
|
||||||
|
|
||||||
|
if (! new)
|
||||||
|
memory_full ();
|
||||||
|
|
||||||
|
new->h.next = last_alloca_header;
|
||||||
|
new->h.deep = depth;
|
||||||
|
|
||||||
|
last_alloca_header = new;
|
||||||
|
|
||||||
|
/* User storage begins just after header. */
|
||||||
|
|
||||||
|
return (void *) (new + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif /* no alloca */
|
||||||
|
#endif /* not GCC || clang */
|
||||||
72
lib/alloca.in.h
Normal file
72
lib/alloca.in.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* Memory allocation on the stack.
|
||||||
|
|
||||||
|
Copyright (C) 1995, 1999, 2001-2004, 2006-2022 Free Software Foundation,
|
||||||
|
Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
/* 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 needed. */
|
||||||
|
# if defined __GNUC__ && (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@
|
||||||
|
# include_next <alloca.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef alloca
|
||||||
|
# if defined __GNUC__ || (__clang_major__ >= 4)
|
||||||
|
# define alloca __builtin_alloca
|
||||||
|
# elif defined _AIX
|
||||||
|
# define alloca __alloca
|
||||||
|
# elif defined _MSC_VER
|
||||||
|
# include <malloc.h>
|
||||||
|
# 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__
|
||||||
|
# include <stdlib.h>
|
||||||
|
# else
|
||||||
|
# include <stddef.h>
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
# endif
|
||||||
|
void *alloca (size_t);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _GL_ALLOCA_H */
|
||||||
26
lib/arg-nonnull.h
Normal file
26
lib/arg-nonnull.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* A C macro for declaring that specific arguments must not be NULL.
|
||||||
|
Copyright (C) 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program 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 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
/* _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__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__
|
||||||
|
# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
|
||||||
|
# else
|
||||||
|
# define _GL_ARG_NONNULL(params)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
34
lib/asnprintf.c
Normal file
34
lib/asnprintf.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* Formatted output to strings.
|
||||||
|
Copyright (C) 1999, 2002, 2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "vasnprintf.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
char *
|
||||||
|
asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
result = vasnprintf (resultbuf, lengthp, format, args);
|
||||||
|
va_end (args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
39
lib/asprintf.c
Normal file
39
lib/asprintf.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* Formatted output to strings.
|
||||||
|
Copyright (C) 1999, 2002, 2006-2007, 2009-2022 Free Software Foundation,
|
||||||
|
Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#ifdef IN_LIBASPRINTF
|
||||||
|
# include "vasprintf.h"
|
||||||
|
#else
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
asprintf (char **resultp, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
result = vasprintf (resultp, format, args);
|
||||||
|
va_end (args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
57
lib/assure.h
Normal file
57
lib/assure.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* Run-time assert-like macros.
|
||||||
|
|
||||||
|
Copyright (C) 2014-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 Paul Eggert. */
|
||||||
|
|
||||||
|
#ifndef _GL_ASSURE_H
|
||||||
|
#define _GL_ASSURE_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "verify.h"
|
||||||
|
|
||||||
|
/* Evaluate an assertion E that is guaranteed to be true.
|
||||||
|
If NDEBUG is not defined, abort the program if E is false.
|
||||||
|
If NDEBUG is defined, the compiler can assume E and behavior is
|
||||||
|
undefined if E is false, fails to evaluate, or has side effects.
|
||||||
|
|
||||||
|
Unlike standard 'assert', this macro evaluates E even when NDEBUG
|
||||||
|
is defined, so as to catch typos, avoid some GCC warnings, and
|
||||||
|
improve performance when E is simple enough.
|
||||||
|
|
||||||
|
Also see the documentation for 'assume' in verify.h. */
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
# define affirm(E) assume (E)
|
||||||
|
#else
|
||||||
|
# define affirm(E) assert (E)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check E's value at runtime, and report an error and abort if not.
|
||||||
|
However, do nothing if NDEBUG is defined.
|
||||||
|
|
||||||
|
Unlike standard 'assert', this macro compiles E even when NDEBUG
|
||||||
|
is defined, so as to catch typos and avoid some GCC warnings.
|
||||||
|
Unlike 'affirm', it is OK for E to use hard-to-optimize features,
|
||||||
|
since E is not executed if NDEBUG is defined. */
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
# define assure(E) ((void) (0 && (E)))
|
||||||
|
#else
|
||||||
|
# define assure(E) assert (E)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
146
lib/at-func.c
Normal file
146
lib/at-func.c
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
|
||||||
|
Copyright (C) 2006, 2009-2022 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 Jim Meyering */
|
||||||
|
|
||||||
|
#include "filename.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
|
||||||
|
|
||||||
|
#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
|
||||||
|
# include <errno.h>
|
||||||
|
# ifndef ENOTSUP
|
||||||
|
# define ENOTSUP EINVAL
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# include "openat.h"
|
||||||
|
# include "openat-priv.h"
|
||||||
|
# include "save-cwd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AT_FUNC_USE_F1_COND
|
||||||
|
# define CALL_FUNC(F) \
|
||||||
|
(flag == AT_FUNC_USE_F1_COND \
|
||||||
|
? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
|
||||||
|
: AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
|
||||||
|
# define VALIDATE_FLAG(F) \
|
||||||
|
if (flag & ~AT_FUNC_USE_F1_COND) \
|
||||||
|
{ \
|
||||||
|
errno = EINVAL; \
|
||||||
|
return FUNC_FAIL; \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
|
||||||
|
# define VALIDATE_FLAG(F) /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AT_FUNC_RESULT
|
||||||
|
# define FUNC_RESULT AT_FUNC_RESULT
|
||||||
|
#else
|
||||||
|
# define FUNC_RESULT int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AT_FUNC_FAIL
|
||||||
|
# define FUNC_FAIL AT_FUNC_FAIL
|
||||||
|
#else
|
||||||
|
# define FUNC_FAIL -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
|
||||||
|
open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value,
|
||||||
|
AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag;
|
||||||
|
call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
|
||||||
|
AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT
|
||||||
|
or AT_FUNC_FAIL are defined. If possible, do it without changing the
|
||||||
|
working directory. Otherwise, resort to using save_cwd/fchdir,
|
||||||
|
then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
|
||||||
|
fails, then give a diagnostic and exit nonzero. */
|
||||||
|
FUNC_RESULT
|
||||||
|
AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
|
||||||
|
{
|
||||||
|
VALIDATE_FLAG (flag);
|
||||||
|
|
||||||
|
if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
|
||||||
|
return CALL_FUNC (file);
|
||||||
|
|
||||||
|
#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return FUNC_FAIL;
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* Be careful to choose names unlikely to conflict with
|
||||||
|
AT_FUNC_POST_FILE_PARAM_DECLS. */
|
||||||
|
struct saved_cwd saved_cwd;
|
||||||
|
int saved_errno;
|
||||||
|
FUNC_RESULT err;
|
||||||
|
|
||||||
|
{
|
||||||
|
char proc_buf[OPENAT_BUFFER_SIZE];
|
||||||
|
char *proc_file = openat_proc_name (proc_buf, fd, file);
|
||||||
|
if (proc_file)
|
||||||
|
{
|
||||||
|
FUNC_RESULT proc_result = CALL_FUNC (proc_file);
|
||||||
|
int proc_errno = errno;
|
||||||
|
if (proc_file != proc_buf)
|
||||||
|
free (proc_file);
|
||||||
|
/* If the syscall succeeds, or if it fails with an unexpected
|
||||||
|
errno value, then return right away. Otherwise, fall through
|
||||||
|
and resort to using save_cwd/restore_cwd. */
|
||||||
|
if (FUNC_FAIL != proc_result)
|
||||||
|
return proc_result;
|
||||||
|
if (! EXPECTED_ERRNO (proc_errno))
|
||||||
|
{
|
||||||
|
errno = proc_errno;
|
||||||
|
return proc_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_cwd (&saved_cwd) != 0)
|
||||||
|
openat_save_fail (errno);
|
||||||
|
if (0 <= fd && fd == saved_cwd.desc)
|
||||||
|
{
|
||||||
|
/* If saving the working directory collides with the user's
|
||||||
|
requested fd, then the user's fd must have been closed to
|
||||||
|
begin with. */
|
||||||
|
free_cwd (&saved_cwd);
|
||||||
|
errno = EBADF;
|
||||||
|
return FUNC_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fchdir (fd) != 0)
|
||||||
|
{
|
||||||
|
saved_errno = errno;
|
||||||
|
free_cwd (&saved_cwd);
|
||||||
|
errno = saved_errno;
|
||||||
|
return FUNC_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CALL_FUNC (file);
|
||||||
|
saved_errno = (err == FUNC_FAIL ? errno : 0);
|
||||||
|
|
||||||
|
if (restore_cwd (&saved_cwd) != 0)
|
||||||
|
openat_restore_fail (errno);
|
||||||
|
|
||||||
|
free_cwd (&saved_cwd);
|
||||||
|
|
||||||
|
if (saved_errno)
|
||||||
|
errno = saved_errno;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#undef CALL_FUNC
|
||||||
|
#undef FUNC_RESULT
|
||||||
|
#undef FUNC_FAIL
|
||||||
226
lib/attribute.h
Normal file
226
lib/attribute.h
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers
|
||||||
|
|
||||||
|
Copyright 2020-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 Paul Eggert. */
|
||||||
|
|
||||||
|
/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_*
|
||||||
|
macros used within Gnulib. */
|
||||||
|
|
||||||
|
/* These attributes can be placed in two ways:
|
||||||
|
- At the start of a declaration (i.e. even before storage-class
|
||||||
|
specifiers!); then they apply to all entities that are declared
|
||||||
|
by the declaration.
|
||||||
|
- Immediately after the name of an entity being declared by the
|
||||||
|
declaration; then they apply to that entity only. */
|
||||||
|
|
||||||
|
#ifndef _GL_ATTRIBUTE_H
|
||||||
|
#define _GL_ATTRIBUTE_H
|
||||||
|
|
||||||
|
|
||||||
|
/* This file defines two types of attributes:
|
||||||
|
* C2x standard attributes. These have macro names that do not begin with
|
||||||
|
'ATTRIBUTE_'.
|
||||||
|
* Selected GCC attributes; see:
|
||||||
|
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
|
||||||
|
https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
|
||||||
|
https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
|
||||||
|
These names begin with 'ATTRIBUTE_' to avoid name clashes. */
|
||||||
|
|
||||||
|
|
||||||
|
/* =============== Attributes for specific kinds of functions =============== */
|
||||||
|
|
||||||
|
/* Attributes for functions that should not be used. */
|
||||||
|
|
||||||
|
/* Warn if the entity is used. */
|
||||||
|
/* Applies to:
|
||||||
|
- function, variable,
|
||||||
|
- struct, union, struct/union member,
|
||||||
|
- enumeration, enumeration item,
|
||||||
|
- typedef,
|
||||||
|
in C++ also: namespace, class, template specialization. */
|
||||||
|
#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED
|
||||||
|
|
||||||
|
/* If a function call is not optimized way, warn with MSG. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg)
|
||||||
|
|
||||||
|
/* If a function call is not optimized way, report an error with MSG. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg)
|
||||||
|
|
||||||
|
|
||||||
|
/* Attributes for memory-allocating functions. */
|
||||||
|
|
||||||
|
/* The function returns a pointer to freshly allocated memory. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC
|
||||||
|
|
||||||
|
/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function
|
||||||
|
is the size of the returned memory block.
|
||||||
|
ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments
|
||||||
|
to determine the size of the returned memory block. */
|
||||||
|
/* Applies to: function, pointer to function, function types. */
|
||||||
|
#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args)
|
||||||
|
|
||||||
|
/* ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
|
||||||
|
that can be freed by passing them as the Ith argument to the
|
||||||
|
function F.
|
||||||
|
ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
|
||||||
|
can be freed via 'free'; it can be used only after declaring 'free'. */
|
||||||
|
/* Applies to: functions. Cannot be used on inline functions. */
|
||||||
|
#define ATTRIBUTE_DEALLOC(f, i) _GL_ATTRIBUTE_DEALLOC(f, i)
|
||||||
|
#define ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC_FREE
|
||||||
|
|
||||||
|
/* Attributes for variadic functions. */
|
||||||
|
|
||||||
|
/* The variadic function expects a trailing NULL argument.
|
||||||
|
ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99).
|
||||||
|
ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos)
|
||||||
|
|
||||||
|
|
||||||
|
/* ================== Attributes for compiler diagnostics ================== */
|
||||||
|
|
||||||
|
/* Attributes that help the compiler diagnose programmer mistakes.
|
||||||
|
Some of them may also help for some compiler optimizations. */
|
||||||
|
|
||||||
|
/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) -
|
||||||
|
The STRING-INDEXth function argument is a format string of style
|
||||||
|
ARCHETYPE, which is one of:
|
||||||
|
printf, gnu_printf
|
||||||
|
scanf, gnu_scanf,
|
||||||
|
strftime, gnu_strftime,
|
||||||
|
strfmon,
|
||||||
|
or the same thing prefixed and suffixed with '__'.
|
||||||
|
If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK
|
||||||
|
are suitable for the format string. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec)
|
||||||
|
|
||||||
|
/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL.
|
||||||
|
ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args)
|
||||||
|
|
||||||
|
/* The function's return value is a non-NULL pointer. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL
|
||||||
|
|
||||||
|
/* Warn if the caller does not use the return value,
|
||||||
|
unless the caller uses something like ignore_value. */
|
||||||
|
/* Applies to: function, enumeration, class. */
|
||||||
|
#define NODISCARD _GL_ATTRIBUTE_NODISCARD
|
||||||
|
|
||||||
|
|
||||||
|
/* Attributes that disable false alarms when the compiler diagnoses
|
||||||
|
programmer "mistakes". */
|
||||||
|
|
||||||
|
/* Do not warn if the entity is not used. */
|
||||||
|
/* Applies to:
|
||||||
|
- function, variable,
|
||||||
|
- struct, union, struct/union member,
|
||||||
|
- enumeration, enumeration item,
|
||||||
|
- typedef,
|
||||||
|
in C++ also: class. */
|
||||||
|
#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED
|
||||||
|
|
||||||
|
/* The contents of a character array is not meant to be NUL-terminated. */
|
||||||
|
/* Applies to: struct/union members and variables that are arrays of element
|
||||||
|
type '[[un]signed] char'. */
|
||||||
|
#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING
|
||||||
|
|
||||||
|
/* Do not warn if control flow falls through to the immediately
|
||||||
|
following 'case' or 'default' label. */
|
||||||
|
/* Applies to: Empty statement (;), inside a 'switch' statement. */
|
||||||
|
#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH
|
||||||
|
|
||||||
|
|
||||||
|
/* ================== Attributes for debugging information ================== */
|
||||||
|
|
||||||
|
/* Attributes regarding debugging information emitted by the compiler. */
|
||||||
|
|
||||||
|
/* Omit the function from stack traces when debugging. */
|
||||||
|
/* Applies to: function. */
|
||||||
|
#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL
|
||||||
|
|
||||||
|
/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */
|
||||||
|
/* Applies to: functions, variables. */
|
||||||
|
#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
|
||||||
|
|
||||||
|
|
||||||
|
/* ========== Attributes that mainly direct compiler optimizations ========== */
|
||||||
|
|
||||||
|
/* The function does not throw exceptions. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW
|
||||||
|
|
||||||
|
/* Do not inline the function. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE
|
||||||
|
|
||||||
|
/* Always inline the function, and report an error if the compiler
|
||||||
|
cannot inline. */
|
||||||
|
/* Applies to: function. */
|
||||||
|
#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE
|
||||||
|
|
||||||
|
/* It is OK for a compiler to omit duplicate calls with the same arguments.
|
||||||
|
This attribute is safe for a function that neither depends on
|
||||||
|
nor affects observable state, and always returns exactly once -
|
||||||
|
e.g., does not loop forever, and does not call longjmp.
|
||||||
|
(This attribute is stricter than ATTRIBUTE_PURE.) */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
|
||||||
|
|
||||||
|
/* It is OK for a compiler to omit duplicate calls with the same
|
||||||
|
arguments if observable state is not changed between calls.
|
||||||
|
This attribute is safe for a function that does not affect
|
||||||
|
observable state, and always returns exactly once.
|
||||||
|
(This attribute is looser than ATTRIBUTE_CONST.) */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE
|
||||||
|
|
||||||
|
/* The function is rarely executed. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD
|
||||||
|
|
||||||
|
/* If called from some other compilation unit, the function executes
|
||||||
|
code from that unit only by return or by exception handling,
|
||||||
|
letting the compiler optimize that unit more aggressively. */
|
||||||
|
/* Applies to: functions. */
|
||||||
|
#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF
|
||||||
|
|
||||||
|
/* For struct members: The member has the smallest possible alignment.
|
||||||
|
For struct, union, class: All members have the smallest possible alignment,
|
||||||
|
minimizing the memory required. */
|
||||||
|
/* Applies to: struct members, struct, union,
|
||||||
|
in C++ also: class. */
|
||||||
|
#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED
|
||||||
|
|
||||||
|
|
||||||
|
/* ================ Attributes that make invalid code valid ================ */
|
||||||
|
|
||||||
|
/* Attributes that prevent fatal compiler optimizations for code that is not
|
||||||
|
fully ISO C compliant. */
|
||||||
|
|
||||||
|
/* Pointers to the type may point to the same storage as pointers to
|
||||||
|
other types, thus disabling strict aliasing optimization. */
|
||||||
|
/* Applies to: types. */
|
||||||
|
#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _GL_ATTRIBUTE_H */
|
||||||
598
lib/base64.c
Normal file
598
lib/base64.c
Normal file
@ -0,0 +1,598 @@
|
|||||||
|
/* base64.c -- Encode binary data using printable characters.
|
||||||
|
Copyright (C) 1999-2001, 2004-2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 Simon Josefsson. Partially adapted from GNU MailUtils
|
||||||
|
* (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
|
||||||
|
* from Paul Eggert, Bruno Haible, and Stepan Kasal.
|
||||||
|
*
|
||||||
|
* See also RFC 4648 <https://www.ietf.org/rfc/rfc4648.txt>.
|
||||||
|
*
|
||||||
|
* Be careful with error checking. Here is how you would typically
|
||||||
|
* use these functions:
|
||||||
|
*
|
||||||
|
* bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
|
||||||
|
* if (!ok)
|
||||||
|
* FAIL: input was not valid base64
|
||||||
|
* if (out == NULL)
|
||||||
|
* FAIL: memory allocation error
|
||||||
|
* OK: data in OUT/OUTLEN
|
||||||
|
*
|
||||||
|
* idx_t outlen = base64_encode_alloc (in, inlen, &out);
|
||||||
|
* if (out == NULL && outlen == 0 && inlen != 0)
|
||||||
|
* FAIL: input too long
|
||||||
|
* if (out == NULL)
|
||||||
|
* FAIL: memory allocation error
|
||||||
|
* OK: data in OUT/OUTLEN.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/* Get prototype. */
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
/* Get imalloc. */
|
||||||
|
#include <ialloc.h>
|
||||||
|
|
||||||
|
#include <intprops.h>
|
||||||
|
|
||||||
|
/* Get UCHAR_MAX. */
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Convert 'char' to 'unsigned char' without casting. */
|
||||||
|
static unsigned char
|
||||||
|
to_uchar (char ch)
|
||||||
|
{
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char b64c[64] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
/* Base64 encode IN array of size INLEN into OUT array. OUT needs
|
||||||
|
to be of length >= BASE64_LENGTH(INLEN), and INLEN needs to be
|
||||||
|
a multiple of 3. */
|
||||||
|
static void
|
||||||
|
base64_encode_fast (const char *restrict in, idx_t inlen, char *restrict out)
|
||||||
|
{
|
||||||
|
while (inlen)
|
||||||
|
{
|
||||||
|
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
|
||||||
|
*out++ = b64c[((to_uchar (in[0]) << 4) + (to_uchar (in[1]) >> 4)) & 0x3f];
|
||||||
|
*out++ = b64c[((to_uchar (in[1]) << 2) + (to_uchar (in[2]) >> 6)) & 0x3f];
|
||||||
|
*out++ = b64c[to_uchar (in[2]) & 0x3f];
|
||||||
|
|
||||||
|
inlen -= 3;
|
||||||
|
in += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
|
||||||
|
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
|
||||||
|
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
|
||||||
|
terminate the output buffer. */
|
||||||
|
void
|
||||||
|
base64_encode (const char *restrict in, idx_t inlen,
|
||||||
|
char *restrict out, idx_t outlen)
|
||||||
|
{
|
||||||
|
/* Note this outlen constraint can be enforced at compile time.
|
||||||
|
I.E. that the output buffer is exactly large enough to hold
|
||||||
|
the encoded inlen bytes. The inlen constraints (of corresponding
|
||||||
|
to outlen, and being a multiple of 3) can change at runtime
|
||||||
|
at the end of input. However the common case when reading
|
||||||
|
large inputs is to have both constraints satisfied, so we depend
|
||||||
|
on both in base_encode_fast(). */
|
||||||
|
if (outlen % 4 == 0 && inlen == (outlen >> 2) * 3)
|
||||||
|
{
|
||||||
|
base64_encode_fast (in, inlen, out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (inlen && outlen)
|
||||||
|
{
|
||||||
|
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
|
||||||
|
if (!--outlen)
|
||||||
|
break;
|
||||||
|
*out++ = b64c[((to_uchar (in[0]) << 4)
|
||||||
|
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
|
||||||
|
& 0x3f];
|
||||||
|
if (!--outlen)
|
||||||
|
break;
|
||||||
|
*out++ =
|
||||||
|
(inlen
|
||||||
|
? b64c[((to_uchar (in[1]) << 2)
|
||||||
|
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
|
||||||
|
& 0x3f]
|
||||||
|
: '=');
|
||||||
|
if (!--outlen)
|
||||||
|
break;
|
||||||
|
*out++ = inlen ? b64c[to_uchar (in[2]) & 0x3f] : '=';
|
||||||
|
if (!--outlen)
|
||||||
|
break;
|
||||||
|
if (inlen)
|
||||||
|
inlen--;
|
||||||
|
if (inlen)
|
||||||
|
in += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outlen)
|
||||||
|
*out = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer and store zero terminated base64 encoded data
|
||||||
|
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
|
||||||
|
the length of the encoded data, excluding the terminating zero. On
|
||||||
|
return, the OUT variable will hold a pointer to newly allocated
|
||||||
|
memory that must be deallocated by the caller. If output string
|
||||||
|
length would overflow, 0 is returned and OUT is set to NULL. If
|
||||||
|
memory allocation failed, OUT is set to NULL, and the return value
|
||||||
|
indicates length of the requested memory block, i.e.,
|
||||||
|
BASE64_LENGTH(inlen) + 1. */
|
||||||
|
idx_t
|
||||||
|
base64_encode_alloc (const char *in, idx_t inlen, char **out)
|
||||||
|
{
|
||||||
|
/* Check for overflow in outlen computation.
|
||||||
|
Treat negative INLEN as overflow, for better compatibility with
|
||||||
|
pre-2021-08-27 API, which used size_t. */
|
||||||
|
idx_t in_over_3 = inlen / 3 + (inlen % 3 != 0), outlen;
|
||||||
|
if (! INT_MULTIPLY_OK (in_over_3, 4, &outlen) || inlen < 0)
|
||||||
|
{
|
||||||
|
*out = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
outlen++;
|
||||||
|
|
||||||
|
*out = imalloc (outlen);
|
||||||
|
if (!*out)
|
||||||
|
return outlen;
|
||||||
|
|
||||||
|
base64_encode (in, inlen, *out, outlen);
|
||||||
|
|
||||||
|
return outlen - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* With this approach this file works independent of the charset used
|
||||||
|
(think EBCDIC). However, it does assume that the characters in the
|
||||||
|
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
|
||||||
|
1003.1-2001 require that char and unsigned char are 8-bit
|
||||||
|
quantities, though, taking care of that problem. But this may be a
|
||||||
|
potential problem on non-POSIX C99 platforms.
|
||||||
|
|
||||||
|
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
|
||||||
|
as the formal parameter rather than "x". */
|
||||||
|
#define B64(_) \
|
||||||
|
((_) == 'A' ? 0 \
|
||||||
|
: (_) == 'B' ? 1 \
|
||||||
|
: (_) == 'C' ? 2 \
|
||||||
|
: (_) == 'D' ? 3 \
|
||||||
|
: (_) == 'E' ? 4 \
|
||||||
|
: (_) == 'F' ? 5 \
|
||||||
|
: (_) == 'G' ? 6 \
|
||||||
|
: (_) == 'H' ? 7 \
|
||||||
|
: (_) == 'I' ? 8 \
|
||||||
|
: (_) == 'J' ? 9 \
|
||||||
|
: (_) == 'K' ? 10 \
|
||||||
|
: (_) == 'L' ? 11 \
|
||||||
|
: (_) == 'M' ? 12 \
|
||||||
|
: (_) == 'N' ? 13 \
|
||||||
|
: (_) == 'O' ? 14 \
|
||||||
|
: (_) == 'P' ? 15 \
|
||||||
|
: (_) == 'Q' ? 16 \
|
||||||
|
: (_) == 'R' ? 17 \
|
||||||
|
: (_) == 'S' ? 18 \
|
||||||
|
: (_) == 'T' ? 19 \
|
||||||
|
: (_) == 'U' ? 20 \
|
||||||
|
: (_) == 'V' ? 21 \
|
||||||
|
: (_) == 'W' ? 22 \
|
||||||
|
: (_) == 'X' ? 23 \
|
||||||
|
: (_) == 'Y' ? 24 \
|
||||||
|
: (_) == 'Z' ? 25 \
|
||||||
|
: (_) == 'a' ? 26 \
|
||||||
|
: (_) == 'b' ? 27 \
|
||||||
|
: (_) == 'c' ? 28 \
|
||||||
|
: (_) == 'd' ? 29 \
|
||||||
|
: (_) == 'e' ? 30 \
|
||||||
|
: (_) == 'f' ? 31 \
|
||||||
|
: (_) == 'g' ? 32 \
|
||||||
|
: (_) == 'h' ? 33 \
|
||||||
|
: (_) == 'i' ? 34 \
|
||||||
|
: (_) == 'j' ? 35 \
|
||||||
|
: (_) == 'k' ? 36 \
|
||||||
|
: (_) == 'l' ? 37 \
|
||||||
|
: (_) == 'm' ? 38 \
|
||||||
|
: (_) == 'n' ? 39 \
|
||||||
|
: (_) == 'o' ? 40 \
|
||||||
|
: (_) == 'p' ? 41 \
|
||||||
|
: (_) == 'q' ? 42 \
|
||||||
|
: (_) == 'r' ? 43 \
|
||||||
|
: (_) == 's' ? 44 \
|
||||||
|
: (_) == 't' ? 45 \
|
||||||
|
: (_) == 'u' ? 46 \
|
||||||
|
: (_) == 'v' ? 47 \
|
||||||
|
: (_) == 'w' ? 48 \
|
||||||
|
: (_) == 'x' ? 49 \
|
||||||
|
: (_) == 'y' ? 50 \
|
||||||
|
: (_) == 'z' ? 51 \
|
||||||
|
: (_) == '0' ? 52 \
|
||||||
|
: (_) == '1' ? 53 \
|
||||||
|
: (_) == '2' ? 54 \
|
||||||
|
: (_) == '3' ? 55 \
|
||||||
|
: (_) == '4' ? 56 \
|
||||||
|
: (_) == '5' ? 57 \
|
||||||
|
: (_) == '6' ? 58 \
|
||||||
|
: (_) == '7' ? 59 \
|
||||||
|
: (_) == '8' ? 60 \
|
||||||
|
: (_) == '9' ? 61 \
|
||||||
|
: (_) == '+' ? 62 \
|
||||||
|
: (_) == '/' ? 63 \
|
||||||
|
: -1)
|
||||||
|
|
||||||
|
static const signed char b64[0x100] = {
|
||||||
|
B64 (0), B64 (1), B64 (2), B64 (3),
|
||||||
|
B64 (4), B64 (5), B64 (6), B64 (7),
|
||||||
|
B64 (8), B64 (9), B64 (10), B64 (11),
|
||||||
|
B64 (12), B64 (13), B64 (14), B64 (15),
|
||||||
|
B64 (16), B64 (17), B64 (18), B64 (19),
|
||||||
|
B64 (20), B64 (21), B64 (22), B64 (23),
|
||||||
|
B64 (24), B64 (25), B64 (26), B64 (27),
|
||||||
|
B64 (28), B64 (29), B64 (30), B64 (31),
|
||||||
|
B64 (32), B64 (33), B64 (34), B64 (35),
|
||||||
|
B64 (36), B64 (37), B64 (38), B64 (39),
|
||||||
|
B64 (40), B64 (41), B64 (42), B64 (43),
|
||||||
|
B64 (44), B64 (45), B64 (46), B64 (47),
|
||||||
|
B64 (48), B64 (49), B64 (50), B64 (51),
|
||||||
|
B64 (52), B64 (53), B64 (54), B64 (55),
|
||||||
|
B64 (56), B64 (57), B64 (58), B64 (59),
|
||||||
|
B64 (60), B64 (61), B64 (62), B64 (63),
|
||||||
|
B64 (64), B64 (65), B64 (66), B64 (67),
|
||||||
|
B64 (68), B64 (69), B64 (70), B64 (71),
|
||||||
|
B64 (72), B64 (73), B64 (74), B64 (75),
|
||||||
|
B64 (76), B64 (77), B64 (78), B64 (79),
|
||||||
|
B64 (80), B64 (81), B64 (82), B64 (83),
|
||||||
|
B64 (84), B64 (85), B64 (86), B64 (87),
|
||||||
|
B64 (88), B64 (89), B64 (90), B64 (91),
|
||||||
|
B64 (92), B64 (93), B64 (94), B64 (95),
|
||||||
|
B64 (96), B64 (97), B64 (98), B64 (99),
|
||||||
|
B64 (100), B64 (101), B64 (102), B64 (103),
|
||||||
|
B64 (104), B64 (105), B64 (106), B64 (107),
|
||||||
|
B64 (108), B64 (109), B64 (110), B64 (111),
|
||||||
|
B64 (112), B64 (113), B64 (114), B64 (115),
|
||||||
|
B64 (116), B64 (117), B64 (118), B64 (119),
|
||||||
|
B64 (120), B64 (121), B64 (122), B64 (123),
|
||||||
|
B64 (124), B64 (125), B64 (126), B64 (127),
|
||||||
|
B64 (128), B64 (129), B64 (130), B64 (131),
|
||||||
|
B64 (132), B64 (133), B64 (134), B64 (135),
|
||||||
|
B64 (136), B64 (137), B64 (138), B64 (139),
|
||||||
|
B64 (140), B64 (141), B64 (142), B64 (143),
|
||||||
|
B64 (144), B64 (145), B64 (146), B64 (147),
|
||||||
|
B64 (148), B64 (149), B64 (150), B64 (151),
|
||||||
|
B64 (152), B64 (153), B64 (154), B64 (155),
|
||||||
|
B64 (156), B64 (157), B64 (158), B64 (159),
|
||||||
|
B64 (160), B64 (161), B64 (162), B64 (163),
|
||||||
|
B64 (164), B64 (165), B64 (166), B64 (167),
|
||||||
|
B64 (168), B64 (169), B64 (170), B64 (171),
|
||||||
|
B64 (172), B64 (173), B64 (174), B64 (175),
|
||||||
|
B64 (176), B64 (177), B64 (178), B64 (179),
|
||||||
|
B64 (180), B64 (181), B64 (182), B64 (183),
|
||||||
|
B64 (184), B64 (185), B64 (186), B64 (187),
|
||||||
|
B64 (188), B64 (189), B64 (190), B64 (191),
|
||||||
|
B64 (192), B64 (193), B64 (194), B64 (195),
|
||||||
|
B64 (196), B64 (197), B64 (198), B64 (199),
|
||||||
|
B64 (200), B64 (201), B64 (202), B64 (203),
|
||||||
|
B64 (204), B64 (205), B64 (206), B64 (207),
|
||||||
|
B64 (208), B64 (209), B64 (210), B64 (211),
|
||||||
|
B64 (212), B64 (213), B64 (214), B64 (215),
|
||||||
|
B64 (216), B64 (217), B64 (218), B64 (219),
|
||||||
|
B64 (220), B64 (221), B64 (222), B64 (223),
|
||||||
|
B64 (224), B64 (225), B64 (226), B64 (227),
|
||||||
|
B64 (228), B64 (229), B64 (230), B64 (231),
|
||||||
|
B64 (232), B64 (233), B64 (234), B64 (235),
|
||||||
|
B64 (236), B64 (237), B64 (238), B64 (239),
|
||||||
|
B64 (240), B64 (241), B64 (242), B64 (243),
|
||||||
|
B64 (244), B64 (245), B64 (246), B64 (247),
|
||||||
|
B64 (248), B64 (249), B64 (250), B64 (251),
|
||||||
|
B64 (252), B64 (253), B64 (254), B64 (255)
|
||||||
|
};
|
||||||
|
|
||||||
|
#if UCHAR_MAX == 255
|
||||||
|
# define uchar_in_range(c) true
|
||||||
|
#else
|
||||||
|
# define uchar_in_range(c) ((c) <= 255)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return true if CH is a character from the Base64 alphabet, and
|
||||||
|
false otherwise. Note that '=' is padding and not considered to be
|
||||||
|
part of the alphabet. */
|
||||||
|
bool
|
||||||
|
isbase64 (char ch)
|
||||||
|
{
|
||||||
|
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize decode-context buffer, CTX. */
|
||||||
|
void
|
||||||
|
base64_decode_ctx_init (struct base64_decode_context *ctx)
|
||||||
|
{
|
||||||
|
ctx->i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
|
||||||
|
none of those four is a newline, then return *IN. Otherwise, copy up to
|
||||||
|
4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
|
||||||
|
index CTX->i and setting CTX->i to reflect the number of bytes copied,
|
||||||
|
and return CTX->buf. In either case, advance *IN to point to the byte
|
||||||
|
after the last one processed, and set *N_NON_NEWLINE to the number of
|
||||||
|
verified non-newline bytes accessible through the returned pointer. */
|
||||||
|
static char *
|
||||||
|
get_4 (struct base64_decode_context *ctx,
|
||||||
|
char const *restrict *in, char const *restrict in_end,
|
||||||
|
idx_t *n_non_newline)
|
||||||
|
{
|
||||||
|
if (ctx->i == 4)
|
||||||
|
ctx->i = 0;
|
||||||
|
|
||||||
|
if (ctx->i == 0)
|
||||||
|
{
|
||||||
|
char const *t = *in;
|
||||||
|
if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
|
||||||
|
{
|
||||||
|
/* This is the common case: no newline. */
|
||||||
|
*in += 4;
|
||||||
|
*n_non_newline = 4;
|
||||||
|
return (char *) t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Copy non-newline bytes into BUF. */
|
||||||
|
char const *p = *in;
|
||||||
|
while (p < in_end)
|
||||||
|
{
|
||||||
|
char c = *p++;
|
||||||
|
if (c != '\n')
|
||||||
|
{
|
||||||
|
ctx->buf[ctx->i++] = c;
|
||||||
|
if (ctx->i == 4)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*in = p;
|
||||||
|
*n_non_newline = ctx->i;
|
||||||
|
return ctx->buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define return_false \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
*outp = out; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
while (false)
|
||||||
|
|
||||||
|
/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
|
||||||
|
into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
|
||||||
|
decoding is successful, false otherwise. If *OUTLEN is too small,
|
||||||
|
as many bytes as possible are written to *OUT. On return, advance
|
||||||
|
*OUT to point to the byte after the last one written, and decrement
|
||||||
|
*OUTLEN to reflect the number of bytes remaining in *OUT. */
|
||||||
|
static bool
|
||||||
|
decode_4 (char const *restrict in, idx_t inlen,
|
||||||
|
char *restrict *outp, idx_t *outleft)
|
||||||
|
{
|
||||||
|
char *out = *outp;
|
||||||
|
if (inlen < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isbase64 (in[0]) || !isbase64 (in[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (*outleft)
|
||||||
|
{
|
||||||
|
*out++ = ((b64[to_uchar (in[0])] << 2)
|
||||||
|
| (b64[to_uchar (in[1])] >> 4));
|
||||||
|
--*outleft;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inlen == 2)
|
||||||
|
return_false;
|
||||||
|
|
||||||
|
if (in[2] == '=')
|
||||||
|
{
|
||||||
|
if (inlen != 4)
|
||||||
|
return_false;
|
||||||
|
|
||||||
|
if (in[3] != '=')
|
||||||
|
return_false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isbase64 (in[2]))
|
||||||
|
return_false;
|
||||||
|
|
||||||
|
if (*outleft)
|
||||||
|
{
|
||||||
|
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
|
||||||
|
| (b64[to_uchar (in[2])] >> 2));
|
||||||
|
--*outleft;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inlen == 3)
|
||||||
|
return_false;
|
||||||
|
|
||||||
|
if (in[3] == '=')
|
||||||
|
{
|
||||||
|
if (inlen != 4)
|
||||||
|
return_false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isbase64 (in[3]))
|
||||||
|
return_false;
|
||||||
|
|
||||||
|
if (*outleft)
|
||||||
|
{
|
||||||
|
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
|
||||||
|
| b64[to_uchar (in[3])]);
|
||||||
|
--*outleft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*outp = out;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decode base64-encoded input array IN of length INLEN to output array
|
||||||
|
OUT that can hold *OUTLEN bytes. The input data may be interspersed
|
||||||
|
with newlines. Return true if decoding was successful, i.e. if the
|
||||||
|
input was valid base64 data, false otherwise. If *OUTLEN is too
|
||||||
|
small, as many bytes as possible will be written to OUT. On return,
|
||||||
|
*OUTLEN holds the length of decoded bytes in OUT. Note that as soon
|
||||||
|
as any non-alphabet, non-newline character is encountered, decoding
|
||||||
|
is stopped and false is returned. If INLEN is zero, then process
|
||||||
|
only whatever data is stored in CTX.
|
||||||
|
|
||||||
|
Initially, CTX must have been initialized via base64_decode_ctx_init.
|
||||||
|
Subsequent calls to this function must reuse whatever state is recorded
|
||||||
|
in that buffer. It is necessary for when a quadruple of base64 input
|
||||||
|
bytes spans two input buffers.
|
||||||
|
|
||||||
|
If CTX is NULL then newlines are treated as garbage and the input
|
||||||
|
buffer is processed as a unit. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
base64_decode_ctx (struct base64_decode_context *ctx,
|
||||||
|
const char *restrict in, idx_t inlen,
|
||||||
|
char *restrict out, idx_t *outlen)
|
||||||
|
{
|
||||||
|
idx_t outleft = *outlen;
|
||||||
|
bool ignore_newlines = ctx != NULL;
|
||||||
|
bool flush_ctx = false;
|
||||||
|
unsigned int ctx_i = 0;
|
||||||
|
|
||||||
|
if (ignore_newlines)
|
||||||
|
{
|
||||||
|
ctx_i = ctx->i;
|
||||||
|
flush_ctx = inlen == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
idx_t outleft_save = outleft;
|
||||||
|
if (ctx_i == 0 && !flush_ctx)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
/* Save a copy of outleft, in case we need to re-parse this
|
||||||
|
block of four bytes. */
|
||||||
|
outleft_save = outleft;
|
||||||
|
if (!decode_4 (in, inlen, &out, &outleft))
|
||||||
|
break;
|
||||||
|
|
||||||
|
in += 4;
|
||||||
|
inlen -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inlen == 0 && !flush_ctx)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Handle the common case of 72-byte wrapped lines.
|
||||||
|
This also handles any other multiple-of-4-byte wrapping. */
|
||||||
|
if (inlen && *in == '\n' && ignore_newlines)
|
||||||
|
{
|
||||||
|
++in;
|
||||||
|
--inlen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore OUT and OUTLEFT. */
|
||||||
|
out -= outleft_save - outleft;
|
||||||
|
outleft = outleft_save;
|
||||||
|
|
||||||
|
{
|
||||||
|
char const *in_end = in + inlen;
|
||||||
|
char const *non_nl;
|
||||||
|
|
||||||
|
if (ignore_newlines)
|
||||||
|
non_nl = get_4 (ctx, &in, in_end, &inlen);
|
||||||
|
else
|
||||||
|
non_nl = in; /* Might have nl in this case. */
|
||||||
|
|
||||||
|
/* If the input is empty or consists solely of newlines (0 non-newlines),
|
||||||
|
then we're done. Likewise if there are fewer than 4 bytes when not
|
||||||
|
flushing context and not treating newlines as garbage. */
|
||||||
|
if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
|
||||||
|
{
|
||||||
|
inlen = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!decode_4 (non_nl, inlen, &out, &outleft))
|
||||||
|
break;
|
||||||
|
|
||||||
|
inlen = in_end - in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*outlen -= outleft;
|
||||||
|
|
||||||
|
return inlen == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate an output buffer in *OUT, and decode the base64 encoded
|
||||||
|
data stored in IN of size INLEN to the *OUT buffer. On return, the
|
||||||
|
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
|
||||||
|
if the caller is not interested in the decoded length. *OUT may be
|
||||||
|
NULL to indicate an out of memory error, in which case *OUTLEN
|
||||||
|
contains the size of the memory block needed. The function returns
|
||||||
|
true on successful decoding and memory allocation errors. (Use the
|
||||||
|
*OUT and *OUTLEN parameters to differentiate between successful
|
||||||
|
decoding and memory error.) The function returns false if the
|
||||||
|
input was invalid, in which case *OUT is NULL and *OUTLEN is
|
||||||
|
undefined. */
|
||||||
|
bool
|
||||||
|
base64_decode_alloc_ctx (struct base64_decode_context *ctx,
|
||||||
|
const char *in, idx_t inlen, char **out,
|
||||||
|
idx_t *outlen)
|
||||||
|
{
|
||||||
|
/* This may allocate a few bytes too many, depending on input,
|
||||||
|
but it's not worth the extra CPU time to compute the exact size.
|
||||||
|
The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
|
||||||
|
input ends with "=" and minus another 1 if the input ends with "==".
|
||||||
|
Shifting before multiplying avoids the possibility of overflow. */
|
||||||
|
idx_t needlen = 3 * ((inlen >> 2) + 1);
|
||||||
|
|
||||||
|
*out = imalloc (needlen);
|
||||||
|
if (!*out)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
|
||||||
|
{
|
||||||
|
free (*out);
|
||||||
|
*out = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outlen)
|
||||||
|
*outlen = needlen;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
68
lib/base64.h
Normal file
68
lib/base64.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* base64.h -- Encode binary data using printable characters.
|
||||||
|
Copyright (C) 2004-2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
Written by Simon Josefsson.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 BASE64_H
|
||||||
|
# define BASE64_H
|
||||||
|
|
||||||
|
/* Get idx_t. */
|
||||||
|
# include <idx.h>
|
||||||
|
|
||||||
|
/* Get bool. */
|
||||||
|
# include <stdbool.h>
|
||||||
|
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* This uses that the expression (n+(k-1))/k means the smallest
|
||||||
|
integer >= n/k, i.e., the ceiling of n/k. */
|
||||||
|
# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
|
||||||
|
|
||||||
|
struct base64_decode_context
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char buf[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern bool isbase64 (char ch) _GL_ATTRIBUTE_CONST;
|
||||||
|
|
||||||
|
extern void base64_encode (const char *restrict in, idx_t inlen,
|
||||||
|
char *restrict out, idx_t outlen);
|
||||||
|
|
||||||
|
extern idx_t base64_encode_alloc (const char *in, idx_t inlen, char **out);
|
||||||
|
|
||||||
|
extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
|
||||||
|
|
||||||
|
extern bool base64_decode_ctx (struct base64_decode_context *ctx,
|
||||||
|
const char *restrict in, idx_t inlen,
|
||||||
|
char *restrict out, idx_t *outlen);
|
||||||
|
|
||||||
|
extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
|
||||||
|
const char *in, idx_t inlen,
|
||||||
|
char **out, idx_t *outlen);
|
||||||
|
|
||||||
|
#define base64_decode(in, inlen, out, outlen) \
|
||||||
|
base64_decode_ctx (NULL, in, inlen, out, outlen)
|
||||||
|
|
||||||
|
#define base64_decode_alloc(in, inlen, out, outlen) \
|
||||||
|
base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
|
||||||
|
|
||||||
|
# ifdef __cplusplus
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif /* BASE64_H */
|
||||||
71
lib/basename-lgpl.c
Normal file
71
lib/basename-lgpl.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* basename.c -- return the last element in a file name
|
||||||
|
|
||||||
|
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2022 Free Software
|
||||||
|
Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "basename-lgpl.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "filename.h"
|
||||||
|
|
||||||
|
char *
|
||||||
|
last_component (char const *name)
|
||||||
|
{
|
||||||
|
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
|
||||||
|
char const *p;
|
||||||
|
bool last_was_slash = false;
|
||||||
|
|
||||||
|
while (ISSLASH (*base))
|
||||||
|
base++;
|
||||||
|
|
||||||
|
for (p = base; *p; p++)
|
||||||
|
{
|
||||||
|
if (ISSLASH (*p))
|
||||||
|
last_was_slash = true;
|
||||||
|
else if (last_was_slash)
|
||||||
|
{
|
||||||
|
base = p;
|
||||||
|
last_was_slash = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *) base;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
78
lib/basename-lgpl.h
Normal file
78
lib/basename-lgpl.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Extract the last component (base name) of a file name.
|
||||||
|
|
||||||
|
Copyright (C) 1998, 2001, 2003-2006, 2009-2022 Free Software Foundation,
|
||||||
|
Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 _BASENAME_LGPL_H
|
||||||
|
#define _BASENAME_LGPL_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||||
|
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the address of the last file name component of FILENAME.
|
||||||
|
If FILENAME has some trailing slash(es), they are considered to be
|
||||||
|
part of the last component.
|
||||||
|
If FILENAME has no relative file name components because it is a file
|
||||||
|
system root, return the empty string.
|
||||||
|
Examples:
|
||||||
|
FILENAME RESULT
|
||||||
|
"foo.c" "foo.c"
|
||||||
|
"foo/bar.c" "bar.c"
|
||||||
|
"/foo/bar.c" "bar.c"
|
||||||
|
"foo/bar/" "bar/"
|
||||||
|
"foo/bar//" "bar//"
|
||||||
|
"/" ""
|
||||||
|
"//" ""
|
||||||
|
"" ""
|
||||||
|
The return value is a tail of the given FILENAME; do NOT free() it! */
|
||||||
|
|
||||||
|
/* This function was traditionally called 'basename', but we avoid this
|
||||||
|
function name because
|
||||||
|
* Various platforms have different functions in their libc.
|
||||||
|
In particular, the glibc basename(), defined in <string.h>, does
|
||||||
|
not consider trailing slashes to be part of the component:
|
||||||
|
FILENAME RESULT
|
||||||
|
"foo/bar/" ""
|
||||||
|
"foo/bar//" ""
|
||||||
|
* The 'basename' command eliminates trailing slashes and for a root
|
||||||
|
produces a non-empty result:
|
||||||
|
FILENAME RESULT
|
||||||
|
"foo/bar/" "bar"
|
||||||
|
"foo/bar//" "bar"
|
||||||
|
"/" "/"
|
||||||
|
"//" "/"
|
||||||
|
*/
|
||||||
|
extern char *last_component (char const *filename) _GL_ATTRIBUTE_PURE;
|
||||||
|
|
||||||
|
/* Return the length of the basename FILENAME.
|
||||||
|
Typically FILENAME is the value returned by base_name or last_component.
|
||||||
|
Act like strlen (FILENAME), except omit all trailing slashes. */
|
||||||
|
extern size_t base_len (char const *filename) _GL_ATTRIBUTE_PURE;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _BASENAME_LGPL_H */
|
||||||
39
lib/binary-io.c
Normal file
39
lib/binary-io.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* Binary mode I/O.
|
||||||
|
Copyright 2017-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
#define BINARY_IO_INLINE _GL_EXTERN_INLINE
|
||||||
|
#include "binary-io.h"
|
||||||
|
|
||||||
|
#if defined __DJGPP__ || defined __EMX__
|
||||||
|
# include <unistd.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
set_binary_mode (int fd, int mode)
|
||||||
|
{
|
||||||
|
if (isatty (fd))
|
||||||
|
/* If FD refers to a console (not a pipe, not a regular file),
|
||||||
|
O_TEXT is the only reasonable mode, both on input and on output.
|
||||||
|
Silently ignore the request. If we were to return -1 here,
|
||||||
|
all programs that use xset_binary_mode would fail when run
|
||||||
|
with console input or console output. */
|
||||||
|
return O_TEXT;
|
||||||
|
else
|
||||||
|
return __gl_setmode (fd, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
77
lib/binary-io.h
Normal file
77
lib/binary-io.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* Binary mode I/O.
|
||||||
|
Copyright (C) 2001, 2003, 2005, 2008-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 _BINARY_H
|
||||||
|
#define _BINARY_H
|
||||||
|
|
||||||
|
/* For systems that distinguish between text and binary I/O.
|
||||||
|
O_BINARY is guaranteed by the gnulib <fcntl.h>. */
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
/* The MSVC7 <stdio.h> doesn't like to be included after '#define fileno ...',
|
||||||
|
so we include it here first. */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef _GL_INLINE_HEADER_BEGIN
|
||||||
|
#error "Please include config.h first."
|
||||||
|
#endif
|
||||||
|
_GL_INLINE_HEADER_BEGIN
|
||||||
|
#ifndef BINARY_IO_INLINE
|
||||||
|
# define BINARY_IO_INLINE _GL_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if O_BINARY
|
||||||
|
# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__
|
||||||
|
# include <io.h> /* declares setmode() */
|
||||||
|
# define __gl_setmode setmode
|
||||||
|
# else
|
||||||
|
# define __gl_setmode _setmode
|
||||||
|
# undef fileno
|
||||||
|
# define fileno _fileno
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
/* On reasonable systems, binary I/O is the only choice. */
|
||||||
|
/* Use a function rather than a macro, to avoid gcc warnings
|
||||||
|
"warning: statement with no effect". */
|
||||||
|
BINARY_IO_INLINE int
|
||||||
|
__gl_setmode (_GL_UNUSED int fd, _GL_UNUSED int mode)
|
||||||
|
{
|
||||||
|
return O_BINARY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set FD's mode to MODE, which should be either O_TEXT or O_BINARY.
|
||||||
|
Return the old mode if successful, -1 (setting errno) on failure.
|
||||||
|
Ordinarily this function would be called 'setmode', since that is
|
||||||
|
its old name on MS-Windows, but it is called 'set_binary_mode' here
|
||||||
|
to avoid colliding with a BSD function of another name. */
|
||||||
|
|
||||||
|
#if defined __DJGPP__ || defined __EMX__
|
||||||
|
extern int set_binary_mode (int fd, int mode);
|
||||||
|
#else
|
||||||
|
BINARY_IO_INLINE int
|
||||||
|
set_binary_mode (int fd, int mode)
|
||||||
|
{
|
||||||
|
return __gl_setmode (fd, mode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This macro is obsolescent. */
|
||||||
|
#define SET_BINARY(fd) ((void) set_binary_mode (fd, O_BINARY))
|
||||||
|
|
||||||
|
_GL_INLINE_HEADER_END
|
||||||
|
|
||||||
|
#endif /* _BINARY_H */
|
||||||
21
lib/bitrotate.c
Normal file
21
lib/bitrotate.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* Rotate bits in integers.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
#define BITROTATE_INLINE _GL_EXTERN_INLINE
|
||||||
|
#include "bitrotate.h"
|
||||||
138
lib/bitrotate.h
Normal file
138
lib/bitrotate.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/* bitrotate.h - Rotate bits in integers
|
||||||
|
Copyright (C) 2008-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 Simon Josefsson <simon@josefsson.org>, 2008. */
|
||||||
|
|
||||||
|
#ifndef _GL_BITROTATE_H
|
||||||
|
#define _GL_BITROTATE_H
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifndef _GL_INLINE_HEADER_BEGIN
|
||||||
|
#error "Please include config.h first."
|
||||||
|
#endif
|
||||||
|
_GL_INLINE_HEADER_BEGIN
|
||||||
|
#ifndef BITROTATE_INLINE
|
||||||
|
# define BITROTATE_INLINE _GL_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UINT64_MAX
|
||||||
|
/* Given an unsigned 64-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the left. N must be between 1 and
|
||||||
|
63 inclusive. */
|
||||||
|
BITROTATE_INLINE uint64_t
|
||||||
|
rotl64 (uint64_t x, int n)
|
||||||
|
{
|
||||||
|
return ((x << n) | (x >> (64 - n))) & UINT64_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an unsigned 64-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the right. N must be between 1 to
|
||||||
|
63 inclusive.*/
|
||||||
|
BITROTATE_INLINE uint64_t
|
||||||
|
rotr64 (uint64_t x, int n)
|
||||||
|
{
|
||||||
|
return ((x >> n) | (x << (64 - n))) & UINT64_MAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Given an unsigned 32-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the left. N must be between 1 and
|
||||||
|
31 inclusive. */
|
||||||
|
BITROTATE_INLINE uint32_t
|
||||||
|
rotl32 (uint32_t x, int n)
|
||||||
|
{
|
||||||
|
return ((x << n) | (x >> (32 - n))) & UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an unsigned 32-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the right. N must be between 1 to
|
||||||
|
31 inclusive.*/
|
||||||
|
BITROTATE_INLINE uint32_t
|
||||||
|
rotr32 (uint32_t x, int n)
|
||||||
|
{
|
||||||
|
return ((x >> n) | (x << (32 - n))) & UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a size_t argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the left. N must be between 1 and
|
||||||
|
(CHAR_BIT * sizeof (size_t) - 1) inclusive. */
|
||||||
|
BITROTATE_INLINE size_t
|
||||||
|
rotl_sz (size_t x, int n)
|
||||||
|
{
|
||||||
|
return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a size_t argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the right. N must be between 1 to
|
||||||
|
(CHAR_BIT * sizeof (size_t) - 1) inclusive. */
|
||||||
|
BITROTATE_INLINE size_t
|
||||||
|
rotr_sz (size_t x, int n)
|
||||||
|
{
|
||||||
|
return ((x >> n) | (x << ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an unsigned 16-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the left. N must be between 1 to
|
||||||
|
15 inclusive, but on most relevant targets N can also be 0 and 16
|
||||||
|
because 'int' is at least 32 bits and the arguments must widen
|
||||||
|
before shifting. */
|
||||||
|
BITROTATE_INLINE uint16_t
|
||||||
|
rotl16 (uint16_t x, int n)
|
||||||
|
{
|
||||||
|
return (((unsigned int) x << n) | ((unsigned int) x >> (16 - n)))
|
||||||
|
& UINT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an unsigned 16-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the right. N must be in 1 to 15
|
||||||
|
inclusive, but on most relevant targets N can also be 0 and 16
|
||||||
|
because 'int' is at least 32 bits and the arguments must widen
|
||||||
|
before shifting. */
|
||||||
|
BITROTATE_INLINE uint16_t
|
||||||
|
rotr16 (uint16_t x, int n)
|
||||||
|
{
|
||||||
|
return (((unsigned int) x >> n) | ((unsigned int) x << (16 - n)))
|
||||||
|
& UINT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an unsigned 8-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the left. N must be between 1 to 7
|
||||||
|
inclusive, but on most relevant targets N can also be 0 and 8
|
||||||
|
because 'int' is at least 32 bits and the arguments must widen
|
||||||
|
before shifting. */
|
||||||
|
BITROTATE_INLINE uint8_t
|
||||||
|
rotl8 (uint8_t x, int n)
|
||||||
|
{
|
||||||
|
return (((unsigned int) x << n) | ((unsigned int) x >> (8 - n))) & UINT8_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an unsigned 8-bit argument X, return the value corresponding
|
||||||
|
to rotating the bits N steps to the right. N must be in 1 to 7
|
||||||
|
inclusive, but on most relevant targets N can also be 0 and 8
|
||||||
|
because 'int' is at least 32 bits and the arguments must widen
|
||||||
|
before shifting. */
|
||||||
|
BITROTATE_INLINE uint8_t
|
||||||
|
rotr8 (uint8_t x, int n)
|
||||||
|
{
|
||||||
|
return (((unsigned int) x >> n) | ((unsigned int) x << (8 - n))) & UINT8_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
_GL_INLINE_HEADER_END
|
||||||
|
|
||||||
|
#endif /* _GL_BITROTATE_H */
|
||||||
39
lib/btowc.c
Normal file
39
lib/btowc.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* Convert unibyte character to wide character.
|
||||||
|
Copyright (C) 2008, 2010-2022 Free Software Foundation, Inc.
|
||||||
|
Written by Bruno Haible <bruno@clisp.org>, 2008.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
wint_t
|
||||||
|
btowc (int c)
|
||||||
|
{
|
||||||
|
if (c != EOF)
|
||||||
|
{
|
||||||
|
char buf[1];
|
||||||
|
wchar_t wc;
|
||||||
|
|
||||||
|
buf[0] = c;
|
||||||
|
if (mbtowc (&wc, buf, 1) >= 0)
|
||||||
|
return wc;
|
||||||
|
}
|
||||||
|
return WEOF;
|
||||||
|
}
|
||||||
331
lib/c++defs.h
Normal file
331
lib/c++defs.h
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
/* C++ compatible function declaration macros.
|
||||||
|
Copyright (C) 2010-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program 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 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 _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_MDA (func, rettype, parameters);
|
||||||
|
is to be used when func is a Microsoft deprecated alias, on native Windows.
|
||||||
|
It declares a C++ alias called GNULIB_NAMESPACE::func
|
||||||
|
that redirects to _func, if GNULIB_NAMESPACE is defined.
|
||||||
|
Example:
|
||||||
|
_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...));
|
||||||
|
*/
|
||||||
|
#define _GL_CXXALIAS_MDA(func,rettype,parameters) \
|
||||||
|
_GL_CXXALIAS_RPL_1 (func, _##func, rettype, parameters)
|
||||||
|
|
||||||
|
/* _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_MDA_CAST (func, rettype, parameters);
|
||||||
|
is like _GL_CXXALIAS_MDA (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. */
|
||||||
|
#define _GL_CXXALIAS_MDA_CAST(func,rettype,parameters) \
|
||||||
|
_GL_CXXALIAS_RPL_CAST_1 (func, _##func, rettype, parameters)
|
||||||
|
|
||||||
|
/* _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 !(defined __GNUC__ && !defined __clang__ && __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 !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__)
|
||||||
|
# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
|
||||||
|
_GL_WARN_ON_USE_CXX (func, rettype, rettype, parameters_and_attributes, \
|
||||||
|
"The symbol ::" #func " refers to the system function. " \
|
||||||
|
"Use " #namespace "::" #func " instead.")
|
||||||
|
# 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 */
|
||||||
21
lib/c-ctype.c
Normal file
21
lib/c-ctype.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* Character handling in C locale.
|
||||||
|
|
||||||
|
Copyright (C) 2003-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
#define C_CTYPE_INLINE _GL_EXTERN_INLINE
|
||||||
|
#include "c-ctype.h"
|
||||||
366
lib/c-ctype.h
Normal file
366
lib/c-ctype.h
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/* Character handling in C locale.
|
||||||
|
|
||||||
|
These functions work like the corresponding functions in <ctype.h>,
|
||||||
|
except that they have the C (POSIX) locale hardwired, whereas the
|
||||||
|
<ctype.h> functions' behaviour depends on the current locale set via
|
||||||
|
setlocale.
|
||||||
|
|
||||||
|
Copyright (C) 2000-2003, 2006, 2008-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 C_CTYPE_H
|
||||||
|
#define C_CTYPE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifndef _GL_INLINE_HEADER_BEGIN
|
||||||
|
#error "Please include config.h first."
|
||||||
|
#endif
|
||||||
|
_GL_INLINE_HEADER_BEGIN
|
||||||
|
#ifndef C_CTYPE_INLINE
|
||||||
|
# define C_CTYPE_INLINE _GL_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* The functions defined in this file assume the "C" locale and a character
|
||||||
|
set without diacritics (ASCII-US or EBCDIC-US or something like that).
|
||||||
|
Even if the "C" locale on a particular system is an extension of the ASCII
|
||||||
|
character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
|
||||||
|
is ISO-8859-1), the functions in this file recognize only the ASCII
|
||||||
|
characters. */
|
||||||
|
|
||||||
|
|
||||||
|
#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
||||||
|
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
|
||||||
|
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
|
||||||
|
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
|
||||||
|
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
|
||||||
|
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
|
||||||
|
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
|
||||||
|
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
|
||||||
|
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
|
||||||
|
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
|
||||||
|
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
|
||||||
|
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
|
||||||
|
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
|
||||||
|
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
|
||||||
|
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
|
||||||
|
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
|
||||||
|
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
|
||||||
|
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
|
||||||
|
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
|
||||||
|
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
|
||||||
|
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
|
||||||
|
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
|
||||||
|
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
|
||||||
|
/* The character set is ASCII or one of its variants or extensions, not EBCDIC.
|
||||||
|
Testing the value of '\n' and '\r' is not relevant. */
|
||||||
|
# define C_CTYPE_ASCII 1
|
||||||
|
#elif ! (' ' == '\x40' && '0' == '\xf0' \
|
||||||
|
&& 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \
|
||||||
|
&& 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
|
||||||
|
# error "Only ASCII and EBCDIC are supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 'A' < 0
|
||||||
|
# error "EBCDIC and char is signed -- not supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Cases for control characters. */
|
||||||
|
|
||||||
|
#define _C_CTYPE_CNTRL \
|
||||||
|
case '\a': case '\b': case '\f': case '\n': \
|
||||||
|
case '\r': case '\t': case '\v': \
|
||||||
|
_C_CTYPE_OTHER_CNTRL
|
||||||
|
|
||||||
|
/* ASCII control characters other than those with \-letter escapes. */
|
||||||
|
|
||||||
|
#if C_CTYPE_ASCII
|
||||||
|
# define _C_CTYPE_OTHER_CNTRL \
|
||||||
|
case '\x00': case '\x01': case '\x02': case '\x03': \
|
||||||
|
case '\x04': case '\x05': case '\x06': case '\x0e': \
|
||||||
|
case '\x0f': case '\x10': case '\x11': case '\x12': \
|
||||||
|
case '\x13': case '\x14': case '\x15': case '\x16': \
|
||||||
|
case '\x17': case '\x18': case '\x19': case '\x1a': \
|
||||||
|
case '\x1b': case '\x1c': case '\x1d': case '\x1e': \
|
||||||
|
case '\x1f': case '\x7f'
|
||||||
|
#else
|
||||||
|
/* Use EBCDIC code page 1047's assignments for ASCII control chars;
|
||||||
|
assume all EBCDIC code pages agree about these assignments. */
|
||||||
|
# define _C_CTYPE_OTHER_CNTRL \
|
||||||
|
case '\x00': case '\x01': case '\x02': case '\x03': \
|
||||||
|
case '\x07': case '\x0e': case '\x0f': case '\x10': \
|
||||||
|
case '\x11': case '\x12': case '\x13': case '\x18': \
|
||||||
|
case '\x19': case '\x1c': case '\x1d': case '\x1e': \
|
||||||
|
case '\x1f': case '\x26': case '\x27': case '\x2d': \
|
||||||
|
case '\x2e': case '\x32': case '\x37': case '\x3c': \
|
||||||
|
case '\x3d': case '\x3f'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Cases for lowercase hex letters, and lowercase letters, all offset by N. */
|
||||||
|
|
||||||
|
#define _C_CTYPE_LOWER_A_THRU_F_N(N) \
|
||||||
|
case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \
|
||||||
|
case 'e' + (N): case 'f' + (N)
|
||||||
|
#define _C_CTYPE_LOWER_N(N) \
|
||||||
|
_C_CTYPE_LOWER_A_THRU_F_N(N): \
|
||||||
|
case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \
|
||||||
|
case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \
|
||||||
|
case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \
|
||||||
|
case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \
|
||||||
|
case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N)
|
||||||
|
|
||||||
|
/* Cases for hex letters, digits, lower, punct, and upper. */
|
||||||
|
|
||||||
|
#define _C_CTYPE_A_THRU_F \
|
||||||
|
_C_CTYPE_LOWER_A_THRU_F_N (0): \
|
||||||
|
_C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a')
|
||||||
|
#define _C_CTYPE_DIGIT \
|
||||||
|
case '0': case '1': case '2': case '3': \
|
||||||
|
case '4': case '5': case '6': case '7': \
|
||||||
|
case '8': case '9'
|
||||||
|
#define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0)
|
||||||
|
#define _C_CTYPE_PUNCT \
|
||||||
|
case '!': case '"': case '#': case '$': \
|
||||||
|
case '%': case '&': case '\'': case '(': \
|
||||||
|
case ')': case '*': case '+': case ',': \
|
||||||
|
case '-': case '.': case '/': case ':': \
|
||||||
|
case ';': case '<': case '=': case '>': \
|
||||||
|
case '?': case '@': case '[': case '\\': \
|
||||||
|
case ']': case '^': case '_': case '`': \
|
||||||
|
case '{': case '|': case '}': case '~'
|
||||||
|
#define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a')
|
||||||
|
|
||||||
|
|
||||||
|
/* Function definitions. */
|
||||||
|
|
||||||
|
/* Unlike the functions in <ctype.h>, which require an argument in the range
|
||||||
|
of the 'unsigned char' type, the functions here operate on values that are
|
||||||
|
in the 'unsigned char' range or in the 'char' range. In other words,
|
||||||
|
when you have a 'char' value, you need to cast it before using it as
|
||||||
|
argument to a <ctype.h> function:
|
||||||
|
|
||||||
|
const char *s = ...;
|
||||||
|
if (isalpha ((unsigned char) *s)) ...
|
||||||
|
|
||||||
|
but you don't need to cast it for the functions defined in this file:
|
||||||
|
|
||||||
|
const char *s = ...;
|
||||||
|
if (c_isalpha (*s)) ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isalnum (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_DIGIT:
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isalpha (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function isascii is not locale dependent.
|
||||||
|
Its use in EBCDIC is questionable. */
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isascii (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
_C_CTYPE_CNTRL:
|
||||||
|
_C_CTYPE_DIGIT:
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
_C_CTYPE_PUNCT:
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isblank (int c)
|
||||||
|
{
|
||||||
|
return c == ' ' || c == '\t';
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_iscntrl (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_CNTRL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isdigit (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_DIGIT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isgraph (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_DIGIT:
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
_C_CTYPE_PUNCT:
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_islower (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isprint (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
_C_CTYPE_DIGIT:
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
_C_CTYPE_PUNCT:
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_ispunct (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_PUNCT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isspace (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isupper (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE bool
|
||||||
|
c_isxdigit (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_DIGIT:
|
||||||
|
_C_CTYPE_A_THRU_F:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE int
|
||||||
|
c_tolower (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_UPPER:
|
||||||
|
return c - 'A' + 'a';
|
||||||
|
default:
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_CTYPE_INLINE int
|
||||||
|
c_toupper (int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
_C_CTYPE_LOWER:
|
||||||
|
return c - 'a' + 'A';
|
||||||
|
default:
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_GL_INLINE_HEADER_END
|
||||||
|
|
||||||
|
#endif /* C_CTYPE_H */
|
||||||
56
lib/c-strcase.h
Normal file
56
lib/c-strcase.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* Case-insensitive string comparison functions in C locale.
|
||||||
|
Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2022 Free Software
|
||||||
|
Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 C_STRCASE_H
|
||||||
|
#define C_STRCASE_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* The functions defined in this file assume the "C" locale and a character
|
||||||
|
set without diacritics (ASCII-US or EBCDIC-US or something like that).
|
||||||
|
Even if the "C" locale on a particular system is an extension of the ASCII
|
||||||
|
character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
|
||||||
|
is ISO-8859-1), the functions in this file recognize only the ASCII
|
||||||
|
characters. More precisely, one of the string arguments must be an ASCII
|
||||||
|
string; the other one can also contain non-ASCII characters (but then
|
||||||
|
the comparison result will be nonzero). */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
|
||||||
|
greater than zero if S1 is lexicographically less than, equal to or greater
|
||||||
|
than S2. */
|
||||||
|
extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE;
|
||||||
|
|
||||||
|
/* Compare no more than N characters of strings S1 and S2, ignoring case,
|
||||||
|
returning less than, equal to or greater than zero if S1 is
|
||||||
|
lexicographically less than, equal to or greater than S2. */
|
||||||
|
extern int c_strncasecmp (const char *s1, const char *s2, size_t n)
|
||||||
|
_GL_ATTRIBUTE_PURE;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* C_STRCASE_H */
|
||||||
56
lib/c-strcasecmp.c
Normal file
56
lib/c-strcasecmp.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* c-strcasecmp.c -- case insensitive string comparator in C locale
|
||||||
|
Copyright (C) 1998-1999, 2005-2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "c-strcase.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "c-ctype.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
c_strcasecmp (const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
register const unsigned char *p1 = (const unsigned char *) s1;
|
||||||
|
register const unsigned char *p2 = (const unsigned char *) s2;
|
||||||
|
unsigned char c1, c2;
|
||||||
|
|
||||||
|
if (p1 == p2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = c_tolower (*p1);
|
||||||
|
c2 = c_tolower (*p2);
|
||||||
|
|
||||||
|
if (c1 == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
++p1;
|
||||||
|
++p2;
|
||||||
|
}
|
||||||
|
while (c1 == c2);
|
||||||
|
|
||||||
|
if (UCHAR_MAX <= INT_MAX)
|
||||||
|
return c1 - c2;
|
||||||
|
else
|
||||||
|
/* On machines where 'char' and 'int' are types of the same size, the
|
||||||
|
difference of two 'unsigned char' values - including the sign bit -
|
||||||
|
doesn't fit in an 'int'. */
|
||||||
|
return _GL_CMP (c1, c2);
|
||||||
|
}
|
||||||
181
lib/c-strcaseeq.h
Normal file
181
lib/c-strcaseeq.h
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/* Optimized case-insensitive string comparison in C locale.
|
||||||
|
Copyright (C) 2001-2002, 2007, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <bruno@clisp.org>. */
|
||||||
|
|
||||||
|
#include "c-strcase.h"
|
||||||
|
#include "c-ctype.h"
|
||||||
|
|
||||||
|
/* STRCASEEQ allows to optimize string comparison with a small literal string.
|
||||||
|
STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
|
||||||
|
is semantically equivalent to
|
||||||
|
c_strcasecmp (s, "UTF-8") == 0
|
||||||
|
just faster. */
|
||||||
|
|
||||||
|
/* Help GCC to generate good code for string comparisons with
|
||||||
|
immediate strings. */
|
||||||
|
#if (defined __GNUC__ || defined __clang__) && defined __OPTIMIZE__
|
||||||
|
|
||||||
|
/* Case insensitive comparison of ASCII characters. */
|
||||||
|
# if C_CTYPE_ASCII
|
||||||
|
# define CASEEQ(other,upper) \
|
||||||
|
(c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
|
||||||
|
# else
|
||||||
|
# define CASEEQ(other,upper) \
|
||||||
|
(c_toupper (other) == (upper))
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq9 (const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
return c_strcasecmp (s1 + 9, s2 + 9) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq8 (const char *s1, const char *s2, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[8], s28))
|
||||||
|
{
|
||||||
|
if (s28 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq9 (s1, s2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq7 (const char *s1, const char *s2, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[7], s27))
|
||||||
|
{
|
||||||
|
if (s27 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq8 (s1, s2, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[6], s26))
|
||||||
|
{
|
||||||
|
if (s26 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq7 (s1, s2, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[5], s25))
|
||||||
|
{
|
||||||
|
if (s25 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq6 (s1, s2, s26, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[4], s24))
|
||||||
|
{
|
||||||
|
if (s24 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq5 (s1, s2, s25, s26, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[3], s23))
|
||||||
|
{
|
||||||
|
if (s23 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[2], s22))
|
||||||
|
{
|
||||||
|
if (s22 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[1], s21))
|
||||||
|
{
|
||||||
|
if (s21 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
|
||||||
|
{
|
||||||
|
if (CASEEQ (s1[0], s20))
|
||||||
|
{
|
||||||
|
if (s20 == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
|
||||||
|
strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
|
||||||
|
(c_strcasecmp (s1, s2) == 0)
|
||||||
|
|
||||||
|
#endif
|
||||||
56
lib/c-strncasecmp.c
Normal file
56
lib/c-strncasecmp.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* c-strncasecmp.c -- case insensitive string comparator in C locale
|
||||||
|
Copyright (C) 1998-1999, 2005-2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "c-strcase.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "c-ctype.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
c_strncasecmp (const char *s1, const char *s2, size_t n)
|
||||||
|
{
|
||||||
|
register const unsigned char *p1 = (const unsigned char *) s1;
|
||||||
|
register const unsigned char *p2 = (const unsigned char *) s2;
|
||||||
|
unsigned char c1, c2;
|
||||||
|
|
||||||
|
if (p1 == p2 || n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = c_tolower (*p1);
|
||||||
|
c2 = c_tolower (*p2);
|
||||||
|
|
||||||
|
if (--n == 0 || c1 == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
++p1;
|
||||||
|
++p2;
|
||||||
|
}
|
||||||
|
while (c1 == c2);
|
||||||
|
|
||||||
|
if (UCHAR_MAX <= INT_MAX)
|
||||||
|
return c1 - c2;
|
||||||
|
else
|
||||||
|
/* On machines where 'char' and 'int' are types of the same size, the
|
||||||
|
difference of two 'unsigned char' values - including the sign bit -
|
||||||
|
doesn't fit in an 'int'. */
|
||||||
|
return _GL_CMP (c1, c2);
|
||||||
|
}
|
||||||
55
lib/calloc.c
Normal file
55
lib/calloc.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* calloc() function that is glibc compatible.
|
||||||
|
This wrapper function is required at least on Tru64 UNIX 5.1 and mingw.
|
||||||
|
Copyright (C) 2004-2007, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 Jim Meyering and Bruno Haible */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "xalloc-oversized.h"
|
||||||
|
|
||||||
|
/* Call the system's calloc below. */
|
||||||
|
#undef calloc
|
||||||
|
|
||||||
|
/* Allocate and zero-fill an NxS-byte block of memory from the heap,
|
||||||
|
even if N or S is zero. */
|
||||||
|
|
||||||
|
void *
|
||||||
|
rpl_calloc (size_t n, size_t s)
|
||||||
|
{
|
||||||
|
if (n == 0 || s == 0)
|
||||||
|
n = s = 1;
|
||||||
|
|
||||||
|
if (xalloc_oversized (n, s))
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *result = calloc (n, s);
|
||||||
|
|
||||||
|
#if !HAVE_MALLOC_POSIX
|
||||||
|
if (result == NULL)
|
||||||
|
errno = ENOMEM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
472
lib/canonicalize-lgpl.c
Normal file
472
lib/canonicalize-lgpl.c
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
/* Return the canonical absolute name of a given file.
|
||||||
|
Copyright (C) 1996-2022 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
#ifndef _LIBC
|
||||||
|
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
|
||||||
|
optimizes away the name == NULL test below. */
|
||||||
|
# define _GL_ARG_NONNULL(params)
|
||||||
|
|
||||||
|
# include <libc-config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <eloop-threshold.h>
|
||||||
|
#include <filename.h>
|
||||||
|
#include <idx.h>
|
||||||
|
#include <intprops.h>
|
||||||
|
#include <scratch_buffer.h>
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
# include <shlib-compat.h>
|
||||||
|
# define GCC_LINT 1
|
||||||
|
# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
|
||||||
|
#else
|
||||||
|
# define __canonicalize_file_name canonicalize_file_name
|
||||||
|
# define __realpath realpath
|
||||||
|
# include "pathmax.h"
|
||||||
|
# define __faccessat faccessat
|
||||||
|
# if defined _WIN32 && !defined __CYGWIN__
|
||||||
|
# define __getcwd _getcwd
|
||||||
|
# elif HAVE_GETCWD
|
||||||
|
# if IN_RELOCWRAPPER
|
||||||
|
/* When building the relocatable program wrapper, use the system's getcwd
|
||||||
|
function, not the gnulib override, otherwise we would get a link error.
|
||||||
|
*/
|
||||||
|
# undef getcwd
|
||||||
|
# endif
|
||||||
|
# if defined VMS && !defined getcwd
|
||||||
|
/* We want the directory in Unix syntax, not in VMS syntax.
|
||||||
|
The gnulib override of 'getcwd' takes 2 arguments; the original VMS
|
||||||
|
'getcwd' takes 3 arguments. */
|
||||||
|
# define __getcwd(buf, max) getcwd (buf, max, 0)
|
||||||
|
# else
|
||||||
|
# define __getcwd getcwd
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define __getcwd(buf, max) getwd (buf)
|
||||||
|
# endif
|
||||||
|
# define __mempcpy mempcpy
|
||||||
|
# define __pathconf pathconf
|
||||||
|
# define __rawmemchr rawmemchr
|
||||||
|
# define __readlink readlink
|
||||||
|
# if IN_RELOCWRAPPER
|
||||||
|
/* When building the relocatable program wrapper, use the system's memmove
|
||||||
|
function, not the gnulib override, otherwise we would get a link error.
|
||||||
|
*/
|
||||||
|
# undef memmove
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
|
||||||
|
#if defined GCC_LINT || defined lint
|
||||||
|
# define IF_LINT(Code) Code
|
||||||
|
#else
|
||||||
|
# define IF_LINT(Code) /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||||
|
# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined _LIBC || !FUNC_REALPATH_WORKS
|
||||||
|
|
||||||
|
/* Return true if FILE's existence can be shown, false (setting errno)
|
||||||
|
otherwise. Follow symbolic links. */
|
||||||
|
static bool
|
||||||
|
file_accessible (char const *file)
|
||||||
|
{
|
||||||
|
# if defined _LIBC || HAVE_FACCESSAT
|
||||||
|
return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
|
||||||
|
# else
|
||||||
|
struct stat st;
|
||||||
|
return stat (file, &st) == 0 || errno == EOVERFLOW;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* True if concatenating END as a suffix to a file name means that the
|
||||||
|
code needs to check that the file name is that of a searchable
|
||||||
|
directory, since the canonicalize_filename_mode_stk code won't
|
||||||
|
check this later anyway when it checks an ordinary file name
|
||||||
|
component within END. END must either be empty, or start with a
|
||||||
|
slash. */
|
||||||
|
|
||||||
|
static bool _GL_ATTRIBUTE_PURE
|
||||||
|
suffix_requires_dir_check (char const *end)
|
||||||
|
{
|
||||||
|
/* If END does not start with a slash, the suffix is OK. */
|
||||||
|
while (ISSLASH (*end))
|
||||||
|
{
|
||||||
|
/* Two or more slashes act like a single slash. */
|
||||||
|
do
|
||||||
|
end++;
|
||||||
|
while (ISSLASH (*end));
|
||||||
|
|
||||||
|
switch (*end++)
|
||||||
|
{
|
||||||
|
default: return false; /* An ordinary file name component is OK. */
|
||||||
|
case '\0': return true; /* Trailing "/" is trouble. */
|
||||||
|
case '.': break; /* Possibly "." or "..". */
|
||||||
|
}
|
||||||
|
/* Trailing "/.", or "/.." even if not trailing, is trouble. */
|
||||||
|
if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append this to a file name to test whether it is a searchable directory.
|
||||||
|
On POSIX platforms "/" suffices, but "/./" is sometimes needed on
|
||||||
|
macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
|
||||||
|
platforms like AIX 7.2 that need at least "/.". */
|
||||||
|
|
||||||
|
# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||||
|
static char const dir_suffix[] = "/";
|
||||||
|
# else
|
||||||
|
static char const dir_suffix[] = "/./";
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
|
||||||
|
DIREND points to the NUL byte at the end of the DIR string.
|
||||||
|
Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
dir_check (char *dir, char *dirend)
|
||||||
|
{
|
||||||
|
strcpy (dirend, dir_suffix);
|
||||||
|
return file_accessible (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idx_t
|
||||||
|
get_path_max (void)
|
||||||
|
{
|
||||||
|
# ifdef PATH_MAX
|
||||||
|
long int path_max = PATH_MAX;
|
||||||
|
# else
|
||||||
|
/* The caller invoked realpath with a null RESOLVED, even though
|
||||||
|
PATH_MAX is not defined as a constant. The glibc manual says
|
||||||
|
programs should not do this, and POSIX says the behavior is undefined.
|
||||||
|
Historically, glibc here used the result of pathconf, or 1024 if that
|
||||||
|
failed; stay consistent with this (dubious) historical practice. */
|
||||||
|
int err = errno;
|
||||||
|
long int path_max = __pathconf ("/", _PC_PATH_MAX);
|
||||||
|
__set_errno (err);
|
||||||
|
# endif
|
||||||
|
return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Act like __realpath (see below), with an additional argument
|
||||||
|
rname_buf that can be used as temporary storage.
|
||||||
|
|
||||||
|
If GCC_LINT is defined, do not inline this function with GCC 10.1
|
||||||
|
and later, to avoid creating a pointer to the stack that GCC
|
||||||
|
-Wreturn-local-addr incorrectly complains about. See:
|
||||||
|
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
|
||||||
|
Although the noinline attribute can hurt performance a bit, no better way
|
||||||
|
to pacify GCC is known; even an explicit #pragma does not pacify GCC.
|
||||||
|
When the GCC bug is fixed this workaround should be limited to the
|
||||||
|
broken GCC versions. */
|
||||||
|
# if __GNUC_PREREQ (10, 1)
|
||||||
|
# if defined GCC_LINT || defined lint
|
||||||
|
__attribute__ ((__noinline__))
|
||||||
|
# elif __OPTIMIZE__ && !__NO_INLINE__
|
||||||
|
# define GCC_BOGUS_WRETURN_LOCAL_ADDR
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
static char *
|
||||||
|
realpath_stk (const char *name, char *resolved,
|
||||||
|
struct scratch_buffer *rname_buf)
|
||||||
|
{
|
||||||
|
char *dest;
|
||||||
|
char const *start;
|
||||||
|
char const *end;
|
||||||
|
int num_links = 0;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
/* As per Single Unix Specification V2 we must return an error if
|
||||||
|
either parameter is a null pointer. We extend this to allow
|
||||||
|
the RESOLVED parameter to be NULL in case the we are expected to
|
||||||
|
allocate the room for the return value. */
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name[0] == '\0')
|
||||||
|
{
|
||||||
|
/* As per Single Unix Specification V2 we must return an error if
|
||||||
|
the name argument points to an empty string. */
|
||||||
|
__set_errno (ENOENT);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct scratch_buffer extra_buffer, link_buffer;
|
||||||
|
scratch_buffer_init (&extra_buffer);
|
||||||
|
scratch_buffer_init (&link_buffer);
|
||||||
|
scratch_buffer_init (rname_buf);
|
||||||
|
char *rname_on_stack = rname_buf->data;
|
||||||
|
char *rname = rname_on_stack;
|
||||||
|
bool end_in_extra_buffer = false;
|
||||||
|
bool failed = true;
|
||||||
|
|
||||||
|
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
|
||||||
|
and MS-DOS X:/foo/bar file names. */
|
||||||
|
idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
|
||||||
|
|
||||||
|
if (!IS_ABSOLUTE_FILE_NAME (name))
|
||||||
|
{
|
||||||
|
while (!__getcwd (rname, rname_buf->length))
|
||||||
|
{
|
||||||
|
if (errno != ERANGE)
|
||||||
|
{
|
||||||
|
dest = rname;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!scratch_buffer_grow (rname_buf))
|
||||||
|
goto error_nomem;
|
||||||
|
rname = rname_buf->data;
|
||||||
|
}
|
||||||
|
dest = __rawmemchr (rname, '\0');
|
||||||
|
start = name;
|
||||||
|
prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dest = __mempcpy (rname, name, prefix_len);
|
||||||
|
*dest++ = '/';
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
|
||||||
|
{
|
||||||
|
if (prefix_len == 0 /* implies ISSLASH (name[0]) */
|
||||||
|
&& ISSLASH (name[1]) && !ISSLASH (name[2]))
|
||||||
|
*dest++ = '/';
|
||||||
|
*dest = '\0';
|
||||||
|
}
|
||||||
|
start = name + prefix_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; *start; start = end)
|
||||||
|
{
|
||||||
|
/* Skip sequence of multiple file name separators. */
|
||||||
|
while (ISSLASH (*start))
|
||||||
|
++start;
|
||||||
|
|
||||||
|
/* Find end of component. */
|
||||||
|
for (end = start; *end && !ISSLASH (*end); ++end)
|
||||||
|
/* Nothing. */;
|
||||||
|
|
||||||
|
/* Length of this file name component; it can be zero if a file
|
||||||
|
name ends in '/'. */
|
||||||
|
idx_t startlen = end - start;
|
||||||
|
|
||||||
|
if (startlen == 0)
|
||||||
|
break;
|
||||||
|
else if (startlen == 1 && start[0] == '.')
|
||||||
|
/* nothing */;
|
||||||
|
else if (startlen == 2 && start[0] == '.' && start[1] == '.')
|
||||||
|
{
|
||||||
|
/* Back up to previous component, ignore if at root already. */
|
||||||
|
if (dest > rname + prefix_len + 1)
|
||||||
|
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
|
||||||
|
continue;
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||||
|
&& dest == rname + 1 && !prefix_len
|
||||||
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ISSLASH (dest[-1]))
|
||||||
|
*dest++ = '/';
|
||||||
|
|
||||||
|
while (rname + rname_buf->length - dest
|
||||||
|
< startlen + sizeof dir_suffix)
|
||||||
|
{
|
||||||
|
idx_t dest_offset = dest - rname;
|
||||||
|
if (!scratch_buffer_grow_preserve (rname_buf))
|
||||||
|
goto error_nomem;
|
||||||
|
rname = rname_buf->data;
|
||||||
|
dest = rname + dest_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = __mempcpy (dest, start, startlen);
|
||||||
|
*dest = '\0';
|
||||||
|
|
||||||
|
char *buf;
|
||||||
|
ssize_t n;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
buf = link_buffer.data;
|
||||||
|
idx_t bufsize = link_buffer.length;
|
||||||
|
n = __readlink (rname, buf, bufsize - 1);
|
||||||
|
if (n < bufsize - 1)
|
||||||
|
break;
|
||||||
|
if (!scratch_buffer_grow (&link_buffer))
|
||||||
|
goto error_nomem;
|
||||||
|
}
|
||||||
|
if (0 <= n)
|
||||||
|
{
|
||||||
|
if (++num_links > __eloop_threshold ())
|
||||||
|
{
|
||||||
|
__set_errno (ELOOP);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[n] = '\0';
|
||||||
|
|
||||||
|
char *extra_buf = extra_buffer.data;
|
||||||
|
idx_t end_idx IF_LINT (= 0);
|
||||||
|
if (end_in_extra_buffer)
|
||||||
|
end_idx = end - extra_buf;
|
||||||
|
size_t len = strlen (end);
|
||||||
|
if (INT_ADD_OVERFLOW (len, n))
|
||||||
|
{
|
||||||
|
__set_errno (ENOMEM);
|
||||||
|
goto error_nomem;
|
||||||
|
}
|
||||||
|
while (extra_buffer.length <= len + n)
|
||||||
|
{
|
||||||
|
if (!scratch_buffer_grow_preserve (&extra_buffer))
|
||||||
|
goto error_nomem;
|
||||||
|
extra_buf = extra_buffer.data;
|
||||||
|
}
|
||||||
|
if (end_in_extra_buffer)
|
||||||
|
end = extra_buf + end_idx;
|
||||||
|
|
||||||
|
/* Careful here, end may be a pointer into extra_buf... */
|
||||||
|
memmove (&extra_buf[n], end, len + 1);
|
||||||
|
name = end = memcpy (extra_buf, buf, n);
|
||||||
|
end_in_extra_buffer = true;
|
||||||
|
|
||||||
|
if (IS_ABSOLUTE_FILE_NAME (buf))
|
||||||
|
{
|
||||||
|
idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
|
||||||
|
|
||||||
|
dest = __mempcpy (rname, buf, pfxlen);
|
||||||
|
*dest++ = '/'; /* It's an absolute symlink */
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
|
||||||
|
{
|
||||||
|
if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
|
||||||
|
*dest++ = '/';
|
||||||
|
*dest = '\0';
|
||||||
|
}
|
||||||
|
/* Install the new prefix to be in effect hereafter. */
|
||||||
|
prefix_len = pfxlen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Back up to previous component, ignore if at root
|
||||||
|
already: */
|
||||||
|
if (dest > rname + prefix_len + 1)
|
||||||
|
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
|
||||||
|
continue;
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
|
||||||
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (! (suffix_requires_dir_check (end)
|
||||||
|
? dir_check (rname, dest)
|
||||||
|
: errno == EINVAL))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
|
||||||
|
--dest;
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
|
||||||
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
|
||||||
|
dest++;
|
||||||
|
failed = false;
|
||||||
|
|
||||||
|
error:
|
||||||
|
*dest++ = '\0';
|
||||||
|
if (resolved != NULL && dest - rname <= get_path_max ())
|
||||||
|
rname = strcpy (resolved, rname);
|
||||||
|
|
||||||
|
error_nomem:
|
||||||
|
scratch_buffer_free (&extra_buffer);
|
||||||
|
scratch_buffer_free (&link_buffer);
|
||||||
|
|
||||||
|
if (failed || rname == resolved)
|
||||||
|
{
|
||||||
|
scratch_buffer_free (rname_buf);
|
||||||
|
return failed ? NULL : resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scratch_buffer_dupfree (rname_buf, dest - rname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the canonical absolute name of file NAME. A canonical name
|
||||||
|
does not contain any ".", ".." components nor any repeated file name
|
||||||
|
separators ('/') or symlinks. All file name components must exist. If
|
||||||
|
RESOLVED is null, the result is malloc'd; otherwise, if the
|
||||||
|
canonical name is PATH_MAX chars or more, returns null with 'errno'
|
||||||
|
set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
|
||||||
|
returns the name in RESOLVED. If the name cannot be resolved and
|
||||||
|
RESOLVED is non-NULL, it contains the name of the first component
|
||||||
|
that cannot be resolved. If the name can be resolved, RESOLVED
|
||||||
|
holds the same value as the value returned. */
|
||||||
|
|
||||||
|
char *
|
||||||
|
__realpath (const char *name, char *resolved)
|
||||||
|
{
|
||||||
|
#ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
|
||||||
|
#warning "GCC might issue a bogus -Wreturn-local-addr warning here."
|
||||||
|
#warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
|
||||||
|
#endif
|
||||||
|
struct scratch_buffer rname_buffer;
|
||||||
|
return realpath_stk (name, resolved, &rname_buffer);
|
||||||
|
}
|
||||||
|
libc_hidden_def (__realpath)
|
||||||
|
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
|
||||||
|
|
||||||
|
#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
|
||||||
|
|
||||||
|
|
||||||
|
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
|
||||||
|
char *
|
||||||
|
attribute_compat_text_section
|
||||||
|
__old_realpath (const char *name, char *resolved)
|
||||||
|
{
|
||||||
|
if (resolved == NULL)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return __realpath (name, resolved);
|
||||||
|
}
|
||||||
|
compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
__canonicalize_file_name (const char *name)
|
||||||
|
{
|
||||||
|
return __realpath (name, NULL);
|
||||||
|
}
|
||||||
|
weak_alias (__canonicalize_file_name, canonicalize_file_name)
|
||||||
489
lib/canonicalize.c
Normal file
489
lib/canonicalize.c
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
/* Return the canonical absolute name of a given file.
|
||||||
|
Copyright (C) 1996-2022 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 <config.h>
|
||||||
|
|
||||||
|
#include "canonicalize.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <filename.h>
|
||||||
|
#include <idx.h>
|
||||||
|
#include <intprops.h>
|
||||||
|
#include <scratch_buffer.h>
|
||||||
|
|
||||||
|
#include "attribute.h"
|
||||||
|
#include "file-set.h"
|
||||||
|
#include "hash-triple.h"
|
||||||
|
#include "xalloc.h"
|
||||||
|
|
||||||
|
/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
|
||||||
|
#if defined GCC_LINT || defined lint
|
||||||
|
# define IF_LINT(Code) Code
|
||||||
|
#else
|
||||||
|
# define IF_LINT(Code) /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||||
|
# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ISSLASH ('\\')
|
||||||
|
# define SLASHES "/\\"
|
||||||
|
#else
|
||||||
|
# define SLASHES "/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return true if FILE's existence can be shown, false (setting errno)
|
||||||
|
otherwise. Follow symbolic links. */
|
||||||
|
static bool
|
||||||
|
file_accessible (char const *file)
|
||||||
|
{
|
||||||
|
# if HAVE_FACCESSAT
|
||||||
|
return faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
|
||||||
|
# else
|
||||||
|
struct stat st;
|
||||||
|
return stat (file, &st) == 0 || errno == EOVERFLOW;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* True if concatenating END as a suffix to a file name means that the
|
||||||
|
code needs to check that the file name is that of a searchable
|
||||||
|
directory, since the canonicalize_filename_mode_stk code won't
|
||||||
|
check this later anyway when it checks an ordinary file name
|
||||||
|
component within END. END must either be empty, or start with a
|
||||||
|
slash. */
|
||||||
|
|
||||||
|
static bool _GL_ATTRIBUTE_PURE
|
||||||
|
suffix_requires_dir_check (char const *end)
|
||||||
|
{
|
||||||
|
/* If END does not start with a slash, the suffix is OK. */
|
||||||
|
while (ISSLASH (*end))
|
||||||
|
{
|
||||||
|
/* Two or more slashes act like a single slash. */
|
||||||
|
do
|
||||||
|
end++;
|
||||||
|
while (ISSLASH (*end));
|
||||||
|
|
||||||
|
switch (*end++)
|
||||||
|
{
|
||||||
|
default: return false; /* An ordinary file name component is OK. */
|
||||||
|
case '\0': return true; /* Trailing "/" is trouble. */
|
||||||
|
case '.': break; /* Possibly "." or "..". */
|
||||||
|
}
|
||||||
|
/* Trailing "/.", or "/.." even if not trailing, is trouble. */
|
||||||
|
if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append this to a file name to test whether it is a searchable directory.
|
||||||
|
On POSIX platforms "/" suffices, but "/./" is sometimes needed on
|
||||||
|
macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
|
||||||
|
platforms like AIX 7.2 that need at least "/.". */
|
||||||
|
|
||||||
|
#ifdef LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||||
|
static char const dir_suffix[] = "/";
|
||||||
|
#else
|
||||||
|
static char const dir_suffix[] = "/./";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
|
||||||
|
DIREND points to the NUL byte at the end of the DIR string.
|
||||||
|
Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
dir_check (char *dir, char *dirend)
|
||||||
|
{
|
||||||
|
strcpy (dirend, dir_suffix);
|
||||||
|
return file_accessible (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !((HAVE_CANONICALIZE_FILE_NAME && FUNC_REALPATH_WORKS) \
|
||||||
|
|| GNULIB_CANONICALIZE_LGPL)
|
||||||
|
/* Return the canonical absolute name of file NAME. A canonical name
|
||||||
|
does not contain any ".", ".." components nor any repeated file name
|
||||||
|
separators ('/') or symlinks. All components must exist.
|
||||||
|
The result is malloc'd. */
|
||||||
|
|
||||||
|
char *
|
||||||
|
canonicalize_file_name (const char *name)
|
||||||
|
{
|
||||||
|
return canonicalize_filename_mode (name, CAN_EXISTING);
|
||||||
|
}
|
||||||
|
#endif /* !HAVE_CANONICALIZE_FILE_NAME */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
multiple_bits_set (canonicalize_mode_t i)
|
||||||
|
{
|
||||||
|
return (i & (i - 1)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if we've already seen the triple, <FILENAME, dev, ino>.
|
||||||
|
If *HT is not initialized, initialize it. */
|
||||||
|
static bool
|
||||||
|
seen_triple (Hash_table **ht, char const *filename, struct stat const *st)
|
||||||
|
{
|
||||||
|
if (*ht == NULL)
|
||||||
|
{
|
||||||
|
idx_t initial_capacity = 7;
|
||||||
|
*ht = hash_initialize (initial_capacity,
|
||||||
|
NULL,
|
||||||
|
triple_hash,
|
||||||
|
triple_compare_ino_str,
|
||||||
|
triple_free);
|
||||||
|
if (*ht == NULL)
|
||||||
|
xalloc_die ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seen_file (*ht, filename, st))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
record_file (*ht, filename, st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Act like canonicalize_filename_mode (see below), with an additional argument
|
||||||
|
rname_buf that can be used as temporary storage.
|
||||||
|
|
||||||
|
If GCC_LINT is defined, do not inline this function with GCC 10.1
|
||||||
|
and later, to avoid creating a pointer to the stack that GCC
|
||||||
|
-Wreturn-local-addr incorrectly complains about. See:
|
||||||
|
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
|
||||||
|
Although the noinline attribute can hurt performance a bit, no better way
|
||||||
|
to pacify GCC is known; even an explicit #pragma does not pacify GCC.
|
||||||
|
When the GCC bug is fixed this workaround should be limited to the
|
||||||
|
broken GCC versions. */
|
||||||
|
#if _GL_GNUC_PREREQ (10, 1)
|
||||||
|
# if defined GCC_LINT || defined lint
|
||||||
|
__attribute__ ((__noinline__))
|
||||||
|
# elif __OPTIMIZE__ && !__NO_INLINE__
|
||||||
|
# define GCC_BOGUS_WRETURN_LOCAL_ADDR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
static char *
|
||||||
|
canonicalize_filename_mode_stk (const char *name, canonicalize_mode_t can_mode,
|
||||||
|
struct scratch_buffer *rname_buf)
|
||||||
|
{
|
||||||
|
char *dest;
|
||||||
|
char const *start;
|
||||||
|
char const *end;
|
||||||
|
Hash_table *ht = NULL;
|
||||||
|
bool logical = (can_mode & CAN_NOLINKS) != 0;
|
||||||
|
int num_links = 0;
|
||||||
|
|
||||||
|
canonicalize_mode_t can_exist = can_mode & CAN_MODE_MASK;
|
||||||
|
if (multiple_bits_set (can_exist))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name[0] == '\0')
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct scratch_buffer extra_buffer, link_buffer;
|
||||||
|
scratch_buffer_init (&extra_buffer);
|
||||||
|
scratch_buffer_init (&link_buffer);
|
||||||
|
scratch_buffer_init (rname_buf);
|
||||||
|
char *rname_on_stack = rname_buf->data;
|
||||||
|
char *rname = rname_on_stack;
|
||||||
|
bool end_in_extra_buffer = false;
|
||||||
|
bool failed = true;
|
||||||
|
|
||||||
|
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
|
||||||
|
and MS-DOS X:/foo/bar file names. */
|
||||||
|
idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
|
||||||
|
|
||||||
|
if (!IS_ABSOLUTE_FILE_NAME (name))
|
||||||
|
{
|
||||||
|
while (!getcwd (rname, rname_buf->length))
|
||||||
|
{
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case ERANGE:
|
||||||
|
if (scratch_buffer_grow (rname_buf))
|
||||||
|
break;
|
||||||
|
FALLTHROUGH;
|
||||||
|
case ENOMEM:
|
||||||
|
xalloc_die ();
|
||||||
|
|
||||||
|
default:
|
||||||
|
dest = rname;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rname = rname_buf->data;
|
||||||
|
}
|
||||||
|
dest = rawmemchr (rname, '\0');
|
||||||
|
start = name;
|
||||||
|
prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dest = mempcpy (rname, name, prefix_len);
|
||||||
|
*dest++ = '/';
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
|
||||||
|
{
|
||||||
|
if (prefix_len == 0 /* implies ISSLASH (name[0]) */
|
||||||
|
&& ISSLASH (name[1]) && !ISSLASH (name[2]))
|
||||||
|
{
|
||||||
|
*dest++ = '/';
|
||||||
|
#if defined _WIN32 && !defined __CYGWIN__
|
||||||
|
/* For UNC file names '\\server\path\to\file', extend the prefix
|
||||||
|
to include the server: '\\server\'. */
|
||||||
|
{
|
||||||
|
idx_t i;
|
||||||
|
for (i = 2; name[i] != '\0' && !ISSLASH (name[i]); )
|
||||||
|
i++;
|
||||||
|
if (name[i] != '\0' /* implies ISSLASH (name[i]) */
|
||||||
|
&& i + 1 < rname_buf->length)
|
||||||
|
{
|
||||||
|
prefix_len = i;
|
||||||
|
memcpy (dest, name + 2, i - 2 + 1);
|
||||||
|
dest += i - 2 + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Either name = '\\server'; this is an invalid file name.
|
||||||
|
Or name = '\\server\...' and server is more than
|
||||||
|
rname_buf->length - 4 bytes long. In either
|
||||||
|
case, stop the UNC processing. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*dest = '\0';
|
||||||
|
}
|
||||||
|
start = name + prefix_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; *start; start = end)
|
||||||
|
{
|
||||||
|
/* Skip sequence of multiple file name separators. */
|
||||||
|
while (ISSLASH (*start))
|
||||||
|
++start;
|
||||||
|
|
||||||
|
/* Find end of component. */
|
||||||
|
for (end = start; *end && !ISSLASH (*end); ++end)
|
||||||
|
/* Nothing. */;
|
||||||
|
|
||||||
|
/* Length of this file name component; it can be zero if a file
|
||||||
|
name ends in '/'. */
|
||||||
|
idx_t startlen = end - start;
|
||||||
|
|
||||||
|
if (startlen == 0)
|
||||||
|
break;
|
||||||
|
else if (startlen == 1 && start[0] == '.')
|
||||||
|
/* nothing */;
|
||||||
|
else if (startlen == 2 && start[0] == '.' && start[1] == '.')
|
||||||
|
{
|
||||||
|
/* Back up to previous component, ignore if at root already. */
|
||||||
|
if (dest > rname + prefix_len + 1)
|
||||||
|
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
|
||||||
|
continue;
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||||
|
&& dest == rname + 1 && !prefix_len
|
||||||
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ISSLASH (dest[-1]))
|
||||||
|
*dest++ = '/';
|
||||||
|
|
||||||
|
while (rname + rname_buf->length - dest
|
||||||
|
< startlen + sizeof dir_suffix)
|
||||||
|
{
|
||||||
|
idx_t dest_offset = dest - rname;
|
||||||
|
if (!scratch_buffer_grow_preserve (rname_buf))
|
||||||
|
xalloc_die ();
|
||||||
|
rname = rname_buf->data;
|
||||||
|
dest = rname + dest_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = mempcpy (dest, start, startlen);
|
||||||
|
*dest = '\0';
|
||||||
|
|
||||||
|
char *buf;
|
||||||
|
ssize_t n = -1;
|
||||||
|
if (!logical)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
buf = link_buffer.data;
|
||||||
|
idx_t bufsize = link_buffer.length;
|
||||||
|
n = readlink (rname, buf, bufsize - 1);
|
||||||
|
if (n < bufsize - 1)
|
||||||
|
break;
|
||||||
|
if (!scratch_buffer_grow (&link_buffer))
|
||||||
|
xalloc_die ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 <= n)
|
||||||
|
{
|
||||||
|
/* A physical traversal and RNAME is a symbolic link. */
|
||||||
|
|
||||||
|
if (num_links < 20)
|
||||||
|
num_links++;
|
||||||
|
else if (*start)
|
||||||
|
{
|
||||||
|
/* Enough symlinks have been seen that it is time to
|
||||||
|
worry about being in a symlink cycle.
|
||||||
|
Get the device and inode of the parent directory, as
|
||||||
|
pre-2017 POSIX says this info is not reliable for
|
||||||
|
symlinks. */
|
||||||
|
struct stat st;
|
||||||
|
dest[- startlen] = '\0';
|
||||||
|
if (stat (*rname ? rname : ".", &st) != 0)
|
||||||
|
goto error;
|
||||||
|
dest[- startlen] = *start;
|
||||||
|
|
||||||
|
/* Detect loops. We cannot use the cycle-check module here,
|
||||||
|
since it's possible to encounter the same parent
|
||||||
|
directory more than once in a given traversal. However,
|
||||||
|
encountering the same (parentdir, START) pair twice does
|
||||||
|
indicate a loop. */
|
||||||
|
if (seen_triple (&ht, start, &st))
|
||||||
|
{
|
||||||
|
if (can_exist == CAN_MISSING)
|
||||||
|
continue;
|
||||||
|
errno = ELOOP;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[n] = '\0';
|
||||||
|
|
||||||
|
char *extra_buf = extra_buffer.data;
|
||||||
|
idx_t end_idx IF_LINT (= 0);
|
||||||
|
if (end_in_extra_buffer)
|
||||||
|
end_idx = end - extra_buf;
|
||||||
|
size_t len = strlen (end);
|
||||||
|
if (INT_ADD_OVERFLOW (len, n))
|
||||||
|
xalloc_die ();
|
||||||
|
while (extra_buffer.length <= len + n)
|
||||||
|
{
|
||||||
|
if (!scratch_buffer_grow_preserve (&extra_buffer))
|
||||||
|
xalloc_die ();
|
||||||
|
extra_buf = extra_buffer.data;
|
||||||
|
}
|
||||||
|
if (end_in_extra_buffer)
|
||||||
|
end = extra_buf + end_idx;
|
||||||
|
|
||||||
|
/* Careful here, end may be a pointer into extra_buf... */
|
||||||
|
memmove (&extra_buf[n], end, len + 1);
|
||||||
|
name = end = memcpy (extra_buf, buf, n);
|
||||||
|
end_in_extra_buffer = true;
|
||||||
|
|
||||||
|
if (IS_ABSOLUTE_FILE_NAME (buf))
|
||||||
|
{
|
||||||
|
idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
|
||||||
|
|
||||||
|
dest = mempcpy (rname, buf, pfxlen);
|
||||||
|
*dest++ = '/'; /* It's an absolute symlink */
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
|
||||||
|
{
|
||||||
|
if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
|
||||||
|
*dest++ = '/';
|
||||||
|
*dest = '\0';
|
||||||
|
}
|
||||||
|
/* Install the new prefix to be in effect hereafter. */
|
||||||
|
prefix_len = pfxlen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Back up to previous component, ignore if at root
|
||||||
|
already: */
|
||||||
|
if (dest > rname + prefix_len + 1)
|
||||||
|
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
|
||||||
|
continue;
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
|
||||||
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (! (can_exist == CAN_MISSING
|
||||||
|
|| (suffix_requires_dir_check (end)
|
||||||
|
? dir_check (rname, dest)
|
||||||
|
: !logical
|
||||||
|
? errno == EINVAL
|
||||||
|
: *end || file_accessible (rname))
|
||||||
|
|| (can_exist == CAN_ALL_BUT_LAST
|
||||||
|
&& errno == ENOENT
|
||||||
|
&& !end[strspn (end, SLASHES)])))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
|
||||||
|
--dest;
|
||||||
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
|
||||||
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
|
||||||
|
dest++;
|
||||||
|
failed = false;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (ht)
|
||||||
|
hash_free (ht);
|
||||||
|
scratch_buffer_free (&extra_buffer);
|
||||||
|
scratch_buffer_free (&link_buffer);
|
||||||
|
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
scratch_buffer_free (rname_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest++ = '\0';
|
||||||
|
char *result = scratch_buffer_dupfree (rname_buf, dest - rname);
|
||||||
|
if (!result)
|
||||||
|
xalloc_die ();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the canonical absolute name of file NAME, while treating
|
||||||
|
missing elements according to CAN_MODE. A canonical name
|
||||||
|
does not contain any ".", ".." components nor any repeated file name
|
||||||
|
separators ('/') or, depending on other CAN_MODE flags, symlinks.
|
||||||
|
Whether components must exist or not depends on canonicalize mode.
|
||||||
|
The result is malloc'd. */
|
||||||
|
|
||||||
|
char *
|
||||||
|
canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
|
||||||
|
{
|
||||||
|
#ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
|
||||||
|
#warning "GCC might issue a bogus -Wreturn-local-addr warning here."
|
||||||
|
#warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
|
||||||
|
#endif
|
||||||
|
struct scratch_buffer rname_buffer;
|
||||||
|
return canonicalize_filename_mode_stk (name, can_mode, &rname_buffer);
|
||||||
|
}
|
||||||
58
lib/canonicalize.h
Normal file
58
lib/canonicalize.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* Return the canonical absolute name of a given file.
|
||||||
|
Copyright (C) 1996-2007, 2009-2022 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 CANONICALIZE_H_
|
||||||
|
# define CANONICALIZE_H_
|
||||||
|
|
||||||
|
#include <stdlib.h> /* for canonicalize_file_name */
|
||||||
|
|
||||||
|
#define CAN_MODE_MASK (CAN_EXISTING | CAN_ALL_BUT_LAST | CAN_MISSING)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum canonicalize_mode_t
|
||||||
|
{
|
||||||
|
/* All components must exist. */
|
||||||
|
CAN_EXISTING = 0,
|
||||||
|
|
||||||
|
/* All components excluding last one must exist. */
|
||||||
|
CAN_ALL_BUT_LAST = 1,
|
||||||
|
|
||||||
|
/* No requirements on components existence. */
|
||||||
|
CAN_MISSING = 2,
|
||||||
|
|
||||||
|
/* Don't expand symlinks. */
|
||||||
|
CAN_NOLINKS = 4
|
||||||
|
};
|
||||||
|
typedef enum canonicalize_mode_t canonicalize_mode_t;
|
||||||
|
|
||||||
|
/* Return the canonical absolute name of file NAME, while treating
|
||||||
|
missing elements according to CAN_MODE. A canonical name
|
||||||
|
does not contain any `.', `..' components nor any repeated file name
|
||||||
|
separators ('/') or, depending on other CAN_MODE flags, symlinks.
|
||||||
|
Whether components must exist or not depends on canonicalize mode.
|
||||||
|
The result is malloc'd.
|
||||||
|
Upon failure, return NULL with errno set. */
|
||||||
|
char *canonicalize_filename_mode (const char *, canonicalize_mode_t)
|
||||||
|
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !CANONICALIZE_H_ */
|
||||||
707
lib/cdefs.h
Normal file
707
lib/cdefs.h
Normal file
@ -0,0 +1,707 @@
|
|||||||
|
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
|
||||||
|
Copyright The GNU Toolchain Authors.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
#ifndef _SYS_CDEFS_H
|
||||||
|
#define _SYS_CDEFS_H 1
|
||||||
|
|
||||||
|
/* We are almost always included from features.h. */
|
||||||
|
#ifndef _FEATURES_H
|
||||||
|
# include <features.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The GNU libc does not support any K&R compilers or the traditional mode
|
||||||
|
of ISO C compilers anymore. Check for some of the combinations not
|
||||||
|
supported anymore. */
|
||||||
|
#if defined __GNUC__ && !defined __STDC__
|
||||||
|
# error "You need a ISO C conforming compiler to use the glibc headers"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some user header file might have defined this before. */
|
||||||
|
#undef __P
|
||||||
|
#undef __PMT
|
||||||
|
|
||||||
|
/* Compilers that lack __has_attribute may object to
|
||||||
|
#if defined __has_attribute && __has_attribute (...)
|
||||||
|
even though they do not need to evaluate the right-hand side of the &&.
|
||||||
|
Similarly for __has_builtin, etc. */
|
||||||
|
#if (defined __has_attribute \
|
||||||
|
&& (!defined __clang_minor__ \
|
||||||
|
|| (defined __apple_build_version__ \
|
||||||
|
? 6000000 <= __apple_build_version__ \
|
||||||
|
: 3 < __clang_major__ + (5 <= __clang_minor__))))
|
||||||
|
# define __glibc_has_attribute(attr) __has_attribute (attr)
|
||||||
|
#else
|
||||||
|
# define __glibc_has_attribute(attr) 0
|
||||||
|
#endif
|
||||||
|
#ifdef __has_builtin
|
||||||
|
# define __glibc_has_builtin(name) __has_builtin (name)
|
||||||
|
#else
|
||||||
|
# define __glibc_has_builtin(name) 0
|
||||||
|
#endif
|
||||||
|
#ifdef __has_extension
|
||||||
|
# define __glibc_has_extension(ext) __has_extension (ext)
|
||||||
|
#else
|
||||||
|
# define __glibc_has_extension(ext) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __GNUC__ || defined __clang__
|
||||||
|
|
||||||
|
/* All functions, except those with callbacks or those that
|
||||||
|
synchronize memory, are leaf functions. */
|
||||||
|
# if __GNUC_PREREQ (4, 6) && !defined _LIBC
|
||||||
|
# define __LEAF , __leaf__
|
||||||
|
# define __LEAF_ATTR __attribute__ ((__leaf__))
|
||||||
|
# else
|
||||||
|
# define __LEAF
|
||||||
|
# define __LEAF_ATTR
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* GCC can always grok prototypes. For C++ programs we add throw()
|
||||||
|
to help it optimize the function calls. But this only works with
|
||||||
|
gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions
|
||||||
|
as non-throwing using a function attribute since programs can use
|
||||||
|
the -fexceptions options for C code as well. */
|
||||||
|
# if !defined __cplusplus \
|
||||||
|
&& (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__))
|
||||||
|
# define __THROW __attribute__ ((__nothrow__ __LEAF))
|
||||||
|
# define __THROWNL __attribute__ ((__nothrow__))
|
||||||
|
# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
|
||||||
|
# define __NTHNL(fct) __attribute__ ((__nothrow__)) fct
|
||||||
|
# else
|
||||||
|
# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4)
|
||||||
|
# if __cplusplus >= 201103L
|
||||||
|
# define __THROW noexcept (true)
|
||||||
|
# else
|
||||||
|
# define __THROW throw ()
|
||||||
|
# endif
|
||||||
|
# define __THROWNL __THROW
|
||||||
|
# define __NTH(fct) __LEAF_ATTR fct __THROW
|
||||||
|
# define __NTHNL(fct) fct __THROW
|
||||||
|
# else
|
||||||
|
# define __THROW
|
||||||
|
# define __THROWNL
|
||||||
|
# define __NTH(fct) fct
|
||||||
|
# define __NTHNL(fct) fct
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else /* Not GCC or clang. */
|
||||||
|
|
||||||
|
# if (defined __cplusplus \
|
||||||
|
|| (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
|
||||||
|
# define __inline inline
|
||||||
|
# else
|
||||||
|
# define __inline /* No inline functions. */
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define __THROW
|
||||||
|
# define __THROWNL
|
||||||
|
# define __NTH(fct) fct
|
||||||
|
|
||||||
|
#endif /* GCC || clang. */
|
||||||
|
|
||||||
|
/* These two macros are not used in glibc anymore. They are kept here
|
||||||
|
only because some other projects expect the macros to be defined. */
|
||||||
|
#define __P(args) args
|
||||||
|
#define __PMT(args) args
|
||||||
|
|
||||||
|
/* For these things, GCC behaves the ANSI way normally,
|
||||||
|
and the non-ANSI way under -traditional. */
|
||||||
|
|
||||||
|
#define __CONCAT(x,y) x ## y
|
||||||
|
#define __STRING(x) #x
|
||||||
|
|
||||||
|
/* This is not a typedef so `const __ptr_t' does the right thing. */
|
||||||
|
#define __ptr_t void *
|
||||||
|
|
||||||
|
|
||||||
|
/* C++ needs to know that types and declarations are C, not C++. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# define __BEGIN_DECLS extern "C" {
|
||||||
|
# define __END_DECLS }
|
||||||
|
#else
|
||||||
|
# define __BEGIN_DECLS
|
||||||
|
# define __END_DECLS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Fortify support. */
|
||||||
|
#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
|
||||||
|
#define __bos0(ptr) __builtin_object_size (ptr, 0)
|
||||||
|
|
||||||
|
/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */
|
||||||
|
#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \
|
||||||
|
|| __GNUC_PREREQ (12, 0))
|
||||||
|
# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
|
||||||
|
# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
|
||||||
|
#else
|
||||||
|
# define __glibc_objsize0(__o) __bos0 (__o)
|
||||||
|
# define __glibc_objsize(__o) __bos (__o)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Compile time conditions to choose between the regular, _chk and _chk_warn
|
||||||
|
variants. These conditions should get evaluated to constant and optimized
|
||||||
|
away. */
|
||||||
|
|
||||||
|
#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
|
||||||
|
#define __glibc_unsigned_or_positive(__l) \
|
||||||
|
((__typeof (__l)) 0 < (__typeof (__l)) -1 \
|
||||||
|
|| (__builtin_constant_p (__l) && (__l) > 0))
|
||||||
|
|
||||||
|
/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
|
||||||
|
condition can be folded to a constant and if it is true. The -1 check is
|
||||||
|
redundant because since it implies that __glibc_safe_len_cond is true. */
|
||||||
|
#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
|
||||||
|
(__glibc_unsigned_or_positive (__l) \
|
||||||
|
&& __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
|
||||||
|
__s, __osz)) \
|
||||||
|
&& __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
|
||||||
|
|
||||||
|
/* Conversely, we know at compile time that the length is unsafe if the
|
||||||
|
__L * __S <= __OBJSZ condition can be folded to a constant and if it is
|
||||||
|
false. */
|
||||||
|
#define __glibc_unsafe_len(__l, __s, __osz) \
|
||||||
|
(__glibc_unsigned_or_positive (__l) \
|
||||||
|
&& __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
|
||||||
|
__s, __osz)) \
|
||||||
|
&& !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
|
||||||
|
|
||||||
|
/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be
|
||||||
|
declared. */
|
||||||
|
|
||||||
|
#define __glibc_fortify(f, __l, __s, __osz, ...) \
|
||||||
|
(__glibc_safe_or_unknown_len (__l, __s, __osz) \
|
||||||
|
? __ ## f ## _alias (__VA_ARGS__) \
|
||||||
|
: (__glibc_unsafe_len (__l, __s, __osz) \
|
||||||
|
? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \
|
||||||
|
: __ ## f ## _chk (__VA_ARGS__, __osz))) \
|
||||||
|
|
||||||
|
/* Fortify function f, where object size argument passed to f is the number of
|
||||||
|
elements and not total size. */
|
||||||
|
|
||||||
|
#define __glibc_fortify_n(f, __l, __s, __osz, ...) \
|
||||||
|
(__glibc_safe_or_unknown_len (__l, __s, __osz) \
|
||||||
|
? __ ## f ## _alias (__VA_ARGS__) \
|
||||||
|
: (__glibc_unsafe_len (__l, __s, __osz) \
|
||||||
|
? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \
|
||||||
|
: __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ (4,3)
|
||||||
|
# define __warnattr(msg) __attribute__((__warning__ (msg)))
|
||||||
|
# define __errordecl(name, msg) \
|
||||||
|
extern void name (void) __attribute__((__error__ (msg)))
|
||||||
|
#else
|
||||||
|
# define __warnattr(msg)
|
||||||
|
# define __errordecl(name, msg) extern void name (void)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Support for flexible arrays.
|
||||||
|
Headers that should use flexible arrays only if they're "real"
|
||||||
|
(e.g. only if they won't affect sizeof()) should test
|
||||||
|
#if __glibc_c99_flexarr_available. */
|
||||||
|
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc
|
||||||
|
# define __flexarr []
|
||||||
|
# define __glibc_c99_flexarr_available 1
|
||||||
|
#elif __GNUC_PREREQ (2,97) || defined __clang__
|
||||||
|
/* GCC 2.97 and clang support C99 flexible array members as an extension,
|
||||||
|
even when in C89 mode or compiling C++ (any version). */
|
||||||
|
# define __flexarr []
|
||||||
|
# define __glibc_c99_flexarr_available 1
|
||||||
|
#elif defined __GNUC__
|
||||||
|
/* Pre-2.97 GCC did not support C99 flexible arrays but did have
|
||||||
|
an equivalent extension with slightly different notation. */
|
||||||
|
# define __flexarr [0]
|
||||||
|
# define __glibc_c99_flexarr_available 1
|
||||||
|
#else
|
||||||
|
/* Some other non-C99 compiler. Approximate with [1]. */
|
||||||
|
# define __flexarr [1]
|
||||||
|
# define __glibc_c99_flexarr_available 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* __asm__ ("xyz") is used throughout the headers to rename functions
|
||||||
|
at the assembly language level. This is wrapped by the __REDIRECT
|
||||||
|
macro, in order to support compilers that can do this some other
|
||||||
|
way. When compilers don't support asm-names at all, we have to do
|
||||||
|
preprocessor tricks instead (which don't have exactly the right
|
||||||
|
semantics, but it's the best we can do).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */
|
||||||
|
|
||||||
|
#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4)
|
||||||
|
|
||||||
|
# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias))
|
||||||
|
# ifdef __cplusplus
|
||||||
|
# define __REDIRECT_NTH(name, proto, alias) \
|
||||||
|
name proto __THROW __asm__ (__ASMNAME (#alias))
|
||||||
|
# define __REDIRECT_NTHNL(name, proto, alias) \
|
||||||
|
name proto __THROWNL __asm__ (__ASMNAME (#alias))
|
||||||
|
# else
|
||||||
|
# define __REDIRECT_NTH(name, proto, alias) \
|
||||||
|
name proto __asm__ (__ASMNAME (#alias)) __THROW
|
||||||
|
# define __REDIRECT_NTHNL(name, proto, alias) \
|
||||||
|
name proto __asm__ (__ASMNAME (#alias)) __THROWNL
|
||||||
|
# endif
|
||||||
|
# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname)
|
||||||
|
# define __ASMNAME2(prefix, cname) __STRING (prefix) cname
|
||||||
|
|
||||||
|
/*
|
||||||
|
#elif __SOME_OTHER_COMPILER__
|
||||||
|
|
||||||
|
# define __REDIRECT(name, proto, alias) name proto; \
|
||||||
|
_Pragma("let " #name " = " #alias)
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GCC and clang have various useful declarations that can be made with
|
||||||
|
the '__attribute__' syntax. All of the ways we use this do fine if
|
||||||
|
they are omitted for compilers that don't understand it. */
|
||||||
|
#if !(defined __GNUC__ || defined __clang__)
|
||||||
|
# define __attribute__(xyz) /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* At some point during the gcc 2.96 development the `malloc' attribute
|
||||||
|
for functions was introduced. We don't want to use it unconditionally
|
||||||
|
(although this would be possible) since it generates warnings. */
|
||||||
|
#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__)
|
||||||
|
# define __attribute_malloc__ __attribute__ ((__malloc__))
|
||||||
|
#else
|
||||||
|
# define __attribute_malloc__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Tell the compiler which arguments to an allocation function
|
||||||
|
indicate the size of the allocation. */
|
||||||
|
#if __GNUC_PREREQ (4, 3)
|
||||||
|
# define __attribute_alloc_size__(params) \
|
||||||
|
__attribute__ ((__alloc_size__ params))
|
||||||
|
#else
|
||||||
|
# define __attribute_alloc_size__(params) /* Ignore. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Tell the compiler which argument to an allocation function
|
||||||
|
indicates the alignment of the allocation. */
|
||||||
|
#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__)
|
||||||
|
# define __attribute_alloc_align__(param) \
|
||||||
|
__attribute__ ((__alloc_align__ param))
|
||||||
|
#else
|
||||||
|
# define __attribute_alloc_align__(param) /* Ignore. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* At some point during the gcc 2.96 development the `pure' attribute
|
||||||
|
for functions was introduced. We don't want to use it unconditionally
|
||||||
|
(although this would be possible) since it generates warnings. */
|
||||||
|
#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__)
|
||||||
|
# define __attribute_pure__ __attribute__ ((__pure__))
|
||||||
|
#else
|
||||||
|
# define __attribute_pure__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This declaration tells the compiler that the value is constant. */
|
||||||
|
#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__)
|
||||||
|
# define __attribute_const__ __attribute__ ((__const__))
|
||||||
|
#else
|
||||||
|
# define __attribute_const__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__)
|
||||||
|
# define __attribute_maybe_unused__ __attribute__ ((__unused__))
|
||||||
|
#else
|
||||||
|
# define __attribute_maybe_unused__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* At some point during the gcc 3.1 development the `used' attribute
|
||||||
|
for functions was introduced. We don't want to use it unconditionally
|
||||||
|
(although this would be possible) since it generates warnings. */
|
||||||
|
#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__)
|
||||||
|
# define __attribute_used__ __attribute__ ((__used__))
|
||||||
|
# define __attribute_noinline__ __attribute__ ((__noinline__))
|
||||||
|
#else
|
||||||
|
# define __attribute_used__ __attribute__ ((__unused__))
|
||||||
|
# define __attribute_noinline__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Since version 3.2, gcc allows marking deprecated functions. */
|
||||||
|
#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__)
|
||||||
|
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
|
||||||
|
#else
|
||||||
|
# define __attribute_deprecated__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Since version 4.5, gcc also allows one to specify the message printed
|
||||||
|
when a deprecated function is used. clang claims to be gcc 4.2, but
|
||||||
|
may also support this feature. */
|
||||||
|
#if __GNUC_PREREQ (4,5) \
|
||||||
|
|| __glibc_has_extension (__attribute_deprecated_with_message__)
|
||||||
|
# define __attribute_deprecated_msg__(msg) \
|
||||||
|
__attribute__ ((__deprecated__ (msg)))
|
||||||
|
#else
|
||||||
|
# define __attribute_deprecated_msg__(msg) __attribute_deprecated__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* At some point during the gcc 2.8 development the `format_arg' attribute
|
||||||
|
for functions was introduced. We don't want to use it unconditionally
|
||||||
|
(although this would be possible) since it generates warnings.
|
||||||
|
If several `format_arg' attributes are given for the same function, in
|
||||||
|
gcc-3.0 and older, all but the last one are ignored. In newer gccs,
|
||||||
|
all designated arguments are considered. */
|
||||||
|
#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__)
|
||||||
|
# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
|
||||||
|
#else
|
||||||
|
# define __attribute_format_arg__(x) /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* At some point during the gcc 2.97 development the `strfmon' format
|
||||||
|
attribute for functions was introduced. We don't want to use it
|
||||||
|
unconditionally (although this would be possible) since it
|
||||||
|
generates warnings. */
|
||||||
|
#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__)
|
||||||
|
# define __attribute_format_strfmon__(a,b) \
|
||||||
|
__attribute__ ((__format__ (__strfmon__, a, b)))
|
||||||
|
#else
|
||||||
|
# define __attribute_format_strfmon__(a,b) /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The nonnull function attribute marks pointer parameters that
|
||||||
|
must not be NULL. This has the name __nonnull in glibc,
|
||||||
|
and __attribute_nonnull__ in files shared with Gnulib to avoid
|
||||||
|
collision with a different __nonnull in DragonFlyBSD 5.9. */
|
||||||
|
#ifndef __attribute_nonnull__
|
||||||
|
# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__)
|
||||||
|
# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params))
|
||||||
|
# else
|
||||||
|
# define __attribute_nonnull__(params)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef __nonnull
|
||||||
|
# define __nonnull(params) __attribute_nonnull__ (params)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The returns_nonnull function attribute marks the return type of the function
|
||||||
|
as always being non-null. */
|
||||||
|
#ifndef __returns_nonnull
|
||||||
|
# if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__returns_nonnull__)
|
||||||
|
# define __returns_nonnull __attribute__ ((__returns_nonnull__))
|
||||||
|
# else
|
||||||
|
# define __returns_nonnull
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If fortification mode, we warn about unused results of certain
|
||||||
|
function calls which can lead to problems. */
|
||||||
|
#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__)
|
||||||
|
# define __attribute_warn_unused_result__ \
|
||||||
|
__attribute__ ((__warn_unused_result__))
|
||||||
|
# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0
|
||||||
|
# define __wur __attribute_warn_unused_result__
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define __attribute_warn_unused_result__ /* empty */
|
||||||
|
#endif
|
||||||
|
#ifndef __wur
|
||||||
|
# define __wur /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forces a function to be always inlined. */
|
||||||
|
#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__)
|
||||||
|
/* The Linux kernel defines __always_inline in stddef.h (283d7573), and
|
||||||
|
it conflicts with this definition. Therefore undefine it first to
|
||||||
|
allow either header to be included first. */
|
||||||
|
# undef __always_inline
|
||||||
|
# define __always_inline __inline __attribute__ ((__always_inline__))
|
||||||
|
#else
|
||||||
|
# undef __always_inline
|
||||||
|
# define __always_inline __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Associate error messages with the source location of the call site rather
|
||||||
|
than with the source location inside the function. */
|
||||||
|
#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__)
|
||||||
|
# define __attribute_artificial__ __attribute__ ((__artificial__))
|
||||||
|
#else
|
||||||
|
# define __attribute_artificial__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
|
||||||
|
inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__
|
||||||
|
or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions
|
||||||
|
older than 4.3 may define these macros and still not guarantee GNU inlining
|
||||||
|
semantics.
|
||||||
|
|
||||||
|
clang++ identifies itself as gcc-4.2, but has support for GNU inlining
|
||||||
|
semantics, that can be checked for by using the __GNUC_STDC_INLINE_ and
|
||||||
|
__GNUC_GNU_INLINE__ macro definitions. */
|
||||||
|
#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \
|
||||||
|
|| (defined __clang__ && (defined __GNUC_STDC_INLINE__ \
|
||||||
|
|| defined __GNUC_GNU_INLINE__)))
|
||||||
|
# if defined __GNUC_STDC_INLINE__ || defined __cplusplus
|
||||||
|
# define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
|
||||||
|
# define __extern_always_inline \
|
||||||
|
extern __always_inline __attribute__ ((__gnu_inline__))
|
||||||
|
# else
|
||||||
|
# define __extern_inline extern __inline
|
||||||
|
# define __extern_always_inline extern __always_inline
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __extern_always_inline
|
||||||
|
# define __fortify_function __extern_always_inline __attribute_artificial__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GCC 4.3 and above allow passing all anonymous arguments of an
|
||||||
|
__extern_always_inline function to some other vararg function. */
|
||||||
|
#if __GNUC_PREREQ (4,3)
|
||||||
|
# define __va_arg_pack() __builtin_va_arg_pack ()
|
||||||
|
# define __va_arg_pack_len() __builtin_va_arg_pack_len ()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* It is possible to compile containing GCC extensions even if GCC is
|
||||||
|
run in pedantic mode if the uses are carefully marked using the
|
||||||
|
`__extension__' keyword. But this is not generally available before
|
||||||
|
version 2.8. */
|
||||||
|
#if !(__GNUC_PREREQ (2,8) || defined __clang__)
|
||||||
|
# define __extension__ /* Ignore */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __restrict is known in EGCS 1.2 and above, and in clang.
|
||||||
|
It works also in C++ mode (outside of arrays), but only when spelled
|
||||||
|
as '__restrict', not 'restrict'. */
|
||||||
|
#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3)
|
||||||
|
# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
|
||||||
|
# define __restrict restrict
|
||||||
|
# else
|
||||||
|
# define __restrict /* Ignore */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is
|
||||||
|
array_name[restrict]
|
||||||
|
GCC 3.1 and clang support this.
|
||||||
|
This syntax is not usable in C++ mode. */
|
||||||
|
#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus
|
||||||
|
# define __restrict_arr __restrict
|
||||||
|
#else
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define __restrict_arr /* Not supported in old GCC. */
|
||||||
|
# else
|
||||||
|
# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
|
||||||
|
# define __restrict_arr restrict
|
||||||
|
# else
|
||||||
|
/* Some other non-C99 compiler. */
|
||||||
|
# define __restrict_arr /* Not supported. */
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect)
|
||||||
|
# define __glibc_unlikely(cond) __builtin_expect ((cond), 0)
|
||||||
|
# define __glibc_likely(cond) __builtin_expect ((cond), 1)
|
||||||
|
#else
|
||||||
|
# define __glibc_unlikely(cond) (cond)
|
||||||
|
# define __glibc_likely(cond) (cond)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (!defined _Noreturn \
|
||||||
|
&& (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
|
||||||
|
&& !(__GNUC_PREREQ (4,7) \
|
||||||
|
|| (3 < __clang_major__ + (5 <= __clang_minor__))))
|
||||||
|
# if __GNUC_PREREQ (2,8)
|
||||||
|
# define _Noreturn __attribute__ ((__noreturn__))
|
||||||
|
# else
|
||||||
|
# define _Noreturn
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ (8, 0)
|
||||||
|
/* Describes a char array whose address can safely be passed as the first
|
||||||
|
argument to strncpy and strncat, as the char array is not necessarily
|
||||||
|
a NUL-terminated string. */
|
||||||
|
# define __attribute_nonstring__ __attribute__ ((__nonstring__))
|
||||||
|
#else
|
||||||
|
# define __attribute_nonstring__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Undefine (also defined in libc-symbols.h). */
|
||||||
|
#undef __attribute_copy__
|
||||||
|
#if __GNUC_PREREQ (9, 0)
|
||||||
|
/* Copies attributes from the declaration or type referenced by
|
||||||
|
the argument. */
|
||||||
|
# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg)))
|
||||||
|
#else
|
||||||
|
# define __attribute_copy__(arg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (!defined _Static_assert && !defined __cplusplus \
|
||||||
|
&& (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
|
||||||
|
&& (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \
|
||||||
|
|| defined __STRICT_ANSI__))
|
||||||
|
# define _Static_assert(expr, diagnostic) \
|
||||||
|
extern int (*__Static_assert_function (void)) \
|
||||||
|
[!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Gnulib avoids including these, as they don't work on non-glibc or
|
||||||
|
older glibc platforms. */
|
||||||
|
#ifndef __GNULIB_CDEFS
|
||||||
|
# include <bits/wordsize.h>
|
||||||
|
# include <bits/long-double.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||||
|
# ifdef __REDIRECT
|
||||||
|
|
||||||
|
/* Alias name defined automatically. */
|
||||||
|
# define __LDBL_REDIR(name, proto) ... unused__ldbl_redir
|
||||||
|
# define __LDBL_REDIR_DECL(name) \
|
||||||
|
extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128"));
|
||||||
|
|
||||||
|
/* Alias name defined automatically, with leading underscores. */
|
||||||
|
# define __LDBL_REDIR2_DECL(name) \
|
||||||
|
extern __typeof (__##name) __##name \
|
||||||
|
__asm (__ASMNAME ("__" #name "ieee128"));
|
||||||
|
|
||||||
|
/* Alias name defined manually. */
|
||||||
|
# define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1
|
||||||
|
# define __LDBL_REDIR1_DECL(name, alias) \
|
||||||
|
extern __typeof (name) name __asm (__ASMNAME (#alias));
|
||||||
|
|
||||||
|
# define __LDBL_REDIR1_NTH(name, proto, alias) \
|
||||||
|
__REDIRECT_NTH (name, proto, alias)
|
||||||
|
# define __REDIRECT_NTH_LDBL(name, proto, alias) \
|
||||||
|
__LDBL_REDIR1_NTH (name, proto, __##alias##ieee128)
|
||||||
|
|
||||||
|
/* Unused. */
|
||||||
|
# define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl
|
||||||
|
# define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth
|
||||||
|
|
||||||
|
# else
|
||||||
|
_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform");
|
||||||
|
# endif
|
||||||
|
#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
|
||||||
|
# define __LDBL_COMPAT 1
|
||||||
|
# ifdef __REDIRECT
|
||||||
|
# define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias)
|
||||||
|
# define __LDBL_REDIR(name, proto) \
|
||||||
|
__LDBL_REDIR1 (name, proto, __nldbl_##name)
|
||||||
|
# define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias)
|
||||||
|
# define __LDBL_REDIR_NTH(name, proto) \
|
||||||
|
__LDBL_REDIR1_NTH (name, proto, __nldbl_##name)
|
||||||
|
# define __LDBL_REDIR2_DECL(name) \
|
||||||
|
extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name));
|
||||||
|
# define __LDBL_REDIR1_DECL(name, alias) \
|
||||||
|
extern __typeof (name) name __asm (__ASMNAME (#alias));
|
||||||
|
# define __LDBL_REDIR_DECL(name) \
|
||||||
|
extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name));
|
||||||
|
# define __REDIRECT_LDBL(name, proto, alias) \
|
||||||
|
__LDBL_REDIR1 (name, proto, __nldbl_##alias)
|
||||||
|
# define __REDIRECT_NTH_LDBL(name, proto, alias) \
|
||||||
|
__LDBL_REDIR1_NTH (name, proto, __nldbl_##alias)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \
|
||||||
|
|| !defined __REDIRECT
|
||||||
|
# define __LDBL_REDIR1(name, proto, alias) name proto
|
||||||
|
# define __LDBL_REDIR(name, proto) name proto
|
||||||
|
# define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW
|
||||||
|
# define __LDBL_REDIR_NTH(name, proto) name proto __THROW
|
||||||
|
# define __LDBL_REDIR2_DECL(name)
|
||||||
|
# define __LDBL_REDIR_DECL(name)
|
||||||
|
# ifdef __REDIRECT
|
||||||
|
# define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias)
|
||||||
|
# define __REDIRECT_NTH_LDBL(name, proto, alias) \
|
||||||
|
__REDIRECT_NTH (name, proto, alias)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __glibc_macro_warning (MESSAGE) issues warning MESSAGE. This is
|
||||||
|
intended for use in preprocessor macros.
|
||||||
|
|
||||||
|
Note: MESSAGE must be a _single_ string; concatenation of string
|
||||||
|
literals is not supported. */
|
||||||
|
#if __GNUC_PREREQ (4,8) || __glibc_clang_prereq (3,5)
|
||||||
|
# define __glibc_macro_warning1(message) _Pragma (#message)
|
||||||
|
# define __glibc_macro_warning(message) \
|
||||||
|
__glibc_macro_warning1 (GCC warning message)
|
||||||
|
#else
|
||||||
|
# define __glibc_macro_warning(msg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Generic selection (ISO C11) is a C-only feature, available in GCC
|
||||||
|
since version 4.9. Previous versions do not provide generic
|
||||||
|
selection, even though they might set __STDC_VERSION__ to 201112L,
|
||||||
|
when in -std=c11 mode. Thus, we must check for !defined __GNUC__
|
||||||
|
when testing __STDC_VERSION__ for generic selection support.
|
||||||
|
On the other hand, Clang also defines __GNUC__, so a clang-specific
|
||||||
|
check is required to enable the use of generic selection. */
|
||||||
|
#if !defined __cplusplus \
|
||||||
|
&& (__GNUC_PREREQ (4, 9) \
|
||||||
|
|| __glibc_has_extension (c_generic_selections) \
|
||||||
|
|| (!defined __GNUC__ && defined __STDC_VERSION__ \
|
||||||
|
&& __STDC_VERSION__ >= 201112L))
|
||||||
|
# define __HAVE_GENERIC_SELECTION 1
|
||||||
|
#else
|
||||||
|
# define __HAVE_GENERIC_SELECTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ (10, 0)
|
||||||
|
/* Designates a 1-based positional argument ref-index of pointer type
|
||||||
|
that can be used to access size-index elements of the pointed-to
|
||||||
|
array according to access mode, or at least one element when
|
||||||
|
size-index is not provided:
|
||||||
|
access (access-mode, <ref-index> [, <size-index>]) */
|
||||||
|
# define __attr_access(x) __attribute__ ((__access__ x))
|
||||||
|
/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may
|
||||||
|
use the access attribute to get object sizes from function definition
|
||||||
|
arguments, so we can't use them on functions we fortify. Drop the object
|
||||||
|
size hints for such functions. */
|
||||||
|
# if __USE_FORTIFY_LEVEL == 3
|
||||||
|
# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o)))
|
||||||
|
# else
|
||||||
|
# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s))
|
||||||
|
# endif
|
||||||
|
# if __GNUC_PREREQ (11, 0)
|
||||||
|
# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno)))
|
||||||
|
# else
|
||||||
|
# define __attr_access_none(argno)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define __fortified_attr_access(a, o, s)
|
||||||
|
# define __attr_access(x)
|
||||||
|
# define __attr_access_none(argno)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ (11, 0)
|
||||||
|
/* Designates dealloc as a function to call to deallocate objects
|
||||||
|
allocated by the declared function. */
|
||||||
|
# define __attr_dealloc(dealloc, argno) \
|
||||||
|
__attribute__ ((__malloc__ (dealloc, argno)))
|
||||||
|
# define __attr_dealloc_free __attr_dealloc (__builtin_free, 1)
|
||||||
|
#else
|
||||||
|
# define __attr_dealloc(dealloc, argno)
|
||||||
|
# define __attr_dealloc_free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Specify that a function such as setjmp or vfork may return
|
||||||
|
twice. */
|
||||||
|
#if __GNUC_PREREQ (4, 1)
|
||||||
|
# define __attribute_returns_twice__ __attribute__ ((__returns_twice__))
|
||||||
|
#else
|
||||||
|
# define __attribute_returns_twice__ /* Ignore. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* sys/cdefs.h */
|
||||||
264
lib/chdir-long.c
Normal file
264
lib/chdir-long.c
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/* provide a chdir function that tries not to fail due to ENAMETOOLONG
|
||||||
|
Copyright (C) 2004-2022 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 Jim Meyering */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "chdir-long.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "assure.h"
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
# error "compile this file only if your system defines PATH_MAX"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The results of openat() in this file are not leaked to any
|
||||||
|
single-threaded code that could use stdio.
|
||||||
|
FIXME - if the kernel ever adds support for multi-thread safety for
|
||||||
|
avoiding standard fds, then we should use openat_safer. */
|
||||||
|
|
||||||
|
struct cd_buf
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
cdb_init (struct cd_buf *cdb)
|
||||||
|
{
|
||||||
|
cdb->fd = AT_FDCWD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cdb_fchdir (struct cd_buf const *cdb)
|
||||||
|
{
|
||||||
|
return fchdir (cdb->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cdb_free (struct cd_buf const *cdb)
|
||||||
|
{
|
||||||
|
if (0 <= cdb->fd)
|
||||||
|
{
|
||||||
|
bool close_fail = close (cdb->fd);
|
||||||
|
assure (! close_fail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a file descriptor of an open directory (or AT_FDCWD), CDB->fd,
|
||||||
|
try to open the CDB->fd-relative directory, DIR. If the open succeeds,
|
||||||
|
update CDB->fd with the resulting descriptor, close the incoming file
|
||||||
|
descriptor, and return zero. Upon failure, return -1 and set errno. */
|
||||||
|
static int
|
||||||
|
cdb_advance_fd (struct cd_buf *cdb, char const *dir)
|
||||||
|
{
|
||||||
|
int new_fd = openat (cdb->fd, dir,
|
||||||
|
O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
|
||||||
|
if (new_fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cdb_free (cdb);
|
||||||
|
cdb->fd = new_fd;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a pointer to the first non-slash in S. */
|
||||||
|
static char * _GL_ATTRIBUTE_PURE
|
||||||
|
find_non_slash (char const *s)
|
||||||
|
{
|
||||||
|
size_t n_slash = strspn (s, "/");
|
||||||
|
return (char *) s + n_slash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a function much like chdir, but without the PATH_MAX limitation
|
||||||
|
on the length of the directory name. A significant difference is that
|
||||||
|
it must be able to modify (albeit only temporarily) the directory
|
||||||
|
name. It handles an arbitrarily long directory name by operating
|
||||||
|
on manageable portions of the name. On systems without the openat
|
||||||
|
syscall, this means changing the working directory to more and more
|
||||||
|
"distant" points along the long directory name and then restoring
|
||||||
|
the working directory. If any of those attempts to save or restore
|
||||||
|
the working directory fails, this function exits nonzero.
|
||||||
|
|
||||||
|
Note that this function may still fail with errno == ENAMETOOLONG, but
|
||||||
|
only if the specified directory name contains a component that is long
|
||||||
|
enough to provoke such a failure all by itself (e.g. if the component
|
||||||
|
has length PATH_MAX or greater on systems that define PATH_MAX). */
|
||||||
|
|
||||||
|
int
|
||||||
|
chdir_long (char *dir)
|
||||||
|
{
|
||||||
|
int e = chdir (dir);
|
||||||
|
if (e == 0 || errno != ENAMETOOLONG)
|
||||||
|
return e;
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t len = strlen (dir);
|
||||||
|
char *dir_end = dir + len;
|
||||||
|
struct cd_buf cdb;
|
||||||
|
size_t n_leading_slash;
|
||||||
|
|
||||||
|
cdb_init (&cdb);
|
||||||
|
|
||||||
|
/* If DIR is the empty string, then the chdir above
|
||||||
|
must have failed and set errno to ENOENT. */
|
||||||
|
assure (0 < len);
|
||||||
|
assure (PATH_MAX <= len);
|
||||||
|
|
||||||
|
/* Count leading slashes. */
|
||||||
|
n_leading_slash = strspn (dir, "/");
|
||||||
|
|
||||||
|
/* Handle any leading slashes as well as any name that matches
|
||||||
|
the regular expression, m!^//hostname[/]*! . Handling this
|
||||||
|
prefix separately usually results in a single additional
|
||||||
|
cdb_advance_fd call, but it's worthwhile, since it makes the
|
||||||
|
code in the following loop cleaner. */
|
||||||
|
if (n_leading_slash == 2)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
/* Find next slash.
|
||||||
|
We already know that dir[2] is neither a slash nor '\0'. */
|
||||||
|
char *slash = memchr (dir + 3, '/', dir_end - (dir + 3));
|
||||||
|
if (slash == NULL)
|
||||||
|
{
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*slash = '\0';
|
||||||
|
err = cdb_advance_fd (&cdb, dir);
|
||||||
|
*slash = '/';
|
||||||
|
if (err != 0)
|
||||||
|
goto Fail;
|
||||||
|
dir = find_non_slash (slash + 1);
|
||||||
|
}
|
||||||
|
else if (n_leading_slash)
|
||||||
|
{
|
||||||
|
if (cdb_advance_fd (&cdb, "/") != 0)
|
||||||
|
goto Fail;
|
||||||
|
dir += n_leading_slash;
|
||||||
|
}
|
||||||
|
|
||||||
|
assure (*dir != '/');
|
||||||
|
assure (dir <= dir_end);
|
||||||
|
|
||||||
|
while (PATH_MAX <= dir_end - dir)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
/* Find a slash that is PATH_MAX or fewer bytes away from dir.
|
||||||
|
I.e. see if there is a slash that will give us a name of
|
||||||
|
length PATH_MAX-1 or less. */
|
||||||
|
char *slash = memrchr (dir, '/', PATH_MAX);
|
||||||
|
if (slash == NULL)
|
||||||
|
{
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*slash = '\0';
|
||||||
|
assure (slash - dir < PATH_MAX);
|
||||||
|
err = cdb_advance_fd (&cdb, dir);
|
||||||
|
*slash = '/';
|
||||||
|
if (err != 0)
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
dir = find_non_slash (slash + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir < dir_end)
|
||||||
|
{
|
||||||
|
if (cdb_advance_fd (&cdb, dir) != 0)
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdb_fchdir (&cdb) != 0)
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
cdb_free (&cdb);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Fail:
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
cdb_free (&cdb);
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TEST_CHDIR
|
||||||
|
|
||||||
|
# include "closeout.h"
|
||||||
|
# include "error.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *line = NULL;
|
||||||
|
size_t n = 0;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
atexit (close_stdout);
|
||||||
|
|
||||||
|
len = getline (&line, &n, stdin);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
if (feof (stdin))
|
||||||
|
exit (0);
|
||||||
|
|
||||||
|
error (EXIT_FAILURE, saved_errno,
|
||||||
|
"reading standard input");
|
||||||
|
}
|
||||||
|
else if (len == 0)
|
||||||
|
exit (0);
|
||||||
|
|
||||||
|
if (line[len-1] == '\n')
|
||||||
|
line[len-1] = '\0';
|
||||||
|
|
||||||
|
if (chdir_long (line) != 0)
|
||||||
|
error (EXIT_FAILURE, errno,
|
||||||
|
"chdir_long failed: %s", line);
|
||||||
|
|
||||||
|
if (argc <= 1)
|
||||||
|
{
|
||||||
|
/* Using 'pwd' here makes sense only if it is a robust implementation,
|
||||||
|
like the one in coreutils after the 2004-04-19 changes. */
|
||||||
|
char const *cmd = "pwd";
|
||||||
|
execlp (cmd, (char *) NULL);
|
||||||
|
error (EXIT_FAILURE, errno, "%s", cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (stdin);
|
||||||
|
fclose (stderr);
|
||||||
|
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
compile-command: "gcc -DTEST_CHDIR=1 -g -O -W -Wall chdir-long.c libcoreutils.a"
|
||||||
|
End:
|
||||||
|
*/
|
||||||
30
lib/chdir-long.h
Normal file
30
lib/chdir-long.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* provide a chdir function that tries not to fail due to ENAMETOOLONG
|
||||||
|
Copyright (C) 2004-2005, 2009-2022 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 Jim Meyering. */
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "pathmax.h"
|
||||||
|
|
||||||
|
/* On systems without PATH_MAX, presume that chdir accepts
|
||||||
|
arbitrarily long directory names. */
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
# define chdir_long(Dir) chdir (Dir)
|
||||||
|
#else
|
||||||
|
int chdir_long (char *dir);
|
||||||
|
#endif
|
||||||
83
lib/cloexec.c
Normal file
83
lib/cloexec.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* cloexec.c - set or clear the close-on-exec descriptor flag
|
||||||
|
|
||||||
|
Copyright (C) 1991, 2004-2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
/* The code is taken from glibc/manual/llio.texi */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "cloexec.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
|
||||||
|
or clear the flag if VALUE is false.
|
||||||
|
Return 0 on success, or -1 on error with 'errno' set.
|
||||||
|
|
||||||
|
Note that on MingW, this function does NOT protect DESC from being
|
||||||
|
inherited into spawned children. Instead, either use dup_cloexec
|
||||||
|
followed by closing the original DESC, or use interfaces such as
|
||||||
|
open or pipe2 that accept flags like O_CLOEXEC to create DESC
|
||||||
|
non-inheritable in the first place. */
|
||||||
|
|
||||||
|
int
|
||||||
|
set_cloexec_flag (int desc, bool value)
|
||||||
|
{
|
||||||
|
#ifdef F_SETFD
|
||||||
|
|
||||||
|
int flags = fcntl (desc, F_GETFD, 0);
|
||||||
|
|
||||||
|
if (0 <= flags)
|
||||||
|
{
|
||||||
|
int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
|
||||||
|
|
||||||
|
if (flags == newflags
|
||||||
|
|| fcntl (desc, F_SETFD, newflags) != -1)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#else /* !F_SETFD */
|
||||||
|
|
||||||
|
/* Use dup2 to reject invalid file descriptors; the cloexec flag
|
||||||
|
will be unaffected. */
|
||||||
|
if (desc < 0)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (dup2 (desc, desc) < 0)
|
||||||
|
/* errno is EBADF here. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* There is nothing we can do on this kind of platform. Punt. */
|
||||||
|
return 0;
|
||||||
|
#endif /* !F_SETFD */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Duplicates a file handle FD, while marking the copy to be closed
|
||||||
|
prior to exec or spawn. Returns -1 and sets errno if FD could not
|
||||||
|
be duplicated. */
|
||||||
|
|
||||||
|
int
|
||||||
|
dup_cloexec (int fd)
|
||||||
|
{
|
||||||
|
return fcntl (fd, F_DUPFD_CLOEXEC, 0);
|
||||||
|
}
|
||||||
36
lib/cloexec.h
Normal file
36
lib/cloexec.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* cloexec.c - set or clear the close-on-exec descriptor flag
|
||||||
|
|
||||||
|
Copyright (C) 2004, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <stdbool.h>
|
||||||
|
|
||||||
|
/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
|
||||||
|
or clear the flag if VALUE is false.
|
||||||
|
Return 0 on success, or -1 on error with 'errno' set.
|
||||||
|
|
||||||
|
Note that on MingW, this function does NOT protect DESC from being
|
||||||
|
inherited into spawned children. Instead, either use dup_cloexec
|
||||||
|
followed by closing the original DESC, or use interfaces such as
|
||||||
|
open or pipe2 that accept flags like O_CLOEXEC to create DESC
|
||||||
|
non-inheritable in the first place. */
|
||||||
|
|
||||||
|
int set_cloexec_flag (int desc, bool value);
|
||||||
|
|
||||||
|
/* Duplicates a file handle FD, while marking the copy to be closed
|
||||||
|
prior to exec or spawn. Returns -1 and sets errno if FD could not
|
||||||
|
be duplicated. */
|
||||||
|
|
||||||
|
int dup_cloexec (int fd);
|
||||||
78
lib/close-stream.c
Normal file
78
lib/close-stream.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Close a stream, with nicer error checking than fclose's.
|
||||||
|
|
||||||
|
Copyright (C) 1998-2002, 2004, 2006-2022 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 <config.h>
|
||||||
|
|
||||||
|
#include "close-stream.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "fpending.h"
|
||||||
|
|
||||||
|
#if USE_UNLOCKED_IO
|
||||||
|
# include "unlocked-io.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Close STREAM. Return 0 if successful, EOF (setting errno)
|
||||||
|
otherwise. A failure might set errno to 0 if the error number
|
||||||
|
cannot be determined.
|
||||||
|
|
||||||
|
A failure with errno set to EPIPE may or may not indicate an error
|
||||||
|
situation worth signaling to the user. See the documentation of the
|
||||||
|
close_stdout_set_ignore_EPIPE function for details.
|
||||||
|
|
||||||
|
If a program writes *anything* to STREAM, that program should close
|
||||||
|
STREAM 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 STREAM. The last
|
||||||
|
printf can succeed in writing to the internal stream buffer, and yet
|
||||||
|
the fclose(STREAM) 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 STREAM -- just let the internal stream state record
|
||||||
|
the failure. That's what the ferror test is checking below. */
|
||||||
|
|
||||||
|
int
|
||||||
|
close_stream (FILE *stream)
|
||||||
|
{
|
||||||
|
const bool some_pending = (__fpending (stream) != 0);
|
||||||
|
const bool prev_fail = (ferror (stream) != 0);
|
||||||
|
const bool fclose_fail = (fclose (stream) != 0);
|
||||||
|
|
||||||
|
/* Return an error indication if there was a previous failure or if
|
||||||
|
fclose failed, with one exception: ignore an fclose failure if
|
||||||
|
there was no previous error, no data remains to be flushed, and
|
||||||
|
fclose failed with EBADF. That can happen when a program like cp
|
||||||
|
is invoked like this 'cp a b >&-' (i.e., with standard output
|
||||||
|
closed) and doesn't generate any output (hence no previous error
|
||||||
|
and nothing to be flushed). */
|
||||||
|
|
||||||
|
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
|
||||||
|
{
|
||||||
|
if (! fclose_fail)
|
||||||
|
errno = 0;
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
20
lib/close-stream.h
Normal file
20
lib/close-stream.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* Close a stream, with nicer error checking than fclose's.
|
||||||
|
|
||||||
|
Copyright (C) 2006-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file 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 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 <stdio.h>
|
||||||
|
|
||||||
|
int close_stream (FILE *stream);
|
||||||
75
lib/close.c
Normal file
75
lib/close.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* close replacement.
|
||||||
|
Copyright (C) 2008-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "fd-hook.h"
|
||||||
|
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
|
||||||
|
# include "msvc-inval.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef close
|
||||||
|
|
||||||
|
#if defined _WIN32 && !defined __CYGWIN__
|
||||||
|
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
|
||||||
|
static int
|
||||||
|
close_nothrow (int fd)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
TRY_MSVC_INVAL
|
||||||
|
{
|
||||||
|
result = _close (fd);
|
||||||
|
}
|
||||||
|
CATCH_MSVC_INVAL
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
errno = EBADF;
|
||||||
|
}
|
||||||
|
DONE_MSVC_INVAL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# define close_nothrow _close
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define close_nothrow close
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Override close() to call into other gnulib modules. */
|
||||||
|
|
||||||
|
int
|
||||||
|
rpl_close (int fd)
|
||||||
|
{
|
||||||
|
#if WINDOWS_SOCKETS
|
||||||
|
int retval = execute_all_close_hooks (close_nothrow, fd);
|
||||||
|
#else
|
||||||
|
int retval = close_nothrow (fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if REPLACE_FCHDIR
|
||||||
|
if (retval >= 0)
|
||||||
|
_gl_unregister_fd (fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
71
lib/closedir.c
Normal file
71
lib/closedir.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* Stop reading the entries of a directory.
|
||||||
|
Copyright (C) 2006-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#if REPLACE_FCHDIR
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_CLOSEDIR
|
||||||
|
|
||||||
|
/* Override closedir(), to keep track of the open file descriptors.
|
||||||
|
Needed because there is a function dirfd(). */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
# include "dirent-private.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
closedir (DIR *dirp)
|
||||||
|
{
|
||||||
|
# if REPLACE_FCHDIR || REPLACE_DIRFD
|
||||||
|
int fd = dirfd (dirp);
|
||||||
|
# endif
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
#if HAVE_CLOSEDIR
|
||||||
|
# undef closedir
|
||||||
|
|
||||||
|
retval = closedir (dirp);
|
||||||
|
|
||||||
|
# ifdef __KLIBC__
|
||||||
|
if (!retval)
|
||||||
|
_gl_unregister_dirp_fd (fd);
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (dirp->current != INVALID_HANDLE_VALUE)
|
||||||
|
FindClose (dirp->current);
|
||||||
|
free (dirp);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if REPLACE_FCHDIR
|
||||||
|
if (retval >= 0)
|
||||||
|
_gl_unregister_fd (fd);
|
||||||
|
#endif
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
136
lib/closeout.c
Normal file
136
lib/closeout.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/* Close standard output and standard error, exiting with a diagnostic on error.
|
||||||
|
|
||||||
|
Copyright (C) 1998-2002, 2004, 2006, 2008-2022 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 <config.h>
|
||||||
|
|
||||||
|
#include "closeout.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "gettext.h"
|
||||||
|
#define _(msgid) gettext (msgid)
|
||||||
|
|
||||||
|
#include "close-stream.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "exitfail.h"
|
||||||
|
#include "quotearg.h"
|
||||||
|
|
||||||
|
#ifndef __has_feature
|
||||||
|
# define __has_feature(a) false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
|
||||||
|
enum { SANITIZE_ADDRESS = true };
|
||||||
|
#else
|
||||||
|
enum { SANITIZE_ADDRESS = false };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char *file_name;
|
||||||
|
|
||||||
|
/* Set the file name to be reported in the event an error is detected
|
||||||
|
by close_stdout. */
|
||||||
|
void
|
||||||
|
close_stdout_set_file_name (const char *file)
|
||||||
|
{
|
||||||
|
file_name = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ignore_EPIPE /* = false */;
|
||||||
|
|
||||||
|
/* Specify the reaction to an EPIPE error during the closing of stdout:
|
||||||
|
- If ignore = true, it shall be ignored.
|
||||||
|
- If ignore = false, it shall evoke a diagnostic, along with a nonzero
|
||||||
|
exit status.
|
||||||
|
The default is ignore = false.
|
||||||
|
|
||||||
|
This setting matters only if the SIGPIPE signal is ignored (i.e. its
|
||||||
|
handler set to SIG_IGN) or blocked. Only particular programs need to
|
||||||
|
temporarily ignore SIGPIPE. If SIGPIPE is ignored or blocked because
|
||||||
|
it was ignored or blocked in the parent process when it created the
|
||||||
|
child process, it usually is a bug in the parent process: It is bad
|
||||||
|
practice to have SIGPIPE ignored or blocked while creating a child
|
||||||
|
process.
|
||||||
|
|
||||||
|
EPIPE occurs when writing to a pipe or socket that has no readers now,
|
||||||
|
when SIGPIPE is ignored or blocked.
|
||||||
|
|
||||||
|
The ignore = false setting is suitable for a scenario where it is normally
|
||||||
|
guaranteed that the pipe writer terminates before the pipe reader. In
|
||||||
|
this case, an EPIPE is an indication of a premature termination of the
|
||||||
|
pipe reader and should lead to a diagnostic and a nonzero exit status.
|
||||||
|
|
||||||
|
The ignore = true setting is suitable for a scenario where you don't know
|
||||||
|
ahead of time whether the pipe writer or the pipe reader will terminate
|
||||||
|
first. In this case, an EPIPE is an indication that the pipe writer can
|
||||||
|
stop doing useless write() calls; this is what close_stdout does anyway.
|
||||||
|
EPIPE is part of the normal pipe/socket shutdown protocol in this case,
|
||||||
|
and should not lead to a diagnostic message. */
|
||||||
|
|
||||||
|
void
|
||||||
|
close_stdout_set_ignore_EPIPE (bool ignore)
|
||||||
|
{
|
||||||
|
ignore_EPIPE = ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close standard output. On error, issue a diagnostic and _exit
|
||||||
|
with status 'exit_failure'.
|
||||||
|
|
||||||
|
Also close standard error. On error, _exit with status 'exit_failure'.
|
||||||
|
|
||||||
|
Since close_stdout is commonly registered via 'atexit', POSIX
|
||||||
|
and the C standard both say that it should not call 'exit',
|
||||||
|
because the behavior is undefined if 'exit' is called more than
|
||||||
|
once. So it calls '_exit' instead of 'exit'. If close_stdout
|
||||||
|
is registered via atexit before other functions are registered,
|
||||||
|
the other functions can act before this _exit is invoked.
|
||||||
|
|
||||||
|
Applications that use close_stdout should flush any streams
|
||||||
|
other than stdout and stderr before exiting, since the call to
|
||||||
|
_exit will bypass other buffer flushing. Applications should
|
||||||
|
be flushing and closing other streams anyway, to check for I/O
|
||||||
|
errors. Also, applications should not use tmpfile, since _exit
|
||||||
|
can bypass the removal of these files.
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
void
|
||||||
|
close_stdout (void)
|
||||||
|
{
|
||||||
|
if (close_stream (stdout) != 0
|
||||||
|
&& !(ignore_EPIPE && errno == EPIPE))
|
||||||
|
{
|
||||||
|
char const *write_error = _("write error");
|
||||||
|
if (file_name)
|
||||||
|
error (0, errno, "%s: %s", quotearg_colon (file_name),
|
||||||
|
write_error);
|
||||||
|
else
|
||||||
|
error (0, errno, "%s", write_error);
|
||||||
|
|
||||||
|
_exit (exit_failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close stderr only if not sanitizing, as sanitizers may report to
|
||||||
|
stderr after this function returns. */
|
||||||
|
if (!SANITIZE_ADDRESS && close_stream (stderr) != 0)
|
||||||
|
_exit (exit_failure);
|
||||||
|
}
|
||||||
36
lib/closeout.h
Normal file
36
lib/closeout.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* Close standard output and standard error.
|
||||||
|
|
||||||
|
Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2022 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 CLOSEOUT_H
|
||||||
|
# define CLOSEOUT_H 1
|
||||||
|
|
||||||
|
# include <stdbool.h>
|
||||||
|
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
# endif
|
||||||
|
|
||||||
|
void close_stdout_set_file_name (const char *file);
|
||||||
|
void close_stdout_set_ignore_EPIPE (bool ignore);
|
||||||
|
void close_stdout (void);
|
||||||
|
|
||||||
|
# ifdef __cplusplus
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
73
lib/concat-filename.c
Normal file
73
lib/concat-filename.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* Construct a full filename from a directory and a relative filename.
|
||||||
|
Copyright (C) 2001-2004, 2006-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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 <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
|
||||||
|
argument may not start with the directory separator (it is relative).
|
||||||
|
Return a freshly allocated filename. Return NULL and set errno
|
||||||
|
upon memory allocation failure. */
|
||||||
|
char *
|
||||||
|
concatenated_filename (const char *directory, const char *filename,
|
||||||
|
const char *suffix)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (strcmp (directory, ".") == 0)
|
||||||
|
{
|
||||||
|
/* No need to prepend the directory. */
|
||||||
|
result = (char *) malloc (strlen (filename)
|
||||||
|
+ (suffix != NULL ? strlen (suffix) : 0)
|
||||||
|
+ 1);
|
||||||
|
if (result == NULL)
|
||||||
|
return NULL; /* errno is set here */
|
||||||
|
p = result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t directory_len = strlen (directory);
|
||||||
|
int need_slash =
|
||||||
|
(directory_len > FILE_SYSTEM_PREFIX_LEN (directory)
|
||||||
|
&& !ISSLASH (directory[directory_len - 1]));
|
||||||
|
result = (char *) malloc (directory_len + need_slash
|
||||||
|
+ strlen (filename)
|
||||||
|
+ (suffix != NULL ? strlen (suffix) : 0)
|
||||||
|
+ 1);
|
||||||
|
if (result == NULL)
|
||||||
|
return NULL; /* errno is set here */
|
||||||
|
memcpy (result, directory, directory_len);
|
||||||
|
p = result + directory_len;
|
||||||
|
if (need_slash)
|
||||||
|
*p++ = '/';
|
||||||
|
}
|
||||||
|
p = stpcpy (p, filename);
|
||||||
|
if (suffix != NULL)
|
||||||
|
stpcpy (p, suffix);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
46
lib/concat-filename.h
Normal file
46
lib/concat-filename.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* Construct a full filename from a directory and a relative filename.
|
||||||
|
Copyright (C) 2001-2004, 2007-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
/* Concatenate a directory filename, a relative filename and an optional
|
||||||
|
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)
|
||||||
|
_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)
|
||||||
|
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
|
||||||
|
_GL_ATTRIBUTE_RETURNS_NONNULL;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _CONCAT_FILENAME_H */
|
||||||
61
lib/copy-acl.c
Normal file
61
lib/copy-acl.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* Copy access control list from one file to file. -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
Copyright (C) 2002-2003, 2005-2022 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, Andreas Grünbacher, and Bruno Haible. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "acl.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "quote.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "gettext.h"
|
||||||
|
#define _(msgid) gettext (msgid)
|
||||||
|
|
||||||
|
|
||||||
|
/* Copy access control lists from one file to another. If SOURCE_DESC is
|
||||||
|
a valid file descriptor, use file descriptor operations, else use
|
||||||
|
filename based operations on SRC_NAME. Likewise for DEST_DESC and
|
||||||
|
DST_NAME.
|
||||||
|
If access control lists are not available, fchmod the target file to
|
||||||
|
MODE. Also sets the non-permission bits of the destination file
|
||||||
|
(S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
|
||||||
|
Return 0 if successful, otherwise output a diagnostic and return a
|
||||||
|
negative error code. */
|
||||||
|
|
||||||
|
int
|
||||||
|
copy_acl (const char *src_name, int source_desc, const char *dst_name,
|
||||||
|
int dest_desc, mode_t mode)
|
||||||
|
{
|
||||||
|
int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode);
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case -2:
|
||||||
|
error (0, errno, "%s", quote (src_name));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
error (0, errno, _("preserving permissions for %s"), quote (dst_name));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user