Adding upstream version 9.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
4b8dc12adb
commit
c08a8f7410
3561 changed files with 1457043 additions and 0 deletions
44
.mailmap
Normal file
44
.mailmap
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Map git author names and email addresses to canonical/preferred form.
|
||||
<jim@meyering.net> <meyering@fb.com>
|
||||
<jim@meyering.net> <meyering@iou.iou>
|
||||
<jim@meyering.net> <meyering@redhat.com>
|
||||
<jim@meyering.net> <meyering@rho.meyering.net>
|
||||
<jim@meyering.net> <meyering@vm.meyering.net.localdomain>
|
||||
Paul Eggert <eggert@cs.ucla.edu> <eggert@penguin.cs.ucla.edu>
|
||||
Paul Eggert <eggert@cs.ucla.edu> <eggert@CS.UCLA.EDU>
|
||||
<eggert@cs.ucla.edu> <eggert@twinsun.com>
|
||||
|
||||
# Evan's two changes listed my email address.
|
||||
Evan Hunt <ethanol@armory.com> Evan Hunt <jim@meyering.net>
|
||||
|
||||
<P@draigBrady.com> <P@draigBrady.com (trivial change)>
|
||||
Pádraig Brady <P@draigBrady.com>
|
||||
<chen.guo.0625@gmail.com> <chenguo4@yahoo.com>
|
||||
<chen.guo.0625@gmail.com> <chenguo4@ucla.edu>
|
||||
<schwab@linux-m68k.org> <schwab@suse.de>
|
||||
<aurel32@debian.org> <aurelien@aurel32.net>
|
||||
<bob@proulx.com> <rwp@fc.hp.com>
|
||||
<bkorb@gnu.org> <bkorb@veritas.com>
|
||||
<bruno@clisp.org> <haible@clisp.cons.org>
|
||||
<eblake@redhat.com> <ebb9@byu.net>
|
||||
<jrv@debian.org> <jrvz@comcast.net>
|
||||
<dave.anglin@nrc.ca> <dave@hiauly1.hia.nrc.ca>
|
||||
<psfales@alcatel-lucent.com> <psfales@lucent.com>
|
||||
<karl@gnu.org> <karl@freefriends.org>
|
||||
<stephane.raimbault@gmail.com> <stephane.raimbault@makina-corpus.com>
|
||||
<jarkko.sakkinen@iki.fi> <jarkko.sakkinen@linux.intel.com>
|
||||
<tobias@stoeckmann.org> <tobias@bugol.de>
|
||||
<cjwatson@debian.org> <cjwatson@ubuntu.com>
|
||||
|
||||
# Prefer spelled-out middle name and its address.
|
||||
Arne Henrik Juul <arnej@imf.unit.no> Arne H. Juul <arnej@solan.unit.no>
|
||||
|
||||
# Had email as name.
|
||||
Dan Jacobson <jidanni@jidanni.org> jidanni@jidanni.org <jidanni@jidanni.org>
|
||||
|
||||
# Consolidate names of same email address.
|
||||
Jeff Liu <jeff.liu@oracle.com> jeff.liu <jeff.liu@oracle.com>
|
||||
Jeff Liu <jeff.liu@oracle.com> Jie Liu <jeff.liu@oracle.com>
|
||||
|
||||
# Convert to latin1 for a better 'THANKS' sort order.
|
||||
Aleksej Shilin <rootlexx@mail.ru> Алексей Шилин <rootlexx@mail.ru>
|
1
.prev-version
Normal file
1
.prev-version
Normal file
|
@ -0,0 +1 @@
|
|||
9.6
|
1
.tarball-version
Normal file
1
.tarball-version
Normal file
|
@ -0,0 +1 @@
|
|||
9.7
|
1
.version
Normal file
1
.version
Normal file
|
@ -0,0 +1 @@
|
|||
9.7
|
100
.vg-suppressions
Normal file
100
.vg-suppressions
Normal file
|
@ -0,0 +1,100 @@
|
|||
# Suppress valgrind diagnostics we don't care about.
|
||||
|
||||
# Copyright (C) 2003-2025 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/>.
|
||||
|
||||
{
|
||||
libc_dl_open
|
||||
Memcheck:Cond
|
||||
fun:_dl_relocate_object
|
||||
obj:/lib/libc-2.3.2.so
|
||||
fun:_dl_catch_error
|
||||
fun:_dl_open
|
||||
}
|
||||
|
||||
{
|
||||
libc_dl_catch_error__map_object
|
||||
Memcheck:Addr1
|
||||
obj:/lib/ld-2.3.2.so
|
||||
fun:_dl_map_object
|
||||
obj:/lib/libc-2.3.2.so
|
||||
fun:_dl_catch_error
|
||||
}
|
||||
{
|
||||
libc_dl_catch_error__map_versions
|
||||
Memcheck:Addr1
|
||||
obj:/lib/ld-2.3.2.so
|
||||
fun:_dl_check_map_versions
|
||||
obj:/lib/libc-2.3.2.so
|
||||
fun:_dl_catch_error
|
||||
}
|
||||
|
||||
{
|
||||
jm_libc_sigaction
|
||||
Memcheck:Param
|
||||
sigaction(act)
|
||||
fun:__libc_sigaction
|
||||
}
|
||||
|
||||
{
|
||||
libc_expand_dynamic_string_token
|
||||
Memcheck:Cond
|
||||
fun:strlen
|
||||
fun:expand_dynamic_string_token
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
}
|
||||
{
|
||||
libc__dl_new_object
|
||||
Memcheck:Cond
|
||||
fun:strlen
|
||||
fun:_dl_new_object
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
}
|
||||
{
|
||||
libc_fillin_rpath
|
||||
Memcheck:Cond
|
||||
fun:strlen
|
||||
fun:fillin_rpath
|
||||
}
|
||||
{
|
||||
libc-getpwuid-leak
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:nss_parse_service_list
|
||||
fun:__nss_database_lookup
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getpwuid_r@@GLIBC_2.2.5
|
||||
fun:getpwuid
|
||||
fun:getuser
|
||||
fun:format_user_width
|
||||
fun:gobble_file
|
||||
fun:main
|
||||
}
|
||||
{
|
||||
utimensat-NULL
|
||||
Memcheck:Param
|
||||
utimensat(filename)
|
||||
fun:futimens
|
||||
fun:gl_futimens
|
||||
fun:main
|
||||
}
|
115
AUTHORS
Normal file
115
AUTHORS
Normal file
|
@ -0,0 +1,115 @@
|
|||
Here are the names of the programs in this package,
|
||||
each followed by the name(s) of its author(s).
|
||||
|
||||
arch: David MacKenzie, Karel Zak
|
||||
b2sum: Pádraig Brady, Samuel Neves
|
||||
base32: Simon Josefsson
|
||||
base64: Simon Josefsson
|
||||
basename: David MacKenzie
|
||||
basenc: Simon Josefsson, Assaf Gordon
|
||||
cat: Torbjörn Granlund, Richard M. Stallman
|
||||
chcon: Russell Coker, Jim Meyering
|
||||
chgrp: David MacKenzie, Jim Meyering
|
||||
chmod: David MacKenzie, Jim Meyering
|
||||
chown: David MacKenzie, Jim Meyering
|
||||
chroot: Roland McGrath
|
||||
cksum: Pádraig Brady, Q. Frank Xia
|
||||
comm: Richard M. Stallman, David MacKenzie
|
||||
coreutils: Alex Deymo
|
||||
cp: Torbjörn Granlund, David MacKenzie, Jim Meyering
|
||||
csplit: Stuart Kemp, David MacKenzie
|
||||
cut: David M. Ihnat, David MacKenzie, Jim Meyering
|
||||
date: David MacKenzie
|
||||
dd: Paul Rubin, David MacKenzie, Stuart Kemp
|
||||
df: Torbjörn Granlund, David MacKenzie, Paul Eggert
|
||||
dir: Richard M. Stallman, David MacKenzie
|
||||
dircolors: H. Peter Anvin
|
||||
dirname: David MacKenzie, Jim Meyering
|
||||
du: Torbjörn Granlund, David MacKenzie, Paul Eggert, Jim Meyering
|
||||
echo: Brian Fox, Chet Ramey
|
||||
env: Richard Mlynarik, David MacKenzie, Assaf Gordon
|
||||
expand: David MacKenzie
|
||||
expr: Mike Parker, James Youngman, Paul Eggert
|
||||
factor: Paul Rubin, Torbjörn Granlund, Niels Möller
|
||||
false: Jim Meyering
|
||||
fmt: Ross Paterson
|
||||
fold: David MacKenzie
|
||||
ginstall: David MacKenzie
|
||||
groups: David MacKenzie, James Youngman
|
||||
head: David MacKenzie, Jim Meyering
|
||||
hostid: Jim Meyering
|
||||
hostname: Jim Meyering
|
||||
id: Arnold Robbins, David MacKenzie
|
||||
join: Mike Haertel
|
||||
kill: Paul Eggert
|
||||
link: Michael Stone
|
||||
ln: Mike Parker, David MacKenzie
|
||||
logname: FIXME: unknown
|
||||
ls: Richard M. Stallman, David MacKenzie
|
||||
md5sum: Ulrich Drepper, Scott Miller, David Madore
|
||||
mkdir: David MacKenzie
|
||||
mkfifo: David MacKenzie
|
||||
mknod: David MacKenzie
|
||||
mktemp: Jim Meyering, Eric Blake
|
||||
mv: Mike Parker, David MacKenzie, Jim Meyering
|
||||
nice: David MacKenzie
|
||||
nl: Scott Bartram, David MacKenzie
|
||||
nohup: Jim Meyering
|
||||
nproc: Giuseppe Scrivano
|
||||
numfmt: Assaf Gordon
|
||||
od: Jim Meyering
|
||||
paste: David M. Ihnat, David MacKenzie
|
||||
pathchk: Paul Eggert, David MacKenzie, Jim Meyering
|
||||
pinky: Joseph Arceneaux, David MacKenzie, Kaveh Ghazi
|
||||
pr: Pete TerMaat, Roland Huebner
|
||||
printenv: David MacKenzie, Richard Mlynarik
|
||||
printf: David MacKenzie
|
||||
ptx: François Pinard
|
||||
pwd: Jim Meyering
|
||||
readlink: Dmitry V. Levin
|
||||
realpath: Pádraig Brady
|
||||
rm: Paul Rubin, David MacKenzie, Richard M. Stallman, Jim Meyering
|
||||
rmdir: David MacKenzie
|
||||
runcon: Russell Coker
|
||||
seq: Ulrich Drepper
|
||||
sha1sum: Ulrich Drepper, Scott Miller, David Madore
|
||||
sha224sum: Ulrich Drepper, Scott Miller, David Madore
|
||||
sha256sum: Ulrich Drepper, Scott Miller, David Madore
|
||||
sha384sum: Ulrich Drepper, Scott Miller, David Madore
|
||||
sha512sum: Ulrich Drepper, Scott Miller, David Madore
|
||||
shred: Colin Plumb
|
||||
shuf: Paul Eggert
|
||||
sleep: Jim Meyering, Paul Eggert
|
||||
sort: Mike Haertel, Paul Eggert
|
||||
split: Torbjörn Granlund, Richard M. Stallman
|
||||
stat: Michael Meskes
|
||||
stdbuf: Pádraig Brady
|
||||
stty: David MacKenzie
|
||||
sum: Kayvan Aghaiepour, David MacKenzie
|
||||
sync: Jim Meyering, Giuseppe Scrivano
|
||||
tac: Jay Lepreau, David MacKenzie
|
||||
tail: Paul Rubin, David MacKenzie, Ian Lance Taylor, Jim Meyering
|
||||
tee: Mike Parker, Richard M. Stallman, David MacKenzie
|
||||
test: Kevin Braunsdorf, Matthew Bradburn
|
||||
timeout: Pádraig Brady
|
||||
touch: Paul Rubin, Arnold Robbins, Jim Kingdon, David MacKenzie, Randy Smith
|
||||
tr: Jim Meyering
|
||||
true: Jim Meyering
|
||||
truncate: Pádraig Brady
|
||||
tsort: Mark Kettenis
|
||||
tty: David MacKenzie
|
||||
uname: David MacKenzie
|
||||
unexpand: David MacKenzie
|
||||
uniq: Richard M. Stallman, David MacKenzie
|
||||
unlink: Michael Stone
|
||||
uptime: Joseph Arceneaux, David MacKenzie, Kaveh Ghazi
|
||||
users: Joseph Arceneaux, David MacKenzie
|
||||
vdir: Richard M. Stallman, David MacKenzie
|
||||
wc: Paul Rubin, David MacKenzie
|
||||
who: Joseph Arceneaux, David MacKenzie, Michael Stone
|
||||
whoami: Richard Mlynarik
|
||||
yes: David MacKenzie
|
||||
|
||||
;; Local Variables:
|
||||
;; coding: utf-8
|
||||
;; End:
|
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. <https://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 <https://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
|
||||
<https://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
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
130
GNUmakefile
Normal file
130
GNUmakefile
Normal file
|
@ -0,0 +1,130 @@
|
|||
# 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-2025 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 --sort=name
|
||||
|
||||
# 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.
|
||||
# This is not part of the essential workflow with .tarball-version. Rather,
|
||||
# it is meant to help the maintainer who has changed the current version
|
||||
# but not done a "make distclean".
|
||||
_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
|
||||
*************************
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
The following shell commands:
|
||||
|
||||
test -f configure || ./bootstrap
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
should configure, build, and install this package. The first line,
|
||||
which bootstraps, is intended for developers; when building from
|
||||
distribution tarballs it does nothing and can be skipped. A package
|
||||
might name the bootstrapping script differently; if the name is
|
||||
‘autogen.sh’, for example, the first line should say ‘./autogen.sh’
|
||||
instead of ‘./bootstrap’.
|
||||
|
||||
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 the GNU Coding Standards.
|
||||
|
||||
Many packages have scripts meant for developers instead of ordinary
|
||||
builders, as they may use developer tools that are less commonly
|
||||
installed, or they may access the network, which has privacy
|
||||
implications. These scripts attempt to bootstrap by building the
|
||||
‘configure’ script and related files, possibly using developer tools or
|
||||
the network. Because the output of bootstrapping is system-independent,
|
||||
it is normally run by a package developer so that its output can be put
|
||||
into the distribution tarball and ordinary builders and users need not
|
||||
bootstrap. Some packages have commands like ‘./autopull.sh’ and
|
||||
‘./autogen.sh’ that you can run instead of ‘./bootstrap’, for more
|
||||
fine-grained control over bootstrapping.
|
||||
|
||||
The ‘configure’ 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 script ‘config.status’ that you can
|
||||
run in the future to recreate the current configuration, and a file
|
||||
‘config.log’ containing output useful 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 ‘autoconf’ program generates ‘configure’ from the file
|
||||
‘configure.ac’. Normally you should edit ‘configure.ac’ instead of
|
||||
editing ‘configure’ directly.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. ‘cd’ to the directory containing the package’s source code.
|
||||
|
||||
2. If this is a developer checkout and file ‘configure’ does not yet
|
||||
exist, run the bootstrapping script (typically ‘./bootstrap’ or
|
||||
‘./autogen.sh’) to bootstrap and create the file. You may need
|
||||
special developer tools and network access to bootstrap, and the
|
||||
network access may have privacy implications.
|
||||
|
||||
3. Type ‘./configure’ to configure the package for your system. This
|
||||
might take a while. While running, ‘configure’ prints messages
|
||||
telling which features it is checking for.
|
||||
|
||||
4. Type ‘make’ to compile the package.
|
||||
|
||||
5. Optionally, type ‘make check’ to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
6. 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.
|
||||
|
||||
7. 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.
|
||||
|
||||
8. 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
|
||||
bootstrap again.
|
||||
|
||||
9. If the package follows the GNU Coding Standards, you can type ‘make
|
||||
uninstall’ to remove the installed files.
|
||||
|
||||
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=gcc CFLAGS=-g LIBS=-lposix
|
||||
|
||||
See “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 system 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
|
||||
system at a time in the source code directory. After you have installed
|
||||
the package for one system, use ‘make distclean’ before reconfiguring
|
||||
for another system.
|
||||
|
||||
Some platforms, notably macOS, support “fat” or “universal” binaries,
|
||||
where a single binary can execute on different architectures. On these
|
||||
platforms you can configure and compile just once, with options specific
|
||||
to that platform.
|
||||
|
||||
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’ and
|
||||
‘--disable-FEATURE’ options to ‘configure’, where FEATURE indicates an
|
||||
optional part of the package. They may also pay attention to
|
||||
‘--with-PACKAGE’ and ‘--without-PACKAGE’ options, where PACKAGE is
|
||||
something like ‘gnu-ld’. ‘./configure --help’ should mention the
|
||||
‘--enable-...’ and ‘--with-...’ options that the package recognizes.
|
||||
|
||||
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’.
|
||||
|
||||
Specifying a System Type
|
||||
========================
|
||||
|
||||
By default ‘configure’ builds for the current system. To create
|
||||
binaries that can run on a different system type, specify a
|
||||
‘--host=TYPE’ option along with compiler variables that specify how to
|
||||
generate object code for TYPE. For example, to create binaries intended
|
||||
to run on a 64-bit ARM processor:
|
||||
|
||||
./configure --host=aarch64-linux-gnu \
|
||||
CC=aarch64-linux-gnu-gcc \
|
||||
CXX=aarch64-linux-gnu-g++
|
||||
|
||||
If done on a machine that can execute these binaries (e.g., via
|
||||
‘qemu-aarch64’, ‘$QEMU_LD_PREFIX’, and Linux’s ‘binfmt_misc’
|
||||
capability), the build behaves like a native build. Otherwise it is a
|
||||
cross-build: ‘configure’ will make cross-compilation guesses instead of
|
||||
running test programs, and ‘make check’ will not work.
|
||||
|
||||
A system type can either be a short name like ‘mingw64’, or a
|
||||
canonical name like ‘x86_64-pc-linux-gnu’. Canonical names have the
|
||||
form CPU-COMPANY-SYSTEM where SYSTEM is either OS or KERNEL-OS. To
|
||||
canonicalize and validate a system type, you can run the command
|
||||
‘config.sub’, which is often squirreled away in a subdirectory like
|
||||
‘build-aux’. For example:
|
||||
|
||||
$ build-aux/config.sub arm64-linux
|
||||
aarch64-unknown-linux-gnu
|
||||
$ build-aux/config.sub riscv-lnx
|
||||
Invalid configuration 'riscv-lnx': OS 'lnx' not recognized
|
||||
|
||||
You can look at the ‘config.sub’ file to see which types are recognized.
|
||||
If the file is absent, this package does not need the system type.
|
||||
|
||||
If ‘configure’ fails with the diagnostic “cannot guess build type”.
|
||||
‘config.sub’ did not recognize your system’s type. In this case, first
|
||||
fetch the newest versions of these files from the GNU config package
|
||||
(https://savannah.gnu.org/projects/config). If that fixes things,
|
||||
please report it to the maintainers of the package containing
|
||||
‘configure’. Otherwise, you can try the configure option ‘--build=TYPE’
|
||||
where TYPE comes close to your system type; also, please report the
|
||||
problem to <config-patches@gnu.org>.
|
||||
|
||||
For more details about configuring system types, see the Autoconf
|
||||
documentation.
|
||||
|
||||
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’.
|
||||
|
||||
‘--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. See “Installation Names” for
|
||||
more details, including other options available for fine-tuning the
|
||||
installation locations.
|
||||
|
||||
‘--host=TYPE’
|
||||
Build binaries for system TYPE. See “Specifying a System Type”.
|
||||
|
||||
‘--enable-FEATURE’
|
||||
‘--disable-FEATURE’
|
||||
Enable or disable the optional FEATURE. See “Optional Features”.
|
||||
|
||||
‘--with-PACKAGE’
|
||||
‘--without-PACKAGE’
|
||||
Use or omit PACKAGE when building. See “Optional Features”.
|
||||
|
||||
‘--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).
|
||||
|
||||
‘--no-create’
|
||||
‘-n’
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
‘configure’ also recognizes several environment variables, and accepts
|
||||
some other, less widely useful, options. Run ‘configure --help’ for
|
||||
more details.
|
||||
|
||||
Copyright notice
|
||||
================
|
||||
|
||||
Copyright © 1994–1996, 1999–2002, 2004–2017, 2020–2024 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.
|
216
Makefile.am
Normal file
216
Makefile.am
Normal file
|
@ -0,0 +1,216 @@
|
|||
# Make coreutils. -*-Makefile-*-
|
||||
|
||||
# Copyright (C) 1990-2025 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/>.
|
||||
|
||||
ALL_RECURSIVE_TARGETS =
|
||||
|
||||
SUBDIRS = po . gnulib-tests
|
||||
|
||||
EXTRA_DIST = \
|
||||
.mailmap \
|
||||
.prev-version \
|
||||
.version \
|
||||
.vg-suppressions \
|
||||
README-install \
|
||||
THANKS.in \
|
||||
THANKS-to-translators \
|
||||
THANKStt.in \
|
||||
bootstrap \
|
||||
bootstrap.conf \
|
||||
build-aux/gen-lists-of-programs.sh \
|
||||
build-aux/gen-single-binary.sh \
|
||||
cfg.mk \
|
||||
dist-check.mk \
|
||||
maint.mk \
|
||||
tests/GNUmakefile \
|
||||
thanks-gen
|
||||
|
||||
gen_progs_lists = $(top_srcdir)/build-aux/gen-lists-of-programs.sh
|
||||
gen_single_binary = $(top_srcdir)/build-aux/gen-single-binary.sh
|
||||
|
||||
# Keep these in sync with bootstrap.conf:bootstrap_post_import_hook().
|
||||
# Use '$(top_srcdir)/m4' and '$(srcdir)/src' for the benefit of non-GNU
|
||||
# makes: it is with those directories that 'cu-progs.m4' and 'cu-progs.mk'
|
||||
# appear in our dependencies.
|
||||
$(top_srcdir)/m4/cu-progs.m4: $(gen_progs_lists)
|
||||
$(AM_V_GEN)rm -f $@ $@-t \
|
||||
&& $(SHELL) $(gen_progs_lists) --autoconf >$@-t \
|
||||
&& chmod a-w $@-t && mv -f $@-t $@
|
||||
$(srcdir)/src/cu-progs.mk: $(gen_progs_lists)
|
||||
$(AM_V_GEN)rm -f $@ $@-t \
|
||||
&& $(SHELL) $(gen_progs_lists) --automake >$@-t \
|
||||
&& chmod a-w $@-t && mv -f $@-t $@
|
||||
$(srcdir)/src/single-binary.mk: $(gen_single_binary) $(srcdir)/src/local.mk
|
||||
$(AM_V_GEN)rm -f $@ $@-t \
|
||||
&& $(SHELL) $(gen_single_binary) $(srcdir)/src/local.mk >$@-t \
|
||||
&& chmod a-w $@-t && mv -f $@-t $@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
# Shortcut targets to make it easier to run (very) expensive tests.
|
||||
check-expensive:
|
||||
$(MAKE) check RUN_EXPENSIVE_TESTS=yes
|
||||
check-very-expensive:
|
||||
$(MAKE) check-expensive RUN_VERY_EXPENSIVE_TESTS=yes
|
||||
|
||||
# Just prior to distribution, ...
|
||||
# transform the automake-generated rule that runs 'rm -f rm'.
|
||||
# On some systems, that command would fail with a diagnostic like
|
||||
# "rm: cannot unlink 'rm': Text file busy" when '.' appears so early
|
||||
# in the shell's search path that running 'rm' would run the 'rm'
|
||||
# executable in the current directory.
|
||||
# Similarly, adjust the clean-binPROGRAMS rule.
|
||||
rm_subst = \
|
||||
s!(rm -f (rm\b|\$$\(bin_PROGRAMS\)$$))!$$1 > /dev/null 2>&1 || /bin/$$1!
|
||||
|
||||
BUILT_SOURCES = .version
|
||||
.version:
|
||||
$(AM_V_GEN)echo $(VERSION) > $@-t && mv $@-t $@
|
||||
|
||||
# Have no read-only files in the tarball to allow easy removal.
|
||||
# Have .tarball-version based versions only in tarball builds.
|
||||
# The perl substitution is to change some key uses of "rm" to "/bin/rm".
|
||||
# See the rm_subst comment for details.
|
||||
# The touch avoids a subtle, spurious "make distcheck" failure.
|
||||
dist-hook: gen-ChangeLog
|
||||
$(AM_V_GEN)chmod -R +rw $(distdir)
|
||||
$(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
|
||||
$(AM_V_at)perl -pi -e '$(rm_subst)' $(distdir)/Makefile.in
|
||||
$(AM_V_at)touch $(distdir)/doc/constants.texi \
|
||||
$(distdir)/doc/coreutils.info
|
||||
|
||||
gen_start_ver = 8.31
|
||||
.PHONY: gen-ChangeLog
|
||||
gen-ChangeLog:
|
||||
$(AM_V_GEN)if test -d .git; then \
|
||||
log_fix="$(srcdir)/build-aux/git-log-fix"; \
|
||||
test -e "$$log_fix" \
|
||||
&& amend_git_log="--amend=$$log_fix" \
|
||||
|| amend_git_log=; \
|
||||
$(top_srcdir)/build-aux/gitlog-to-changelog $$amend_git_log \
|
||||
-- v$(gen_start_ver)~.. > $(distdir)/cl-t && \
|
||||
{ printf '\n\nSee the source repo for older entries\n' \
|
||||
>> $(distdir)/cl-t && \
|
||||
rm -f $(distdir)/ChangeLog && \
|
||||
mv $(distdir)/cl-t $(distdir)/ChangeLog; } \
|
||||
fi
|
||||
|
||||
ALL_RECURSIVE_TARGETS += distcheck-hook
|
||||
distcheck-hook: check-ls-dircolors
|
||||
$(MAKE) my-distcheck
|
||||
$(MAKE) taint-distcheck
|
||||
|
||||
DISTCLEANFILES = VERSION
|
||||
MAINTAINERCLEANFILES = THANKS-to-translators
|
||||
THANKS-to-translators: po/LINGUAS THANKStt.in
|
||||
$(AM_V_GEN)( \
|
||||
cat $(srcdir)/THANKStt.in; \
|
||||
for lang in `cat $(srcdir)/po/LINGUAS`; do \
|
||||
echo https://translationproject.org/team/$$lang.html; \
|
||||
done; \
|
||||
) > $@-tmp && mv $@-tmp $@
|
||||
|
||||
# Ensure that the sets of two-letter codes in ls.c and dircolors.c
|
||||
# remain in sync.
|
||||
.PHONY: check-ls-dircolors
|
||||
check-ls-dircolors:
|
||||
$(AM_V_GEN)dc=$$(sed -n '/static.*ls_codes\[/,/};'/p \
|
||||
$(srcdir)/src/dircolors.c \
|
||||
|sed -n '/^ *"/p'|tr , '\n'|sed 's/^ *//' \
|
||||
|sed -n 's/^"\(..\)"/\1/p'|sort -u); \
|
||||
ls=$$(sed -n '/static.*indicator_name\[/,/};'/\p \
|
||||
$(srcdir)/src/ls.c \
|
||||
|sed -n '/^ *{/ { s/{.\([a-z]\).,.\([a-z]\).}/"\1\2"/g; p; }' \
|
||||
|tr , '\n'|sed 's/^ *//' \
|
||||
|sed -n 's/^"\(..\)"/\1/p'|sort -u); \
|
||||
test "$$dc" = "$$ls"
|
||||
|
||||
# Sort in traditional ASCII order, regardless of the current locale;
|
||||
# otherwise we may get into trouble with distinct strings that the
|
||||
# current locale considers to be equal.
|
||||
ASSORT = LC_ALL=C sort
|
||||
|
||||
# Extract all lines up to the first one starting with "##".
|
||||
prologue = perl -ne '/^\#\#/ and exit; print' $(srcdir)/THANKS.in
|
||||
|
||||
# FIXME: avoid dependency to build our own 'sort' for 'make dist' ...
|
||||
# when common platforms have a functional case-folding implementation:
|
||||
# $ test 'abácad' = "$(printf '%s\n' 'ab' 'ác' 'ad' \
|
||||
# | LC_ALL=en_US.UTF-8 sort -f \
|
||||
# | tr -d '\n')" && echo GOOD || echo BAD
|
||||
# Note we don't enable case folding (-f) in the sort below, due to bugs
|
||||
# in the I18N patch used in many distros (as of 2015). Also using our
|
||||
# own src/sort here would induce awkward dependencies for `make dist`.
|
||||
THANKS: THANKS.in Makefile.am .mailmap thanks-gen .version
|
||||
$(AM_V_GEN)rm -f $@-t $@; \
|
||||
{ \
|
||||
$(prologue); echo; \
|
||||
{ perl -ne '/^$$/.../^$$/ and !/^$$/ and s/ +/\0/ and print' \
|
||||
$(srcdir)/THANKS.in; \
|
||||
git log --pretty=format:'%aN%x00%aE' \
|
||||
| $(ASSORT) -u; \
|
||||
} | $(srcdir)/thanks-gen \
|
||||
| LC_ALL=en_US.UTF-8 sort -k1,1; \
|
||||
echo; \
|
||||
printf ';; %s\n' 'Local Variables:' 'coding: utf-8' End:; \
|
||||
} > $@-t && chmod a-w $@-t && mv $@-t $@
|
||||
|
||||
# Some of our git hook scripts are supposed to be identical to git's samples.
|
||||
# See if they are still in sync.
|
||||
.PHONY: check-git-hook-script-sync
|
||||
check-git-hook-script-sync:
|
||||
@fail=0; \
|
||||
t=$$(mktemp -d) \
|
||||
&& cd $$t && git init -q && cd .git/hooks \
|
||||
&& for i in pre-commit pre-applypatch applypatch-msg; do \
|
||||
diff $(abs_top_srcdir)/scripts/git-hooks/$$i $$i.sample \
|
||||
|| fail=1; \
|
||||
done; \
|
||||
rm -rf $$t; \
|
||||
test $$fail = 0
|
||||
|
||||
# If we are building a single-binary, create symlinks or shebangs for
|
||||
# the selected tools when installing.
|
||||
install-exec-hook:
|
||||
$(AM_V_at)ctrans=$$(printf coreutils | sed -e "$(transform)"); \
|
||||
for p in x $(single_binary_progs); do \
|
||||
test $$p = x && continue; \
|
||||
ptrans=$$(printf '%s' "$$p" | sed -e "$(transform)"); \
|
||||
rm -f $(DESTDIR)$(bindir)/$$ptrans$(EXEEXT) || exit $$?; \
|
||||
if test "x$(single_binary_install_type)" = xshebangs; then \
|
||||
printf '#!%s --coreutils-prog-shebang=%s\n' \
|
||||
$(bindir)/$$ctrans$(EXEEXT) $$p \
|
||||
>$(DESTDIR)$(bindir)/$$ptrans$(EXEEXT) || exit $$?; \
|
||||
chmod a+x,a-w $(DESTDIR)$(bindir)/$$ptrans$(EXEEXT) || exit $$?;\
|
||||
else \
|
||||
$(LN_S) -s $$ctrans$(EXEEXT) \
|
||||
$(DESTDIR)$(bindir)/$$ptrans$(EXEEXT) || exit $$?; \
|
||||
fi \
|
||||
done
|
||||
|
||||
noinst_LIBRARIES =
|
||||
MOSTLYCLEANFILES =
|
||||
CLEANFILES =
|
||||
MOSTLYCLEANDIRS =
|
||||
|
||||
AM_CPPFLAGS = -Ilib -I$(top_srcdir)/lib -Isrc -I$(top_srcdir)/src
|
||||
|
||||
include $(top_srcdir)/gl/local.mk
|
||||
include $(top_srcdir)/lib/local.mk
|
||||
include $(top_srcdir)/src/local.mk
|
||||
include $(top_srcdir)/doc/local.mk
|
||||
include $(top_srcdir)/man/local.mk
|
||||
include $(top_srcdir)/tests/local.mk
|
28920
Makefile.in
Normal file
28920
Makefile.in
Normal file
File diff suppressed because it is too large
Load diff
141
README
Normal file
141
README
Normal file
|
@ -0,0 +1,141 @@
|
|||
These are the GNU core utilities. This package is the union of
|
||||
the GNU fileutils, sh-utils, and textutils packages.
|
||||
|
||||
Most of these programs have significant advantages over their Unix
|
||||
counterparts, such as greater speed, additional options, and fewer
|
||||
arbitrary limits.
|
||||
|
||||
The programs that can be built with this package are:
|
||||
|
||||
[ arch b2sum base32 base64 basename basenc cat chcon chgrp chmod chown
|
||||
chroot cksum comm coreutils cp csplit cut date dd df dir dircolors dirname
|
||||
du echo env expand expr factor false fmt fold groups head hostid hostname
|
||||
id install join kill link ln logname ls md5sum mkdir mkfifo mknod mktemp
|
||||
mv nice nl nohup nproc numfmt od paste pathchk pinky pr printenv printf ptx
|
||||
pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum
|
||||
sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty sum sync
|
||||
tac tail tee test timeout touch tr true truncate tsort tty uname unexpand
|
||||
uniq unlink uptime users vdir wc who whoami yes
|
||||
|
||||
See the file NEWS for a list of major changes in the current release.
|
||||
|
||||
If you obtained this file as part of a "git clone", then see the
|
||||
README-hacking file. If this file came to you as part of a tar archive,
|
||||
then see the file INSTALL for general compilation and installation
|
||||
instructions, or README-install for system and coreutils specific instructions.
|
||||
|
||||
Like the rest of the GNU system, these programs mostly conform to
|
||||
POSIX, with BSD and other extensions. For closer conformance, or
|
||||
conformance to a particular POSIX version, set the POSIXLY_CORRECT
|
||||
and the _POSIX2_VERSION environment variables, as described in
|
||||
the documentation under "Standards conformance".
|
||||
|
||||
The ls, dir, and vdir commands are all separate executables instead of
|
||||
one program that checks argv[0] because people often rename these
|
||||
programs to things like gls, gnuls, l, etc. Renaming a program
|
||||
file shouldn't affect how it operates, so that people can get the
|
||||
behavior they want with whatever name they want.
|
||||
|
||||
Special thanks to Paul Eggert, Brian Matthews, Bruce Evans, Karl Berry,
|
||||
Kaveh Ghazi, and François Pinard for help with debugging and porting
|
||||
these programs. Many thanks to all of the people who have taken the
|
||||
time to submit problem reports and fixes. All contributed changes are
|
||||
attributed in the commit logs.
|
||||
|
||||
And thanks to the following people who have provided accounts for
|
||||
portability testing on many different types of systems: Bob Proulx,
|
||||
Christian Robert, François Pinard, Greg McGary, Harlan Stenn,
|
||||
Joel N. Weber, Mark D. Roth, Matt Schalit, Nelson H. F. Beebe,
|
||||
Réjean Payette, Sam Tardieu.
|
||||
|
||||
Thanks to Michael Stone for inflicting test releases of this package
|
||||
on Debian's unstable distribution, and to all the kind folks who used
|
||||
that distribution and found and reported bugs.
|
||||
|
||||
Note that each man page is now automatically generated from a template
|
||||
and from the corresponding --help usage message. Patches to the template
|
||||
files (man/*.x) are welcome. However, the authoritative documentation
|
||||
is in texinfo form in the doc directory.
|
||||
|
||||
|
||||
***************
|
||||
Feature requests:
|
||||
---------------
|
||||
|
||||
If you would like to add a new feature, please try to get some sort of
|
||||
consensus that it is a worthwhile change. One way to do that is to send
|
||||
mail to coreutils@gnu.org including as much description and justification
|
||||
as you can. Based on the feedback that generates, you may be able to
|
||||
convince us that it's worth adding. Please also consult the list of
|
||||
previously discussed but ultimately rejected feature requests at:
|
||||
https://www.gnu.org/software/coreutils/rejected_requests.html
|
||||
|
||||
|
||||
***************
|
||||
Reporting bugs:
|
||||
---------------
|
||||
|
||||
Send bug reports, questions, comments, etc. to bug-coreutils@gnu.org.
|
||||
To suggest a patch, see the files README-hacking and HACKING for tips.
|
||||
|
||||
All of these programs except 'test' recognize the '--version' option.
|
||||
When reporting bugs, please include in the subject line both the package
|
||||
name/version and the name of the program for which you found a problem.
|
||||
|
||||
If you have a problem with 'sort', try running 'sort --debug', as it
|
||||
can often help find and fix problems without having to wait for an
|
||||
answer to a bug report. If the debug output does not suffice to fix
|
||||
the problem on your own, please compress and attach it to the rest of
|
||||
your bug report.
|
||||
|
||||
IMPORTANT: if you take the time to report a test failure,
|
||||
please be sure to include the output of running 'make check'
|
||||
in verbose mode for each failing test. For example,
|
||||
if the test that fails is tests/df/df-P.sh, then you would
|
||||
run this command:
|
||||
|
||||
make check TESTS=tests/df/df-P.sh VERBOSE=yes SUBDIRS=. >> log 2>&1
|
||||
|
||||
For some tests, particularly perl tests, you can get even more detail by adding
|
||||
DEBUG=yes. Then include the contents of the file 'log' in your bug report.
|
||||
|
||||
|
||||
***************************************
|
||||
|
||||
There are many tests, but nowhere near as many as we need.
|
||||
Additions and corrections are very welcome.
|
||||
|
||||
If you see a problem that you've already reported, feel free to re-report
|
||||
it -- it won't bother us to get a reminder. Besides, the more messages we
|
||||
get regarding a particular problem the sooner it'll be fixed -- usually.
|
||||
If you sent a complete patch and, after a couple weeks you haven't
|
||||
received any acknowledgement, please ping us. A complete patch includes
|
||||
a well-written ChangeLog entry, unified (diff -u format) diffs relative
|
||||
to the most recent test release (or, better, relative to the latest
|
||||
sources in the public repository), an explanation for why the patch is
|
||||
necessary or useful, and if at all possible, enough information to
|
||||
reproduce whatever problem prompted it. Plus, you'll earn lots of
|
||||
karma if you include a test case to exercise any bug(s) you fix.
|
||||
Here are instructions for checking out the latest development sources:
|
||||
|
||||
https://savannah.gnu.org/git/?group=coreutils
|
||||
|
||||
For general documentation on the coding and usage standards
|
||||
this distribution follows, see the GNU Coding Standards at:
|
||||
https://www.gnu.org/prep/standards/
|
||||
|
||||
For any copyright year range specified as YYYY-ZZZZ in this package
|
||||
note that the range specifies every single year in that closed interval.
|
||||
|
||||
Please see the file COPYING for copying conditions.
|
||||
|
||||
========================================================================
|
||||
|
||||
Copyright (C) 1998-2025 Free Software Foundation, Inc.
|
||||
|
||||
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, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the "GNU Free
|
||||
Documentation License" file as part of this distribution.
|
111
README-install
Normal file
111
README-install
Normal file
|
@ -0,0 +1,111 @@
|
|||
Please see the file INSTALL for generic build and installation instructions.
|
||||
This file details coreutils and system specific build instructions.
|
||||
|
||||
|
||||
*********************
|
||||
Pre-C99 build failure
|
||||
---------------------
|
||||
|
||||
In 2009 we added this requirement:
|
||||
To build the coreutils from source, you must have a C99-conforming
|
||||
compiler, due to the use of declarations after non-declaration statements
|
||||
in several files in src/. There is code in configure to find and, if
|
||||
possible, enable an appropriate compiler. However, if configure doesn't
|
||||
find a C99 compiler, it continues nonetheless, and your build will fail.
|
||||
There used to be a "c99-to-c89.diff" patch you could apply to convert
|
||||
to code that even an old pre-c99 compiler can handle, but it was too
|
||||
tedious to maintain, so has been removed.
|
||||
|
||||
|
||||
***********************
|
||||
HPUX 11.x build failure
|
||||
-----------------------
|
||||
|
||||
A known problem exists when compiling on HPUX on both hppa and ia64
|
||||
in 64-bit mode (i.e., +DD64) on HP-UX 11.0, 11.11, and 11.23. This
|
||||
is not due to a bug in the package but instead due to a bug in the
|
||||
system header file which breaks things in 64-bit mode. The default
|
||||
compilation mode is 32-bit and the software compiles fine using the
|
||||
default mode. To build this software in 64-bit mode you will need
|
||||
to fix the system /usr/include/inttypes.h header file. After
|
||||
correcting that file the software also compiles fine in 64-bit mode.
|
||||
Here is one possible patch to correct the problem:
|
||||
|
||||
--- /usr/include/inttypes.h.orig Thu May 30 01:00:00 1996
|
||||
+++ /usr/include/inttypes.h Sun Mar 23 00:20:36 2003
|
||||
@@ -489 +489 @@
|
||||
-#ifndef __STDC_32_MODE__
|
||||
+#ifndef __LP64__
|
||||
|
||||
|
||||
************************
|
||||
OSF/1 4.0d and AIX build failures
|
||||
------------------------
|
||||
|
||||
If you use /usr/bin/make on these systems, the build will fail due
|
||||
to the presence of the "[" target. OSF/1 make(1) appears to
|
||||
treat "[" as some syntax relating to locks, while AIX make(1)
|
||||
appears to skip the "[" target. To work around these issues
|
||||
the best solution is to use GNU make. Otherwise, simply remove
|
||||
all mention of "[$(EXEEXT)" from src/Makefile.
|
||||
|
||||
|
||||
************************
|
||||
32 bit time_t build failures
|
||||
------------------------
|
||||
|
||||
Although 32-bit builds fail if that forces time_t to be 32 bits, this
|
||||
can be fixed by using 64-bit builds. For example, on AIX where GCC
|
||||
defaults to 32 bits, one can use "./configure CC='gcc -maix64' AR='ar
|
||||
-X64'"; similarly, on Solaris one can configure with CC='gcc -m64'.
|
||||
If all else fails one can configure with --disable-year2038;
|
||||
however, this will mishandle timestamps after 2038, and please file
|
||||
bug reports for any such situations.
|
||||
|
||||
|
||||
*************************************************
|
||||
"make check" failure on IRIX 6.5 and Solaris <= 9
|
||||
-------------------------------------------------
|
||||
|
||||
Using the vendor make program to run "make check" fails on these two systems.
|
||||
If you want to run all of the tests there, use GNU make.
|
||||
|
||||
|
||||
|
||||
**********************
|
||||
Running tests as root:
|
||||
----------------------
|
||||
|
||||
If you run the tests as root, note that a few of them create files
|
||||
and/or run programs as a non-root user, 'nobody' by default.
|
||||
If you want to use some other non-root username, specify it via
|
||||
the NON_ROOT_USERNAME environment variable. Depending on the
|
||||
permissions with which the working directories have been created,
|
||||
using 'nobody' may fail, because that user won't have the required
|
||||
read and write access to the build and test directories.
|
||||
I find that it is best to unpack and build as a non-privileged
|
||||
user, and then to run the following command as that user in order
|
||||
to run the privilege-requiring tests:
|
||||
|
||||
sudo env PATH="$PATH" NON_ROOT_USERNAME=$USER make -k check-root
|
||||
|
||||
If you can run the tests as root, please do so and report any
|
||||
problems. We get much less test coverage in that mode, and it's
|
||||
arguably more important that these tools work well when run by
|
||||
root than when run by less privileged users.
|
||||
|
||||
|
||||
|
||||
**********************
|
||||
autotools considerations:
|
||||
----------------------
|
||||
|
||||
WARNING: Now that we use the ./bootstrap script, you should not run
|
||||
autoreconf manually. Doing that will overwrite essential source files
|
||||
with older versions, which may make the package unbuildable or introduce
|
||||
subtle bugs.
|
||||
|
||||
WARNING: If you modify files like configure.in, m4/*.m4, aclocal.m4,
|
||||
or any Makefile.am, then don't be surprised if what gets regenerated no
|
||||
longer works. To make things work, you'll have to be using appropriate
|
||||
versions of the tools listed in bootstrap.conf's buildreq string.
|
961
THANKS
Normal file
961
THANKS
Normal file
|
@ -0,0 +1,961 @@
|
|||
These people have contributed to the GNU coreutils (formerly, the fileutils,
|
||||
textutils, and/or sh-utils packages). Some have reported problems, others
|
||||
have contributed improvements to the documentation, actual code, and even
|
||||
complete programs. Those contributions are described in the version control
|
||||
logs and ChangeLog files. If your name has been left out, if you'd rather
|
||||
not be listed, or if you'd prefer a different address be used, please send a
|
||||
note to the GNU coreutils mailing list <coreutils@gnu.org>.
|
||||
|
||||
??? kytek@cybercomm.net
|
||||
A Costa agcosta@gis.net
|
||||
Aaron Burgemeister dajoker@gmail.com
|
||||
Aaron Davies aaron.davies@gmail.com
|
||||
Aaron Hawley ashawley@uvm.edu
|
||||
Achilles Gaikwad agaikwad@redhat.com
|
||||
Achim Blumensath blume@corona.oche.de
|
||||
Adam Borowski kilobyte@angband.pl
|
||||
Adam Jimerson vendion@charter.net
|
||||
Adam Klein aklein@debian.org
|
||||
Adam Sampson ats@offog.org
|
||||
Adrian Bunk bunk@stusta.de
|
||||
Aearil aearil@paranoici.org
|
||||
AIDA Shinra shinra@j10n.org
|
||||
Akim Demaille akim.demaille@gmail.com
|
||||
Alain Magloire alain@qnx.com
|
||||
Alan Curry pacman-cu@kosh.dhis.org
|
||||
Alan Iwi iwi@atm.ox.ac.uk
|
||||
Alan Jenkins alan-jenkins@tuffmail.co.uk
|
||||
Alban Bedel alban.bedel@avionic-design.de
|
||||
Albert Chin-A-Young china@thewrittenword.com
|
||||
Albert Hopkins ahopkins@dynacare.com
|
||||
Alberto Accomazzi alberto@cfa0.harvard.edu
|
||||
aldomel aldomel@ix.netcom.com
|
||||
Aleksej Serdjukov deletesoftware@yandex.ru
|
||||
Aleksej Shilin rootlexx@mail.ru
|
||||
Alen Muzinic zveki@fly.cc.fer.hr
|
||||
Alex Deymo deymo@chromium.org
|
||||
Alexander Nguyen vinh@seas.ucla.edu
|
||||
Alexander V. Lukyanov lav@netis.ru
|
||||
Alexandre Duret-Lutz duret_g@epita.fr
|
||||
Alexey Solovyov alekso@math.uu.se
|
||||
Alexey Vyskubov alexey@pippuri.mawhrin.net
|
||||
Alfred M. Szmidt ams@kemisten.nu
|
||||
Allen Hewes allen@decisiv.net
|
||||
Álvar Ibeas a.ibeas@gmx.com
|
||||
Ambrose Feinstein ambrose@google.com
|
||||
Amr Ali amr.ali.cc@gmail.com
|
||||
Anders Jonsson anders.jonsson@norsjovallen.se
|
||||
Anders Kaseorg andersk@mit.edu
|
||||
Andi Kleen freitag@alancoxonachip.com
|
||||
Andre Novaes Cunha Andre.Cunha@br.global-one.net
|
||||
Andreas Dilger adilger@sun.com
|
||||
Andreas Dilger adilger@whamcloud.com
|
||||
Andreas Frische andreasfrische@gmail.com
|
||||
Andreas Gruenbacher andreas.gruenbacher@gmail.com
|
||||
Andreas Jaeger jaeger@gnu.org
|
||||
Andreas Luik luik@isa.de
|
||||
Andreas Mohr andi@lisas.de
|
||||
Andreas Schwab schwab@linux-m68k.org
|
||||
Andreas Stolcke stolcke@ICSI.Berkeley.EDU
|
||||
Andrei Gaponenko andr@triumf.ca
|
||||
Andres Soolo andres@soolo.matti.ee
|
||||
Andrew Burgess aab@cichlid.com
|
||||
Andrew Church achurch@achurch.org
|
||||
Andrew Dalke dalke@bioreason.com
|
||||
Andrew D Warshall warshall@99main.com
|
||||
Andrew Fabbro andrew@fabbro.org
|
||||
Andrew Pham andpha@us.ibm.com
|
||||
Andrew Tridgell tridge@samba.org
|
||||
Andrey Borzenkov arvidjaar@mail.ru
|
||||
Andries Brouwer Andries.Brouwer@cwi.nl
|
||||
Andy Longton alongton@metamark.com
|
||||
Ángel González keisial@gmail.com
|
||||
Anoop Sharma sendtoanoop@gmail.com
|
||||
Anthony Thyssen anthony@griffith.edu.au
|
||||
Anton Ovchinnikov revolver112@gmail.com
|
||||
Antonio Ospite ao2@ao2.it
|
||||
Antonio Rendas ajrendas@yahoo.com
|
||||
Ariel Faigon ariel@cthulhu.engr.sgi.com
|
||||
Arjan Opmeer arjan.opmeer@gmail.com
|
||||
Arkadiusz Miśkiewicz arekm@maven.pl
|
||||
Arman Absalan armanaxh@gmail.com
|
||||
Arne Henrik Juul arnej@imf.unit.no
|
||||
Arnold Robbins arnold@skeeve.com
|
||||
Arsen Arsenović arsen@aarsen.me
|
||||
Arthur Pool pool@commerce.uq.edu.au
|
||||
Arun Sharma arun.sharma@intel.com
|
||||
Arvind Autar Autar022@planet.nl
|
||||
Assaf Gordon assafgordon@gmail.com
|
||||
Augey Mikus mikus@dqc.org
|
||||
Aurelien Jarno aurel32@debian.org
|
||||
Austin Donnelly Austin.Donnelly@cl.cam.ac.uk
|
||||
Axel Dörfler axeld@pinc-software.de
|
||||
Axel Kittenberger Anshil@gmx.net
|
||||
Ayappan ayappap2@in.ibm.com
|
||||
Barry Kelly http://blog.barrkel.com/
|
||||
Bauke Jan Douma bjdouma@xs4all.nl
|
||||
Ben Elliston bje@air.net.au
|
||||
Ben Harris bjh21@netbsd.org
|
||||
Ben Pfaff blp@cs.stanford.edu
|
||||
Ben Walton bdwalton@gmail.com
|
||||
Bengt Martensson bengt@mathematik.uni-Bremen.de
|
||||
Benjamin Cutler cutlerbc@simla.colostate.edu
|
||||
Benno Schulenberg bensberg@justemail.net
|
||||
Benno Schulenberg bensberg@telfort.nl
|
||||
Benoît Knecht benoit.knecht@fsfe.org
|
||||
Bernard Giroud bernard.giroud@creditlyonnais.ch
|
||||
Bernd Eckenfels ecki@debian.org
|
||||
Bernd Leibing bernd.leibing@rz.uni-ulm.de
|
||||
Bernd Melchers melchers@cis.fu-berlin.de
|
||||
Bernhard Baehr bernhard.baehr@gmx.de
|
||||
Bernhard Gabler bernhard@uni-koblenz.de
|
||||
Bernhard Marx berny@bernhard-marx.de
|
||||
Bernhard Rosenkraenzer bero@redhat.de
|
||||
Bernhard Voelker mail@bernhard-voelker.de
|
||||
Bert Deknuydt Bert.Deknuydt@esat.kuleuven.ac.be
|
||||
Bert Wesarg bert.wesarg@googlemail.com
|
||||
Bill Brelsford wb@k2di.net
|
||||
Bill Peters peters@gaffel.as.arizona.edu
|
||||
Bishop Bettini bishop.bettini@gmail.com
|
||||
Bjarni Ingi Gislason bjarniig@rhi.hi.is
|
||||
Bjorn Helgaas helgaas@rsn.hp.com
|
||||
Bo Borgerson gigabo@gmail.com
|
||||
Bo Rydberg bolry@hotmail.com
|
||||
Bob McCracken kerouac@ravenet.com
|
||||
Bob Proulx bob@proulx.com
|
||||
Bogdan Drozdowski bogdandr@op.pl
|
||||
Boris Ranto branto@redhat.com
|
||||
Branden Robinson branden@necrotic.deadbeast.net
|
||||
Brendan O'Dea bod@compusol.com.au
|
||||
Brent Petit brent.petit@hpe.com
|
||||
Brian Foster bfoster@redhat.com
|
||||
Brian Kimball bfk@footbag.org
|
||||
Brian M. Carlson sandals@crustytoothpaste.ath.cx
|
||||
Brian Silverman bsilverman@conceptxdesign.com
|
||||
Brian Youmans 3diff@gnu.org
|
||||
Britton Leo Kerin fsblk@aurora.uaf.edu
|
||||
Bruce Jerrick bmj001@gmail.com
|
||||
Bruce Korb bkorb@gnu.org
|
||||
Bruce Robertson brucer@theodolite.dyndns.org
|
||||
Bruno Haible bruno@clisp.org
|
||||
Brynnen Owen owen@illinois.edu
|
||||
C de-Avillez hggdh2@gmail.com
|
||||
Carl Edquist edquist@cs.wisc.edu
|
||||
Carl Johnson carlj@cjlinux.home.org
|
||||
Carl Lowenstein cdl@mpl.UCSD.EDU
|
||||
Carl Roth roth@urs.us
|
||||
Carlos Canau Carlos.Canau@relay.puug.pt
|
||||
Carlos Santos casantos@datacom.com.br
|
||||
Charles Karney karney@pppl.gov
|
||||
Charles Randall crandall@matchlogic.com
|
||||
Chas. Owens chas.owens@gmail.com
|
||||
Chen Guo chen.guo.0625@gmail.com
|
||||
Chengwei Yang chengwei.yang@intel.com
|
||||
Chih-Hsuan Yen yan12125@gmail.com
|
||||
Chip Salzenberg chip@valinux.com
|
||||
Choi Jongu zoopi01@gmail.com
|
||||
Chris Clayton chris2553@googlemail.com
|
||||
Chris Davies chris@roaima.co.uk
|
||||
Chris Faylor cgf@cygnus.com
|
||||
Chris J. Bednar cjb@AdvancedDataSolutions.com
|
||||
Chris Jones cjns1989@gmail.com
|
||||
Chris Lesniewski ctl@mit.edu
|
||||
Chris Meyering christophe.meyering@gmail.com
|
||||
Chris Sylvain csylvain@umm.edu
|
||||
Chris Yeo cyeo@biking.org
|
||||
Christi Alice Scarborough christi@chiark.greenend.org.uk
|
||||
Christian Göttsche cgzones@googlemail.com
|
||||
Christian Harkort christian.harkort@web.de
|
||||
Christian Hesse mail@eworm.de
|
||||
Christian Jullien eligis@orange.fr
|
||||
Christian Krackowizer ckrackowiz@std.schuler-ag.com
|
||||
Christian Rose menthos@menthos.com
|
||||
Christian von Roques roques@pond.sub.org
|
||||
Christoph Anton Mitterer calestyo@scientia.net
|
||||
Christophe LYON christophe.lyon@st.com
|
||||
ChuanGang Jiang jiangchuanganghw@outlook.com
|
||||
Chuck Hedrick hedrick@klinzhai.rutgers.edu
|
||||
Chusslove Illich caslav.ilic@gmx.net
|
||||
Clark Morgan cmorgan@aracnet.com
|
||||
Clement Wang clem.wang@overture.com
|
||||
Cliff Miller cbm@whatexit.org
|
||||
Cojocaru Alexandru xojoc@gmx.com
|
||||
Colin Leitner colin.leitner@googlemail.com
|
||||
Colin Plumb colin@nyx.net
|
||||
Colin Watson cjwatson@debian.org
|
||||
Collin Funk collin.funk1@gmail.com
|
||||
Collin Rogowski collin@rogowski.de
|
||||
Cray-Cyber Project https://www.cray-cyber.org
|
||||
Cristian Cadar cristic@stanford.edu
|
||||
Cyril Bouthors cyril@bouthors.org
|
||||
D. Hugh Redelmeier hugh@mimosa.com
|
||||
Daan De Meyer daan.j.demeyer@gmail.com
|
||||
Daiki Ueno ueno@gnu.org
|
||||
Dale Scheetz dwarf@polaris.net
|
||||
Dameon G. Rogers dgr03@uark.edu
|
||||
Daming Yang lion@aosc.io
|
||||
Dan Hagerty hag@gnu.ai.it.edu
|
||||
Dan Hipschman dsh@linux.ucla.edu
|
||||
Dan Jacobson jidanni@jidanni.org
|
||||
Dan Pascu dan@services.iiruc.ro
|
||||
Daniel Bergstrom noa@melody.se
|
||||
Daniel Carpenter dansebpub@gmail.com
|
||||
Daniel Dunbar daniel@zuster.org
|
||||
Daniel Hofstetter dhofstet@gmail.com
|
||||
Daniel J Walsh dwalsh@redhat.com
|
||||
Daniel Knittl-Frank knittl89@googlemail.com
|
||||
Daniel Lockyer thisisdaniellockyer@gmail.com
|
||||
Daniel Mach dmach@redhat.com
|
||||
Daniel P. Berrangé berrange@redhat.com
|
||||
Daniel Schepler dschepler@gmail.com
|
||||
Daniel Stavrovski d@stavrovski.net
|
||||
Daniel Tschinder daniel.tschinder@project-a.com
|
||||
Dániel Varga danielv@axelero.hu
|
||||
dann frazier dann.frazier@canonical.com
|
||||
Danny Levinson danny.levinson@overture.com
|
||||
Dario Giovannetti dariogiova@gmail.com
|
||||
Darrel Francis d.francis@cheerful.com
|
||||
Darren Salt ds@youmustbejoking.demon.co.uk
|
||||
Dave Beckett dajobe@dajobe.org
|
||||
Dave Chiluk chiluk@canonical.com
|
||||
David Alan Gilbert gilbertd@treblig.org
|
||||
David A. Wheeler dwheeler@dwheeler.com
|
||||
David Bartley dtbartle@csclub.uwaterloo.ca
|
||||
David Diggles david.diggles@dnrm.qld.gov.au
|
||||
David Dyck dcd@tc.fluke.COM
|
||||
David Eisner cradle@umd.edu
|
||||
David Flynn dav@chess.plus.com
|
||||
David Gast dgast@csulb.edu
|
||||
David Godfrey dave@delta.demon.co.uk
|
||||
David Luyer david_luyer@pacific.net.au
|
||||
David Madore david.madore@ens.fr
|
||||
David Malone dwmalone@cnri.dit.ie
|
||||
David Matei matei@cs.toronto.edu
|
||||
David Michael fedora.dm0@gmail.com
|
||||
David Pinto carandraug+dev@gmail.com
|
||||
David Sterba dsterba@suse.cz
|
||||
Davide Canova kc.canova@gmail.com
|
||||
Dawson Engler engler@stanford.edu
|
||||
Dean Gaudet dean-savannah@arctic.org
|
||||
Deepak Goel deego@gnufans.org
|
||||
Denis Excoffier gcc@Denis-Excoffier.org
|
||||
Denis McKeon dmckeon@swcp.com
|
||||
Dennis Clarke dclarke@blastwave.org
|
||||
Dennis Henriksen opus@flamingo.osrl.dk
|
||||
Dennis Smit ds@nerds-incorporated.org
|
||||
Dennis Williamson dennis@netstrata.com
|
||||
Derek Clegg dclegg@next.com
|
||||
Dick Streefland dick_streefland@tasking.com
|
||||
Dirk Lattermann dlatt@t-online.de
|
||||
Dirk-Jan Faber djfaber@snow.nl
|
||||
Dmitry Monakhov dmonakhov@openvz.org
|
||||
Dmitry Rutsky rutsky@school.ioffe.rssi.ru
|
||||
Dmitry V. Levin ldv@altlinux.org
|
||||
Don Parsons dparsons@synapse.kent.edu
|
||||
Donni Erpel donald@appc11.gsi.de
|
||||
Doug Coleman coleman@iarc1.ece.utexas.edu
|
||||
Doug McLaren dougmc@comco.com
|
||||
Dragan Simic dsimic@manjaro.org
|
||||
Dragos Harabor dharabor@us.oracle.com
|
||||
Duncan Roe duncanr@optimation.com.au
|
||||
Dylan Cali calid1984@gmail.com
|
||||
Dylan Simon dylan@dylex.net
|
||||
Ed Avis ed@membled.com
|
||||
Ed Santiago ed@edsantiago.com
|
||||
Edgars Irmejs edgars.irmejs@gmail.com
|
||||
Edward Schwartz edmcman@cmu.edu
|
||||
Edward Welbourne eddy@chaos.org.uk
|
||||
Edzer Pebesma Edzer.Pebesma@rivm.nl
|
||||
Egmont Koblinger egmont@uhulinux.hu
|
||||
Eirik Fuller eirik@hackrat.com
|
||||
Eivind eivindt@multinet.no
|
||||
Elbert Pol elbert.pol@gmail.com
|
||||
Eldon Stegall eldon@eldondev.com
|
||||
Eli Zaretskii eliz@is.elta.co.il
|
||||
Elias Pipping pipping@gentoo.org
|
||||
Emanuel Landeholm emanuel.landeholm@gmail.com
|
||||
Emanuele Giacomelli vpooldyn-linux@yahoo.it
|
||||
Emil Engler me@emilengler.com
|
||||
Emile LeBlanc leblanc@math.toronto.edu
|
||||
Emmanuel Lacour elacour@home-dn.net
|
||||
Enrico Scholz enrico.scholz@informatik.tu-chemnitz.de
|
||||
Eric Backus ericb@lsid.hp.com
|
||||
Eric Bergen eric.bergen@gmail.com
|
||||
Eric Blake eblake@redhat.com
|
||||
Eric G. Miller egm2@jps.net
|
||||
Eric Pemente pemente@northpark.edu
|
||||
Eric S. Raymond esr@snark.thyrsus.com
|
||||
Erik Auerswald auerswal@unix-ag.uni-kl.de
|
||||
Erik Bennett bennett@cvo.oneworld.com
|
||||
Erik Bernstein erik@fscking.org
|
||||
Erik Corry erik@kroete2.freinet.de
|
||||
Evan Hunt ethanol@armory.com
|
||||
Evgeny Nizhibitsky nizhibitsky@gmail.com
|
||||
Federico Simoncelli fsimonce@redhat.com
|
||||
Felix Lee flee@teleport.com
|
||||
Felix Rauch Valenti frauch@cse.unsw.edu.au
|
||||
Ferdinand fw@scenic.mine.nu
|
||||
Filipp Gunbin fgunbin@fastmail.fm
|
||||
Filipus Klutiero chealer@gmail.com
|
||||
Fletcher Mattox fletcher@cs.utexas.edu
|
||||
Florent Bayle florent@sarcelle.net
|
||||
Florian Schlichting fschlich@cis.fu-berlin.de
|
||||
Florin Iucha fiucha@hsys.mic.ro
|
||||
Francesco Montorsi fr_m@hotmail.com
|
||||
François Pinard pinard@iro.umontreal.ca
|
||||
François Rigault rigault.francois@gmail.com
|
||||
Frank Adler fadler@allesklar.de
|
||||
Frank Busse f.busse@imperial.ac.uk
|
||||
Frank T Lofaro ftlofaro@snooks.Egr.UNLV.EDU
|
||||
Fred Fish fnf@ninemoons.com
|
||||
Frédéric L. W. Meunier 0@pervalidus.net
|
||||
Frédéric Yhuel frederic.yhuel@dalibo.com
|
||||
Frederik Eaton frederik@caltech.edu
|
||||
Fridolin Pokorny fpokorny@redhat.com
|
||||
FUJIWARA Katsunori foozy@lares.dti.ne.jp
|
||||
G. Branden Robinson g.branden.robinson@gmail.com
|
||||
Gabor Z. Papp gzp@gzp.org.hu
|
||||
Gaël Quéri gqueri@mail.dotcom.fr
|
||||
Galen Hazelwood galenh@micron.net
|
||||
Gary Anderson ganderson@clark.net
|
||||
Gary Johnson garyjohn@spk.agilent.com
|
||||
Gary V. Vaughan gary@gnu.org
|
||||
Gaute Hvoslef Kvalnes gaute@verdsveven.com
|
||||
Geoff Collyer geoff at collyer.net
|
||||
Geoff Kuenning geoff@cs.hmc.edu
|
||||
Geoff Odhner geoff@franklin.com
|
||||
Geoff Whale geoffw@cse.unsw.EDU.AU
|
||||
George Burgess IV gbiv@chromium.org
|
||||
Gerald Pfeifer gerald@pfeifer.com
|
||||
Gerhard Poul gpoul@gnu.org
|
||||
Germano Leichsenring germano@jedi.cs.kobe-u.ac.jp
|
||||
Gian Piero Carrubba gpiero@rm-rf.it
|
||||
Gilles Espinasse g.esp@free.fr
|
||||
Giuseppe Scrivano gscrivano@gnu.org
|
||||
Glen Lenker glen.lenker@gmail.com
|
||||
Glenn Golden gdg@zplane.com
|
||||
Göran Uddeborg goeran@uddeborg.se
|
||||
GOTO Masanori gotom@debian.or.jp
|
||||
G.P. Halkes buscom@ghalkes.nl
|
||||
Greg Louis glouis@dynamicro.on.ca
|
||||
Greg McGary gkm@gnu.org
|
||||
Greg Metcalfe metcalfegreg@qwest.net
|
||||
Greg Schafer gschafer@zip.com.au
|
||||
Greg Troxel gdt@bbn.com
|
||||
Greg Wooledge greg@wooledge.org
|
||||
Gregory Leblanc gleblanc@cu-portland.edu
|
||||
Grigorii Sokolik g.sokol99@g-sokol.info
|
||||
Grisha Levit grishalevit@gmail.com
|
||||
Guenter Knauf lists@gknw.net
|
||||
Guido Leenders guido.leenders@invantive.com
|
||||
Guilherme de Almeida Suckevicz guito.linux@gmail.com
|
||||
Guntram Blohm Extern.Guntram.Blohm@AUDI.DE
|
||||
Guochun Shi gshi@ncsa.uiuc.edu
|
||||
H. J. Lu hjl@valinux.com
|
||||
Hans Ginzel hans@matfyz.cz
|
||||
Hans Lermen lermen@fgan.de
|
||||
Hans Verkuil hans@wyst.hobby.nl
|
||||
Harald Dunkel harald.dunkel@t-online.de
|
||||
Harald Hoyer harald@redhat.com
|
||||
Harry Liu rliu@lek.ugcs.caltech.edu
|
||||
Harti Brandt brandt@fokus.fraunhofer.de
|
||||
Harvey Eneman Harvey.Eneman@oracle.com
|
||||
Heikki Orsila heikki.orsila@iki.fi
|
||||
Heiko Marr h.marr@webmasters.de
|
||||
Helen Faulkner helen_ml_faulkner@yahoo.co.uk
|
||||
Herbert Xu herbert@gondor.apana.org.au
|
||||
Holger Berger hberger@ess.nec.de
|
||||
Hon-Yin Kok hkok@yoda.unl.edu
|
||||
Hugh Daniel hugh@xanadu.com
|
||||
Iain Calder ic56@rogers.com
|
||||
Ian Bruce ian.bruce@myrealbox.com
|
||||
Ian Jackson ijackson@chiark.greenend.org.uk
|
||||
Ian Kent ikent@redhat.com
|
||||
Ian Lance Taylor ian@cygnus.com
|
||||
Ian Turner vectro@pipeline.com
|
||||
Iida Yosiaki iida@gnu.org
|
||||
Illia Bobyr ibobyr@google.com
|
||||
Ilya N. Golubev gin@mo.msk.ru
|
||||
Ingo Saitz ingo@debian.org
|
||||
Ingo Weinhold ingo_weinhold@gmx.de
|
||||
Ivan Labath labath3@st.fmph.uniba.sk
|
||||
Ivan Radić ivan-radic@users.noreply.github.com
|
||||
Ivan Sichmann Freitas ivansichfreitas@gmail.com
|
||||
Ivo Timmermans ivo@debian.org
|
||||
J. Scott Edwards qrw.software@gmail.com
|
||||
Jaak Ristioja jaak.ristioja@cyber.ee
|
||||
Jack Howarth howarth.mailing.lists@gmail.com
|
||||
Jacky Fong jacky.fong@utoronto.ca
|
||||
Jacob Keller jacob.e.keller@intel.com
|
||||
Jakob Truelsen jakob@scalgo.com
|
||||
James Antill jmanti%essex.ac.uk@seralph21.essex.ac.uk
|
||||
James Hunt jamesodhunt@hotmail.com
|
||||
James james@albion.glarp.com
|
||||
James Lemley James.Lemley@acxiom.com
|
||||
James Ralston ralston@pobox.com
|
||||
James R. Van Zandt jrv@debian.org
|
||||
James Sneeringer jvs@ocslink.com
|
||||
James Tanis jtt@soscorp.com
|
||||
James Youngman jay@gnu.org
|
||||
Jamie Lokier jamie@imbolc.ucc.ie
|
||||
Jamie McClelland jm@mayfirst.org
|
||||
Jan Blunck jblunck@suse.de
|
||||
Jan Engelhardt jengelh@medozas.de
|
||||
Jan Fedak J.Fedak@sh.cvut.cz
|
||||
Jan Moringen jan.moringen@uni-bielefeld.de
|
||||
Jan Nieuwenhuizen janneke@gnu.org
|
||||
Janne Snabb snabb@epipe.com
|
||||
Janos Farkas chexum@shadow.banki.hu
|
||||
Jan-Pawel Wrozstinski jpwroz@gmail.com
|
||||
Jari Aalto jari.aalto@cante.net
|
||||
Jarkko Hietaniemi jhi@epsilon.hut.fi
|
||||
Jarkko Sakkinen jarkko.sakkinen@iki.fi
|
||||
Jarod Wilson jwilson@redhat.com
|
||||
Jaroslav Skarvada jskarvad@redhat.com
|
||||
Jarosław Gruca jgruca1981@gmail.com
|
||||
Jason Kim git@jasonk.me
|
||||
Jason Smith jasonmsmith@google.com
|
||||
Javier López chilicuil@ubuntu.com
|
||||
Jean Charles Delepine delepine@u-picardie.fr
|
||||
Jean Delvare jdelvare@suse.de
|
||||
Jean-Pierre Tosoni jpt.7196@gmail.com
|
||||
Jeff Layton jlayton@kernel.org
|
||||
Jeff Liu jeff.liu@oracle.com
|
||||
Jeff Moore jbm@mordor.com
|
||||
Jeff Sheinberg jeff@bsrd.net
|
||||
Jens Elkner elkner@imsgroup.de
|
||||
Jens Schmidt jms@jsds.hamburg.com
|
||||
Jeph Cowan jeph@ucar.edu
|
||||
Jeremy Maitin-Shepard jbms@cmu.edu
|
||||
Jérémy Compostella jeremy.compostella@gmail.com
|
||||
Jérémy Magrin jeremy.magrin@epitech.eu
|
||||
Jerome Abela abela@hsc.fr
|
||||
Jérôme Zago bug-coreutils-ml@agt-the-walker.net
|
||||
Jerry Snitselaar dev@snitselaar.org
|
||||
Jesse Kornblum kornblum@usna.edu
|
||||
Jesse Thilo jgt2@eecs.lehigh.edu
|
||||
Jie Xu xuj@iag.net
|
||||
Jim Blandy jimb@cyclic.com
|
||||
Jim Dennis jimd@starshine.org
|
||||
Jim Meyering jim@meyering.net
|
||||
Jim Meyering meyering@meta.com
|
||||
Jirka Hladky jhladky@redhat.com
|
||||
Joachim Schmitz jojo@schmitz-digital.de
|
||||
Joakim Rosqvist dvljrt@cs.umu.se
|
||||
Jochen Hein jochen@jochen.org
|
||||
Joe Orton joe@manyfish.co.uk
|
||||
Joel E. Denny jdenny@clemson.edu
|
||||
Joerg Sonnenberger joerg@britannica.bec.de
|
||||
Joey Degges jdegges@gmail.com
|
||||
Joey Hess joeyh@debian.org
|
||||
Johan Boule bohan@bohan.dyndns.org
|
||||
Johan Danielsson joda@pdc.kth.se
|
||||
Johannes Altmanninger aclopte@gmail.com
|
||||
John Bley jbb6@acpub.duke.edu
|
||||
John da_audiophile@yahoo.com
|
||||
John David Anglin dave.anglin@nrc.ca
|
||||
John Gatewood Ham zappaman@alphabox.compsci.buu.ac.th
|
||||
John Gotts jgotts@umich.edu
|
||||
John Kendall kendall@capps.com
|
||||
John Kodis kodis@acm.org
|
||||
John Murphy jam@philabs.research.philips.com
|
||||
John Roll john@panic.harvard.edu
|
||||
John Salmon johns@mullet.anu.edu.au
|
||||
John Stanley johnstops@verizon.net
|
||||
John Summerfield summer@OS2.ami.com.au
|
||||
Jon Peatfield J.S.Peatfield@damtp.cam.ac.uk
|
||||
Jon Ringuette jonr@scharp.org
|
||||
Joost van Baal joostvb@xs4all.nl
|
||||
Jordi Pujol jordipujolp@gmail.com
|
||||
Jorge Stolfi stolfi@ic.unicamp.br
|
||||
Josef Cejka jcejka@suse.com
|
||||
Joseph D. Wagner joe@josephdwagner.info
|
||||
Joseph S. Myers jsm28@cam.ac.uk
|
||||
Josh Triplett josh@freedesktop.org
|
||||
Joshua Hudson joshudson@gmail.com
|
||||
Josselin Mouette joss@debian.org
|
||||
Juan F. Codagnone juam@arnet.com.ar
|
||||
Juan M. Guerrero st001906@hrz1.hrz.tu-darmstadt.de
|
||||
Julian Bradfield jcb@inf.ed.ac.uk
|
||||
Julian Büning julian.buening@rwth-aachen.de
|
||||
Jungshik Shin jshin@pantheon.yale.edu
|
||||
Juraj Marko jmarko@redhat.com
|
||||
Jürgen Fluk louis@dachau.marco.de
|
||||
Jurriaan thunder7@xs4all.nl
|
||||
Justin Pryzby justinpryzby@users.sourceforge.net
|
||||
Justin Tracey j2tracey@gmail.com
|
||||
jvogel jvogel@linkny.com
|
||||
Kai Henningsen kai@debian.org
|
||||
Kai-Uwe Rommel rommel@informatik.tu-muenchen.de
|
||||
Kalle Olavi Niemitalo kon@iki.fi
|
||||
Kamal Paul Nigam Kamal_Paul_Nigam@gs35.sp.cs.cmu.edu
|
||||
Kamil Dudka kdudka@redhat.com
|
||||
Karel Zak kzak@redhat.com
|
||||
Karl Berry karl@gnu.org
|
||||
Karl Eichwalder keichwa@gmx.net
|
||||
Karl Heuer kwzh@gnu.org
|
||||
Karl-Michael Schneider schneide@phil.uni-passau.de
|
||||
Karsten Thygesen karthy@kom.auc.dk
|
||||
Kaveh R. Ghazi ghazi@caip.rutgers.edu
|
||||
Kaxandra Labat kaxandra.labat@gmail.com
|
||||
Keith M. Briggs keith.briggs@bt.com
|
||||
Keith Owens kaos@audio.apana.org.au
|
||||
Keith Thompson Keith.S.Thompson@gmail.com
|
||||
Ken Booth ken@booths.org.uk
|
||||
Ken Irving ken.irving@alaska.edu
|
||||
Ken Pizzini kenp@halcyon.com
|
||||
Kevin Locke kevin@kevinlocke.name
|
||||
Kevin Lyda kevin@ie.suberic.net
|
||||
Kevin Mudrick kmudrick@healthmarketscience.com
|
||||
Kim Hansen kim@i9.dk
|
||||
Kirk Kelsey kirk.kelsey@0x4b.net
|
||||
Kjetil Torgrim Homme kjetilho@ifi.uio.no
|
||||
KO Myung-Hun komh@chollian.net
|
||||
KOBAYASHI Takashi a1415tk@aiit.ac.jp
|
||||
Konrad Wróblewski coni@o2.pl
|
||||
Kristin E Thomas kristint@us.ibm.com
|
||||
Kristoffer Brånemyr ztion1@yahoo.se
|
||||
Kristoffer Rose kris@diku.dk
|
||||
Krzysztof Goj krzysztof.goj@gmail.com
|
||||
Ladislav Hagara ladislav.hagara@unob.cz
|
||||
Larry McVoy lm@sgi.com
|
||||
Lars Hecking lhecking@nmrc.ucc.ie
|
||||
Lasse Collin lasse.collin@tukaani.org
|
||||
Leah Q eequor@earthlink.net
|
||||
Lehti Rami rammer@cs.tut.fi
|
||||
Leonard N. Zubkoff lnz@dandelion.com
|
||||
Leonardo Milano lmilano@udel.edu
|
||||
Lluís Batlle viriketo@gmail.com
|
||||
Lorne Baker lbaker@nitro.avint.net
|
||||
Ludovic Courtès ludo@gnu.org
|
||||
Lukáš Zaoral lzaoral@redhat.com
|
||||
Luke Hassell lukehassell@yahoo.com
|
||||
Luke Kendall lukekendall@optushome.com.au
|
||||
Luther Thompson lutheroto@gmail.com
|
||||
lvgenggeng lvgenggeng@uniontech.com
|
||||
M. P. Suzuki mpsuzuki@hiroshima-u.ac.jp
|
||||
Maciej Kwapulinski pikpok@univ.gda.pl
|
||||
Manas Garg manas@cygsoft.com
|
||||
Manfred Hollstein manfred@s-direktnet.de
|
||||
Manolis Ragkousis manolis837@gmail.com
|
||||
Marc Boucher marc@mbsi.ca
|
||||
Marc Haber mh+debian-bugs@zugschlus.de
|
||||
Marc Kleine-Budde mkl@pengutronix.de
|
||||
Marc Lehman schmorp@schmorp.de
|
||||
Marc Mengel mengel@fnal.gov
|
||||
Marc Olzheim marcolz@stack.nl
|
||||
Marcel Böhme https://www.comp.nus.edu.sg/~mboehme
|
||||
Marco Franzen Marco.Franzen@Thyron.com
|
||||
Marcus Brinkmann https://www.marcus-brinkmann.de
|
||||
Marcus Daniels marcus@ee.pdx.edu
|
||||
Marek Polacek mpolacek@redhat.com
|
||||
Mark A. Thomas thommark@access.digex.net
|
||||
Mark Conty Mark_Conty@cargill.com
|
||||
Mark D. Roth roth@uiuc.edu
|
||||
Mark Funkenhauser mfunkenhauser@rogers.com
|
||||
Mark Harris mark@monitor.designacc.com
|
||||
Mark Hewitt mhewitt@armature.com
|
||||
Mark Hounschell markh@compro.net
|
||||
Mark Hubbart discord@mac.com
|
||||
Mark Kettenis kettenis@phys.uva.nl
|
||||
Mark Korenberg socketpair@gmail.com
|
||||
Mark Melahn mmelahn@gmail.com
|
||||
Mark Nudelman marknu@flash.net
|
||||
Mark W. Eichin eichin@cygnus.com
|
||||
Markus Demleitner msdemlei@auriga.ari.uni-heidelberg.de
|
||||
Markus Duft mduft@gentoo.org
|
||||
Martial Bornet mbornet.pro@gmail.com
|
||||
Martin Buck martin.buck@ascom.ch
|
||||
Martin Bukatovic martin.bukatovic@gmail.com
|
||||
Martin Castillo castilma@uni-bremen.de
|
||||
Martin Gallant martyg@goodbit.net
|
||||
Martin Hippe martin.hippe@schlund.de
|
||||
Martin Jacobs martin.jacobs@arcor.de
|
||||
Martin martin@dresden.nacamar.de
|
||||
Martin Michlmayr tbm@cyrius.com
|
||||
Martin Mitchell martin@debian.org
|
||||
Martin P.J. Zinser zinser@decus.de
|
||||
Marty Leisner leisner@sdsp.mc.xerox.com
|
||||
Masami Takikawa takikawm@CS.ORST.EDU
|
||||
Masatake YAMATO yamato@redhat.com
|
||||
Mate Wierdl mw@moni.msci.memphis.edu
|
||||
Matej Vela mvela@public.srce.hr
|
||||
Matěj Cepl mcepl@redhat.com
|
||||
Matheus Afonso Martins Moreira matheus.a.m.moreira@gmail.com
|
||||
Mathias Brodala info@noctus.net
|
||||
Mathieu Bridon bochecha@fedoraproject.org
|
||||
Matias A. Fonzo selk@dragora.org
|
||||
Matt Harden matth@mindspring.com
|
||||
Matt Kraai kraai@ftbfs.org
|
||||
Matt McCutchen matt@mattmccutchen.net
|
||||
Matt Perry matt@primefactor.com
|
||||
Matt Pham mattvpham@gmail.com
|
||||
Matt Schalit mschalit@pacbell.net
|
||||
Matt Swift swift@alum.mit.edu
|
||||
Matthew Arnison maffew@cat.org.au
|
||||
Matthew Braun matthew@ans.net
|
||||
Matthew Clarke Matthew_Clarke@mindlink.bc.ca
|
||||
Matthew M. Boedicker matthewm@boedicker.org
|
||||
Matthew Pfeiffer spferical@gmail.com
|
||||
Matthew S. Levine mslevine@theory.lcs.mit.edu
|
||||
Matthew Smith matts@bluesguitar.org
|
||||
Matthew Swift swift@alum.mit.edu
|
||||
Matthew Woehlke mw_triad@users.sourceforge.net
|
||||
Matthias Urlichs smurf@noris.de
|
||||
Matti Aarnio matti.aarnio@zmailer.org
|
||||
Mattias Wadenstein maswan@acc.umu.se
|
||||
Max Chang maxchang@ucla.edu
|
||||
Max Filippov jcmvbkbc@gmail.com
|
||||
Maxime de Roucy maxime.deroucy@gmail.com
|
||||
Meelis Roos mroos@tartu.cyber.ee
|
||||
Micah Cowan micah@cowan.name
|
||||
Michael Bacarella mbac@netgraft.com
|
||||
Michael Deutschmann michael@talamasca.ocis.net
|
||||
Michael Elizabeth Chastain mec.gnu@mindspring.com
|
||||
Michael Gaughen mgaughen@polyserve.com
|
||||
Michael Hasselberg mikelh@zonta.ping.de
|
||||
Michael Heimpold mhei@heimpold.de
|
||||
Michael Hohn hohn@math.utah.edu
|
||||
Michael J. Croghan mcroghan@usatoday.com
|
||||
Michael J. Daniel michael.j.daniel@comcast.net
|
||||
Michael McFarland sidlon@yahoo.com
|
||||
Michael McLagan mmclagan@invlogic.com
|
||||
Michael Meskes michael@fam-meskes.de
|
||||
Michael michael@aplatform.com
|
||||
Michael ??? michael@roka.net
|
||||
Michael Mol mikemol@gmail.com
|
||||
Michael Orlitzky michael@orlitzky.com
|
||||
Michael Piefel piefel@informatik.hu-berlin.de
|
||||
Michael Price mprice@atl.lmco.com
|
||||
Michael Speer knomenet@gmail.com
|
||||
Michael Steffens michael.steffens@s.netic.de
|
||||
Michael Stone mstone@debian.org
|
||||
Michael Stummvoll michael@stummi.org
|
||||
Michael Stutz stutz@dsl.org
|
||||
Michael van Elst mlelstv@dev.de.cw.net
|
||||
Michael Veksler mveksler@techunix.technion.ac.il
|
||||
Michael Witten mfwitten@gmail.com
|
||||
Michail Litvak mci@owl.openwall.com
|
||||
Michal Nazarewicz mina86@mina86.com
|
||||
Michal Politowski mpol@charybda.icm.edu.pl
|
||||
Michal Svec msvec@suse.cz
|
||||
Michal Trunecka mtruneck@redhat.com
|
||||
Michel Lind michel@michel-slm.name
|
||||
Michel Robitaille robitail@IRO.UMontreal.CA
|
||||
Michiel Bacchiani bacchian@raven.bu.edu
|
||||
Mikael Magnusson mikachu@gmail.com
|
||||
Mike Castle dalgoda@ix.netcom.com
|
||||
Mike Coleman mkc@mathdogs.com
|
||||
Mike Frysinger vapier@gentoo.org
|
||||
Mike Jetzer mjetzer@mke.catalystwms.com
|
||||
Mike Swanson mikeonthecomputer@gmail.com
|
||||
Mikko Tuumanen m@sorvankyla.yok.utu.fi
|
||||
Mikulas Patocka mikulas@artax.karlin.mff.cuni.cz
|
||||
Miles Bader miles@gnu.ai.mit.edu
|
||||
Minh Tran-Le tranle@intellicorp.com
|
||||
Mitchel Humpherys mitch.special@gmail.com
|
||||
Moritz Orbach ml-coreutils@apfelboymchen.homeunix.net
|
||||
Morten Welinder terra@diku.dk
|
||||
Nadav Har'El nyh@math.technion.ac.il
|
||||
Namhyung Kim namhyung@gmail.com
|
||||
Nao Nishijima nao.nishijima.xt@hitachi.com
|
||||
Neal H Walfield neal@cs.uml.edu
|
||||
Neil F. Brown neilb@suse.de
|
||||
Nelson H. F. Beebe beebe@math.utah.edu
|
||||
Nguyễn Thái Ngọc Duy pclouds@gmail.com
|
||||
Nick Alcock nick.alcock@oracle.com
|
||||
Nick Estes debian@nickstoys.com
|
||||
Nick Graham nick.d.graham@gmail.com
|
||||
Nick Lawes nlawes@silverplatter.com
|
||||
Nickolai Zeldovich nickolai@cs.stanford.edu
|
||||
Nicolas François nicolas.francois@centraliens.net
|
||||
Nicolas Iooss nicolas.iooss@m4x.org
|
||||
Niels Möller nisse@lysator.liu.se
|
||||
Niklas Edmundsson nikke@acc.umu.se
|
||||
Nikola Milutinovic Nikola.Milutinovic@ev.co.yu
|
||||
Nikolaos Chatzikonstantinou nchatz314@gmail.com
|
||||
Nikolas Kallis nik@nikolaskallis.com
|
||||
Nikolaus Rath Nikolaus@rath.org
|
||||
Nikolay Nechaev Nikolay_Nechaev@mail.ru
|
||||
Nikos Mavrogiannopoulos nmav@redhat.com
|
||||
Nima Nikzad nnikzad@ucla.edu
|
||||
Nishant Nayan nishant.nayan@oracle.com
|
||||
Nix nix@esperi.org.uk
|
||||
nl6720 nl6720@gmail.com
|
||||
Noah Friedman friedman@splode.com
|
||||
Noel Cragg noel@red-bean.com
|
||||
Norbert Kiesel nkiesel@tbdnetworks.com
|
||||
Norihiro Kamae norihiro@nagater.net
|
||||
Olatunji Oluwabukunmi Ruwase tjruwase@stanford.edu
|
||||
Olav Morkrid olav@funcom.com
|
||||
Ole Laursen olau@hardworking.dk
|
||||
Oliver Kiddle okiddle@yahoo.co.uk
|
||||
Olivier Fourdan ofourdan@redhat.com
|
||||
Ondrej Oprala ooprala@redhat.com
|
||||
Ondřej Vašík ovasik@redhat.com
|
||||
Ørn E. Hansen oehansen@daimi.aau.dk
|
||||
Oskar Liljeblad osk@hem.passagen.se
|
||||
Otavio Salvador otavio@ossystems.com.br
|
||||
Pádraig Brady pbrady@fb.com
|
||||
Pádraig Brady P@draigBrady.com
|
||||
Paolo Bonzini bonzini@gnu.org
|
||||
Patrick Mauritz oxygene@studentenbude.ath.cx
|
||||
Patrick Schoenfeld schoenfeld@debian.org
|
||||
Patrick W. Plusnick II pwplusnick2@gmail.com
|
||||
Paul D. Smith psmith@gnu.org
|
||||
Paul Eggert eggert@cs.ucla.edu
|
||||
Paul Ghaleb paul.ghaleb@st.com
|
||||
Paul Jarc prj@po.cwru.edu
|
||||
Paul Marinescu paul.marinescu@imperial.ac.uk
|
||||
Paul Nevai nevai@ops.mps.ohio-state.edu
|
||||
Paul Sauer paul@alexa.com
|
||||
Paul Slootman paul@debian.org
|
||||
Paul Townsend aab@purdue.edu
|
||||
Paul Worrall paul@basilisk.uklinux.net
|
||||
Pawel Prokop pablo@wizard.ae.krakow.pl
|
||||
Peng Yu pengyu.ut@gmail.com
|
||||
Per Cederqvist ceder@lysator.liu.se
|
||||
Per Kristian Hove perhov@math.ntnu.no
|
||||
Per Starbäck starback@stp.lingfil.uu.se
|
||||
Peter Benie pjb1008@cam.ac.uk
|
||||
Peter Bray pdb_ml@yahoo.com.au
|
||||
Peter Breitenlohner peb@mppmu.mpg.de
|
||||
Peter Dyballa peter_dyballa@web.de
|
||||
Peter Eriksson peter@ifm.liu.se
|
||||
Peter Evans peter@ixp.jp
|
||||
Peter Fales psfales@alcatel-lucent.com
|
||||
Peter Horst peter@ointment.org
|
||||
Peter Moulder reiter@netspace.net.au
|
||||
Peter O'Gorman bug-coreutils@mlists.thewrittenword.com
|
||||
Peter Samuelson psamuels@sampo.creighton.edu
|
||||
Peter Seebach seebs@taniemarie.solon.com
|
||||
Petr Malat oss@malat.biz
|
||||
Petr Pisar petr.pisar@atlas.cz
|
||||
Petr Salinger Petr.Salinger@seznam.cz
|
||||
Petr Stodůlka pstodulk@redhat.com
|
||||
Petr Uzel petr.uzel@suse.cz
|
||||
Petter Reinholdtsen pere@hungry.com
|
||||
Phelippe Neveu pneveu@pcigeomatics.com
|
||||
Phil Richards phil.richards@vf.vodafone.co.uk
|
||||
Philip Rowlands phr@doc.ic.ac.uk
|
||||
Philipp Gortan gortan@gmail.com
|
||||
Philipp Thomas pth@suse.de
|
||||
Philippe De Muyter phdm@macqel.be
|
||||
Philippe Schnoebelen Philippe.Schnoebelen@imag.fr
|
||||
Phillip Jones mouse@datastacks.com
|
||||
Piergiorgio Sartor sartor@sony.de
|
||||
Pierre Marsais pierre.marsais@lse.epita.fr
|
||||
Pieter Bowman bowman@math.utah.edu
|
||||
Piotr Gackiewicz gacek@intertele.pl
|
||||
Piotr Kwapulinski kwap@univ.gda.pl
|
||||
Pozsár Balázs pozsy@uhulinux.hu
|
||||
Prashant TR tr@eth.net
|
||||
Prateek saxena prateeksaxena2@gmail.com
|
||||
Priit Jõerüüt jemm4jemm@yahoo.com
|
||||
Primoz PETERLIN primozz.peterlin@gmail.com
|
||||
Raimonds Miltins raimonds@pro-9.com
|
||||
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
|
||||
Ralf Wildenhues Ralf.Wildenhues@gmx.de
|
||||
Ralf W. Stephan stephan@tmt.de
|
||||
Ralph Loader loader@maths.ox.ac.uk
|
||||
Rasmus Borup Hansen rbh@intomics.com
|
||||
Rasmus Villemoes rasmus.villemoes@prevas.dk
|
||||
Rasmus Villemoes rv@rasmusvillemoes.dk
|
||||
Raul Miller moth@magenta.com
|
||||
Raúl Núñez de Arenas Coronado raul@pleyades.net
|
||||
Rémy Lefevre lefevreremy@gmail.com
|
||||
Reuben Thomas rrt@sc3d.org
|
||||
ribalba geerd.dietger.hoffmann@gmail.com
|
||||
Rich Burridge rich.burridge@oracle.com
|
||||
Richard A Downing richard.downing@bcs.org.uk
|
||||
Richard Braakman dark@xs4all.nl
|
||||
Richard Dawe rich@phekda.freeserve.co.uk
|
||||
Richard J. Rauenzahn rrauenza@hairball.cup.hp.com
|
||||
Richard Neill rn214@hermes.cam.ac.uk
|
||||
Richard Purdie richard.purdie@linuxfoundation.org
|
||||
Richard Russon rich@flatcap.org
|
||||
Richard Sharman rsharman@magmacom.com
|
||||
Rick Sladkey jrs@world.std.com
|
||||
Rick Stanley rstanley@rsiny.com
|
||||
Rik Faith faith@cs.unc.edu
|
||||
Rishabh Dave rishabhddave@gmail.com
|
||||
Risto Kankkunen kankkune@lingsoft.fi
|
||||
Rob Day robertkday@gmail.com
|
||||
Rob Wortman wyrm@haell.com
|
||||
Robert H. de Vries robert@and.nl
|
||||
Robert Lindgren robert@orcafat.com
|
||||
Robert Millan zeratul2@wanadoo.es
|
||||
Robert Schwebel r.schwebel@pengutronix.de
|
||||
Robin H. Johnson robbat2@gentoo.org
|
||||
Rodrigo Campos rodrigo@sdfg.com.ar
|
||||
Rogier Wolff R.E.Wolff@BitWizard.nl
|
||||
Rohan Sable rsable@redhat.com
|
||||
Roland Hieber rohieb@rohieb.name
|
||||
Roland Huebner ro-huebner@gmx.de
|
||||
Roland Turner raz.tah.bet@raz.cx
|
||||
Roman Rybalko devel@romanr.info
|
||||
Ronald F. Guilmette rfg@netcom.com
|
||||
Ross Alexander r.alexander@auckland.ac.nz
|
||||
Ross Paterson rap@doc.ic.ac.uk
|
||||
Ross Ridge rridge@calum.csclub.uwaterloo.ca
|
||||
Rudolf Kastl rkastl@redhat.com
|
||||
Ruediger Meier sweet_f_a@gmx.de
|
||||
Sahil Amoli sahilamoli@gmail.com
|
||||
Sam Russell sam.h.russell@gmail.com
|
||||
Sami Farin sfarin@ratol.fi
|
||||
Sami Kerola kerolasa@iki.fi
|
||||
Samuel Neves sneves@dei.uc.pt
|
||||
Samuel Tardieu sam@rfc1149.net
|
||||
Samuel Thibault samuel.thibault@ens-lyon.org
|
||||
Samuli Karkkainen Samuli.Karkkainen@hut.fi
|
||||
Sander van Malssen svm@kozmix.ow.nl
|
||||
Santiago Vila Doncel sanvila@unex.es
|
||||
Savochkin Andrey Vladimirovich saw@msu.ru
|
||||
Scott Harrison scott.gnu.2009@scottrix.co.uk
|
||||
Scott Lurndal slurn@griffin.engr.sgi.com
|
||||
Sebastian Kisela skisela@redhat.com
|
||||
Sébastien Maret smaret@umich.edu
|
||||
Sergei Steshenko sergstesh@yahoo.com
|
||||
Sergey Vlasov vsu@altlinux.org
|
||||
Sergio Durigan Junior sergiodj@sergiodj.net
|
||||
Shane M Seymour shane.seymour@hp.com
|
||||
Shayan Pooya shayan@liveve.org
|
||||
Shing-Shong Shei shei@cs.indiana.edu
|
||||
Shugo Maeda shugo@ruby-lang.org
|
||||
Simon Josefsson simon@josefsson.org
|
||||
Soeren Sonnenburg sonnenburg@informatik.hu-berlin.de
|
||||
Solar Designer solar@owl.openwall.com
|
||||
Stanislav Ievlev inger@altlinux.ru
|
||||
Stavros Passas stabat@ics.forth.gr
|
||||
Stefan Kangas stefankangas@gmail.com
|
||||
Stefan Vargyas stvar@yahoo.com
|
||||
Stefano Lattarini stefano.lattarini@gmail.com
|
||||
Stephan Krempel krempel@par-tec.com
|
||||
Stephane Chazelas stephane.chazelas@gmail.com
|
||||
Stephane Chazelas stephane@chazelas.org
|
||||
Stéphane Aulery saulery@free.fr
|
||||
Stéphane Campinas stephane.campinas@gmail.com
|
||||
Stéphane Chazelas Stephane_CHAZELAS@yahoo.fr
|
||||
Stéphane Raimbault stephane.raimbault@gmail.com
|
||||
Stephen Depooter sbdep@myrealbox.com
|
||||
Stephen Eglen eglen@pcg.wustl.edu
|
||||
Stephen Gildea gildea@stop.mail-abuse.org
|
||||
Stephen Kitt skitt@redhat.com
|
||||
Stephen Shirley kormat@gmail.com
|
||||
Stephen Smoogen smooge@mindspring.com
|
||||
Steve McConnel steve@acadcomp.sil.org
|
||||
Steve McIntyre steve@einval.com
|
||||
Steve Ward planet36@gmail.com
|
||||
Steven Drake sbd@users.sourceforge.net
|
||||
Steven G. Johnson stevenj@alum.mit.edu
|
||||
Steven Mocking ufo@quicknet.nl
|
||||
Steven Parkes smparkes@smparkes.net
|
||||
Steven P Watson steven@magelico.net
|
||||
Steven Schubiger schubiger@gmail.com
|
||||
Steven Schveighoffer schveiguy@yahoo.com
|
||||
Stuart Citrin ctrn3e8@gmail.com
|
||||
Stuart Kemp skemp@peter.bmc.com
|
||||
Stuart Shelton stuart@shelton.me
|
||||
Sven Breuner sven.breuner@itwm.fraunhofer.de
|
||||
Sven Joachim svenjoac@gmx.de
|
||||
Sylvestre Ledru sylvestre@debian.org
|
||||
Szakacsits Szabolcs szaka@sienet.hu
|
||||
Tadayoshi Funaba tadf@kt.rim.or.jp
|
||||
TAKAI Kousuke takai@vlsi.kuee.kyoto-u.ac.jp
|
||||
The Wanderer inverseparadox@comcast.net
|
||||
Theodore Ts'o tytso@rsts-11.mit.edu
|
||||
Theodoros V. Kalamatianos thkala@softlab.ece.ntua.gr
|
||||
Thiago Farina tfransosi@gmail.com
|
||||
Thien-Thi Nguyen ttn@gnuvola.org
|
||||
Thomas Bushnell thomas@gnu.ai.mit.edu
|
||||
Thomas Deutschmann whissi@gentoo.org
|
||||
Thomas Goerlich thomas@schnappmatik.de
|
||||
Thomas Hood jdthood@yahoo.co.uk
|
||||
Thomas Jarosch thomas.jarosch@intra2net.com
|
||||
Thomas Luzat thomas@luzat.com
|
||||
Thomas M.Ott thmo-13@gmx.de
|
||||
Thomas Quinot thomas@Cuivre.FR.EU.ORG
|
||||
Thomas Schwinge tschwinge@gnu.org
|
||||
Thomas Wolff mined@towo.net
|
||||
Tianjia Zhang tianjia.zhang@linux.alibaba.com
|
||||
Tiger Lee i@tigerlee.me
|
||||
Tim Gates tim.gates@iress.com
|
||||
Tim J. Robbins tjr@FreeBSD.org
|
||||
Tim Mooney mooney@dogbert.cc.ndsu.NoDak.edu
|
||||
Tim Ryan Tim_Ryan@bnz.co.nz
|
||||
Tim Smithers mouse@dmouse.com.au
|
||||
Tim Underwood timunderwood@gmail.com
|
||||
Tim Waugh twaugh@redhat
|
||||
Tobias Quathamer toddy@debian.org
|
||||
Tobias Stoeckmann tobias@stoeckmann.org
|
||||
Toby Peterson toby@opendarwin.org
|
||||
Todd A. Jacobs tjacobs@codegnome.org
|
||||
Tom Fitzhenry tom@tom-fitzhenry.me.uk
|
||||
Tom Haynes thomas@netapp.com
|
||||
Tom Quinn trq@dionysos.thphys.ox.ac.uk
|
||||
Tomas Pospisek tpo@sourcepole.ch
|
||||
Tomas Smetana t.smetana@gmail.com
|
||||
Tommi Kyntola tkyntola@cc.hut.fi
|
||||
Ton Hospel thospel@mail.dma.be
|
||||
Ton Nijkes ton@murphy.nl
|
||||
Tony Kocurko akocurko@mun.ca
|
||||
Tony Leneis tony@plaza.ds.adp.com
|
||||
Tony Robinson ajr@eng.cam.ac.uk
|
||||
Toomas Soome Toomas.Soome@Elion.ee
|
||||
Toralf Förster toralf.foerster@gmx.de
|
||||
Torbjörn Granlund tg@gmplib.org
|
||||
Torbjörn Lindgren tl@funcom.no
|
||||
Torsten Landschoff torsten@pclab.ifg.uni-kiel.de
|
||||
Travis Gummels tgummels@redhat.com
|
||||
Tristan Miller psychonaut@nothingisreal.com
|
||||
Tzvi Rotshtein tzvi.ro@gmail.com
|
||||
Ulrich Drepper drepper@gnu.org
|
||||
Ulrich Hermisson ulrich_hermisson@hotmail.com
|
||||
Urs Thuermann urs@isnogud.escape.de
|
||||
Uwe H. Steinfeld usteinfeld@gmx.net
|
||||
Vesselin Atanasov vesselin@bgnet.bg
|
||||
Ville Skyttä ville.skytta@iki.fi
|
||||
Vin Shelton acs@alumni.princeton.edu
|
||||
Vincent Lefevre vincent@vinc17.net
|
||||
Vineet Chadha chadha@acis.ufl.edu
|
||||
Vitali Lovich vlovich@gmail.com
|
||||
Vitaly A. Ostanin vyt@altlinux.org
|
||||
Vito Caputo vcaputo@pengaru.com
|
||||
Vlada Macek tuttle@bbs.fsik.cvut.cz
|
||||
Volker Borchert bt@teknon.de
|
||||
Volker Paul vpaul@dohle.com
|
||||
Wartan Hachaturow wart@tepkom.ru
|
||||
Wayne Stewart wstewa@atl.com
|
||||
Wenjun Zheng zwj@yahoo.com
|
||||
Werner Almesberger Werner.Almesberger@epfl.ch
|
||||
Wichert Akkerman wichert@cistron.nl
|
||||
Wieland Hoffmann themineo@gmail.com
|
||||
Will Edgington wedgingt@acm.org
|
||||
William Bader william@nscs.fast.net
|
||||
William Dowling will@franklin.com
|
||||
William Lewis wiml@omnigroup.com
|
||||
William R. Fraser wfraser@codewise.org
|
||||
wiregauze wiregauze@yahoo.com
|
||||
Wis Macomson wis.macomson@intel.com
|
||||
Wodry coreutils3422@runbox.com
|
||||
Wojciech Purczynski cliph@isec.pl
|
||||
Wolfram Kleff kleff@cs.uni-bonn.de
|
||||
Won-kyu Park wkpark@chem.skku.ac.kr
|
||||
Xu Zhongxing xu_zhong_xing@163.com
|
||||
Yang Ren ryang@redhat.com
|
||||
Yanko Kaneti yaneti@declera.com
|
||||
Yann Dirson dirson@debian.org
|
||||
Yigal Korman yigal@plexistor.com
|
||||
Youngjun Song mastojun@gmail.com
|
||||
Yunlian Jiang yunlian@chromium.org
|
||||
Yurij Goncharuk lnkgyv@gmail.com
|
||||
Yury Usishchev y.usishchev@samsung.com
|
||||
Yutaka Amanai yasai-itame1942@jade.plala.or.jp
|
||||
Zartaj Majeed zmajeed@sbcglobal.net
|
||||
Zooko zookog@gmail.com
|
||||
Zorro Lang zlang@redhat.com
|
||||
Zvi Har'El rl@math.technion.ac.il
|
||||
|
||||
;; Local Variables:
|
||||
;; coding: utf-8
|
||||
;; End:
|
49
THANKS-to-translators
Normal file
49
THANKS-to-translators
Normal file
|
@ -0,0 +1,49 @@
|
|||
The following teams have translated the many diagnostics of this
|
||||
package into many different languages. Thank you!
|
||||
|
||||
---
|
||||
https://translationproject.org/team/af.html
|
||||
https://translationproject.org/team/be.html
|
||||
https://translationproject.org/team/bg.html
|
||||
https://translationproject.org/team/ca.html
|
||||
https://translationproject.org/team/cs.html
|
||||
https://translationproject.org/team/da.html
|
||||
https://translationproject.org/team/de.html
|
||||
https://translationproject.org/team/el.html
|
||||
https://translationproject.org/team/eo.html
|
||||
https://translationproject.org/team/es.html
|
||||
https://translationproject.org/team/et.html
|
||||
https://translationproject.org/team/eu.html
|
||||
https://translationproject.org/team/fi.html
|
||||
https://translationproject.org/team/fr.html
|
||||
https://translationproject.org/team/ga.html
|
||||
https://translationproject.org/team/gl.html
|
||||
https://translationproject.org/team/hr.html
|
||||
https://translationproject.org/team/hu.html
|
||||
https://translationproject.org/team/ia.html
|
||||
https://translationproject.org/team/id.html
|
||||
https://translationproject.org/team/it.html
|
||||
https://translationproject.org/team/ja.html
|
||||
https://translationproject.org/team/ka.html
|
||||
https://translationproject.org/team/kk.html
|
||||
https://translationproject.org/team/ko.html
|
||||
https://translationproject.org/team/lg.html
|
||||
https://translationproject.org/team/lt.html
|
||||
https://translationproject.org/team/ms.html
|
||||
https://translationproject.org/team/nb.html
|
||||
https://translationproject.org/team/nl.html
|
||||
https://translationproject.org/team/pl.html
|
||||
https://translationproject.org/team/pt.html
|
||||
https://translationproject.org/team/pt_BR.html
|
||||
https://translationproject.org/team/ro.html
|
||||
https://translationproject.org/team/ru.html
|
||||
https://translationproject.org/team/sk.html
|
||||
https://translationproject.org/team/sl.html
|
||||
https://translationproject.org/team/sr.html
|
||||
https://translationproject.org/team/sv.html
|
||||
https://translationproject.org/team/ta.html
|
||||
https://translationproject.org/team/tr.html
|
||||
https://translationproject.org/team/uk.html
|
||||
https://translationproject.org/team/vi.html
|
||||
https://translationproject.org/team/zh_CN.html
|
||||
https://translationproject.org/team/zh_TW.html
|
679
THANKS.in
Normal file
679
THANKS.in
Normal file
|
@ -0,0 +1,679 @@
|
|||
These people have contributed to the GNU coreutils (formerly, the fileutils,
|
||||
textutils, and/or sh-utils packages). Some have reported problems, others
|
||||
have contributed improvements to the documentation, actual code, and even
|
||||
complete programs. Those contributions are described in the version control
|
||||
logs and ChangeLog files. If your name has been left out, if you'd rather
|
||||
not be listed, or if you'd prefer a different address be used, please send a
|
||||
note to the GNU coreutils mailing list <coreutils@gnu.org>.
|
||||
##
|
||||
## There is no need to list here any name that appears as an Author in
|
||||
## "git log" output. Those are automatically added when this template
|
||||
## is used to generate the THANKS file. Note that numerous people listed
|
||||
## here would have been listed as commit authors if we had been using git
|
||||
## for version control when they contributed.
|
||||
##
|
||||
## Let's keep the list in this order ... which sc_THANKS_in_sorted ensures:
|
||||
## $ LC_ALL=en_US.UTF-8 src/sort -f -k1,1
|
||||
|
||||
??? kytek@cybercomm.net
|
||||
A Costa agcosta@gis.net
|
||||
Aaron Davies aaron.davies@gmail.com
|
||||
Aaron Hawley ashawley@uvm.edu
|
||||
Achim Blumensath blume@corona.oche.de
|
||||
Adam Jimerson vendion@charter.net
|
||||
Adam Klein aklein@debian.org
|
||||
Adam Sampson ats@offog.org
|
||||
Adrian Bunk bunk@stusta.de
|
||||
AIDA Shinra shinra@j10n.org
|
||||
Alain Magloire alain@qnx.com
|
||||
Alan Iwi iwi@atm.ox.ac.uk
|
||||
Alan Jenkins alan-jenkins@tuffmail.co.uk
|
||||
Albert Chin-A-Young china@thewrittenword.com
|
||||
Albert Hopkins ahopkins@dynacare.com
|
||||
Alberto Accomazzi alberto@cfa0.harvard.edu
|
||||
aldomel aldomel@ix.netcom.com
|
||||
Alen Muzinic zveki@fly.cc.fer.hr
|
||||
Alexander Nguyen vinh@seas.ucla.edu
|
||||
Alexander V. Lukyanov lav@netis.ru
|
||||
Alexandre Duret-Lutz duret_g@epita.fr
|
||||
Alexey Solovyov alekso@math.uu.se
|
||||
Alexey Vyskubov alexey@pippuri.mawhrin.net
|
||||
Alfred M. Szmidt ams@kemisten.nu
|
||||
Allen Hewes allen@decisiv.net
|
||||
Ambrose Feinstein ambrose@google.com
|
||||
Amr Ali amr.ali.cc@gmail.com
|
||||
Anders Kaseorg andersk@mit.edu
|
||||
Andi Kleen freitag@alancoxonachip.com
|
||||
Andre Novaes Cunha Andre.Cunha@br.global-one.net
|
||||
Andreas Frische andreasfrische@gmail.com
|
||||
Andreas Jaeger jaeger@gnu.org
|
||||
Andreas Luik luik@isa.de
|
||||
Andreas Stolcke stolcke@ICSI.Berkeley.EDU
|
||||
Andrei Gaponenko andr@triumf.ca
|
||||
Andres Soolo andres@soolo.matti.ee
|
||||
Andrew Burgess aab@cichlid.com
|
||||
Andrew Dalke dalke@bioreason.com
|
||||
Andrew Fabbro andrew@fabbro.org
|
||||
Andrew Pham andpha@us.ibm.com
|
||||
Andrew Tridgell tridge@samba.org
|
||||
Andrey Borzenkov arvidjaar@mail.ru
|
||||
Andries Brouwer Andries.Brouwer@cwi.nl
|
||||
Andy Longton alongton@metamark.com
|
||||
Anoop Sharma sendtoanoop@gmail.com
|
||||
Anthony Thyssen anthony@griffith.edu.au
|
||||
Antonio Rendas ajrendas@yahoo.com
|
||||
Ariel Faigon ariel@cthulhu.engr.sgi.com
|
||||
Arjan Opmeer arjan.opmeer@gmail.com
|
||||
Arkadiusz Miśkiewicz arekm@maven.pl
|
||||
Arne Henrik Juul arnej@imf.unit.no
|
||||
Arnold Robbins arnold@skeeve.com
|
||||
Arthur Pool pool@commerce.uq.edu.au
|
||||
Arun Sharma arun.sharma@intel.com
|
||||
Arvind Autar Autar022@planet.nl
|
||||
Augey Mikus mikus@dqc.org
|
||||
Austin Donnelly Austin.Donnelly@cl.cam.ac.uk
|
||||
Axel Dörfler axeld@pinc-software.de
|
||||
Axel Kittenberger Anshil@gmx.net
|
||||
Barry Kelly http://blog.barrkel.com/
|
||||
Bauke Jan Douma bjdouma@xs4all.nl
|
||||
Ben Elliston bje@air.net.au
|
||||
Ben Harris bjh21@netbsd.org
|
||||
Bengt Martensson bengt@mathematik.uni-Bremen.de
|
||||
Benjamin Cutler cutlerbc@simla.colostate.edu
|
||||
Bernard Giroud bernard.giroud@creditlyonnais.ch
|
||||
Bernd Eckenfels ecki@debian.org
|
||||
Bernd Leibing bernd.leibing@rz.uni-ulm.de
|
||||
Bernd Melchers melchers@cis.fu-berlin.de
|
||||
Bernhard Baehr bernhard.baehr@gmx.de
|
||||
Bernhard Gabler bernhard@uni-koblenz.de
|
||||
Bernhard Rosenkraenzer bero@redhat.de
|
||||
Bert Deknuydt Bert.Deknuydt@esat.kuleuven.ac.be
|
||||
Bert Wesarg bert.wesarg@googlemail.com
|
||||
Bill Brelsford wb@k2di.net
|
||||
Bill Peters peters@gaffel.as.arizona.edu
|
||||
Bjorn Helgaas helgaas@rsn.hp.com
|
||||
Bob McCracken kerouac@ravenet.com
|
||||
Branden Robinson branden@necrotic.deadbeast.net
|
||||
Brendan O'Dea bod@compusol.com.au
|
||||
Brian Foster bfoster@redhat.com
|
||||
Brian Kimball bfk@footbag.org
|
||||
Brian M. Carlson sandals@crustytoothpaste.ath.cx
|
||||
Brian Silverman bsilverman@conceptxdesign.com
|
||||
Brian Youmans 3diff@gnu.org
|
||||
Britton Leo Kerin fsblk@aurora.uaf.edu
|
||||
Bruce Robertson brucer@theodolite.dyndns.org
|
||||
Brynnen Owen owen@illinois.edu
|
||||
Carl Johnson carlj@cjlinux.home.org
|
||||
Carl Lowenstein cdl@mpl.UCSD.EDU
|
||||
Carl Roth roth@urs.us
|
||||
Carlos Canau Carlos.Canau@relay.puug.pt
|
||||
Charles Karney karney@pppl.gov
|
||||
Charles Randall crandall@matchlogic.com
|
||||
Chas. Owens chas.owens@gmail.com
|
||||
Chip Salzenberg chip@valinux.com
|
||||
Choi Jongu zoopi01@gmail.com
|
||||
Chris Clayton chris2553@googlemail.com
|
||||
Chris Faylor cgf@cygnus.com
|
||||
Chris J. Bednar cjb@AdvancedDataSolutions.com
|
||||
Chris Jones cjns1989@gmail.com
|
||||
Chris Lesniewski ctl@mit.edu
|
||||
Chris Sylvain csylvain@umm.edu
|
||||
Chris Yeo cyeo@biking.org
|
||||
Christi Alice Scarborough christi@chiark.greenend.org.uk
|
||||
Christian Harkort christian.harkort@web.de
|
||||
Christian Jullien eligis@orange.fr
|
||||
Christian Krackowizer ckrackowiz@std.schuler-ag.com
|
||||
Christian Rose menthos@menthos.com
|
||||
Christian von Roques roques@pond.sub.org
|
||||
Christophe LYON christophe.lyon@st.com
|
||||
Chuck Hedrick hedrick@klinzhai.rutgers.edu
|
||||
Chusslove Illich caslav.ilic@gmx.net
|
||||
Clark Morgan cmorgan@aracnet.com
|
||||
Clement Wang clem.wang@overture.com
|
||||
Colin Plumb colin@nyx.net
|
||||
Collin Rogowski collin@rogowski.de
|
||||
Cray-Cyber Project https://www.cray-cyber.org
|
||||
Cristian Cadar cristic@stanford.edu
|
||||
Cyril Bouthors cyril@bouthors.org
|
||||
Dale Scheetz dwarf@polaris.net
|
||||
Dameon G. Rogers dgr03@uark.edu
|
||||
Dan Hagerty hag@gnu.ai.it.edu
|
||||
Dan Pascu dan@services.iiruc.ro
|
||||
Daniel Bergstrom noa@melody.se
|
||||
Daniel Carpenter dansebpub@gmail.com
|
||||
Daniel Mach dmach@redhat.com
|
||||
Daniel P. Berrangé berrange@redhat.com
|
||||
Daniel Stavrovski d@stavrovski.net
|
||||
Daniel Tschinder daniel.tschinder@project-a.com
|
||||
Dániel Varga danielv@axelero.hu
|
||||
Danny Levinson danny.levinson@overture.com
|
||||
Darrel Francis d.francis@cheerful.com
|
||||
Darren Salt ds@youmustbejoking.demon.co.uk
|
||||
Dave Beckett dajobe@dajobe.org
|
||||
David Alan Gilbert gilbertd@treblig.org
|
||||
David Diggles david.diggles@dnrm.qld.gov.au
|
||||
David Dyck dcd@tc.fluke.COM
|
||||
David Eisner cradle@umd.edu
|
||||
David Flynn dav@chess.plus.com
|
||||
David Gast dgast@csulb.edu
|
||||
David Godfrey dave@delta.demon.co.uk
|
||||
David Luyer david_luyer@pacific.net.au
|
||||
David Madore david.madore@ens.fr
|
||||
David Malone dwmalone@cnri.dit.ie
|
||||
David Matei matei@cs.toronto.edu
|
||||
David Pinto carandraug+dev@gmail.com
|
||||
Davide Canova kc.canova@gmail.com
|
||||
Dawson Engler engler@stanford.edu
|
||||
Dean Gaudet dean-savannah@arctic.org
|
||||
Deepak Goel deego@gnufans.org
|
||||
Denis Excoffier gcc@Denis-Excoffier.org
|
||||
Denis McKeon dmckeon@swcp.com
|
||||
Dennis Clarke dclarke@blastwave.org
|
||||
Dennis Henriksen opus@flamingo.osrl.dk
|
||||
Dennis Smit ds@nerds-incorporated.org
|
||||
Derek Clegg dclegg@next.com
|
||||
Dick Streefland dick_streefland@tasking.com
|
||||
Dirk Lattermann dlatt@t-online.de
|
||||
Dirk-Jan Faber djfaber@snow.nl
|
||||
Dmitry Rutsky rutsky@school.ioffe.rssi.ru
|
||||
Don Parsons dparsons@synapse.kent.edu
|
||||
Donni Erpel donald@appc11.gsi.de
|
||||
Doug Coleman coleman@iarc1.ece.utexas.edu
|
||||
Doug McLaren dougmc@comco.com
|
||||
Dragos Harabor dharabor@us.oracle.com
|
||||
Duncan Roe duncanr@optimation.com.au
|
||||
Edward Schwartz edmcman@cmu.edu
|
||||
Edzer Pebesma Edzer.Pebesma@rivm.nl
|
||||
Egmont Koblinger egmont@uhulinux.hu
|
||||
Eirik Fuller eirik@hackrat.com
|
||||
Eivind eivindt@multinet.no
|
||||
Elbert Pol elbert.pol@gmail.com
|
||||
Eldon Stegall eldon@eldondev.com
|
||||
Eli Zaretskii eliz@is.elta.co.il
|
||||
Emanuel Landeholm emanuel.landeholm@gmail.com
|
||||
Emile LeBlanc leblanc@math.toronto.edu
|
||||
Emmanuel Lacour elacour@home-dn.net
|
||||
Eric Backus ericb@lsid.hp.com
|
||||
Eric Bergen eric.bergen@gmail.com
|
||||
Eric G. Miller egm2@jps.net
|
||||
Eric Pemente pemente@northpark.edu
|
||||
Eric S. Raymond esr@snark.thyrsus.com
|
||||
Erik Bennett bennett@cvo.oneworld.com
|
||||
Erik Bernstein erik@fscking.org
|
||||
Erik Corry erik@kroete2.freinet.de
|
||||
Felix Lee flee@teleport.com
|
||||
Felix Rauch Valenti frauch@cse.unsw.edu.au
|
||||
Ferdinand fw@scenic.mine.nu
|
||||
Fletcher Mattox fletcher@cs.utexas.edu
|
||||
Florent Bayle florent@sarcelle.net
|
||||
Florian Schlichting fschlich@cis.fu-berlin.de
|
||||
Florin Iucha fiucha@hsys.mic.ro
|
||||
Francesco Montorsi fr_m@hotmail.com
|
||||
François Pinard pinard@iro.umontreal.ca
|
||||
François Rigault rigault.francois@gmail.com
|
||||
Frank Adler fadler@allesklar.de
|
||||
Frank Busse f.busse@imperial.ac.uk
|
||||
Frank T Lofaro ftlofaro@snooks.Egr.UNLV.EDU
|
||||
Fred Fish fnf@ninemoons.com
|
||||
Frédéric L. W. Meunier 0@pervalidus.net
|
||||
Frederik Eaton frederik@caltech.edu
|
||||
Gabor Z. Papp gzp@gzp.org.hu
|
||||
Gaël Quéri gqueri@mail.dotcom.fr
|
||||
Galen Hazelwood galenh@micron.net
|
||||
Gary Anderson ganderson@clark.net
|
||||
Gary Johnson garyjohn@spk.agilent.com
|
||||
Gary V. Vaughan gary@gnu.org
|
||||
Gaute Hvoslef Kvalnes gaute@verdsveven.com
|
||||
Geoff Collyer geoff at collyer.net
|
||||
Geoff Kuenning geoff@cs.hmc.edu
|
||||
Geoff Odhner geoff@franklin.com
|
||||
Geoff Whale geoffw@cse.unsw.EDU.AU
|
||||
Gerald Pfeifer gerald@pfeifer.com
|
||||
Gerhard Poul gpoul@gnu.org
|
||||
Germano Leichsenring germano@jedi.cs.kobe-u.ac.jp
|
||||
Glen Lenker glen.lenker@gmail.com
|
||||
Glenn Golden gdg@zplane.com
|
||||
GOTO Masanori gotom@debian.or.jp
|
||||
Greg Louis glouis@dynamicro.on.ca
|
||||
Greg McGary gkm@gnu.org
|
||||
Greg Metcalfe metcalfegreg@qwest.net
|
||||
Greg Schafer gschafer@zip.com.au
|
||||
Greg Troxel gdt@bbn.com
|
||||
Gregory Leblanc gleblanc@cu-portland.edu
|
||||
Guido Leenders guido.leenders@invantive.com
|
||||
Guntram Blohm Extern.Guntram.Blohm@AUDI.DE
|
||||
Guochun Shi gshi@ncsa.uiuc.edu
|
||||
H. J. Lu hjl@valinux.com
|
||||
Hans Ginzel hans@matfyz.cz
|
||||
Hans Lermen lermen@fgan.de
|
||||
Hans Verkuil hans@wyst.hobby.nl
|
||||
Harald Dunkel harald.dunkel@t-online.de
|
||||
Harry Liu rliu@lek.ugcs.caltech.edu
|
||||
Harti Brandt brandt@fokus.fraunhofer.de
|
||||
Harvey Eneman Harvey.Eneman@oracle.com
|
||||
Heiko Marr h.marr@webmasters.de
|
||||
Helen Faulkner helen_ml_faulkner@yahoo.co.uk
|
||||
Herbert Xu herbert@gondor.apana.org.au
|
||||
Holger Berger hberger@ess.nec.de
|
||||
Hon-Yin Kok hkok@yoda.unl.edu
|
||||
Hugh Daniel hugh@xanadu.com
|
||||
Iain Calder ic56@rogers.com
|
||||
Ian Bruce ian.bruce@myrealbox.com
|
||||
Ian Jackson ijackson@chiark.greenend.org.uk
|
||||
Ian Kent ikent@redhat.com
|
||||
Ian Lance Taylor ian@cygnus.com
|
||||
Ian Turner vectro@pipeline.com
|
||||
Iida Yosiaki iida@gnu.org
|
||||
Illia Bobyr ibobyr@google.com
|
||||
Ilya N. Golubev gin@mo.msk.ru
|
||||
Ingo Saitz ingo@debian.org
|
||||
Ivan Labath labath3@st.fmph.uniba.sk
|
||||
Ivo Timmermans ivo@debian.org
|
||||
Jack Howarth howarth.mailing.lists@gmail.com
|
||||
Jacky Fong jacky.fong@utoronto.ca
|
||||
James Antill jmanti%essex.ac.uk@seralph21.essex.ac.uk
|
||||
James Hunt jamesodhunt@hotmail.com
|
||||
James james@albion.glarp.com
|
||||
James Lemley James.Lemley@acxiom.com
|
||||
James Ralston ralston@pobox.com
|
||||
James Sneeringer jvs@ocslink.com
|
||||
James Tanis jtt@soscorp.com
|
||||
Jamie Lokier jamie@imbolc.ucc.ie
|
||||
Jamie McClelland jm@mayfirst.org
|
||||
Jan Engelhardt jengelh@medozas.de
|
||||
Jan Fedak J.Fedak@sh.cvut.cz
|
||||
Jan Moringen jan.moringen@uni-bielefeld.de
|
||||
Janos Farkas chexum@shadow.banki.hu
|
||||
Jan-Pawel Wrozstinski jpwroz@gmail.com
|
||||
Jari Aalto jari.aalto@cante.net
|
||||
Jarkko Hietaniemi jhi@epsilon.hut.fi
|
||||
Jarod Wilson jwilson@redhat.com
|
||||
Jason Smith jasonmsmith@google.com
|
||||
Jean Charles Delepine delepine@u-picardie.fr
|
||||
Jean-Pierre Tosoni jpt.7196@gmail.com
|
||||
Jeff Moore jbm@mordor.com
|
||||
Jeff Sheinberg jeff@bsrd.net
|
||||
Jens Elkner elkner@imsgroup.de
|
||||
Jens Schmidt jms@jsds.hamburg.com
|
||||
Jeph Cowan jeph@ucar.edu
|
||||
Jeremy Maitin-Shepard jbms@cmu.edu
|
||||
Jérémy Magrin jeremy.magrin@epitech.eu
|
||||
Jerome Abela abela@hsc.fr
|
||||
Jérôme Zago bug-coreutils-ml@agt-the-walker.net
|
||||
Jesse Kornblum kornblum@usna.edu
|
||||
Jesse Thilo jgt2@eecs.lehigh.edu
|
||||
Jie Xu xuj@iag.net
|
||||
Jim Blandy jimb@cyclic.com
|
||||
Jim Dennis jimd@starshine.org
|
||||
Jirka Hladky jhladky@redhat.com
|
||||
Joakim Rosqvist dvljrt@cs.umu.se
|
||||
Jochen Hein jochen@jochen.org
|
||||
Joe Orton joe@manyfish.co.uk
|
||||
Joerg Sonnenberger joerg@britannica.bec.de
|
||||
Joey Hess joeyh@debian.org
|
||||
Johan Boule bohan@bohan.dyndns.org
|
||||
Johan Danielsson joda@pdc.kth.se
|
||||
Johannes Altmanninger aclopte@gmail.com
|
||||
John Bley jbb6@acpub.duke.edu
|
||||
John Gatewood Ham zappaman@alphabox.compsci.buu.ac.th
|
||||
John Gotts jgotts@umich.edu
|
||||
John Kendall kendall@capps.com
|
||||
John Kodis kodis@acm.org
|
||||
John Murphy jam@philabs.research.philips.com
|
||||
John Roll john@panic.harvard.edu
|
||||
John Salmon johns@mullet.anu.edu.au
|
||||
John Stanley johnstops@verizon.net
|
||||
John Summerfield summer@OS2.ami.com.au
|
||||
Jon Peatfield J.S.Peatfield@damtp.cam.ac.uk
|
||||
Joost van Baal joostvb@xs4all.nl
|
||||
Jordi Pujol jordipujolp@gmail.com
|
||||
Jorge Stolfi stolfi@ic.unicamp.br
|
||||
Joseph D. Wagner joe@josephdwagner.info
|
||||
Joseph S. Myers jsm28@cam.ac.uk
|
||||
Josh Triplett josh@freedesktop.org
|
||||
Joshua Hudson joshudson@gmail.com
|
||||
Josselin Mouette joss@debian.org
|
||||
Juan F. Codagnone juam@arnet.com.ar
|
||||
Juan M. Guerrero st001906@hrz1.hrz.tu-darmstadt.de
|
||||
Julian Bradfield jcb@inf.ed.ac.uk
|
||||
Julian Büning julian.buening@rwth-aachen.de
|
||||
Jungshik Shin jshin@pantheon.yale.edu
|
||||
Juraj Marko jmarko@redhat.com
|
||||
Jürgen Fluk louis@dachau.marco.de
|
||||
Jurriaan thunder7@xs4all.nl
|
||||
Justin Pryzby justinpryzby@users.sourceforge.net
|
||||
jvogel jvogel@linkny.com
|
||||
Kai Henningsen kai@debian.org
|
||||
Kai-Uwe Rommel rommel@informatik.tu-muenchen.de
|
||||
Kalle Olavi Niemitalo kon@iki.fi
|
||||
Kamal Paul Nigam Kamal_Paul_Nigam@gs35.sp.cs.cmu.edu
|
||||
Karl Eichwalder keichwa@gmx.net
|
||||
Karl-Michael Schneider schneide@phil.uni-passau.de
|
||||
Karsten Thygesen karthy@kom.auc.dk
|
||||
Kaveh R. Ghazi ghazi@caip.rutgers.edu
|
||||
Keith M. Briggs keith.briggs@bt.com
|
||||
Keith Owens kaos@audio.apana.org.au
|
||||
Keith Thompson Keith.S.Thompson@gmail.com
|
||||
Ken Irving ken.irving@alaska.edu
|
||||
Ken Pizzini kenp@halcyon.com
|
||||
Kevin Mudrick kmudrick@healthmarketscience.com
|
||||
Kirk Kelsey kirk.kelsey@0x4b.net
|
||||
Kjetil Torgrim Homme kjetilho@ifi.uio.no
|
||||
Konrad Wróblewski coni@o2.pl
|
||||
Kristin E Thomas kristint@us.ibm.com
|
||||
Kristoffer Rose kris@diku.dk
|
||||
Ladislav Hagara ladislav.hagara@unob.cz
|
||||
Larry McVoy lm@sgi.com
|
||||
Lars Hecking lhecking@nmrc.ucc.ie
|
||||
Leah Q eequor@earthlink.net
|
||||
Lehti Rami rammer@cs.tut.fi
|
||||
Leonard N. Zubkoff lnz@dandelion.com
|
||||
Leonardo Milano lmilano@udel.edu
|
||||
Lluís Batlle viriketo@gmail.com
|
||||
Lorne Baker lbaker@nitro.avint.net
|
||||
Luke Hassell lukehassell@yahoo.com
|
||||
Luke Kendall lukekendall@optushome.com.au
|
||||
M. P. Suzuki mpsuzuki@hiroshima-u.ac.jp
|
||||
Maciej Kwapulinski pikpok@univ.gda.pl
|
||||
Manas Garg manas@cygsoft.com
|
||||
Manfred Hollstein manfred@s-direktnet.de
|
||||
Marc Boucher marc@mbsi.ca
|
||||
Marc Haber mh+debian-bugs@zugschlus.de
|
||||
Marc Lehman schmorp@schmorp.de
|
||||
Marc Mengel mengel@fnal.gov
|
||||
Marc Olzheim marcolz@stack.nl
|
||||
Marcel Böhme https://www.comp.nus.edu.sg/~mboehme
|
||||
Marco Franzen Marco.Franzen@Thyron.com
|
||||
Marcus Brinkmann https://www.marcus-brinkmann.de
|
||||
Marcus Daniels marcus@ee.pdx.edu
|
||||
Mark A. Thomas thommark@access.digex.net
|
||||
Mark Conty Mark_Conty@cargill.com
|
||||
Mark D. Roth roth@uiuc.edu
|
||||
Mark Funkenhauser mfunkenhauser@rogers.com
|
||||
Mark Harris mark@monitor.designacc.com
|
||||
Mark Hewitt mhewitt@armature.com
|
||||
Mark Hounschell markh@compro.net
|
||||
Mark Hubbart discord@mac.com
|
||||
Mark Kettenis kettenis@phys.uva.nl
|
||||
Mark Korenberg socketpair@gmail.com
|
||||
Mark Melahn mmelahn@gmail.com
|
||||
Mark Nudelman marknu@flash.net
|
||||
Mark W. Eichin eichin@cygnus.com
|
||||
Markus Demleitner msdemlei@auriga.ari.uni-heidelberg.de
|
||||
Martin Buck martin.buck@ascom.ch
|
||||
Martin Gallant martyg@goodbit.net
|
||||
Martin Hippe martin.hippe@schlund.de
|
||||
Martin Jacobs martin.jacobs@arcor.de
|
||||
Martin martin@dresden.nacamar.de
|
||||
Martin Michlmayr tbm@cyrius.com
|
||||
Martin Mitchell martin@debian.org
|
||||
Martin P.J. Zinser zinser@decus.de
|
||||
Marty Leisner leisner@sdsp.mc.xerox.com
|
||||
Masami Takikawa takikawm@CS.ORST.EDU
|
||||
Mate Wierdl mw@moni.msci.memphis.edu
|
||||
Matej Vela mvela@public.srce.hr
|
||||
Matheus Afonso Martins Moreira matheus.a.m.moreira@gmail.com
|
||||
Mathias Brodala info@noctus.net
|
||||
Matias A. Fonzo selk@dragora.org
|
||||
Matt Kraai kraai@ftbfs.org
|
||||
Matt McCutchen matt@mattmccutchen.net
|
||||
Matt Perry matt@primefactor.com
|
||||
Matt Pham mattvpham@gmail.com
|
||||
Matt Schalit mschalit@pacbell.net
|
||||
Matt Swift swift@alum.mit.edu
|
||||
Matthew Arnison maffew@cat.org.au
|
||||
Matthew Braun matthew@ans.net
|
||||
Matthew Clarke Matthew_Clarke@mindlink.bc.ca
|
||||
Matthew M. Boedicker matthewm@boedicker.org
|
||||
Matthew Pfeiffer spferical@gmail.com
|
||||
Matthew S. Levine mslevine@theory.lcs.mit.edu
|
||||
Matthew Smith matts@bluesguitar.org
|
||||
Matthew Swift swift@alum.mit.edu
|
||||
Matthias Urlichs smurf@noris.de
|
||||
Matti Aarnio matti.aarnio@zmailer.org
|
||||
Mattias Wadenstein maswan@acc.umu.se
|
||||
Max Chang maxchang@ucla.edu
|
||||
Meelis Roos mroos@tartu.cyber.ee
|
||||
Michael Bacarella mbac@netgraft.com
|
||||
Michael Deutschmann michael@talamasca.ocis.net
|
||||
Michael Elizabeth Chastain mec.gnu@mindspring.com
|
||||
Michael Gaughen mgaughen@polyserve.com
|
||||
Michael Hasselberg mikelh@zonta.ping.de
|
||||
Michael Hohn hohn@math.utah.edu
|
||||
Michael J. Croghan mcroghan@usatoday.com
|
||||
Michael J. Daniel michael.j.daniel@comcast.net
|
||||
Michael McFarland sidlon@yahoo.com
|
||||
Michael McLagan mmclagan@invlogic.com
|
||||
Michael michael@aplatform.com
|
||||
Michael ??? michael@roka.net
|
||||
Michael Mol mikemol@gmail.com
|
||||
Michael Piefel piefel@informatik.hu-berlin.de
|
||||
Michael Price mprice@atl.lmco.com
|
||||
Michael Steffens michael.steffens@s.netic.de
|
||||
Michael Stummvoll michael@stummi.org
|
||||
Michael Stutz stutz@dsl.org
|
||||
Michael van Elst mlelstv@dev.de.cw.net
|
||||
Michael Veksler mveksler@techunix.technion.ac.il
|
||||
Michail Litvak mci@owl.openwall.com
|
||||
Michal Politowski mpol@charybda.icm.edu.pl
|
||||
Michal Svec msvec@suse.cz
|
||||
Michal Trunecka mtruneck@redhat.com
|
||||
Michel Robitaille robitail@IRO.UMontreal.CA
|
||||
Michiel Bacchiani bacchian@raven.bu.edu
|
||||
Mike Castle dalgoda@ix.netcom.com
|
||||
Mike Coleman mkc@mathdogs.com
|
||||
Mike Jetzer mjetzer@mke.catalystwms.com
|
||||
Mikko Tuumanen m@sorvankyla.yok.utu.fi
|
||||
Mikulas Patocka mikulas@artax.karlin.mff.cuni.cz
|
||||
Miles Bader miles@gnu.ai.mit.edu
|
||||
Minh Tran-Le tranle@intellicorp.com
|
||||
Morten Welinder terra@diku.dk
|
||||
Nao Nishijima nao.nishijima.xt@hitachi.com
|
||||
Neal H Walfield neal@cs.uml.edu
|
||||
Neil F. Brown neilb@suse.de
|
||||
Nelson H. F. Beebe beebe@math.utah.edu
|
||||
Nick Estes debian@nickstoys.com
|
||||
Nick Graham nick.d.graham@gmail.com
|
||||
Nick Lawes nlawes@silverplatter.com
|
||||
Nickolai Zeldovich nickolai@cs.stanford.edu
|
||||
Nicolas François nicolas.francois@centraliens.net
|
||||
Niklas Edmundsson nikke@acc.umu.se
|
||||
Nikola Milutinovic Nikola.Milutinovic@ev.co.yu
|
||||
Nikolaus Rath Nikolaus@rath.org
|
||||
Nikos Mavrogiannopoulos nmav@redhat.com
|
||||
Nima Nikzad nnikzad@ucla.edu
|
||||
Noah Friedman friedman@splode.com
|
||||
Noel Cragg noel@red-bean.com
|
||||
Norbert Kiesel nkiesel@tbdnetworks.com
|
||||
Norihiro Kamae norihiro@nagater.net
|
||||
Olatunji Oluwabukunmi Ruwase tjruwase@stanford.edu
|
||||
Olav Morkrid olav@funcom.com
|
||||
Ole Laursen olau@hardworking.dk
|
||||
Oliver Kiddle okiddle@yahoo.co.uk
|
||||
Olivier Fourdan ofourdan@redhat.com
|
||||
Ørn E. Hansen oehansen@daimi.aau.dk
|
||||
Oskar Liljeblad osk@hem.passagen.se
|
||||
Otavio Salvador otavio@ossystems.com.br
|
||||
Patrick Mauritz oxygene@studentenbude.ath.cx
|
||||
Paul D. Smith psmith@gnu.org
|
||||
Paul Ghaleb paul.ghaleb@st.com
|
||||
Paul Jarc prj@po.cwru.edu
|
||||
Paul Marinescu paul.marinescu@imperial.ac.uk
|
||||
Paul Nevai nevai@ops.mps.ohio-state.edu
|
||||
Paul Sauer paul@alexa.com
|
||||
Paul Slootman paul@debian.org
|
||||
Paul Townsend aab@purdue.edu
|
||||
Paul Worrall paul@basilisk.uklinux.net
|
||||
Pawel Prokop pablo@wizard.ae.krakow.pl
|
||||
Peng Yu pengyu.ut@gmail.com
|
||||
Per Cederqvist ceder@lysator.liu.se
|
||||
Per Kristian Hove perhov@math.ntnu.no
|
||||
Per Starbäck starback@stp.lingfil.uu.se
|
||||
Peter Breitenlohner peb@mppmu.mpg.de
|
||||
Peter Dyballa peter_dyballa@web.de
|
||||
Peter Eriksson peter@ifm.liu.se
|
||||
Peter Evans peter@ixp.jp
|
||||
Peter Horst peter@ointment.org
|
||||
Peter Moulder reiter@netspace.net.au
|
||||
Peter Samuelson psamuels@sampo.creighton.edu
|
||||
Peter Seebach seebs@taniemarie.solon.com
|
||||
Petr Pisar petr.pisar@atlas.cz
|
||||
Petr Uzel petr.uzel@suse.cz
|
||||
Petter Reinholdtsen pere@hungry.com
|
||||
Phelippe Neveu pneveu@pcigeomatics.com
|
||||
Phil Richards phil.richards@vf.vodafone.co.uk
|
||||
Philipp Gortan gortan@gmail.com
|
||||
Philippe De Muyter phdm@macqel.be
|
||||
Philippe Schnoebelen Philippe.Schnoebelen@imag.fr
|
||||
Phillip Jones mouse@datastacks.com
|
||||
Piergiorgio Sartor sartor@sony.de
|
||||
Pieter Bowman bowman@math.utah.edu
|
||||
Piotr Gackiewicz gacek@intertele.pl
|
||||
Piotr Kwapulinski kwap@univ.gda.pl
|
||||
Prashant TR tr@eth.net
|
||||
Priit Jõerüüt jemm4jemm@yahoo.com
|
||||
Primoz PETERLIN primozz.peterlin@gmail.com
|
||||
Raimonds Miltins raimonds@pro-9.com
|
||||
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
|
||||
Ralf W. Stephan stephan@tmt.de
|
||||
Ralph Loader loader@maths.ox.ac.uk
|
||||
Raul Miller moth@magenta.com
|
||||
Raúl Núñez de Arenas Coronado raul@pleyades.net
|
||||
Rich Burridge rich.burridge@oracle.com
|
||||
Richard A Downing richard.downing@bcs.org.uk
|
||||
Richard Braakman dark@xs4all.nl
|
||||
Richard Dawe rich@phekda.freeserve.co.uk
|
||||
Richard J. Rauenzahn rrauenza@hairball.cup.hp.com
|
||||
Richard Neill rn214@hermes.cam.ac.uk
|
||||
Richard Sharman rsharman@magmacom.com
|
||||
Rick Sladkey jrs@world.std.com
|
||||
Rick Stanley rstanley@rsiny.com
|
||||
Rik Faith faith@cs.unc.edu
|
||||
Risto Kankkunen kankkune@lingsoft.fi
|
||||
Rob Wortman wyrm@haell.com
|
||||
Robert H. de Vries robert@and.nl
|
||||
Robert Lindgren robert@orcafat.com
|
||||
Robert Millan zeratul2@wanadoo.es
|
||||
Robert Schwebel r.schwebel@pengutronix.de
|
||||
Robin H. Johnson robbat2@gentoo.org
|
||||
Rogier Wolff R.E.Wolff@BitWizard.nl
|
||||
Roland Huebner ro-huebner@gmx.de
|
||||
Roland Turner raz.tah.bet@raz.cx
|
||||
Ronald F. Guilmette rfg@netcom.com
|
||||
Ross Alexander r.alexander@auckland.ac.nz
|
||||
Ross Paterson rap@doc.ic.ac.uk
|
||||
Ross Ridge rridge@calum.csclub.uwaterloo.ca
|
||||
Rudolf Kastl rkastl@redhat.com
|
||||
Sahil Amoli sahilamoli@gmail.com
|
||||
Sami Farin sfarin@ratol.fi
|
||||
Samuel Neves sneves@dei.uc.pt
|
||||
Samuel Thibault samuel.thibault@ens-lyon.org
|
||||
Samuli Karkkainen Samuli.Karkkainen@hut.fi
|
||||
Sander van Malssen svm@kozmix.ow.nl
|
||||
Santiago Vila Doncel sanvila@unex.es
|
||||
Savochkin Andrey Vladimirovich saw@msu.ru
|
||||
Scott Harrison scott.gnu.2009@scottrix.co.uk
|
||||
Scott Lurndal slurn@griffin.engr.sgi.com
|
||||
Sébastien Maret smaret@umich.edu
|
||||
Sergei Steshenko sergstesh@yahoo.com
|
||||
Sergey Vlasov vsu@altlinux.org
|
||||
Shing-Shong Shei shei@cs.indiana.edu
|
||||
Soeren Sonnenburg sonnenburg@informatik.hu-berlin.de
|
||||
Solar Designer solar@owl.openwall.com
|
||||
Stanislav Ievlev inger@altlinux.ru
|
||||
Stavros Passas stabat@ics.forth.gr
|
||||
Stefan Vargyas stvar@yahoo.com
|
||||
Stéphane Chazelas Stephane_CHAZELAS@yahoo.fr
|
||||
Stephen Depooter sbdep@myrealbox.com
|
||||
Stephen Eglen eglen@pcg.wustl.edu
|
||||
Stephen Gildea gildea@stop.mail-abuse.org
|
||||
Stephen Shirley kormat@gmail.com
|
||||
Stephen Smoogen smooge@mindspring.com
|
||||
Steve McConnel steve@acadcomp.sil.org
|
||||
Steve McIntyre steve@einval.com
|
||||
Steve Ward planet36@gmail.com
|
||||
Steven Drake sbd@users.sourceforge.net
|
||||
Steven G. Johnson stevenj@alum.mit.edu
|
||||
Steven Mocking ufo@quicknet.nl
|
||||
Steven Parkes smparkes@smparkes.net
|
||||
Steven P Watson steven@magelico.net
|
||||
Steven Schveighoffer schveiguy@yahoo.com
|
||||
Stuart Citrin ctrn3e8@gmail.com
|
||||
Stuart Kemp skemp@peter.bmc.com
|
||||
Stuart Shelton stuart@shelton.me
|
||||
Sven Breuner sven.breuner@itwm.fraunhofer.de
|
||||
Szakacsits Szabolcs szaka@sienet.hu
|
||||
Tadayoshi Funaba tadf@kt.rim.or.jp
|
||||
TAKAI Kousuke takai@vlsi.kuee.kyoto-u.ac.jp
|
||||
The Wanderer inverseparadox@comcast.net
|
||||
Theodore Ts'o tytso@rsts-11.mit.edu
|
||||
Thomas Bushnell thomas@gnu.ai.mit.edu
|
||||
Thomas Goerlich thomas@schnappmatik.de
|
||||
Thomas Hood jdthood@yahoo.co.uk
|
||||
Thomas Luzat thomas@luzat.com
|
||||
Thomas M.Ott thmo-13@gmx.de
|
||||
Thomas Quinot thomas@Cuivre.FR.EU.ORG
|
||||
Thomas Schwinge tschwinge@gnu.org
|
||||
Thomas Wolff mined@towo.net
|
||||
Tim J. Robbins tjr@FreeBSD.org
|
||||
Tim Mooney mooney@dogbert.cc.ndsu.NoDak.edu
|
||||
Tim Ryan Tim_Ryan@bnz.co.nz
|
||||
Tim Smithers mouse@dmouse.com.au
|
||||
Tim Underwood timunderwood@gmail.com
|
||||
Tim Waugh twaugh@redhat
|
||||
Toby Peterson toby@opendarwin.org
|
||||
Todd A. Jacobs tjacobs@codegnome.org
|
||||
Tom Fitzhenry tom@tom-fitzhenry.me.uk
|
||||
Tom Haynes thomas@netapp.com
|
||||
Tom Quinn trq@dionysos.thphys.ox.ac.uk
|
||||
Tomas Pospisek tpo@sourcepole.ch
|
||||
Tommi Kyntola tkyntola@cc.hut.fi
|
||||
Ton Hospel thospel@mail.dma.be
|
||||
Ton Nijkes ton@murphy.nl
|
||||
Tony Kocurko akocurko@mun.ca
|
||||
Tony Leneis tony@plaza.ds.adp.com
|
||||
Tony Robinson ajr@eng.cam.ac.uk
|
||||
Toomas Soome Toomas.Soome@Elion.ee
|
||||
Toralf Förster toralf.foerster@gmx.de
|
||||
Torbjörn Lindgren tl@funcom.no
|
||||
Torsten Landschoff torsten@pclab.ifg.uni-kiel.de
|
||||
Travis Gummels tgummels@redhat.com
|
||||
Tristan Miller psychonaut@nothingisreal.com
|
||||
Tzvi Rotshtein tzvi.ro@gmail.com
|
||||
Ulrich Drepper drepper@gnu.org
|
||||
Ulrich Hermisson ulrich_hermisson@hotmail.com
|
||||
Urs Thuermann urs@isnogud.escape.de
|
||||
Uwe H. Steinfeld usteinfeld@gmx.net
|
||||
Vesselin Atanasov vesselin@bgnet.bg
|
||||
Vin Shelton acs@alumni.princeton.edu
|
||||
Vineet Chadha chadha@acis.ufl.edu
|
||||
Vitali Lovich vlovich@gmail.com
|
||||
Vitaly A. Ostanin vyt@altlinux.org
|
||||
Vito Caputo vcaputo@pengaru.com
|
||||
Vlada Macek tuttle@bbs.fsik.cvut.cz
|
||||
Volker Borchert bt@teknon.de
|
||||
Volker Paul vpaul@dohle.com
|
||||
Wartan Hachaturow wart@tepkom.ru
|
||||
Wayne Stewart wstewa@atl.com
|
||||
Wenjun Zheng zwj@yahoo.com
|
||||
Werner Almesberger Werner.Almesberger@epfl.ch
|
||||
Wichert Akkerman wichert@cistron.nl
|
||||
Will Edgington wedgingt@acm.org
|
||||
William Bader william@nscs.fast.net
|
||||
William Dowling will@franklin.com
|
||||
William Lewis wiml@omnigroup.com
|
||||
wiregauze wiregauze@yahoo.com
|
||||
Wis Macomson wis.macomson@intel.com
|
||||
Wojciech Purczynski cliph@isec.pl
|
||||
Wolfram Kleff kleff@cs.uni-bonn.de
|
||||
Won-kyu Park wkpark@chem.skku.ac.kr
|
||||
Xu Zhongxing xu_zhong_xing@163.com
|
||||
Yang Ren ryang@redhat.com
|
||||
Yanko Kaneti yaneti@declera.com
|
||||
Yann Dirson dirson@debian.org
|
||||
Youngjun Song mastojun@gmail.com
|
||||
Yutaka Amanai yasai-itame1942@jade.plala.or.jp
|
||||
|
||||
;; Local Variables:
|
||||
;; coding: utf-8
|
||||
;; End:
|
4
THANKStt.in
Normal file
4
THANKStt.in
Normal file
|
@ -0,0 +1,4 @@
|
|||
The following teams have translated the many diagnostics of this
|
||||
package into many different languages. Thank you!
|
||||
|
||||
---
|
159
TODO
Normal file
159
TODO
Normal file
|
@ -0,0 +1,159 @@
|
|||
If you're interested in helping, here are some tasks that we've considered
|
||||
over the years. Beware: some are quite old and no longer valid. To avoid
|
||||
wasting your time by duplicating work or by working on a task that is no
|
||||
longer pertinent, please search the mailing list and post your intent
|
||||
before embarking on a big project.
|
||||
|
||||
==================================================
|
||||
Modify chmod so that it does not change an inode's st_ctime
|
||||
when the selected operation would have no other effect.
|
||||
First suggested by Hans Ecke <https://hans.ecke.ws> in
|
||||
https://lists.gnu.org/r/bug-coreutils/2004-09/msg00145.html
|
||||
Discussed more recently on <https://bugs.debian.org/497514>.
|
||||
|
||||
document the following in coreutils.texi:
|
||||
[
|
||||
pinky
|
||||
|
||||
Suggestion from Paul Eggert:
|
||||
More generally, there's not that much use for imaxtostr nowadays,
|
||||
since the inttypes module and newer versions of gettext allow things
|
||||
like _("truncating %s at %jd bytes") to work portably.
|
||||
I suspect that (if someone cares to take the time) we can remove
|
||||
all instances of imaxtostr and umaxtostr in coreutils and gnulib.
|
||||
|
||||
cp --recursive: use fts and *at functions to perform directory traversals
|
||||
in source and destination hierarchy rather than forming full file names.
|
||||
The latter (current) approach fails unnecessarily when the names
|
||||
become very long, and requires space and time that is quadratic in the
|
||||
depth of the hierarchy. [Bo Borgerson is working on this]
|
||||
|
||||
printf:
|
||||
Now that gnulib supports *printf("%a"), import one of the
|
||||
*printf-posix modules so that printf(1) will support %a even on
|
||||
platforms where the native *printf(3) is deficient.
|
||||
Suggestion from Eric Blake.
|
||||
|
||||
consider adding some implementation of the "col" utility
|
||||
Suggested by Karl Berry.
|
||||
|
||||
doc/coreutils.texi:
|
||||
Address this comment: FIXME: mv's behavior in this case is system-dependent
|
||||
Better still: fix the code so it's *not* system-dependent.
|
||||
|
||||
ls: add --format=FORMAT option that controls how each line is printed.
|
||||
|
||||
copy.c: Address the FIXME-maybe comment in copy_internal.
|
||||
And once that's done, add an exclusion so that 'cp --link'
|
||||
no longer incurs the overhead of saving src. dev/ino and dest. filename
|
||||
in the hash table.
|
||||
|
||||
Write an autoconf test to work around build failure in HPUX's 64-bit mode.
|
||||
See notes in README-install -- and remove them once there's a work-around.
|
||||
|
||||
Integrate use of sendfile, suggested here:
|
||||
https://lists.gnu.org/r/bug-fileutils/2003-03/msg00030.html
|
||||
I don't plan to do that, since a few tests demonstrate no significant benefit.
|
||||
|
||||
printf: consider adapting builtins/printf.def from bash
|
||||
|
||||
tail: don't use xlseek; it *exits*.
|
||||
Instead, maybe use a macro and return nonzero.
|
||||
|
||||
tr: support nontrivial equivalence classes, e.g. [=e=] with LC_COLLATE=fr_FR
|
||||
|
||||
lib/strftime.c: Since %N is the only format that we need but that
|
||||
glibc's strftime doesn't support, consider using a wrapper that
|
||||
would expand /%(-_)?\d*N/ to the desired string and then pass the
|
||||
resulting string to glibc's strftime.
|
||||
|
||||
sort: Investigate better sorting algorithms; see Knuth vol. 3.
|
||||
|
||||
We tried list merge sort, but it was about 50% slower than the
|
||||
recursive algorithm currently used by sortlines, and it used more
|
||||
comparisons. We're not sure why this was, as the theory suggests it
|
||||
should do fewer comparisons, so perhaps this should be revisited.
|
||||
List merge sort was implemented in the style of Knuth algorithm
|
||||
5.2.4L, with the optimization suggested by exercise 5.2.4-22. The
|
||||
test case was 140,213,394 bytes, 426,4424 lines, text taken from the
|
||||
GCC 3.3 distribution, sort.c compiled with GCC 2.95.4 and running on
|
||||
Debian 3.0r1 GNU/Linux, 2.4GHz Pentium 4, single pass with no
|
||||
temporary files and plenty of RAM.
|
||||
|
||||
Since comparisons seem to be the bottleneck, perhaps the best
|
||||
algorithm to try next should be merge insertion. See Knuth section
|
||||
5.3.1, who credits Lester Ford, Jr. and Selmer Johnson, American
|
||||
Mathematical Monthly 66 (1959), 387-389.
|
||||
|
||||
shred: Update shred as described here to conform to DoD 5220 rules:
|
||||
https://lists.gnu.org/r/bug-coreutils/2007-05/msg00075.html
|
||||
|
||||
Remove suspicious uses of alloca (ones that may allocate more than
|
||||
about 4k)
|
||||
|
||||
Improve test coverage.
|
||||
See HACKING for instructions on generating an html test coverage report.
|
||||
Find a program that has poor coverage and improve.
|
||||
|
||||
Changes expected to go in, someday.
|
||||
======================================
|
||||
|
||||
dd patch from Olivier Delhomme
|
||||
|
||||
test/mv/*: clean up $other_partition_tmpdir in all cases
|
||||
|
||||
ls: when both -l and --dereference-command-line-symlink-to-dir are
|
||||
specified, consider whether to let the latter select whether to
|
||||
dereference command line symlinks to directories. Since -l has
|
||||
an implicit --NO-dereference-command-line-symlink-to-dir meaning.
|
||||
Pointed out by Karl Berry.
|
||||
|
||||
Pending copyright papers:
|
||||
------------------------
|
||||
getpwnam from Bruce Korb
|
||||
|
||||
pb (progress bar) from Miika Pekkarinen
|
||||
|
||||
------------------------------
|
||||
|
||||
Remove long-deprecated options. Search case-insensitive for
|
||||
'deprecated' and 'remove in '. Automate this.
|
||||
|
||||
Add a distcheck-time test to ensure that every distributed
|
||||
file is either read-only(indicating generated) or is
|
||||
version-controlled and up to date.
|
||||
|
||||
remove all uses of the 'register' keyword: Done. add a maint.mk rule
|
||||
for this, too.
|
||||
|
||||
remove or adjust chown's --changes option, since it
|
||||
can't always do what it currently says it does.
|
||||
|
||||
Support arbitrary-precision arithmetic in those tools for which it
|
||||
makes sense. Factor and expr already support this via libgmp.
|
||||
The "test" program is covered via its string-based comparison of
|
||||
integers. To be converted: seq.
|
||||
|
||||
Adapt tools like wc, tr, fmt, etc. (most of the textutils) to be
|
||||
multibyte aware. The problem is that I want to avoid duplicating
|
||||
significant blocks of logic, yet I also want to incur only minimal
|
||||
(preferably 'no') cost when operating in single-byte mode.
|
||||
|
||||
pr's use of nstrftime can make it malloc a very large (up to SIZE_MAX) buffer
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 2002-2025 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/>.
|
1651
aclocal.m4
vendored
Normal file
1651
aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
433
bootstrap.conf
Normal file
433
bootstrap.conf
Normal file
|
@ -0,0 +1,433 @@
|
|||
# Bootstrap configuration.
|
||||
|
||||
# Copyright (C) 2006-2025 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/>.
|
||||
|
||||
|
||||
# We don't need these modules.
|
||||
avoided_gnulib_modules='
|
||||
--avoid=canonicalize-lgpl
|
||||
--avoid=dummy
|
||||
--avoid=mbuiter
|
||||
--avoid=mbuiterf
|
||||
'
|
||||
|
||||
# gnulib modules used by this package.
|
||||
gnulib_modules="
|
||||
$avoided_gnulib_modules
|
||||
acl
|
||||
acl-permissions
|
||||
alignalloc
|
||||
alignasof
|
||||
alloca
|
||||
announce-gen
|
||||
areadlink-with-size
|
||||
areadlinkat-with-size
|
||||
argmatch
|
||||
argv-iter
|
||||
assert
|
||||
assert-h
|
||||
assure
|
||||
attribute
|
||||
autobuild
|
||||
backup-rename
|
||||
backupfile
|
||||
base32
|
||||
base64
|
||||
bool
|
||||
btoc32
|
||||
buffer-lcm
|
||||
c-strcase
|
||||
c32iscntrl
|
||||
c32isspace
|
||||
c32width
|
||||
canon-host
|
||||
canonicalize
|
||||
chmodat
|
||||
chown
|
||||
chownat
|
||||
cl-strtod
|
||||
cl-strtold
|
||||
closein
|
||||
closeout
|
||||
config-h
|
||||
configmake
|
||||
copy-file-range
|
||||
crc-x86_64
|
||||
crypto/md5
|
||||
crypto/sha1
|
||||
crypto/sha256
|
||||
crypto/sha512
|
||||
crypto/sm3
|
||||
cycle-check
|
||||
d-ino
|
||||
d-type
|
||||
di-set
|
||||
dirfd
|
||||
dirname
|
||||
do-release-commit-and-tag
|
||||
dtimespec-bound
|
||||
dtoastr
|
||||
dup2
|
||||
endian
|
||||
environ
|
||||
error
|
||||
euidaccess
|
||||
exclude
|
||||
exitfail
|
||||
explicit_bzero
|
||||
faccessat
|
||||
fadvise
|
||||
fchdir
|
||||
fchmodat
|
||||
fchownat
|
||||
fclose
|
||||
fcntl
|
||||
fcntl-safer
|
||||
fd-reopen
|
||||
fdatasync
|
||||
fdopen
|
||||
fdutimensat
|
||||
file-has-acl
|
||||
file-type
|
||||
fileblocks
|
||||
filemode
|
||||
filenamecat
|
||||
filevercmp
|
||||
flexmember
|
||||
fnmatch-gnu
|
||||
fopen-safer
|
||||
fprintftime
|
||||
fpurge
|
||||
free-posix
|
||||
freopen
|
||||
freopen-safer
|
||||
fseeko
|
||||
fstatat
|
||||
fsusage
|
||||
fsync
|
||||
ftoastr
|
||||
ftruncate
|
||||
fts
|
||||
full-read
|
||||
full-write
|
||||
gethrxtime
|
||||
getline
|
||||
getloadavg
|
||||
getlogin
|
||||
getndelim2
|
||||
getopt-gnu
|
||||
getpagesize
|
||||
gettext-h
|
||||
gettime
|
||||
gettime-res
|
||||
git-version-gen
|
||||
gitlog-to-changelog
|
||||
gnu-web-doc-update
|
||||
gnumakefile
|
||||
gnupload
|
||||
hard-locale
|
||||
hash
|
||||
hash-triple
|
||||
heap
|
||||
host-os
|
||||
human
|
||||
idcache
|
||||
idx
|
||||
ignore-value
|
||||
inttostr
|
||||
inttypes-h
|
||||
isapipe
|
||||
isatty
|
||||
isblank
|
||||
largefile
|
||||
lchmod
|
||||
ldtoastr
|
||||
lib-ignore
|
||||
libgmp
|
||||
linebuffer
|
||||
link
|
||||
link-follow
|
||||
linkat
|
||||
long-options
|
||||
lstat
|
||||
maintainer-makefile
|
||||
malloc-gnu
|
||||
manywarnings
|
||||
mbrlen
|
||||
mbrtoc32
|
||||
mbrtowc
|
||||
mbschr
|
||||
mbslen
|
||||
mbswidth
|
||||
mbszero
|
||||
mcel-prefer
|
||||
memcasecmp
|
||||
memchr
|
||||
memcmp2
|
||||
mempcpy
|
||||
memrchr
|
||||
minmax
|
||||
mkancesdirs
|
||||
mkdir
|
||||
mkdir-p
|
||||
mkdirat
|
||||
mkfifo
|
||||
mkfifoat
|
||||
mknod
|
||||
mkostemp
|
||||
mkstemp
|
||||
mktime
|
||||
modechange
|
||||
mountlist
|
||||
mpsort
|
||||
nproc
|
||||
nstrftime
|
||||
nullptr
|
||||
obstack
|
||||
open
|
||||
openat-safer
|
||||
parse-datetime
|
||||
parse-datetime2
|
||||
pathmax
|
||||
perl
|
||||
physmem
|
||||
pipe-posix
|
||||
pipe2
|
||||
posix-shell
|
||||
posixtm
|
||||
posixver
|
||||
priv-set
|
||||
progname
|
||||
propername-lite
|
||||
pthread-cond
|
||||
pthread-mutex
|
||||
pthread-thread
|
||||
pthread_sigmask
|
||||
putenv-gnu
|
||||
quote
|
||||
quotearg
|
||||
randint
|
||||
randperm
|
||||
rawmemchr
|
||||
read-file
|
||||
readtokens
|
||||
readtokens0
|
||||
readutmp
|
||||
regex
|
||||
remove
|
||||
renameat
|
||||
renameatu
|
||||
rmdir
|
||||
root-dev-ino
|
||||
safe-read
|
||||
same
|
||||
save-cwd
|
||||
savedir
|
||||
savewd
|
||||
select
|
||||
selinux-at
|
||||
setenv
|
||||
settime
|
||||
sig2str
|
||||
sigaction
|
||||
skipchars
|
||||
smack
|
||||
ssize_t
|
||||
stat-macros
|
||||
stat-size
|
||||
stat-time
|
||||
stdc_leading_zeros
|
||||
stdc_trailing_zeros
|
||||
stdckdint-h
|
||||
stdlib-safer
|
||||
stpcpy
|
||||
str_endswith
|
||||
strdup-posix
|
||||
strnlen
|
||||
strnumcmp
|
||||
strsignal
|
||||
strtoimax
|
||||
strtoumax
|
||||
symlinkat
|
||||
sys_ioctl-h
|
||||
sys_resource-h
|
||||
sys_stat-h
|
||||
sys_types-h
|
||||
sys_wait-h
|
||||
targetdir
|
||||
tempname
|
||||
termios-h
|
||||
time_rz
|
||||
timer-time
|
||||
timespec
|
||||
tmpdir
|
||||
uname
|
||||
unicodeio
|
||||
unistd-safer
|
||||
unlink-busy
|
||||
unlinkat
|
||||
unlinkdir
|
||||
unlocked-io
|
||||
unsetenv
|
||||
update-copyright
|
||||
useless-if-before-free
|
||||
userspec
|
||||
utimecmp
|
||||
utimens
|
||||
utimensat
|
||||
vasprintf-posix
|
||||
vc-list-files
|
||||
verify
|
||||
verror
|
||||
version-etc-fsf
|
||||
winsz-ioctl
|
||||
winsz-termios
|
||||
write-any-file
|
||||
xalignalloc
|
||||
xalloc
|
||||
xbinary-io
|
||||
xdectoint
|
||||
xfts
|
||||
xgetcwd
|
||||
xgetgroups
|
||||
xgethostname
|
||||
xmemcoll
|
||||
xnanosleep
|
||||
xprintf
|
||||
xprintf-posix
|
||||
xreadlink
|
||||
xstrtod
|
||||
xstrtoimax
|
||||
xstrtol
|
||||
xstrtol-error
|
||||
xstrtold
|
||||
xstrtoumax
|
||||
xvasprintf
|
||||
year2038-recommended
|
||||
yesno
|
||||
"
|
||||
|
||||
# Other locale categories that need message catalogs.
|
||||
EXTRA_LOCALE_CATEGORIES=LC_TIME
|
||||
|
||||
# Additional xgettext options to use. Use "\\\newline" to break lines.
|
||||
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
|
||||
--flag=asnprintf:3:c-format\\\
|
||||
--flag=asprintf:2:c-format\\\
|
||||
--flag=error:3:c-format\\\
|
||||
--flag=error_at_line:5:c-format\\\
|
||||
--flag=vasnprintf:3:c-format\\\
|
||||
--flag=vasprintf:2:c-format\\\
|
||||
--flag=verror:3:c-format\\\
|
||||
--flag=verror_at_line:5:c-format\\\
|
||||
--flag=wrapf:1:c-format\\\
|
||||
--flag=xasprintf:1:c-format\\\
|
||||
--flag=xfprintf:2:c-format\\\
|
||||
--flag=xprintf:1:c-format\\\
|
||||
--from-code=UTF-8\\\
|
||||
'
|
||||
|
||||
# Append these, since we use the propername module.
|
||||
see_manual='"This is a proper name. See the gettext manual, section Names."'
|
||||
see_manual=\'"$see_manual"\'
|
||||
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
|
||||
--keyword=proper_name:1,'"$see_manual"'\\\
|
||||
--keyword=proper_name_lite:1,'"$see_manual"'\\\
|
||||
'
|
||||
|
||||
gnulib_tool_option_extras="--tests-base=gnulib-tests --with-tests --symlink\
|
||||
--makefile-name=gnulib.mk --automake-subdir
|
||||
"
|
||||
|
||||
# Build prerequisites
|
||||
buildreq="\
|
||||
autoconf 2.64
|
||||
automake 1.11.2
|
||||
autopoint 0.19.2
|
||||
bison -
|
||||
gettext 0.19.2
|
||||
git 1.4.4
|
||||
gperf -
|
||||
gzip -
|
||||
m4 -
|
||||
makeinfo 6.1
|
||||
texi2pdf 6.1
|
||||
patch -
|
||||
perl 5.5
|
||||
tar -
|
||||
wget -
|
||||
xz -
|
||||
"
|
||||
|
||||
bootstrap_post_import_hook ()
|
||||
{
|
||||
# Automake requires that ChangeLog exist.
|
||||
touch ChangeLog || return 1
|
||||
# List of coreutils programs. See heading comments in the invoked
|
||||
# script for more info. Keep this in sync with the rules in
|
||||
(m4f=m4/cu-progs.m4 mkf=src/cu-progs.mk tmp=cu-progs.tmp \
|
||||
&& rm -f $m4f $mkf $tmp-1 $tmp-2 \
|
||||
&& build-aux/gen-lists-of-programs.sh --autoconf >$tmp-1 \
|
||||
&& build-aux/gen-lists-of-programs.sh --automake >$tmp-2 \
|
||||
&& chmod a-w $tmp-1 $tmp-2 \
|
||||
&& mv -f $tmp-1 $m4f && mv -f $tmp-2 $mkf)
|
||||
|
||||
# Regenerate src/single-binary.mk
|
||||
(mkf=src/single-binary.mk tmp=single-binary.tmp \
|
||||
&& rm -f $mkf $tmp \
|
||||
&& build-aux/gen-single-binary.sh src/local.mk >$tmp \
|
||||
&& chmod a-w $tmp \
|
||||
&& mv -f $tmp $mkf)
|
||||
|
||||
# Copy tests/init.sh from Gnulib.
|
||||
$gnulib_tool --copy-file tests/init.sh
|
||||
}
|
||||
|
||||
|
||||
bootstrap_epilogue()
|
||||
{
|
||||
# Since this is a "GNU" package, replace this line
|
||||
# if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null \
|
||||
# | grep -v 'libtool:' >/dev/null; then
|
||||
# with this:
|
||||
# if true; then
|
||||
# Why? That pipeline searches all files in $(top_srcdir), and if you
|
||||
# happen to have large files (or apparently large sparse files), the
|
||||
# first grep may well run out of memory.
|
||||
perl -pi -e 's/if LC_ALL=C grep .GNU .PACKAGE.*; then/if true; then/' \
|
||||
po/Makefile.in.in
|
||||
|
||||
# Add dummy 'install-html' target, required for packages using
|
||||
# non-recursive makefiles with older gettext.
|
||||
# See https://debbugs.gnu.org/25690
|
||||
if ! grep -w 'install-html' po/Makefile.in.in ; then
|
||||
printf 'install-%s:;\n' dvi ps pdf html >> po/Makefile.in.in
|
||||
fi
|
||||
|
||||
# Install our git hooks, as long as "cp" accepts the --backup option,
|
||||
# so that we can back up any existing files.
|
||||
case $(cp --help) in *--backup*) backup=1;; *) backup=0;; esac
|
||||
if test $backup = 1; then
|
||||
hooks=$(cd scripts/git-hooks && git ls-files)
|
||||
for f in $hooks; do
|
||||
# If it is identical, skip it.
|
||||
cmp scripts/git-hooks/$f .git/hooks/$f > /dev/null \
|
||||
&& continue
|
||||
cp --backup=numbered scripts/git-hooks/$f .git/hooks
|
||||
chmod a-w .git/hooks/$f
|
||||
done
|
||||
fi
|
||||
}
|
739
build-aux/announce-gen
Executable file
739
build-aux/announce-gen
Executable file
|
@ -0,0 +1,739 @@
|
|||
#!/bin/sh
|
||||
#! -*-perl-*-
|
||||
|
||||
# Generate a release announcement message.
|
||||
|
||||
# Copyright (C) 2002-2025 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 = '2025-01-31 23:21'; # 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 = $VERSION) =~ s/^(\d*)-.*$/$1/;
|
||||
|
||||
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
|
||||
--cksum-checksums emit SHA256 checksums in a form that requires
|
||||
cksum from coreutils or OpenBSD
|
||||
--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
|
||||
|
||||
Send patches and bug reports to <bug-gnulib\@gnu.org>.
|
||||
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 -L $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
|
||||
|
||||
# This digest function omits the "=" padding that is required by cksum,
|
||||
# so add the 0..2 bytes of padding required for each of Digest's algorithms.
|
||||
# To verify such a digest, users need
|
||||
# - a particular command ('cksum -a sha256 --check')
|
||||
# - and particular tools (coreutils >= 9.2 or OpenBSD's cksum since 2007).
|
||||
sub digest_file_base64_wrap ($$)
|
||||
{
|
||||
my ($file, $alg) = @_;
|
||||
my $h = digest_file_base64($file, $alg);
|
||||
$alg =~ tr{-}{}d;
|
||||
my %pad = (MD5 => 2, SHA1 => 1, SHA256 => 1, SHA384 => 0, SHA512 => 2);
|
||||
return $h . '=' x $pad{$alg};
|
||||
}
|
||||
|
||||
sub print_checksums ($@)
|
||||
{
|
||||
my ($prefer_cksum, @file) = @_;
|
||||
|
||||
print "Here are the SHA1 and SHA256 checksums:\n";
|
||||
print "\n";
|
||||
|
||||
use Digest::file qw(digest_file_hex digest_file_base64);
|
||||
|
||||
if ($prefer_cksum)
|
||||
{
|
||||
foreach my $f (@file)
|
||||
{
|
||||
print ' ', digest_file_hex ($f, "SHA-1"), " $f\n";
|
||||
print ' ', digest_file_base64_wrap ($f, "SHA-256"), " $f\n";
|
||||
}
|
||||
print "\nVerify the base64 SHA256 checksum with cksum -a sha256 --check\n";
|
||||
print "from coreutils-9.2 or OpenBSD's cksum since 2007.\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach my $f (@file)
|
||||
{
|
||||
print " File: $f\n";
|
||||
print ' SHA1 sum: ', digest_file_hex ($f, "SHA-1"), "\n";
|
||||
print ' SHA256 sum: ', digest_file_hex ($f, "SHA-256"), "\n";
|
||||
print "\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 =~ /.* ([a-f\d][\w.-]+)$/)
|
||||
{
|
||||
$t = ucfirst $t;
|
||||
push @tool_version_pair, "$t $1";
|
||||
}
|
||||
else
|
||||
{
|
||||
warn "$t: unexpected --version output:\n$first_line";
|
||||
defined $first_line
|
||||
and $first_line = '';
|
||||
$fail = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$fail
|
||||
and exit 1;
|
||||
|
||||
return @tool_version_pair;
|
||||
}
|
||||
|
||||
# Print a more human-friendly representation of $SEC seconds.
|
||||
sub readable_interval0($)
|
||||
{
|
||||
my $sec = shift;
|
||||
$sec < 60 and return "$sec seconds";
|
||||
|
||||
my $min = int($sec / 60); $sec %= 60;
|
||||
30 < $sec and $min++;
|
||||
$min < 60 and return "$min minutes";
|
||||
|
||||
my $hr = int($min / 60); $min %= 60;
|
||||
30 < $min and $hr++;
|
||||
$hr < 24 and return "$hr hours";
|
||||
|
||||
my $day = int($hr / 24); $hr %= 24;
|
||||
12 < $hr and $day++;
|
||||
$day < 50 and return "$day days";
|
||||
|
||||
my $wk = int($day / 7); $day %= 7;
|
||||
4 < $day and $wk++;
|
||||
return "$wk weeks";
|
||||
}
|
||||
|
||||
# Convert e.g., "1 weeks", to "1 week".
|
||||
sub readable_interval($)
|
||||
{
|
||||
my $interval_str = shift;
|
||||
my $i = readable_interval0 $interval_str;
|
||||
$i =~ m{^1 \w+s$} and chop $i;
|
||||
return $i;
|
||||
}
|
||||
|
||||
{
|
||||
# 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 $cksum_checksums_p;
|
||||
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,
|
||||
'cksum-checksums' => \$cksum_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;
|
||||
|
||||
! grep (/^gnulib$/, @tool_list) && defined $gnulib_version
|
||||
and (warn "with --gnulib-version=V you must use --bootstrap-tools=...\n"
|
||||
. "including gnulib in that list"), $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>
|
||||
This is to announce $package_name-$curr_version, a $release_type release.
|
||||
|
||||
FIXME: put comments here
|
||||
|
||||
EOF
|
||||
|
||||
my $v0 = $prev_version;
|
||||
my $v1 = $curr_version;
|
||||
|
||||
(my $first_name = `git -C "$srcdir" config user.name|cut -d' ' -f1`)
|
||||
=~ m{\S} or die "no name? set user.name in ~/.gitconfig\n";
|
||||
|
||||
chomp (my $n_ci = `git -C "$srcdir" rev-list "v$v0..v$v1" | wc -l`);
|
||||
chomp (my $n_p = `git -C "$srcdir" shortlog "v$v0..v$v1" | grep -c '^[^ ]'`);
|
||||
|
||||
my $this_commit_hash = `git -C "$srcdir" log --pretty=%H -1 "v$v1"`;
|
||||
chop $this_commit_hash;
|
||||
my $prev_release_date = `git -C "$srcdir" log --pretty=%ct -1 "v$v0"`;
|
||||
my $this_release_date = `git -C "$srcdir" log --pretty=%ct -1 "v$v1"`;
|
||||
my $n_seconds = $this_release_date - $prev_release_date;
|
||||
my $time_since_prev = readable_interval $n_seconds;
|
||||
my $names = `git -C "$srcdir" shortlog "v$v0..v$v1"|perl -lne '/^(\\w.*):/ and print " ".\$1'`;
|
||||
|
||||
print <<EOF;
|
||||
There have been $n_ci commits by $n_p people in the $time_since_prev since $v0.
|
||||
|
||||
See the NEWS below for a brief summary.
|
||||
|
||||
Thanks to everyone who has contributed!
|
||||
The following people contributed changes to this release:
|
||||
|
||||
$names
|
||||
$first_name [on behalf of the $package_name maintainers]
|
||||
==================================================================
|
||||
|
||||
Here is the GNU $package_name home page:
|
||||
https://gnu.org/s/$package_name/
|
||||
|
||||
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 ($cksum_checksums_p, @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
|
||||
|
||||
EOF
|
||||
my $gpg_fingerprint = `LC_ALL=C gpg --fingerprint $gpg_key_id | grep -v ^sub`;
|
||||
if ($gpg_fingerprint =~ /^pub/)
|
||||
{
|
||||
chop $gpg_fingerprint;
|
||||
$gpg_fingerprint =~ s/ \[expires:.*//mg;
|
||||
$gpg_fingerprint =~ s/^uid \[ultimate\]/uid /mg;
|
||||
$gpg_fingerprint =~ s/^/ /mg;
|
||||
print<<EOF
|
||||
The signature should match the fingerprint of the following key:
|
||||
|
||||
$gpg_fingerprint
|
||||
EOF
|
||||
}
|
||||
print <<EOF;
|
||||
If that command fails because you don't have the required public key,
|
||||
or that public key has expired, try the following commands to retrieve
|
||||
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
|
||||
}
|
||||
print <<EOF;
|
||||
|
||||
As a last resort to find the key, you can try the official GNU
|
||||
keyring:
|
||||
|
||||
wget -q https://ftp.gnu.org/gnu/gnu-keyring.gpg
|
||||
gpg --keyring gnu-keyring.gpg --verify $tarballs[0].sig
|
||||
EOF
|
||||
|
||||
print <<EOF;
|
||||
|
||||
This release is based on the $package_name git repository, available as
|
||||
|
||||
git clone https://git.savannah.gnu.org/git/$package_name.git
|
||||
|
||||
with commit $this_commit_hash tagged as v$v1.
|
||||
|
||||
For a summary of changes and contributors, see:
|
||||
|
||||
https://git.sv.gnu.org/gitweb/?p=$package_name.git;a=shortlog;h=v$v1
|
||||
|
||||
or run this command from a git-cloned $package_name directory:
|
||||
|
||||
git shortlog v$v0..v$v1
|
||||
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 nil t)
|
||||
## 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:
|
1815
build-aux/config.guess
vendored
Executable file
1815
build-aux/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
751
build-aux/config.rpath
Executable file
751
build-aux/config.rpath
Executable file
|
@ -0,0 +1,751 @@
|
|||
#! /bin/sh
|
||||
# Output a system dependent set of variables, describing how to set the
|
||||
# run time search path of shared libraries in a binary (executable or
|
||||
# shared library).
|
||||
#
|
||||
# Copyright 1996-2025 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.
|
||||
|
||||
# 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.
|
||||
|
||||
# func_usage
|
||||
# outputs to stdout the --help usage message.
|
||||
func_usage ()
|
||||
{
|
||||
echo "\
|
||||
Usage: config.rpath [OPTION] HOST
|
||||
|
||||
Prints shell variable assignments that describe how to hardcode a directory
|
||||
for the lookup of shared libraries into a binary (executable or shared library).
|
||||
|
||||
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.
|
||||
|
||||
Options:
|
||||
--help print this help and exit
|
||||
--version print version information and exit
|
||||
|
||||
Send patches and bug reports to <bug-gnulib@gnu.org>."
|
||||
}
|
||||
|
||||
# func_version
|
||||
# outputs to stdout the --version message.
|
||||
func_version ()
|
||||
{
|
||||
echo "config.rpath (GNU gnulib, module havelib)"
|
||||
echo "Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
License: All-Permissive.
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law."
|
||||
echo
|
||||
printf 'Written by %s.\n' "Bruno Haible"
|
||||
}
|
||||
|
||||
# func_fatal_error message
|
||||
# outputs to stderr a fatal error message, and terminates the program.
|
||||
func_fatal_error ()
|
||||
{
|
||||
echo "config.rpath: *** $1" 1>&2
|
||||
echo "config.rpath: *** Stop." 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Command-line option processing.
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
--help | --hel | --he | --h )
|
||||
func_usage
|
||||
exit 0 ;;
|
||||
--version | --versio | --versi | --vers | --ver | --ve | --v )
|
||||
func_version
|
||||
exit 0 ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
-* )
|
||||
func_fatal_error "unrecognized option: $1"
|
||||
;;
|
||||
* )
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test $# -gt 1; then
|
||||
func_fatal_error "too many arguments"
|
||||
fi
|
||||
if test $# -lt 1; then
|
||||
func_fatal_error "too few arguments"
|
||||
fi
|
||||
|
||||
# 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
|
2354
build-aux/config.sub
vendored
Executable file
2354
build-aux/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
792
build-aux/depcomp
Executable file
792
build-aux/depcomp
Executable file
|
@ -0,0 +1,792 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2024-12-03.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2025 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>.
|
||||
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||
General help using GNU software: <https://www.gnu.org/gethelp/>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp (GNU Automake) $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 interference 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 obsolete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IBM 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 nil t)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
179
build-aux/do-release-commit-and-tag
Executable file
179
build-aux/do-release-commit-and-tag
Executable file
|
@ -0,0 +1,179 @@
|
|||
#!/bin/sh
|
||||
# In a git/autoconf/automake-enabled project with a NEWS file and a version-
|
||||
# controlled .prev-version file, automate the procedure by which we record
|
||||
# the date, release-type and version string in the NEWS file. That commit
|
||||
# will serve to identify the release, so apply a signed tag to it as well.
|
||||
VERSION=2024-07-04.10 # UTC
|
||||
|
||||
# Note: this is a bash script (could be zsh or dash)
|
||||
|
||||
# Copyright (C) 2009-2025 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
|
||||
|
||||
ME=$(basename "$0")
|
||||
warn() { printf '%s: %s\n' "$ME" "$*" >&2; }
|
||||
die() { warn "$*"; exit 1; }
|
||||
|
||||
help()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: $ME [OPTION...] VERSION RELEASE_TYPE
|
||||
|
||||
Run this script from top_srcdir to perform the final pre-release NEWS
|
||||
update in which the date, release-type and version string are
|
||||
recorded. Commit that result with a log entry marking the release,
|
||||
and apply a signed tag. Run it from your project's top-level
|
||||
directory.
|
||||
|
||||
Requirements:
|
||||
- you use git for version-control
|
||||
- a version-controlled .prev-version file
|
||||
- a NEWS file, with line 3 identical to this:
|
||||
$noteworthy_stub
|
||||
|
||||
Options:
|
||||
--branch=BRANCH set release branch (default: $branch)
|
||||
-C, --builddir=DIR location of (configured) Makefile (default: $builddir)
|
||||
--help print this help, then exit
|
||||
--version print version number, then exit
|
||||
|
||||
EXAMPLE:
|
||||
To update NEWS and tag the beta 8.1 release of coreutils, I would run this:
|
||||
|
||||
$ME 8.1 beta
|
||||
|
||||
Report bugs and patches to <bug-gnulib@gnu.org>.
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
version()
|
||||
{
|
||||
year=$(echo "$VERSION" | sed 's/[^0-9].*//')
|
||||
cat <<EOF
|
||||
$ME $VERSION
|
||||
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
|
||||
}
|
||||
|
||||
## ------ ##
|
||||
## Main. ##
|
||||
## ------ ##
|
||||
|
||||
# Constants.
|
||||
noteworthy='* Noteworthy changes in release'
|
||||
noteworthy_stub="$noteworthy ?.? (????-??-??) [?]"
|
||||
|
||||
# Variables.
|
||||
branch=$(git branch | sed -ne '/^\* /{s///;p;q;}')
|
||||
builddir=.
|
||||
|
||||
while test $# != 0
|
||||
do
|
||||
# Handle --option=value by splitting apart and putting back on argv.
|
||||
case $1 in
|
||||
--*=*)
|
||||
opt=$(echo "$1" | sed -e 's/=.*//')
|
||||
val=$(echo "$1" | sed -e 's/[^=]*=//')
|
||||
shift
|
||||
set dummy "$opt" "$val" "$@"; shift
|
||||
;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--help|--version) ${1#--};;
|
||||
--branch) shift; branch=$1; shift ;;
|
||||
-C|--builddir) shift; builddir=$1; shift ;;
|
||||
--*) die "unrecognized option: $1";;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
test $# = 2 \
|
||||
|| die "Usage: $ME [OPTION...] VERSION TYPE"
|
||||
|
||||
ver=$1
|
||||
type=$2
|
||||
|
||||
|
||||
## ---------------------- ##
|
||||
## First, sanity checks. ##
|
||||
## ---------------------- ##
|
||||
|
||||
# Verify that $ver looks like a version number, and...
|
||||
echo "$ver"|grep -E '^[0-9][0-9.]*[0-9]$' > /dev/null \
|
||||
|| die "invalid version: $ver"
|
||||
prev_ver=$(cat .prev-version) \
|
||||
|| die 'failed to determine previous version number from .prev-version'
|
||||
|
||||
# Verify that $ver is sensible (> .prev-version).
|
||||
case $(printf "%s\n%s\n" "$prev_ver" "$ver"|sort -V -u|tr '\n' ':') in
|
||||
"$prev_ver:$ver:") ;;
|
||||
*) die "invalid version: $ver (<= $prev_ver)";;
|
||||
esac
|
||||
|
||||
case $type in
|
||||
alpha|beta|stable) ;;
|
||||
*) die "invalid release type: $type";;
|
||||
esac
|
||||
|
||||
# No local modifications allowed.
|
||||
case $(git diff-index --name-only HEAD) in
|
||||
'') ;;
|
||||
*) die 'this tree is dirty; commit your changes first';;
|
||||
esac
|
||||
|
||||
# Ensure the current branch name is correct:
|
||||
curr_br=$(git rev-parse --symbolic-full-name HEAD)
|
||||
test "$curr_br" = "refs/heads/$branch" || die not on branch $branch
|
||||
|
||||
# Extract package name from Makefile.
|
||||
Makefile=$builddir/Makefile
|
||||
pkg=$(sed -n 's/^PACKAGE = \(.*\)/\1/p' "$Makefile") \
|
||||
|| die "failed to determine package name from $Makefile"
|
||||
|
||||
# Check that line 3 of NEWS is the stub line about to be replaced.
|
||||
test "$(sed -n 3p NEWS)" = "$noteworthy_stub" \
|
||||
|| die "line 3 of NEWS must be exactly '$noteworthy_stub'"
|
||||
|
||||
## --------------- ##
|
||||
## Then, changes. ##
|
||||
## --------------- ##
|
||||
|
||||
# Update NEWS to have today's date, plus desired version number and $type.
|
||||
perl -MPOSIX -ni -e 'my $today = strftime "%F", localtime time;' \
|
||||
-e 'my ($type, $ver) = qw('"$type $ver"');' \
|
||||
-e 'my $pfx = "'"$noteworthy"'";' \
|
||||
-e 'print $.==3 ? "$pfx $ver ($today) [$type]\n" : $_' \
|
||||
NEWS || die 'failed to update NEWS'
|
||||
|
||||
printf "version %s\n\n* NEWS: Record release date.\n" "$ver" \
|
||||
| git commit -F - -a || die 'git commit failed'
|
||||
git tag -s -m "$pkg $ver" v$ver HEAD || die 'git tag failed'
|
||||
|
||||
# Local variables:
|
||||
# indent-tabs-mode: nil
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
|
||||
# time-stamp-start: "VERSION="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: " # UTC"
|
||||
# End:
|
196
build-aux/gen-lists-of-programs.sh
Executable file
196
build-aux/gen-lists-of-programs.sh
Executable file
|
@ -0,0 +1,196 @@
|
|||
#!/bin/sh
|
||||
# Generate lists of all coreutils programs, to be fed both to Autoconf
|
||||
# and Automake, and with further distinctions about how and when these
|
||||
# programs should be built. This is useful to avoid duplicating these
|
||||
# list definitions among several files ('configure.ac' and
|
||||
# 'src/local.mk' at least); such duplication had proved a source of
|
||||
# inconsistencies and bugs in the past.
|
||||
|
||||
set -u
|
||||
set -e
|
||||
|
||||
# These are the names of programs that are neither built nor installed
|
||||
# by default. This list is *not* intended for programs like 'who',
|
||||
# 'nice', 'chroot', etc., that are built only when certain requisite
|
||||
# system features are detected.
|
||||
# If you would like to install programs from this list anyway, say A and B,
|
||||
# use "--enable-install-program=A,B" when invoking configure.
|
||||
disabled_by_default_progs='
|
||||
arch
|
||||
coreutils
|
||||
hostname
|
||||
'
|
||||
|
||||
# Programs that can be built only when certain requisite system
|
||||
# features are detected at configure time.
|
||||
build_if_possible_progs='
|
||||
chroot
|
||||
df
|
||||
hostid
|
||||
libstdbuf.so
|
||||
nice
|
||||
pinky
|
||||
stdbuf
|
||||
stty
|
||||
timeout
|
||||
users
|
||||
who
|
||||
'
|
||||
|
||||
# All the other programs, to be built by default, and that should
|
||||
# be buildable without problems on any target system.
|
||||
normal_progs='
|
||||
[
|
||||
b2sum
|
||||
base64
|
||||
base32
|
||||
basenc
|
||||
basename
|
||||
cat
|
||||
chcon
|
||||
chgrp
|
||||
chmod
|
||||
chown
|
||||
cksum
|
||||
comm
|
||||
cp
|
||||
csplit
|
||||
cut
|
||||
date
|
||||
dd
|
||||
dir
|
||||
dircolors
|
||||
dirname
|
||||
du
|
||||
echo
|
||||
env
|
||||
expand
|
||||
expr
|
||||
factor
|
||||
false
|
||||
fmt
|
||||
fold
|
||||
ginstall
|
||||
groups
|
||||
head
|
||||
id
|
||||
join
|
||||
kill
|
||||
link
|
||||
ln
|
||||
logname
|
||||
ls
|
||||
md5sum
|
||||
mkdir
|
||||
mkfifo
|
||||
mknod
|
||||
mktemp
|
||||
mv
|
||||
nl
|
||||
nproc
|
||||
nohup
|
||||
numfmt
|
||||
od
|
||||
paste
|
||||
pathchk
|
||||
pr
|
||||
printenv
|
||||
printf
|
||||
ptx
|
||||
pwd
|
||||
readlink
|
||||
realpath
|
||||
rm
|
||||
rmdir
|
||||
runcon
|
||||
seq
|
||||
sha1sum
|
||||
sha224sum
|
||||
sha256sum
|
||||
sha384sum
|
||||
sha512sum
|
||||
shred
|
||||
shuf
|
||||
sleep
|
||||
sort
|
||||
split
|
||||
stat
|
||||
sum
|
||||
sync
|
||||
tac
|
||||
tail
|
||||
tee
|
||||
test
|
||||
touch
|
||||
tr
|
||||
true
|
||||
truncate
|
||||
tsort
|
||||
tty
|
||||
uname
|
||||
unexpand
|
||||
uniq
|
||||
unlink
|
||||
uptime
|
||||
vdir
|
||||
wc
|
||||
whoami
|
||||
yes
|
||||
'
|
||||
|
||||
me=`echo "$0" | sed 's,.*/,,'`
|
||||
msg="Automatically generated by $me. DO NOT EDIT BY HAND!"
|
||||
|
||||
case $#,$1 in
|
||||
1,--autoconf|1,--for-autoconf)
|
||||
echo "dnl $msg"
|
||||
for p in $normal_progs; do
|
||||
test x"$p" = x"[" && p='@<:@'
|
||||
echo "gl_ADD_PROG([optional_bin_progs], [$p])"
|
||||
done
|
||||
# Extra 'echo' to normalize whitespace.
|
||||
echo "no_install_progs_default='`echo $disabled_by_default_progs`'"
|
||||
sed 's/^ *//' <<END
|
||||
# Given the name of a variable containing a space-separated
|
||||
# list of install-by-default programs and the actual list of
|
||||
# do-not-install-by-default programs, modify the former variable
|
||||
# to reflect any "do-install" and "don't-install" requests.
|
||||
# That is, add any program specified via --enable-install-program,
|
||||
# and remove any program specified via --enable-no-install-program.
|
||||
# Note how the second argument below is a literal, with ","
|
||||
# separators. That is required due to the way the macro works,
|
||||
# and since the corresponding ./configure option argument is
|
||||
# comma-separated on input.
|
||||
gl_INCLUDE_EXCLUDE_PROG([optional_bin_progs], [`\
|
||||
echo $disabled_by_default_progs \
|
||||
| sed 's/ /,/g'`])
|
||||
END
|
||||
;;
|
||||
1,--automake|1,--for-automake)
|
||||
echo "## $msg"
|
||||
progsdir=src
|
||||
echo no_install__progs =
|
||||
for p in $disabled_by_default_progs; do
|
||||
echo no_install__progs += $progsdir/$p
|
||||
done
|
||||
echo build_if_possible__progs =
|
||||
for p in $build_if_possible_progs; do
|
||||
echo build_if_possible__progs += $progsdir/$p
|
||||
done
|
||||
echo default__progs =
|
||||
for p in $normal_progs; do
|
||||
echo default__progs += $progsdir/$p
|
||||
done
|
||||
;;
|
||||
1,--list-progs)
|
||||
for p in $disabled_by_default_progs $build_if_possible_progs \
|
||||
$normal_progs; do
|
||||
echo $p
|
||||
done
|
||||
;;
|
||||
*)
|
||||
echo "$0: invalid usage" >&2; exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
119
build-aux/gen-single-binary.sh
Executable file
119
build-aux/gen-single-binary.sh
Executable file
|
@ -0,0 +1,119 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Generate the list of rules for the single-binary option based on all the other
|
||||
# binaries found in src/local.mk.
|
||||
#
|
||||
# We need to duplicate the specific rules to build each program into a new
|
||||
# static library target. We can't reuse the existing target since we need to
|
||||
# create a .a file instead of linking the program. We can't do this at
|
||||
# ./configure since the file names need to be available when automake runs
|
||||
# to let it generate all the required rules in Makefile.in. The configure
|
||||
# step will select which ones will be used to build, but they need to be
|
||||
# generated beforehand.
|
||||
#
|
||||
# Instead of maintaining a duplicated list of rules, we generate the
|
||||
# single-binary required rules based on the normal configuration found on
|
||||
# src/local.mk with this script.
|
||||
|
||||
if test "x$1" = "x"; then
|
||||
echo "Usage: $0 path/to/src/local.mk" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
LOCAL_MK=$1
|
||||
GEN_LISTS_OF_PROGRAMS="`dirname "$0"`/gen-lists-of-programs.sh"
|
||||
|
||||
ALL_PROGRAMS=$($GEN_LISTS_OF_PROGRAMS --list-progs \
|
||||
| grep -v -F -e coreutils -e libstdbuf.so \
|
||||
| tr '[' '_')
|
||||
|
||||
# Compute default SOURCES. automake will assume the source file for the
|
||||
# src_${cmd} target to be src/${cmd}.c, but we will add rules to generate
|
||||
# the lib src_libsinglebin_${cmd}_a which won't match the autogenerated source
|
||||
# file. This loop will initialize the default source file and will be reset
|
||||
# later if needed.
|
||||
for cmd in $ALL_PROGRAMS; do
|
||||
eval "src_${cmd}_SOURCES=src/${cmd}.c"
|
||||
done
|
||||
|
||||
# Load actual values from src/local.mk. This will read all the variables from
|
||||
# the local.mk matching the src_${cmd}_... case.
|
||||
while read l; do
|
||||
if echo "$l" | grep -E '^src_[_[:alnum:]]+ +\+?=' > /dev/null; then
|
||||
var=$(echo $l | cut -f 1 -d ' ')
|
||||
value=$(echo $l | cut -f 2- -d =)
|
||||
if [ "$value" != " \$(LDADD)" ]; then
|
||||
oldvalue=""
|
||||
if echo $l | grep -F '+=' >/dev/null; then
|
||||
eval "oldvalue=\${$var}"
|
||||
fi
|
||||
value=$(echo "$value" | sed "s/'/'\"'\"'/g")
|
||||
eval "$var='$oldvalue "$value"'"
|
||||
fi
|
||||
fi
|
||||
done < $LOCAL_MK
|
||||
|
||||
me=`echo "$0" | sed 's,.*/,,'`
|
||||
echo "## Automatically generated by $me. DO NOT EDIT BY HAND!"
|
||||
|
||||
# Override the sources for some tools, to use smaller variants
|
||||
override_single() {
|
||||
from="$1"; to="$2";
|
||||
|
||||
eval "src_${from}_SOURCES='src/coreutils-${from}.c'"
|
||||
eval "src_from_LDADD=\$src_${from}_LDADD"
|
||||
eval "src_${from}_LDADD='$src_from_LDADD src/libsinglebin_${to}.a'"
|
||||
eval "src_libsinglebin_${from}_a_DEPENDENCIES='src/libsinglebin_${to}.a'"
|
||||
echo "src_libsinglebin_${from}_a_DEPENDENCIES = src/libsinglebin_${to}.a"
|
||||
}
|
||||
override_single dir ls
|
||||
override_single vdir ls
|
||||
override_single arch uname
|
||||
override_single chgrp chown
|
||||
|
||||
for cmd in $ALL_PROGRAMS; do
|
||||
echo "# Command $cmd"
|
||||
echo noinst_LIBRARIES += src/libsinglebin_${cmd}.a
|
||||
base="src_libsinglebin_${cmd}_a"
|
||||
# SOURCES
|
||||
var=src_${cmd}_SOURCES
|
||||
eval "value=\$$var"
|
||||
echo "${base}_SOURCES = $value"
|
||||
|
||||
# LDADD
|
||||
var=src_${cmd}_LDADD
|
||||
eval "value=\$$var"
|
||||
if [ "x$value" != "x" ]; then
|
||||
echo "${base}_ldadd = $value"
|
||||
fi
|
||||
|
||||
# DEPENDENCIES
|
||||
var=src_libsinglebin_${cmd}_a_DEPENDENCIES
|
||||
eval "value=\$$var"
|
||||
if [ "x$value" = "x" ]; then
|
||||
echo "$var = \$(src_${cmd}_DEPENDENCIES)"
|
||||
fi
|
||||
|
||||
# CFLAGS
|
||||
# Hack any other program defining a main() replacing its main by
|
||||
# single_binary_main_$PROGRAM_NAME.
|
||||
echo "${base}_CFLAGS = \"-Dmain=single_binary_main_${cmd} (int, char **);" \
|
||||
" int single_binary_main_${cmd}\" " \
|
||||
"-Dusage=_usage_${cmd} \$(src_coreutils_CFLAGS)"
|
||||
var=src_${cmd}_CFLAGS
|
||||
eval "value=\$$var"
|
||||
if [ "x$value" != "x" ]; then
|
||||
echo "${base}_CFLAGS += $value"
|
||||
fi
|
||||
|
||||
# CPPFLAGS
|
||||
var=src_${cmd}_CPPFLAGS
|
||||
eval "value=\$$var"
|
||||
if [ "x$value" != "x" ]; then
|
||||
echo "${base}_CPPFLAGS = $value"
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
562
build-aux/gendocs.sh
Executable file
562
build-aux/gendocs.sh
Executable file
|
@ -0,0 +1,562 @@
|
|||
#!/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=2025-01-01.00
|
||||
|
||||
# Copyright 2003-2025 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_TIME= 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 invocations.
|
||||
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
|
||||
unset source_extra
|
||||
split=node
|
||||
srcfile=
|
||||
texarg="-t @finalout"
|
||||
|
||||
version="gendocs.sh $scriptversion
|
||||
|
||||
Copyright 2025-2025 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_html=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: @{[sort keys %need]}\n"; # for debugging, show images found.
|
||||
FILE: for my $f (sort 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... (%s)\n" "$cmd"
|
||||
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... (%s)\n" "$cmd"
|
||||
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... (%s)\n" "$cmd"
|
||||
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 %s... (%s)\n" "$1" "$cmd"
|
||||
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... (%s)\n" "$cmd"
|
||||
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 %s... (%s)\n" "$split" "$cmd"
|
||||
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... (%s)\n" "$cmd"
|
||||
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" || exit
|
||||
|
||||
# Set PATS to a list of globbing patterns that expand to
|
||||
# file names to be put into the .tar.gz for sources.
|
||||
# Omit patterns that do not expand to file names.
|
||||
pats=
|
||||
|
||||
if case `$MAKEINFO --version | sed -e 's/^[^0-9]*//' -e 1q` in \
|
||||
[1-6]* | 7.[01]*) false;; \
|
||||
*) true;; \
|
||||
esac \
|
||||
; then
|
||||
|
||||
for pat in '*.eps'; do
|
||||
for file in $pat; do
|
||||
test "$file" = "$pat" && test ! -e "$file" || pats="$pats $pat"
|
||||
break
|
||||
done
|
||||
done
|
||||
|
||||
# if $MAKEINFO is recent enough, use --trace-includes on the
|
||||
# $srcfile to get the included files of the targeted manual only
|
||||
base=`basename "$srcfile"`
|
||||
|
||||
cmd="$SETLANG $MAKEINFO $commonarg --trace-includes \"$base\""
|
||||
eval "$cmd" \
|
||||
| tar -czhf "$abs_outdir/$PACKAGE.texi.tar.gz" \
|
||||
--verbatim-files-from -T- -- "$base" $pats \
|
||||
${source_extra+"$source_extra"} \
|
||||
&& ls -l "$abs_outdir/$PACKAGE.texi.tar.gz"
|
||||
else
|
||||
for pat in '*.texinfo' '*.texi' '*.txi' '*.eps'; do
|
||||
for file in $pat; do
|
||||
test "$file" = "$pat" && test ! -e "$file" || pats="$pats $pat"
|
||||
break
|
||||
done
|
||||
done
|
||||
|
||||
tar -czhf "$abs_outdir/$PACKAGE.texi.tar.gz" \
|
||||
-- $pats ${source_extra+"$source_extra"} \
|
||||
&& ls -l "$abs_outdir/$PACKAGE.texi.tar.gz"
|
||||
fi
|
||||
) || exit
|
||||
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... (%s)\n" "$cmd"
|
||||
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... (%s)\n" "$cmd"
|
||||
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... (%s)\n" "$cmd"
|
||||
eval "$cmd"
|
||||
docbook_ascii_size=`calcsize $PACKAGE-db.txt`
|
||||
mv $PACKAGE-db.txt "$outdir/"
|
||||
|
||||
cmd="$DOCBOOK2PDF \"${outdir}/$PACKAGE-db.xml\""
|
||||
printf "\nGenerating docbook PDF... (%s)\n" "$cmd"
|
||||
eval "$cmd"
|
||||
docbook_pdf_size=`calcsize $PACKAGE-db.pdf`
|
||||
mv $PACKAGE-db.pdf "$outdir/"
|
||||
fi
|
||||
|
||||
#
|
||||
printf "\nMaking index.html for %s...\n" "$PACKAGE"
|
||||
if test -z "$use_texi2html"; then
|
||||
if test x$split = xnode; then
|
||||
CONDS="/%%IF *HTML_NODE%%/d;/%%ENDIF *HTML_NODE%%/d;\
|
||||
/%%IF *HTML_CHAPTER%%/,/%%ENDIF *HTML_CHAPTER%%/d;\
|
||||
/%%IF *HTML_SECTION%%/,/%%ENDIF *HTML_SECTION%%/d;"
|
||||
elif test x$split = xchapter; then
|
||||
CONDS="/%%IF *HTML_CHAPTER%%/d;/%%ENDIF *HTML_CHAPTER%%/d;\
|
||||
/%%IF *HTML_SECTION%%/,/%%ENDIF *HTML_SECTION%%/d;\
|
||||
/%%IF *HTML_NODE%%/,/%%ENDIF *HTML_NODE%%/d;"
|
||||
elif test x$split = xsection; then
|
||||
CONDS="/%%IF *HTML_SECTION%%/d;/%%ENDIF *HTML_SECTION%%/d;\
|
||||
/%%IF *HTML_CHAPTER%%/,/%%ENDIF *HTML_CHAPTER%%/d;\
|
||||
/%%IF *HTML_NODE%%/,/%%ENDIF *HTML_NODE%%/d;"
|
||||
else
|
||||
CONDS="/%%IF.*%%/d;/%%ENDIF.*%%/d;" # invalid split argument
|
||||
fi
|
||||
else
|
||||
# for texi2html, we do not take account of --split and simply output
|
||||
# all variants
|
||||
CONDS="/%%IF.*%%/d;/%%ENDIF.*%%/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 nil t)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
251
build-aux/git-version-gen
Executable file
251
build-aux/git-version-gen
Executable file
|
@ -0,0 +1,251 @@
|
|||
#!/bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2025-01-28.09; # UTC
|
||||
|
||||
# Copyright (C) 2007-2025 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/>.
|
||||
|
||||
# This script is derived from GIT-VERSION-GEN from GIT: https://git-scm.com/.
|
||||
|
||||
# It may be run in the following ways, presuming the script is invoked
|
||||
# like "./git-version-gen .tarball-version":
|
||||
#
|
||||
# - from a git repository in which the "git describe" command below
|
||||
# produces useful output (thus requiring at least one signed tag)
|
||||
#
|
||||
# - from a "make dist" non-git-repo directory containing a
|
||||
# .tarball-version file
|
||||
#
|
||||
# - from a "git archive" non-git-repo directory containing a
|
||||
# .tarball-version-git file
|
||||
|
||||
# In order to use intra-version strings in your project, you will need some
|
||||
# separate generated version string files:
|
||||
#
|
||||
# .tarball-version - contains the version number assigned by the maintainer.
|
||||
# Present or missing in a checked-out repository, at the discretion of the
|
||||
# maintainer/contributor. Present in a distribution tarball, because the
|
||||
# tarball does not include the version control history.
|
||||
# Used by git-version-gen as an override.
|
||||
# Cannot be used in any dependencies (since it may be absent).
|
||||
# GNUmakefile has hooks to force a reconfigure at "make dist" time to get
|
||||
# the value correct, without penalizing normal development with extra
|
||||
# reconfigures.
|
||||
#
|
||||
# .tarball-version-git - a file committed to git containing a single
|
||||
# line with the string $Format:%(describe)$ and that the file is
|
||||
# marked in .gitattributes with ".tarball-version-git export-subst".
|
||||
# If the file doesn't exist or the export-subst keyword wasn't
|
||||
# effective, the file is ignored.
|
||||
#
|
||||
# Use the following snippet in your configure.ac, so that $(VERSION) will
|
||||
# automatically be up-to-date each time configure is run (and note that
|
||||
# since configure.ac no longer includes a version string, Makefile rules
|
||||
# should not depend on configure.ac for version updates).
|
||||
#
|
||||
# AC_INIT([@var{package}], [package])
|
||||
# AC_CONFIG_SRCDIR([@var{unique-file-in-source-dir}])
|
||||
# AC_CONFIG_AUX_DIR([build-aux])
|
||||
# VERSION_NUMBER=`cd $srcdir \
|
||||
# && build-aux/git-version-gen .tarball-version`
|
||||
# gl_INIT_PACKAGE_VERSION([$VERSION_NUMBER])
|
||||
# AM_INIT_AUTOMAKE([@var{options}])
|
||||
#
|
||||
# Then use the following lines in your Makefile.am, so that
|
||||
# .tarball-version will exist in distribution tarballs.
|
||||
#
|
||||
# dist-hook: dist-tarball-version
|
||||
# .PHONY: dist-tarball-version
|
||||
# dist-tarball-version:
|
||||
# echo '$(VERSION)' > $(distdir)/.tarball-version
|
||||
#
|
||||
# To setup support for "git archive" tarballs, use the following:
|
||||
#
|
||||
# echo '$Format:%(describe)$' > .tarball-version-git
|
||||
# echo '.tarball-version-git export-subst' >> .gitattributes
|
||||
# git add .tarball-version-git .gitattributes
|
||||
# git commit -m "Add .tarball-version-git for git-version-gen."
|
||||
|
||||
me=$0
|
||||
|
||||
year=`expr "$scriptversion" : '\([^-]*\)'`
|
||||
version="git-version-gen $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."
|
||||
|
||||
usage="\
|
||||
Usage: $me [OPTION]... \$srcdir/.tarball-version [TAG-NORMALIZATION-SED-SCRIPT]
|
||||
Print a version string.
|
||||
|
||||
Options:
|
||||
|
||||
--prefix PREFIX prefix of git tags (default 'v')
|
||||
--fallback VERSION
|
||||
fallback version to use if \"git --version\" fails
|
||||
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
Send patches and bug reports to <bug-gnulib@gnu.org>."
|
||||
|
||||
prefix=v
|
||||
fallback=
|
||||
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--help) echo "$usage"; exit 0;;
|
||||
--version) echo "$version"; exit 0;;
|
||||
--prefix) shift; prefix=${1?};;
|
||||
--fallback) shift; fallback=${1?};;
|
||||
-*)
|
||||
echo "$0: Unknown option '$1'." >&2
|
||||
echo "$0: Try '--help' for more information." >&2
|
||||
exit 1;;
|
||||
*)
|
||||
if test "x$tarball_version_file" = x; then
|
||||
tarball_version_file="$1"
|
||||
elif test "x$tag_sed_script" = x; then
|
||||
tag_sed_script="$1"
|
||||
else
|
||||
echo "$0: extra non-option argument '$1'." >&2
|
||||
exit 1
|
||||
fi;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test "x$tarball_version_file" = x; then
|
||||
echo "$usage"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tag_sed_script="${tag_sed_script:-s/x/x/}"
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# Avoid meddling by environment variable of the same name.
|
||||
v=
|
||||
v_from_git=
|
||||
|
||||
# First see if there is a tarball-only version file.
|
||||
# then try "git describe", then default.
|
||||
if test -f "$tarball_version_file"
|
||||
then
|
||||
v=`cat "$tarball_version_file"` || v=
|
||||
case $v in
|
||||
*$nl*) v= ;; # reject multi-line output
|
||||
esac
|
||||
test "x$v" = x \
|
||||
&& echo "$0: WARNING: $tarball_version_file is damaged" 1>&2
|
||||
fi
|
||||
|
||||
if test "x$v" != x
|
||||
then
|
||||
: # use $v
|
||||
# Otherwise, if there is at least one git commit involving the working
|
||||
# directory, and "git describe" output looks sensible, use that to
|
||||
# derive a version string.
|
||||
elif test "`git log -1 --pretty=format:x . 2>&1`" = x \
|
||||
&& v=`git describe --abbrev=4 --match="$prefix*" HEAD 2>/dev/null \
|
||||
|| git describe --abbrev=4 HEAD 2>/dev/null` \
|
||||
&& v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \
|
||||
&& case $v in
|
||||
$prefix[0-9]*) ;;
|
||||
*) (exit 1) ;;
|
||||
esac
|
||||
then
|
||||
# Is this a new git that lists number of commits since the last
|
||||
# tag or the previous older version that did not?
|
||||
# Newer: v6.10-77-g0f8faeb
|
||||
# Older: v6.10-g0f8faeb
|
||||
vprefix=`expr "X$v" : 'X\(.*\)-g[^-]*$'` || vprefix=$v
|
||||
case $vprefix in
|
||||
*-*) : git describe is probably okay three part flavor ;;
|
||||
*)
|
||||
: git describe is older two part flavor
|
||||
# Recreate the number of commits and rewrite such that the
|
||||
# result is the same as if we were using the newer version
|
||||
# of git describe.
|
||||
vtag=`echo "$v" | sed 's/-.*//'`
|
||||
commit_list=`git rev-list "$vtag"..HEAD 2>/dev/null` \
|
||||
|| { commit_list=failed;
|
||||
echo "$0: WARNING: git rev-list failed" 1>&2; }
|
||||
numcommits=`echo "$commit_list" | wc -l`
|
||||
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
|
||||
test "$commit_list" = failed && v=UNKNOWN
|
||||
;;
|
||||
esac
|
||||
v_from_git=1
|
||||
elif test "x$fallback" = x || git --version >/dev/null 2>&1; then
|
||||
v=UNKNOWN
|
||||
else
|
||||
v=$fallback
|
||||
fi
|
||||
|
||||
if test "x$v" = xUNKNOWN \
|
||||
&& test -f "$tarball_version_file"-git \
|
||||
&& v=$(head -1 "$tarball_version_file"-git); then
|
||||
case $v in
|
||||
*Format*) v=UNKNOWN ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Change the penultimate "-" to ".", for version-comparing tools.
|
||||
# Remove the "g" to save a byte.
|
||||
v=`echo "$v" | sed 's/-\([^-]*\)-g\([^-]*\)$/.\1-\2/'`;
|
||||
|
||||
v=`echo "$v" |sed "s/^$prefix//"`
|
||||
|
||||
# The "-modified" suffix was previously called "-dirty". While this term
|
||||
# was invented by the git people to designate a checkout that is not "clean",
|
||||
# it has a negative connotation that is not in line with the fact that
|
||||
# a Free Software developer routinely works with modified source code.
|
||||
# In fact, modifying source code is the *essence* of Free Software.
|
||||
# What we need here is a term that is suitable for naming tarballs, without
|
||||
# shaming the developer. Giving a name to a tarball is something else than
|
||||
# describing the state of a git checkout.
|
||||
#
|
||||
# Test whether to append the "-modified" suffix only if the version
|
||||
# string we're using came from git. I.e., skip the test if it's "UNKNOWN"
|
||||
# or if it came from .tarball-version.
|
||||
if test "x$v_from_git" != x; then
|
||||
# Don't declare a version "modified" merely because a timestamp has changed.
|
||||
git update-index --refresh > /dev/null 2>&1
|
||||
|
||||
modified=`exec 2>/dev/null;git diff-index --name-only HEAD` || modified=
|
||||
case "$modified" in
|
||||
'') ;;
|
||||
*) # Append the suffix only if there isn't one already.
|
||||
case $v in
|
||||
*-dirty | *-modified) ;;
|
||||
*) v="$v-modified" ;;
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
printf %s "$v"
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
550
build-aux/gitlog-to-changelog
Executable file
550
build-aux/gitlog-to-changelog
Executable file
|
@ -0,0 +1,550 @@
|
|||
#!/bin/sh
|
||||
#! -*-perl-*-
|
||||
|
||||
# Convert git log output to ChangeLog format.
|
||||
|
||||
# Copyright (C) 2008-2025 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 running 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 = '2024-07-17 02:20'; # 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 = $VERSION) =~ s/^(\d*)-.*$/$1/;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
(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] [ARGS]
|
||||
|
||||
Convert git log output to ChangeLog format. If present, any ARGS
|
||||
are passed to "git log". To avoid ARGS being parsed as options to
|
||||
$ME, they may be preceded by '--'.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
--amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
|
||||
makes a change to SHA1's commit log text or metadata.
|
||||
--append-dot append a dot to the first line of each commit message if
|
||||
there is no other punctuation or blank at the end.
|
||||
--no-cluster never cluster commit messages under the same date/author
|
||||
header; the default is to cluster adjacent commit messages
|
||||
if their headers are the same and neither commit message
|
||||
contains multiple paragraphs.
|
||||
--srcdir=DIR the root of the source tree, from which the .git/
|
||||
directory can be derived.
|
||||
--since=DATE convert only the logs since DATE;
|
||||
the default is to convert all log entries.
|
||||
--until=DATE convert only the logs older than DATE.
|
||||
--ignore-matching=PAT ignore commit messages whose first lines match PAT.
|
||||
--ignore-line=PAT ignore lines of commit messages that match PAT.
|
||||
--format=FMT set format string for commit subject and body;
|
||||
see 'man git-log' for the list of format metacharacters;
|
||||
the default is '%s%n%b%n'
|
||||
--strip-tab remove one additional leading TAB from commit message lines.
|
||||
--strip-cherry-pick remove data inserted by "git cherry-pick";
|
||||
this includes the "cherry picked from commit ..." line,
|
||||
and the possible final "Conflicts:" paragraph.
|
||||
--commit-timezone use dates respecting the timezone commits were made in.
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
EXAMPLE:
|
||||
|
||||
$ME --since=2008-01-01 > ChangeLog
|
||||
$ME -- -n 5 foo > last-5-commits-to-branch-foo
|
||||
|
||||
SPECIAL SYNTAX:
|
||||
|
||||
The following types of strings are interpreted specially when they appear
|
||||
at the beginning of a log message line. They are not copied to the output.
|
||||
|
||||
Copyright-paperwork-exempt: Yes
|
||||
Append the "(tiny change)" notation to the usual "date name email"
|
||||
ChangeLog header to mark a change that does not require a copyright
|
||||
assignment.
|
||||
Co-authored-by: Joe User <user\@example.com>
|
||||
List the specified name and email address on a second
|
||||
ChangeLog header, denoting a co-author.
|
||||
Signed-off-by: Joe User <user\@example.com>
|
||||
These lines are simply elided.
|
||||
|
||||
In a FILE specified via --amend, comment lines (starting with "#") are ignored.
|
||||
FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
|
||||
a line) referring to a commit in the current project, and CODE refers to one
|
||||
or more consecutive lines of Perl code. Pairs must be separated by one or
|
||||
more blank line.
|
||||
|
||||
Here is sample input for use with --amend=FILE, from coreutils:
|
||||
|
||||
3a169f4c5d9159283548178668d2fae6fced3030
|
||||
# fix typo in title:
|
||||
s/all tile types/all file types/
|
||||
|
||||
1379ed974f1fa39b12e2ffab18b3f7a607082202
|
||||
# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
|
||||
# Change the author to be Paul. Note the escaped "@":
|
||||
s,Jim .*>,Paul Eggert <eggert\\\@cs.ucla.edu>,
|
||||
|
||||
Send patches and bug reports to <bug-gnulib\@gnu.org>.
|
||||
EOF
|
||||
}
|
||||
exit $exit_code;
|
||||
}
|
||||
|
||||
sub print_version ()
|
||||
{
|
||||
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";
|
||||
}
|
||||
|
||||
# If the string $S is a well-behaved file name, simply return it.
|
||||
# If it contains white space, quotes, etc., quote it, and return the new string.
|
||||
sub shell_quote($)
|
||||
{
|
||||
my ($s) = @_;
|
||||
if ($s =~ m![^\w+/.,-]!)
|
||||
{
|
||||
# Convert each single quote to '\''
|
||||
$s =~ s/\'/\'\\\'\'/g;
|
||||
# Then single quote the string.
|
||||
$s = "'$s'";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub quoted_cmd(@)
|
||||
{
|
||||
return join (' ', map {shell_quote $_} @_);
|
||||
}
|
||||
|
||||
# Parse file F.
|
||||
# Comment lines (starting with "#") are ignored.
|
||||
# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
|
||||
# (alone on a line) referring to a commit in the current project, and
|
||||
# CODE refers to one or more consecutive lines of Perl code.
|
||||
# Pairs must be separated by one or more blank line.
|
||||
sub parse_amend_file($)
|
||||
{
|
||||
my ($f) = @_;
|
||||
|
||||
open F, '<', $f
|
||||
or die "$ME: $f: failed to open for reading: $!\n";
|
||||
|
||||
my $fail;
|
||||
my $h = {};
|
||||
my $in_code = 0;
|
||||
my $sha;
|
||||
while (defined (my $line = <F>))
|
||||
{
|
||||
$line =~ /^\#/
|
||||
and next;
|
||||
chomp $line;
|
||||
$line eq ''
|
||||
and $in_code = 0, next;
|
||||
|
||||
if (!$in_code)
|
||||
{
|
||||
$line =~ /^([[:xdigit:]]{40})$/
|
||||
or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
|
||||
$fail = 1, next;
|
||||
$sha = lc $1;
|
||||
$in_code = 1;
|
||||
exists $h->{$sha}
|
||||
and (warn "$ME: $f:$.: duplicate SHA1\n"),
|
||||
$fail = 1, next;
|
||||
}
|
||||
else
|
||||
{
|
||||
$h->{$sha} ||= '';
|
||||
$h->{$sha} .= "$line\n";
|
||||
}
|
||||
}
|
||||
close F;
|
||||
|
||||
$fail
|
||||
and exit 1;
|
||||
|
||||
return $h;
|
||||
}
|
||||
|
||||
# git_dir_option $SRCDIR
|
||||
#
|
||||
# From $SRCDIR, the --git-dir option to pass to git (none if $SRCDIR
|
||||
# is undef). Return as a list (0 or 1 element).
|
||||
sub git_dir_option($)
|
||||
{
|
||||
my ($srcdir) = @_;
|
||||
my @res = ();
|
||||
if (defined $srcdir)
|
||||
{
|
||||
my $qdir = shell_quote $srcdir;
|
||||
my $cmd = "cd $qdir && git rev-parse --show-toplevel";
|
||||
my $qcmd = shell_quote $cmd;
|
||||
my $git_dir = qx($cmd);
|
||||
defined $git_dir
|
||||
or die "$ME: cannot run $qcmd: $!\n";
|
||||
$? == 0
|
||||
or die "$ME: $qcmd had unexpected exit code or signal ($?)\n";
|
||||
chomp $git_dir;
|
||||
push @res, "--git-dir=$git_dir/.git";
|
||||
}
|
||||
@res;
|
||||
}
|
||||
|
||||
{
|
||||
my $since_date;
|
||||
my $until_date;
|
||||
my $format_string = '%s%n%b%n';
|
||||
my $amend_file;
|
||||
my $append_dot = 0;
|
||||
my $cluster = 1;
|
||||
my $ignore_matching;
|
||||
my $ignore_line;
|
||||
my $strip_tab = 0;
|
||||
my $strip_cherry_pick = 0;
|
||||
my $commit_timezone = 0;
|
||||
my $srcdir;
|
||||
GetOptions
|
||||
(
|
||||
help => sub { usage 0 },
|
||||
version => sub { print_version; exit },
|
||||
'since=s' => \$since_date,
|
||||
'until=s' => \$until_date,
|
||||
'format=s' => \$format_string,
|
||||
'amend=s' => \$amend_file,
|
||||
'append-dot' => \$append_dot,
|
||||
'cluster!' => \$cluster,
|
||||
'ignore-matching=s' => \$ignore_matching,
|
||||
'ignore-line=s' => \$ignore_line,
|
||||
'strip-tab' => \$strip_tab,
|
||||
'strip-cherry-pick' => \$strip_cherry_pick,
|
||||
'commit-timezone' => \$commit_timezone,
|
||||
'srcdir=s' => \$srcdir,
|
||||
) or usage 1;
|
||||
|
||||
defined $since_date
|
||||
and unshift @ARGV, "--since=$since_date";
|
||||
defined $until_date
|
||||
and unshift @ARGV, "--until=$until_date";
|
||||
|
||||
# This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
|
||||
# that makes a correction in the log or attribution of that commit.
|
||||
my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
|
||||
|
||||
my $commit_time_format = $commit_timezone ? '%cI' : '%ct';
|
||||
my @cmd = ('git',
|
||||
git_dir_option $srcdir,
|
||||
qw(log --log-size),
|
||||
("--pretty=format:%H:$commit_time_format"
|
||||
. ' %an <%ae>%n%n'.$format_string, @ARGV));
|
||||
open PIPE, '-|', @cmd
|
||||
or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
|
||||
. "(Is your Git too old? Version 1.5.1 or later is required.)\n");
|
||||
|
||||
my $prev_multi_paragraph;
|
||||
my $prev_date_line = '';
|
||||
my @prev_coauthors = ();
|
||||
my @skipshas = ();
|
||||
while (1)
|
||||
{
|
||||
defined (my $in = <PIPE>)
|
||||
or last;
|
||||
$in =~ /^log size (\d+)$/
|
||||
or die "$ME:$.: Invalid line (expected log size):\n$in";
|
||||
my $log_nbytes = $1;
|
||||
|
||||
my $log;
|
||||
my $n_read = read PIPE, $log, $log_nbytes;
|
||||
$n_read == $log_nbytes
|
||||
or die "$ME:$.: unexpected EOF\n";
|
||||
|
||||
# Extract leading hash.
|
||||
my ($sha, $rest) = split ':', $log, 2;
|
||||
defined $sha
|
||||
or die "$ME:$.: malformed log entry\n";
|
||||
$sha =~ /^[[:xdigit:]]{40}$/
|
||||
or die "$ME:$.: invalid SHA1: $sha\n";
|
||||
|
||||
my $skipflag = 0;
|
||||
if (@skipshas)
|
||||
{
|
||||
foreach(@skipshas)
|
||||
{
|
||||
if ($sha =~ /^$_/)
|
||||
{
|
||||
$skipflag = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If this commit's log requires any transformation, do it now.
|
||||
my $code = $amend_code->{$sha};
|
||||
if (defined $code)
|
||||
{
|
||||
eval 'use Safe';
|
||||
my $s = new Safe;
|
||||
# Put the unpreprocessed entry into "$_".
|
||||
$_ = $rest;
|
||||
|
||||
# Let $code operate on it, safely.
|
||||
my $r = $s->reval("$code")
|
||||
or die "$ME:$.:$sha: failed to eval \"$code\":\n$@\n";
|
||||
|
||||
# Note that we've used this entry.
|
||||
delete $amend_code->{$sha};
|
||||
|
||||
# Update $rest upon success.
|
||||
$rest = $_;
|
||||
}
|
||||
|
||||
# Remove lines inserted by "git cherry-pick".
|
||||
if ($strip_cherry_pick)
|
||||
{
|
||||
$rest =~ s/^\s*Conflicts:\n.*//sm;
|
||||
$rest =~ s/^\s*\(cherry picked from commit [\da-f]+\)\n//m;
|
||||
}
|
||||
|
||||
my @line = split /[ \t]*\n/, $rest;
|
||||
my $author_line = shift @line;
|
||||
defined $author_line
|
||||
or die "$ME:$.: unexpected EOF\n";
|
||||
$author_line =~ /^(\S+) (.*>)$/
|
||||
or die "$ME:$.: Invalid line "
|
||||
. "(expected date/author/email):\n$author_line\n";
|
||||
|
||||
# Author <email>
|
||||
my $author = $2;
|
||||
|
||||
my $commit_date = $1;
|
||||
if (! $commit_timezone)
|
||||
{
|
||||
# Seconds since the Epoch.
|
||||
$commit_date = strftime "%Y-%m-%d", localtime ($commit_date);
|
||||
}
|
||||
else
|
||||
{
|
||||
# ISO 8601 date.
|
||||
$commit_date =~ s/T.*$//;
|
||||
}
|
||||
|
||||
# Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
|
||||
# '(tiny change)' annotation.
|
||||
my $tiny = (grep (/^(?:Copyright-paperwork-exempt|Tiny-change):\s+[Yy]es$/, @line)
|
||||
? ' (tiny change)' : '');
|
||||
|
||||
my $date_line = "$commit_date $author$tiny\n";
|
||||
|
||||
my @coauthors = grep /^Co-authored-by:.*$/, @line;
|
||||
# Omit meta-data lines we've already interpreted.
|
||||
@line = grep !/^(?:Signed-off-by:[ ].*>$
|
||||
|Co-authored-by:[ ]
|
||||
|Copyright-paperwork-exempt:[ ]
|
||||
|Tiny-change:[ ]
|
||||
)/x, @line;
|
||||
|
||||
# Remove leading and trailing blank lines.
|
||||
if (@line)
|
||||
{
|
||||
while ($line[0] =~ /^\s*$/) { shift @line; }
|
||||
while ($line[$#line] =~ /^\s*$/) { pop @line; }
|
||||
}
|
||||
|
||||
# Handle Emacs gitmerge.el "skipped" commits.
|
||||
# Yes, this should be controlled by an option. So sue me.
|
||||
if ( grep /^(; )?Merge from /, @line )
|
||||
{
|
||||
my $found = 0;
|
||||
foreach (@line)
|
||||
{
|
||||
if (grep /^The following commit.*skipped:$/, $_)
|
||||
{
|
||||
$found = 1;
|
||||
## Reset at each merge to reduce chance of false matches.
|
||||
@skipshas = ();
|
||||
next;
|
||||
}
|
||||
if ($found && $_ =~ /^([[:xdigit:]]{7,}) [^ ]/)
|
||||
{
|
||||
push ( @skipshas, $1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Ignore commits that match the --ignore-matching pattern, if specified.
|
||||
if (defined $ignore_matching && @line && $line[0] =~ /$ignore_matching/)
|
||||
{
|
||||
$skipflag = 1;
|
||||
}
|
||||
elsif ($skipflag)
|
||||
{
|
||||
## Perhaps only warn if a pattern matches more than once?
|
||||
warn "$ME: warning: skipping $sha due to $skipflag\n";
|
||||
}
|
||||
|
||||
if (! $skipflag)
|
||||
{
|
||||
if (defined $ignore_line && @line)
|
||||
{
|
||||
@line = grep ! /$ignore_line/, @line;
|
||||
while ($line[$#line] =~ /^\s*$/) { pop @line; }
|
||||
}
|
||||
|
||||
# Record whether there are two or more paragraphs.
|
||||
my $multi_paragraph = grep /^\s*$/, @line;
|
||||
|
||||
# Format 'Co-authored-by: A U Thor <email@example.com>' lines in
|
||||
# standard multi-author ChangeLog format.
|
||||
for (@coauthors)
|
||||
{
|
||||
s/^Co-authored-by:\s*/\t /;
|
||||
s/\s*</ </;
|
||||
|
||||
/<.*?@.*\..*>/
|
||||
or warn "$ME: warning: missing email address for "
|
||||
. substr ($_, 5) . "\n";
|
||||
}
|
||||
|
||||
# If clustering of commit messages has been disabled, if this header
|
||||
# would be different from the previous date/name/etc. header,
|
||||
# or if this or the previous entry consists of two or more paragraphs,
|
||||
# then print the header.
|
||||
if ( ! $cluster
|
||||
|| $date_line ne $prev_date_line
|
||||
|| "@coauthors" ne "@prev_coauthors"
|
||||
|| $multi_paragraph
|
||||
|| $prev_multi_paragraph)
|
||||
{
|
||||
$prev_date_line eq ''
|
||||
or print "\n";
|
||||
print $date_line;
|
||||
@coauthors
|
||||
and print join ("\n", @coauthors), "\n";
|
||||
}
|
||||
$prev_date_line = $date_line;
|
||||
@prev_coauthors = @coauthors;
|
||||
$prev_multi_paragraph = $multi_paragraph;
|
||||
|
||||
# If there were any lines
|
||||
if (@line == 0)
|
||||
{
|
||||
warn "$ME: warning: empty commit message:\n"
|
||||
. " commit $sha\n $date_line\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($append_dot)
|
||||
{
|
||||
# If the first line of the message has enough room, then
|
||||
if (length $line[0] < 72)
|
||||
{
|
||||
# append a dot if there is no other punctuation or blank
|
||||
# at the end.
|
||||
$line[0] =~ /[[:punct:]\s]$/
|
||||
or $line[0] .= '.';
|
||||
}
|
||||
}
|
||||
|
||||
# Remove one additional leading TAB from each line.
|
||||
$strip_tab
|
||||
and map { s/^\t// } @line;
|
||||
|
||||
# Prefix each non-empty line with a TAB.
|
||||
@line = map { length $_ ? "\t$_" : '' } @line;
|
||||
|
||||
print "\n", join ("\n", @line), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
defined ($in = <PIPE>)
|
||||
or last;
|
||||
$in ne "\n"
|
||||
and die "$ME:$.: unexpected line:\n$in";
|
||||
}
|
||||
|
||||
close PIPE
|
||||
or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
|
||||
# FIXME-someday: include $PROCESS_STATUS in the diagnostic
|
||||
|
||||
# Complain about any unused entry in the --amend=F specified file.
|
||||
my $fail = 0;
|
||||
foreach my $sha (sort keys %$amend_code)
|
||||
{
|
||||
warn "$ME:$amend_file: unused entry: $sha\n";
|
||||
$fail = 1;
|
||||
}
|
||||
|
||||
exit $fail;
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# mode: perl
|
||||
# indent-tabs-mode: nil
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
|
||||
# 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:
|
216
build-aux/gnu-web-doc-update
Executable file
216
build-aux/gnu-web-doc-update
Executable file
|
@ -0,0 +1,216 @@
|
|||
#!/bin/sh
|
||||
# Run this after each non-alpha release, to update the web documentation at
|
||||
# https://www.gnu.org/software/$pkg/manual/
|
||||
|
||||
VERSION=2024-07-04.10; # UTC
|
||||
|
||||
# Copyright (C) 2009-2025 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/>.
|
||||
|
||||
ME=$(basename "$0")
|
||||
warn() { printf '%s: %s\n' "$ME" "$*" >&2; }
|
||||
die() { warn "$*"; exit 1; }
|
||||
|
||||
help()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: $ME
|
||||
|
||||
Run this script from top_srcdir (no arguments) after each non-alpha
|
||||
release, to update the web documentation at
|
||||
https://www.gnu.org/software/\$pkg/manual/
|
||||
|
||||
This script assumes you're using git for revision control, and
|
||||
requires a .prev-version file as well as a Makefile, from which it
|
||||
extracts the version number and package name, respectively. Also, it
|
||||
assumes all documentation is in the doc/ sub-directory.
|
||||
|
||||
Options:
|
||||
-C, --builddir=DIR location of (configured) Makefile (default: .)
|
||||
-n, --dry-run don't actually commit anything
|
||||
-m, --mirror remove out of date files from document server
|
||||
-u, --user the name of the CVS user on Savannah
|
||||
--help print this help, then exit
|
||||
--version print version number, then exit
|
||||
|
||||
Report bugs and patches to <bug-gnulib@gnu.org>.
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
version()
|
||||
{
|
||||
year=$(echo "$VERSION" | sed 's/[^0-9].*//')
|
||||
cat <<EOF
|
||||
$ME $VERSION
|
||||
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
|
||||
}
|
||||
|
||||
# find_tool ENVVAR NAMES...
|
||||
# -------------------------
|
||||
# Search for a required program. Use the value of ENVVAR, if set,
|
||||
# otherwise find the first of the NAMES that can be run (i.e.,
|
||||
# supports --version). If found, set ENVVAR to the program name,
|
||||
# die otherwise.
|
||||
#
|
||||
# FIXME: code duplication, see also bootstrap.
|
||||
find_tool ()
|
||||
{
|
||||
find_tool_envvar=$1
|
||||
shift
|
||||
find_tool_names=$@
|
||||
eval "find_tool_res=\$$find_tool_envvar"
|
||||
if test x"$find_tool_res" = x; then
|
||||
for i
|
||||
do
|
||||
if ($i --version </dev/null) >/dev/null 2>&1; then
|
||||
find_tool_res=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
find_tool_error_prefix="\$$find_tool_envvar: "
|
||||
fi
|
||||
test x"$find_tool_res" != x \
|
||||
|| die "one of these is required: $find_tool_names"
|
||||
($find_tool_res --version </dev/null) >/dev/null 2>&1 \
|
||||
|| die "${find_tool_error_prefix}cannot run $find_tool_res --version"
|
||||
eval "$find_tool_envvar=\$find_tool_res"
|
||||
eval "export $find_tool_envvar"
|
||||
}
|
||||
|
||||
## ------ ##
|
||||
## Main. ##
|
||||
## ------ ##
|
||||
|
||||
# Requirements: everything required to bootstrap your package, plus
|
||||
# these.
|
||||
find_tool CVS cvs
|
||||
find_tool GIT git
|
||||
find_tool RSYNC rsync
|
||||
find_tool XARGS gxargs xargs
|
||||
|
||||
builddir=.
|
||||
dryrun=
|
||||
rm_stale='echo'
|
||||
cvs_user="$USER"
|
||||
while test $# != 0
|
||||
do
|
||||
# Handle --option=value by splitting apart and putting back on argv.
|
||||
case $1 in
|
||||
--*=*)
|
||||
opt=$(echo "$1" | sed -e 's/=.*//')
|
||||
val=$(echo "$1" | sed -e 's/[^=]*=//')
|
||||
shift
|
||||
set dummy "$opt" "$val" "$@"; shift
|
||||
;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--help|--version) ${1#--};;
|
||||
-C|--builddir) shift; builddir=$1; shift ;;
|
||||
-n|--dry-run) dryrun=echo; shift;;
|
||||
-m|--mirror) rm_stale=''; shift;;
|
||||
-u|--user) shift; cvs_user=$1; shift ;;
|
||||
--*) die "unrecognized option: $1";;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
test $# = 0 \
|
||||
|| die "too many arguments"
|
||||
|
||||
prev=.prev-version
|
||||
version=$(cat $prev) || die "no $prev file?"
|
||||
pkg=$(sed -n 's/^PACKAGE = \(.*\)/\1/p' $builddir/Makefile) \
|
||||
|| die "no Makefile?"
|
||||
tmp_branch=web-doc-$version-$$
|
||||
current_branch=$($GIT branch | sed -ne '/^\* /{s///;p;q;}')
|
||||
|
||||
cleanup()
|
||||
{
|
||||
__st=$?
|
||||
$dryrun rm -rf "$tmp"
|
||||
$GIT checkout "$current_branch"
|
||||
$GIT submodule update --recursive
|
||||
$GIT branch -d $tmp_branch
|
||||
exit $__st
|
||||
}
|
||||
trap cleanup EXIT
|
||||
trap 'exit $?' HUP INT PIPE TERM
|
||||
|
||||
# We must build using sources for which --version reports the
|
||||
# just-released version number, not some string like 7.6.18-20761.
|
||||
# That version string propagates into all documentation.
|
||||
set -e
|
||||
$GIT checkout -b $tmp_branch v$version
|
||||
$GIT submodule update --recursive
|
||||
./bootstrap
|
||||
srcdir=$(pwd)
|
||||
cd "$builddir"
|
||||
builddir=$(pwd)
|
||||
./config.status --recheck
|
||||
./config.status
|
||||
make
|
||||
make web-manual
|
||||
cd "$srcdir"
|
||||
set +e
|
||||
|
||||
tmp=$(mktemp -d web-doc-update.XXXXXX) || exit 1
|
||||
( cd $tmp \
|
||||
&& $CVS -d $cvs_user@cvs.savannah.gnu.org:/webcvs/$pkg co $pkg )
|
||||
$RSYNC -avP "$builddir"/doc/manual/ $tmp/$pkg/manual
|
||||
|
||||
(
|
||||
cd $tmp/$pkg
|
||||
test -d manual/CVS || $dryrun $CVS add -ko manual
|
||||
|
||||
cd manual
|
||||
|
||||
# Add all the files. This is simpler than trying to add only the
|
||||
# new ones because of new directories
|
||||
# First add non empty dirs individually
|
||||
find . -name CVS -prune -o -type d \! -empty -print \
|
||||
| $XARGS -n1 --no-run-if-empty -- $dryrun $CVS add -ko
|
||||
# Now add all files
|
||||
find . -name CVS -prune -o -type f -print \
|
||||
| $XARGS --no-run-if-empty -- $dryrun $CVS add -ko
|
||||
|
||||
# Report/Remove stale files
|
||||
# excluding doc server specific files like CVS/* and .symlinks
|
||||
if test -n "$rm_stale"; then
|
||||
echo 'Consider the --mirror option if all of the manual is generated,' >&2
|
||||
echo 'which will run `cvs remove` to remove stale files.' >&2
|
||||
fi
|
||||
{ find . \( -name CVS -o -type f -name '.*' \) -prune -o -type f -print
|
||||
(cd "$builddir"/doc/manual/ && find . -type f -print | sed p)
|
||||
} | sort | uniq -u \
|
||||
| $XARGS --no-run-if-empty -- ${rm_stale:-$dryrun} $CVS remove -f
|
||||
|
||||
$dryrun $CVS ci -m $version
|
||||
)
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
|
||||
# time-stamp-start: "VERSION="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
483
build-aux/gnupload
Executable file
483
build-aux/gnupload
Executable file
|
@ -0,0 +1,483 @@
|
|||
#!/bin/sh
|
||||
# Sign files and upload them.
|
||||
|
||||
scriptversion=2024-12-09.08; # UTC
|
||||
|
||||
# Copyright (C) 2004-2025 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.
|
||||
|
||||
You may need to set GPG_TTY=\$(tty) in your environment. See the
|
||||
gpg-agent man page.
|
||||
|
||||
<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 - download.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 nil t)
|
||||
# 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=2024-12-03.03; # 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.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||
General help using GNU software: <https://www.gnu.org/gethelp/>."
|
||||
|
||||
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 (GNU Automake) $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-writable /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 incompatibility 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 nil t)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
230
build-aux/mdate-sh
Executable file
230
build-aux/mdate-sh
Executable file
|
@ -0,0 +1,230 @@
|
|||
#!/bin/sh
|
||||
# Get modification time of a file or directory and pretty-print it.
|
||||
|
||||
scriptversion=2024-12-03.03; # UTC
|
||||
|
||||
# Copyright (C) 1995-2025 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>.
|
||||
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||
General help using GNU software: <https://www.gnu.org/gethelp/>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "mdate-sh (GNU Automake) $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 nil t)
|
||||
# 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:
|
12232
build-aux/texinfo.tex
Normal file
12232
build-aux/texinfo.tex
Normal file
File diff suppressed because it is too large
Load diff
307
build-aux/update-copyright
Executable file
307
build-aux/update-copyright
Executable file
|
@ -0,0 +1,307 @@
|
|||
#!/bin/sh
|
||||
#! -*-perl-*-
|
||||
|
||||
# Update an FSF copyright year list to include the current year.
|
||||
|
||||
# Copyright (C) 2009-2025 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, 2025 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 "\(en" (for troff). 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 running 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 = '2025-01-01.07:36'; # 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;
|
||||
use re 'eval';
|
||||
|
||||
my $copyright_re = 'Copyright';
|
||||
my $circle_c_re = '(?:\([cC]\)|@copyright\{}|\\\\\(co|©|©)';
|
||||
my $ndash_re = '(?:--?|\\\\\(en)';
|
||||
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 $stmt_re;
|
||||
my $found;
|
||||
while (/(^|\n)(.{0,$prefix_max})$copyright_re/cg)
|
||||
{
|
||||
my $pos=pos();
|
||||
my $leading = "$1$2";
|
||||
my $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;
|
||||
}
|
||||
}
|
||||
my $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?|$ndash_re))*"
|
||||
. "((?:\\d\\d)?\\d\\d)$ws_re$holder_re";
|
||||
if (/\G$stmt_remainder_re/)
|
||||
{
|
||||
$found = 1;
|
||||
$stmt_re =
|
||||
quotemeta($leading) . "($copyright_re$stmt_remainder_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/(^|[^\d])$final_year_orig\b/$1$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})$ndash_re(\d{4})/join(', ', $1..$2)/eg;
|
||||
}
|
||||
else
|
||||
{
|
||||
my $ndash = ($ARGV =~ /\.tex(i(nfo)?)?$/ ? "--"
|
||||
: $ARGV =~ /\.(\d[a-z]*|man)(\.in)?$/ && $ARGV !~ /ChangeLog\./ ? "\\(en"
|
||||
: "-");
|
||||
|
||||
$stmt =~
|
||||
s/
|
||||
(\d{4})
|
||||
(?:
|
||||
(,\ |$ndash_re)
|
||||
((??{
|
||||
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/(^|[^\d])(\d{4})\b.*(?:[^\d])(\d{4})\b/$1$2$ndash$3/;
|
||||
}
|
||||
|
||||
# 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.
|
||||
my $p = pos();
|
||||
s/$stmt_re/$stmt_wrapped/g;
|
||||
pos() = $p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found)
|
||||
{
|
||||
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 nil t)
|
||||
# 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:
|
241
build-aux/useless-if-before-free
Executable file
241
build-aux/useless-if-before-free
Executable file
|
@ -0,0 +1,241 @@
|
|||
#!/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-2025 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 = '2024-07-17 02:10'; # 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 = $VERSION) =~ s/^(\d*)-.*$/$1/;
|
||||
|
||||
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
|
||||
|
||||
Send patches and bug reports to <bug-gnulib\@gnu.org>.
|
||||
EOF
|
||||
}
|
||||
exit $exit_code;
|
||||
}
|
||||
|
||||
sub is_NULL ($)
|
||||
{
|
||||
my ($expr) = @_;
|
||||
return ($expr eq 'NULL' || $expr eq 'nullptr' || $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|nullptr))?\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|nullptr))?\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 nil t)
|
||||
## 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=2024-07-04.10; # UTC
|
||||
|
||||
# Copyright (C) 2006-2025 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 nil t)
|
||||
# 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:
|
963
cfg.mk
Normal file
963
cfg.mk
Normal file
|
@ -0,0 +1,963 @@
|
|||
# Customize maint.mk -*- makefile -*-
|
||||
# Copyright (C) 2003-2025 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/>.
|
||||
|
||||
# Used in maint.mk's web-manual rule
|
||||
manual_title = Core GNU utilities
|
||||
|
||||
# Use the direct link. This is guaranteed to work immediately, while
|
||||
# it can take a while for the faster mirror links to become usable.
|
||||
url_dir_list = https://ftp.gnu.org/gnu/$(PACKAGE)
|
||||
|
||||
# Exclude bundled external projects from syntax checks
|
||||
VC_LIST_ALWAYS_EXCLUDE_REGEX = src/blake2/.*$$
|
||||
|
||||
# Tests not to run as part of "make distcheck".
|
||||
local-checks-to-skip = \
|
||||
sc_indent
|
||||
|
||||
# Tools used to bootstrap this package, used for "announcement".
|
||||
bootstrap-tools = autoconf,automake,gnulib,bison
|
||||
|
||||
# Now that we have better tests, make this the default.
|
||||
export VERBOSE = yes
|
||||
|
||||
# Comparing tarball sizes compressed using different xz presets, we see that
|
||||
# an -8e-compressed tarball is only 9KiB larger than the -9e-compressed one.
|
||||
# Using -8e is preferred, since that lets the decompression process use half
|
||||
# the memory (32MiB rather than 64MiB).
|
||||
# $ for i in {7,8,9}{e,}; do \
|
||||
# (n=$(xz -$i < coreutils-8.15*.tar|wc -c);echo $n $i) & done |sort -nr
|
||||
# 5129388 7
|
||||
# 5036524 7e
|
||||
# 5017476 8
|
||||
# 5010604 9
|
||||
# 4923016 8e
|
||||
# 4914152 9e
|
||||
export XZ_OPT = -8e
|
||||
|
||||
old_NEWS_hash = be5016485c56f34b60ba4e6d3b407489
|
||||
|
||||
# Add an exemption for sc_makefile_at_at_check.
|
||||
_makefile_at_at_check_exceptions = \
|
||||
' && !/MAKEINFO/ && !/^cu_install_prog/ && !/dynamic-dep/'
|
||||
|
||||
# Our help-version script is in a slightly different location.
|
||||
_hv_file ?= $(srcdir)/tests/misc/help-version
|
||||
|
||||
world:
|
||||
./bootstrap && \
|
||||
./configure --quiet && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) -j $$(nproc 2>/dev/null || echo 1)
|
||||
|
||||
# Ensure that the list of O_ symbols used to compute O_FULLBLOCK is complete.
|
||||
dd = $(srcdir)/src/dd.c
|
||||
sc_dd_O_FLAGS:
|
||||
@rm -f $@.1 $@.2
|
||||
@{ echo O_FULLBLOCK; echo O_NOCACHE; \
|
||||
perl -nle '/^ +\| (O_\w*)$$/ and print $$1' $(dd); } | sort > $@.1
|
||||
@{ echo O_NOFOLLOW; perl -nle '/{"[a-z]+",\s*(O_\w+)},/ and print $$1' \
|
||||
$(dd); } | sort > $@.2
|
||||
@diff -u $@.1 $@.2; diff=$$?; \
|
||||
rm -f $@.1 $@.2; \
|
||||
test "$$diff" = 0 \
|
||||
|| { echo '$(ME): $(dd) has inconsistent O_ flag lists'>&2; \
|
||||
exit 1; }
|
||||
|
||||
# Ensure that dd's definition of LONGEST_SYMBOL stays in sync
|
||||
# with the strings from the two affected variables.
|
||||
dd_c = $(srcdir)/src/dd.c
|
||||
sc_dd_max_sym_length:
|
||||
ifneq ($(wildcard $(dd_c)),)
|
||||
@len=$$( (sed -n '/conversions\[] =$$/,/^};/p' $(dd_c);\
|
||||
sed -n '/flags\[] =$$/,/^};/p' $(dd_c) ) \
|
||||
|sed -n '/"/s/^[^"]*"\([^"]*\)".*/\1/p'| wc -L);\
|
||||
max=$$(sed -n '/^#define LONGEST_SYMBOL /s///p' $(dd_c) \
|
||||
|tr -d '"' | wc -L); \
|
||||
if test "$$len" = "$$max"; then :; else \
|
||||
echo 'dd.c: LONGEST_SYMBOL is not longest' 1>&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
endif
|
||||
|
||||
# Many m4 macros names once began with 'jm_'.
|
||||
# On 2004-04-13, they were all changed to start with gl_ instead.
|
||||
# Make sure that none are inadvertently reintroduced.
|
||||
sc_prohibit_jm_in_m4:
|
||||
@grep -nE 'jm_[A-Z]' \
|
||||
$$($(VC_LIST) m4 |grep '\.m4$$'; echo /dev/null) && \
|
||||
{ echo '$(ME): do not use jm_ in m4 macro names' \
|
||||
1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that each root-requiring test is run via the "check-root" rule.
|
||||
sc_root_tests:
|
||||
@t1=sc-root.expected; t2=sc-root.actual; \
|
||||
grep -nl '^ *require_root_$$' `$(VC_LIST) tests` | \
|
||||
sed 's|.*/tests/|tests/|' | sort > $$t1; \
|
||||
for t in $(all_root_tests); do echo $$t; done | sort > $$t2; \
|
||||
st=0; diff -u $$t1 $$t2 || st=1; \
|
||||
rm -f $$t1 $$t2; \
|
||||
exit $$st
|
||||
|
||||
# Ensure that all version-controlled test cases are listed in $(all_tests).
|
||||
sc_tests_list_consistency:
|
||||
@bs="\\"; \
|
||||
test_extensions_rx=`echo $(TEST_EXTENSIONS) \
|
||||
| sed -e "s/ /|/g" -e "s/$$bs./$$bs$$bs./g"`; \
|
||||
{ \
|
||||
for t in $(all_tests); do echo $$t; done; \
|
||||
cd $(top_srcdir); \
|
||||
$(SHELL) build-aux/vc-list-files tests \
|
||||
| grep -Ev '^tests/(factor/(run|create-test)|init)\.sh$$' \
|
||||
| grep -E "($$test_extensions_rx)$$"; \
|
||||
} | sort | uniq -u | grep . && exit 1; :
|
||||
|
||||
# Ensure that all version-controlled test scripts are executable.
|
||||
sc_tests_executable:
|
||||
@set -o noglob 2>/dev/null || set -f; \
|
||||
cd $(srcdir); \
|
||||
find_ext="-name '' "`printf -- "-o -name *%s " $(TEST_EXTENSIONS)`;\
|
||||
find $(srcdir)/tests/ \( $$find_ext \) \! -perm -u+x -print \
|
||||
| { sed "s|^$(srcdir)/||"; git ls-files $(srcdir)/tests/; } \
|
||||
| sort | uniq -d \
|
||||
| sed -e "s/^/$(ME): Please make test executable: /" | grep . \
|
||||
&& exit 1; :
|
||||
|
||||
# Ensure all gnulib patches apply cleanly
|
||||
sc_ensure_gl_diffs_apply_cleanly:
|
||||
@find $(srcdir)/gl/ -name '*.diff' | while read p; do \
|
||||
patch --fuzz=0 -f -s -d $(srcdir)/gnulib/ -p1 --dry-run < "$$p" >&2 \
|
||||
|| { echo "$$p" >&2; echo 'To refresh all gl patches run:' \
|
||||
'make refresh-gnulib-patches' >&2; exit 1; } \
|
||||
done
|
||||
|
||||
# Avoid :>file which doesn't propagate errors
|
||||
sc_prohibit_colon_redirection:
|
||||
@cd $(srcdir)/tests && GIT_PAGER= git grep -En ': *>.*\|\|' \
|
||||
&& { echo '$(ME): '"The leading colon in :> will hide errors" >&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
# Ensure emit_mandatory_arg_note() is called if required
|
||||
sc_ensure_emit_mandatory_arg_note:
|
||||
@cd $(srcdir)/src && GIT_PAGER= git \
|
||||
grep -l -- '^ *-[^-].*--.*[^[]=' *.c \
|
||||
| xargs grep -L emit_mandatory_arg_note | grep . \
|
||||
&& { echo '$(ME): '"emit_mandatory_arg_note() missing" 1>&2; \
|
||||
exit 1; } || :
|
||||
|
||||
# Create a list of regular expressions matching the names
|
||||
# of files included from system.h. Exclude a couple.
|
||||
.re-list:
|
||||
@sed -n '/^# *include /s///p' $(srcdir)/src/system.h \
|
||||
| grep -Ev 'sys/(param|file)\.h' \
|
||||
| sed 's/ .*//;;s/^["<]/^# *include [<"]/;s/\.h[">]$$/\\.h[">]/' \
|
||||
> $@-t
|
||||
@mv $@-t $@
|
||||
|
||||
define gl_trap_
|
||||
Exit () { set +e; (exit $$1); exit $$1; }; \
|
||||
for sig in 1 2 3 13 15; do \
|
||||
eval "trap 'Exit $$(expr $$sig + 128)' $$sig"; \
|
||||
done
|
||||
endef
|
||||
|
||||
# Files in src/ should not include directly any of
|
||||
# the headers already included via system.h.
|
||||
sc_system_h_headers: .re-list
|
||||
@if test -f $(srcdir)/src/system.h; then \
|
||||
trap 'rc=$$?; rm -f .re-list; exit $$rc' 0; \
|
||||
$(gl_trap_); \
|
||||
grep -nE -f .re-list \
|
||||
$$($(VC_LIST_EXCEPT) | grep -E '^($(srcdir)/)?src/') \
|
||||
&& { echo '$(ME): the above are already included via system.h'\
|
||||
1>&2; exit 1; } || :; \
|
||||
fi
|
||||
|
||||
# Files in src/ should not use '%s' notation in format strings,
|
||||
# i.e., single quotes around %s (or similar) should be avoided.
|
||||
sc_prohibit_quotes_notation:
|
||||
@cd $(srcdir)/src && GIT_PAGER= git grep -n "\".*[\`']%s'.*\"" *.c \
|
||||
&& { echo '$(ME): '"Use quote() to avoid quoted '%s' notation" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
error_fns = (error|diagnose)
|
||||
|
||||
# Files in src/ should quote all strings in error() output, so that
|
||||
# unexpected input chars like \r etc. don't corrupt the error.
|
||||
# In edge cases this can be avoided by putting the format string
|
||||
# on a separate line to the arguments, or the arguments in parenthesis.
|
||||
sc_error_quotes:
|
||||
@cd $(srcdir)/src \
|
||||
&& GIT_PAGER= git grep -E -n '$(error_fns) *\(.*%s.*, [^(]*\);$$' \
|
||||
*.c | grep -v ', q' \
|
||||
&& { echo '$(ME): '"Use quote() for error string arguments" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
# Files in src/ should quote all file names in error() output
|
||||
# using quotef(), to provide quoting only when necessary,
|
||||
# but also provide better support for copy and paste when used.
|
||||
sc_error_shell_quotes:
|
||||
@cd $(srcdir)/src && \
|
||||
{ GIT_PAGER= git grep -E \
|
||||
'$(error_fns) \(.*%s[:"], .*(name|file)[^"]*\);$$' *.c; \
|
||||
GIT_PAGER= git grep -E \
|
||||
' quote[ _].*file' *.c; } \
|
||||
| grep -Ev '(quotef|q[^ ]*name)' \
|
||||
&& { echo '$(ME): '"Use quotef() for colon delimited names" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
# Files in src/ should quote all file names in error() output
|
||||
# using quoteaf() when the name is separated with spaces,
|
||||
# to distinguish the file name at issue and
|
||||
# to provide better support for copy and paste.
|
||||
sc_error_shell_always_quotes:
|
||||
@cd $(srcdir)/src && GIT_PAGER= git grep -E \
|
||||
'$(error_fns) \(.*[^:] %s[ "].*, .*(name|file)[^"]*\);$$' \
|
||||
*.c | grep -Ev '(quoteaf|q[^ ]*name)' \
|
||||
&& { echo '$(ME): '"Use quoteaf() for space delimited names" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
@cd $(srcdir)/src && GIT_PAGER= git grep -E -A1 \
|
||||
'$(error_fns) \([^%]*[^:] %s[ "]' *.c | grep 'quotef' \
|
||||
&& { echo '$(ME): '"Use quoteaf() for space delimited names" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
# Avoid unstyled quoting to internal slots and thus destined for diagnostics
|
||||
# as that can leak unescaped control characters to the output, when using
|
||||
# the default "literal" quoting style.
|
||||
# Instead use quotef(), or quoteaf() or in edge cases quotearg_n_style_colon().
|
||||
# A more general PCRE would be @prohibit='quotearg_.*(?!(style|buffer))'
|
||||
sc_prohibit-quotearg:
|
||||
@prohibit='quotearg(_n)?(|_colon|_char|_mem) ' \
|
||||
in_vc_files='\.c$$' \
|
||||
halt='Unstyled diagnostic quoting detected' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
sc_prohibit-skip:
|
||||
@prohibit='\|\| skip ' \
|
||||
halt='Use skip_ not skip' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
sc_sun_os_names:
|
||||
@grep -nEi \
|
||||
'solaris[^[:alnum:]]*2\.(7|8|9|[1-9][0-9])|sunos[^[:alnum:]][6-9]' \
|
||||
$$($(VC_LIST_EXCEPT)) && \
|
||||
{ echo '$(ME): found misuse of Sun OS version numbers' 1>&2; \
|
||||
exit 1; } || :
|
||||
|
||||
# Ensure that the list of programs and author names is accurate.
|
||||
# We need a UTF8 locale. If a lack of locale support or a missing
|
||||
# translation inhibits printing of UTF-8 names, just skip this test.
|
||||
au_dotdot = authors-dotdot
|
||||
au_actual = authors-actual
|
||||
sc_check-AUTHORS: $(all_programs)
|
||||
@locale=en_US.UTF-8; \
|
||||
LC_ALL=$$locale ./src/factor --version \
|
||||
| grep ' Torbjorn ' > /dev/null \
|
||||
&& { echo "$@: skipping this check"; exit 0; }; \
|
||||
rm -f $(au_actual) $(au_dotdot); \
|
||||
for i in `ls $(all_programs) \
|
||||
| sed -e 's,^src/,,' -e 's,$(EXEEXT)$$,,' \
|
||||
| sed /libstdbuf/d \
|
||||
| $(ASSORT) -u`; do \
|
||||
test "$$i" = '[' && continue; \
|
||||
exe=$$i; \
|
||||
if test "$$i" = install; then \
|
||||
exe=ginstall; \
|
||||
elif test "$$i" = test; then \
|
||||
exe='['; \
|
||||
fi; \
|
||||
LC_ALL=$$locale ./src/$$exe --version \
|
||||
| perl -0 -p -e 's/,\n/, /gm' \
|
||||
| sed -n -e '/Written by /{ s//'"$$i"': /;' \
|
||||
-e 's/,* and /, /; s/\.$$//; p; }'; \
|
||||
done > $(au_actual) && \
|
||||
sed -n '/^[^ ][^ ]*:/p' $(srcdir)/AUTHORS > $(au_dotdot) \
|
||||
&& diff $(au_actual) $(au_dotdot) \
|
||||
&& rm -f $(au_actual) $(au_dotdot)
|
||||
|
||||
# Ensure the alternative __attribute (keyword) form isn't used as
|
||||
# that form is not elided where required. Also ensure that we don't
|
||||
# directly use attributes already defined by gnulib.
|
||||
# TODO: move the check for _GL... attributes to gnulib.
|
||||
sc_prohibit-gl-attributes:
|
||||
@prohibit='__attribute |__(unused|pure|const)__' \
|
||||
in_vc_files='\.[ch]$$' \
|
||||
halt='Use _GL... attribute macros' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Prefer the const declaration form, with const following the type
|
||||
sc_prohibit-const-char:
|
||||
@prohibit='const char \*' \
|
||||
in_vc_files='\.[ch]$$' \
|
||||
halt='Use char const *, not const char *' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Look for lines longer than 80 characters, except omit:
|
||||
# - urls
|
||||
# - the fdl.texi file copied from gnulib,
|
||||
# - the help2man script copied from upstream,
|
||||
# - tests involving long checksum lines, and
|
||||
# - the 'pr' test cases.
|
||||
FILTER_LONG_LINES = \
|
||||
\|^[^:]*NEWS:.*https\{,1\}://| d; \
|
||||
\|^[^:]*doc/fdl.texi:| d; \
|
||||
\|^[^:]*man/help2man:| d; \
|
||||
\|^[^:]*tests/cksum/sha[0-9]*sum.*\.pl[-:]| d; \
|
||||
\|^[^:]*tests/pr/|{ \|^[^:]*tests/pr/pr-tests:| !d; };
|
||||
sc_long_lines:
|
||||
@wc -L /dev/null >/dev/null 2>/dev/null \
|
||||
|| { echo "$@: skipping: wc -L not supported"; exit 0; }; \
|
||||
sed -r 1q /dev/null 2>/dev/null \
|
||||
|| { echo "$@: skipping: sed -r not supported"; exit 0; }; \
|
||||
files=$$($(VC_LIST_EXCEPT) | xargs wc -L | sed -rn '/ total$$/d;\
|
||||
s/^ *(8[1-9]|9[0-9]|[0-9]{3,}) //p'); \
|
||||
halt='line(s) with more than 80 characters; reindent'; \
|
||||
for file in $$files; do \
|
||||
expand $$file | grep -nE '^.{80}.' | \
|
||||
sed -e "s|^|$$file:|" -e '$(FILTER_LONG_LINES)'; \
|
||||
done | grep . && { msg="$$halt" $(_sc_say_and_exit) } || :
|
||||
|
||||
# Option descriptions should not start with a capital letter.
|
||||
# One could grep source directly as follows:
|
||||
# grep -E " {2,6}-.*[^.] [A-Z][a-z]" $$($(VC_LIST_EXCEPT) | grep '\.c$$')
|
||||
# but that would miss descriptions not on the same line as the -option.
|
||||
sc_option_desc_uppercase: $(ALL_MANS)
|
||||
@grep '^\\fB\\-' -A1 man/*.1 | LC_ALL=C grep '\.1.[A-Z][a-z]' \
|
||||
&& { echo 1>&2 '$@: found initial capitals in --help'; exit 1; } || :
|
||||
|
||||
# '--' should not be treated as '–' (U+2013 EN DASH) in long option names.
|
||||
sc_texi_long_option_escaped: doc/coreutils.info
|
||||
@grep ' –[^ ]' '$<' \
|
||||
&& { echo 1>&2 '$@: found unquoted --long-option'; exit 1; } || :
|
||||
|
||||
# Ensure all man/*.[1x] files are present.
|
||||
sc_man_file_correlation: check-x-vs-1 check-programs-vs-x
|
||||
|
||||
# Ensure that for each .x file in the 'man/' subdirectory, there is a
|
||||
# corresponding .1 file in the definition of $(EXTRA_MANS).
|
||||
# But since that expansion usually lacks programs like arch and hostname,
|
||||
# add them here manually.
|
||||
.PHONY: check-x-vs-1
|
||||
check-x-vs-1:
|
||||
@PATH=./src$(PATH_SEPARATOR)$$PATH; export PATH; \
|
||||
t=$@-t; \
|
||||
(cd $(srcdir)/man && ls -1 *.x) \
|
||||
| sed 's/\.x$$//' | $(ASSORT) > $$t; \
|
||||
(echo $(patsubst man/%,%,$(ALL_MANS)) \
|
||||
| tr -s ' ' '\n' | sed 's/\.1$$//') \
|
||||
| $(ASSORT) -u | diff - $$t || { rm $$t; exit 1; }; \
|
||||
rm $$t
|
||||
|
||||
# Ensure that non-trivial .x files in the 'man/' subdirectory,
|
||||
# i.e., files exceeding a line count of 20 or a byte count of 1000,
|
||||
# contain a Copyright notice.
|
||||
.PHONY: sc_man_check_x_copyright
|
||||
sc_man_check_x_copyright:
|
||||
@status=0; \
|
||||
cd $(srcdir) && wc -cl man/*.x | head -n-1 \
|
||||
| awk '$$1 >= 20 || $$2 >= 1000 {print $$3}' \
|
||||
| xargs grep -L 'Copyright .* Free Software Foundation' \
|
||||
| grep . \
|
||||
&& { echo 1>&2 '$@: exceeding file size/line count limit' \
|
||||
'- please add a copyright note'; status=1; }; \
|
||||
exit $$status
|
||||
|
||||
# Writing a portable rule to generate a manpage like '[.1' would be
|
||||
# a nightmare, so filter that out.
|
||||
all-progs-but-lbracket = $(filter-out [,$(patsubst src/%,%,$(all_programs)))
|
||||
|
||||
# Ensure that for each coreutils program there is a corresponding
|
||||
# '.x' file in the 'man/' subdirectory.
|
||||
.PHONY: check-programs-vs-x
|
||||
check-programs-vs-x:
|
||||
@status=0; \
|
||||
for p in dummy $(all-progs-but-lbracket); do \
|
||||
case $$p in *.so) continue;; esac; \
|
||||
test $$p = dummy && continue; \
|
||||
test $$p = ginstall && p=install || : ; \
|
||||
test -f $(srcdir)/man/$$p.x \
|
||||
|| { echo missing $$p.x 1>&2; status=1; }; \
|
||||
done; \
|
||||
exit $$status
|
||||
|
||||
# Ensure we can check out on case insensitive file systems
|
||||
sc_case_insensitive_file_names: src/uniq
|
||||
@git -C $(srcdir) ls-files | sort -f | src/uniq -Di | grep . && \
|
||||
{ echo "$(ME): the above file(s) conflict on case insensitive" \
|
||||
" file systems" 1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that the end of each release's section is marked by two empty lines.
|
||||
sc_NEWS_two_empty_lines:
|
||||
@sed -n 4,/Noteworthy/p $(srcdir)/NEWS \
|
||||
| perl -n0e '/(^|\n)\n\n\* Noteworthy/ or exit 1' \
|
||||
|| { echo '$(ME): use two empty lines to separate NEWS sections' \
|
||||
1>&2; exit 1; } || :
|
||||
|
||||
# With split lines, don't leave an operator at end of line.
|
||||
# Instead, put it on the following line, where it is more apparent.
|
||||
# Don't bother checking for "*" at end of line, since it provokes
|
||||
# far too many false positives, matching constructs like "TYPE *".
|
||||
# Similarly, omit "=" (initializers).
|
||||
binop_re_ ?= [-/+^!<>]|[-/+*^!<>=]=|&&?|\|\|?|<<=?|>>=?
|
||||
sc_prohibit_operator_at_end_of_line:
|
||||
@prohibit='. ($(binop_re_))$$' \
|
||||
in_vc_files='\.[chly]$$' \
|
||||
halt='found operator at end of line' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Partial substitutes for GNU extensions \< and \> in regexps.
|
||||
begword = (^|[^_[:alnum:]])
|
||||
endword = ($$|[^_[:alnum:]])
|
||||
|
||||
# Don't use address of "stat" or "lstat" functions
|
||||
sc_prohibit_stat_macro_address:
|
||||
@prohibit='$(begword)l?stat '':|&l?stat$(endword)' \
|
||||
halt='stat() and lstat() may be function-like macros' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that date's --help output stays in sync with the info
|
||||
# documentation for GNU strftime. The only exception is %N and %q,
|
||||
# which date accepts but GNU strftime does not.
|
||||
#
|
||||
# "info foo" fails with error, but not "info foo >/dev/null".
|
||||
extract_char = sed 's/^[^%][^%]*%\(.\).*/\1/'
|
||||
sc_strftime_check:
|
||||
@if test -f $(srcdir)/src/date.c; then \
|
||||
if info libc date calendar format 2>/dev/null | \
|
||||
grep "^ *['\`]%.'$$" >$@-tmp; then \
|
||||
{ echo N; echo q; $(extract_char) $@-tmp; }| sort \
|
||||
>$@-info; \
|
||||
grep '^ %. ' $(srcdir)/src/date.c | sort \
|
||||
| $(extract_char) > $@-src; \
|
||||
diff -u $@-src $@-info || exit 1; \
|
||||
else \
|
||||
echo '$(ME): skipping $@: libc info not installed' 1>&2; \
|
||||
fi; \
|
||||
rm -f $@-info $@-src $@-tmp; \
|
||||
fi
|
||||
|
||||
# Indent only with spaces.
|
||||
sc_prohibit_tab_based_indentation:
|
||||
@prohibit='^ * ' \
|
||||
halt='TAB in indentation; use only spaces' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Enforce lowercase 'e' in "I.e.".
|
||||
sc_prohibit_uppercase_id_est:
|
||||
@prohibit='I\.E\.' \
|
||||
halt='Uppercase "Id Est" abbreviation; use "I.e.," instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Enforce double-space before "I.e." at the beginning of a sentence.
|
||||
sc_ensure_dblspace_after_dot_before_id_est:
|
||||
@prohibit='\. I\.e\.' \
|
||||
halt='Single space after dot before "i.e."; use ". i.e." instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Enforce comma after "i.e." (at least before a blank or at EOL).
|
||||
sc_ensure_comma_after_id_est:
|
||||
@prohibit='[Ii]\.e\.( |$$)' \
|
||||
halt='Missing comma after "i.e."; use "i.e.," instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# The SEE ALSO section of a man page should not be terminated with
|
||||
# a period. Check the first line after each "SEE ALSO" line in man/*.x:
|
||||
sc_prohibit_man_see_also_period:
|
||||
@grep -nB1 '\.$$' $$($(VC_LIST_EXCEPT) | grep 'man/.*\.x$$') \
|
||||
| grep -A1 -e '-\[SEE ALSO]' | grep '\.$$' && \
|
||||
{ echo '$(ME): do not end "SEE ALSO" section with a period' \
|
||||
1>&2; exit 1; } || :
|
||||
|
||||
sc_prohibit_exit_write_error:
|
||||
@prohibit='error.*EXIT_FAILURE.*write error' \
|
||||
in_vc_files='\.c$$' \
|
||||
halt='Use write_error() instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
sc_prohibit_NULL:
|
||||
@prohibit='$(begword)NULL$(endword)' \
|
||||
in_vc_files='\.[ch]$$' \
|
||||
halt='use nullptr instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
sc_prohibit_bare_set:
|
||||
@prohibit='^ *set [`$$]' \
|
||||
in_vc_files='\.sh$$' \
|
||||
halt='use set -- $$args instead of set $$args' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Don't use "indent-tabs-mode: nil" anymore. No longer needed.
|
||||
sc_prohibit_emacs__indent_tabs_mode__setting:
|
||||
@prohibit='^( *[*#] *)?indent-tabs-mode:' \
|
||||
halt='use of emacs indent-tabs-mode: setting' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that tests don't include a redundant fail=0.
|
||||
sc_prohibit_fail_0:
|
||||
@prohibit='$(begword)fail=0$(endword)' \
|
||||
halt='fail=0 initialization' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that tests don't use `cmd ... && fail=1` as that hides crashes.
|
||||
# The "exclude" expression allows common idioms like `test ... && fail=1`
|
||||
# and the 2>... portion allows commands that redirect stderr and so probably
|
||||
# independently check its contents and thus detect any crash messages.
|
||||
sc_prohibit_and_fail_1:
|
||||
@prohibit='&& fail=1' \
|
||||
exclude='(returns_|stat|kill|test |EGREP|grep|compare|2> *[^/])' \
|
||||
halt='&& fail=1 detected. Please use: returns_ 1 ... || fail=1' \
|
||||
in_vc_files='^tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that tests don't use `cmd ... || fail` as that's a noop.
|
||||
sc_prohibit_or_fail:
|
||||
@prohibit='\|\| fail$$' \
|
||||
exclude=':#' \
|
||||
halt='|| fail detected. Please use: || fail=1' \
|
||||
in_vc_files='^tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that env vars are not passed through returns_ as
|
||||
# that was seen to fail on FreeBSD /bin/sh at least
|
||||
sc_prohibit_env_returns:
|
||||
@prohibit='=[^ ]* returns_ ' \
|
||||
exclude='_ returns_ ' \
|
||||
halt='Passing env vars to returns_ is non portable' \
|
||||
in_vc_files='^tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# The mode part of a setfacl -m option argument must be three bytes long.
|
||||
# I.e., an argument of user:bin:rw or user:bin:r will make Solaris 10's
|
||||
# setfacl reject it with: "Unrecognized character found in mode field".
|
||||
# Use hyphens to give it a length of 3: "...:rw-" or "...:r--".
|
||||
sc_prohibit_short_facl_mode_spec:
|
||||
@prohibit='$(begword)setfacl .*-m.*:.*:[rwx-]{1,2} ' \
|
||||
halt='setfacl mode string length < 3; extend with hyphen(s)' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that "stdio--.h" is used where appropriate.
|
||||
sc_require_stdio_safer:
|
||||
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
|
||||
files=$$(grep -El '$(begword)freopen ?\(' $$($(VC_LIST_EXCEPT)\
|
||||
| grep '\.[ch]$$')); \
|
||||
test -n "$$files" && grep -LE 'include "stdio--.h"' $$files \
|
||||
| grep . && \
|
||||
{ echo '$(ME): the above files should use "stdio--.h"' \
|
||||
1>&2; exit 1; } || :; \
|
||||
else :; \
|
||||
fi
|
||||
|
||||
# Ensure that "stdlib--.h" is used where appropriate.
|
||||
sc_require_stdlib_safer:
|
||||
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
|
||||
files=$$(grep -El '$(begword)mkstemp ?\(' $$($(VC_LIST_EXCEPT)\
|
||||
| grep '\.[ch]$$')); \
|
||||
test -n "$$files" && grep -LE 'include "stdlib--.h"' $$files \
|
||||
| grep . && \
|
||||
{ echo '$(ME): the above files should use "stdlib--.h"' \
|
||||
1>&2; exit 1; } || :; \
|
||||
else :; \
|
||||
fi
|
||||
|
||||
sc_prohibit_perl_hash_quotes:
|
||||
@prohibit="\{'[A-Z_]+' *[=}]" \
|
||||
halt="in Perl code, write \$$hash{KEY}, not \$$hash{'K''EY'}" \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Prefer xnanosleep over other less-precise sleep methods
|
||||
sc_prohibit_sleep:
|
||||
@prohibit='$(begword)(nano|u)?sleep \(' \
|
||||
halt='prefer xnanosleep over other sleep interfaces' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Use print_ver_ (from init.cfg), not open-coded $VERBOSE check.
|
||||
sc_prohibit_verbose_version:
|
||||
@prohibit='test "\$$VERBOSE" = yes && .* --version' \
|
||||
halt='use the print_ver_ function instead...' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Enforce print_ver_ tracking of dependencies
|
||||
# Each coreutils specific program a test requires
|
||||
# should be tagged by calling through env(1).
|
||||
sc_env_test_dependencies:
|
||||
@cd $(top_srcdir) && GIT_PAGER= git grep -E \
|
||||
"env ($$(build-aux/gen-lists-of-programs.sh --list-progs | \
|
||||
grep -vF '[' |paste -d'|' -s))" tests | \
|
||||
sed "s/\([^:]\):.*env \([^)' ]*\).*/\1 \2/" | uniq | \
|
||||
while read test prog; do \
|
||||
printf '%s' $$test | grep '\.pl$$' >/dev/null && continue; \
|
||||
grep "print_ver_.* $$prog" $$test >/dev/null \
|
||||
|| echo $$test should call: print_ver_ $$prog; \
|
||||
done | grep . && exit 1 || :
|
||||
|
||||
# Use framework_failure_, not the old name without the trailing underscore.
|
||||
sc_prohibit_framework_failure:
|
||||
@prohibit='$(begword)framework_''failure$(endword)' \
|
||||
halt='use framework_failure_ instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Prohibit the use of `...` in tests/. Use $(...) instead.
|
||||
sc_prohibit_test_backticks:
|
||||
@prohibit='`' in_vc_files='^tests/' \
|
||||
halt='use $$(...), not `...` in tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that compare is used to check empty files
|
||||
# so that the unexpected contents are displayed
|
||||
sc_prohibit_test_empty:
|
||||
@prohibit='test -s.*&&' in_vc_files='^tests/' \
|
||||
halt='use `compare /dev/null ...`, not `test -s ...` in tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Programs like sort, ls, expr use PROG_FAILURE in place of EXIT_FAILURE.
|
||||
# Others, use the EXIT_CANCELED, EXIT_ENOENT, etc. macros defined in system.h.
|
||||
# In those programs, ensure that EXIT_FAILURE is not used by mistake.
|
||||
sc_some_programs_must_avoid_exit_failure:
|
||||
@cd $(srcdir) \
|
||||
&& grep -nw EXIT_FAILURE \
|
||||
$$(git grep -El '[^T]_FAILURE|EXIT_CANCELED' src/) \
|
||||
| grep -v '^src/system\.h:' \
|
||||
| grep -vE '= EXIT_FAILURE|return .* \?' | grep . \
|
||||
&& { echo '$(ME): do not use EXIT_FAILURE in the above' \
|
||||
1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that tests call the get_min_ulimit_v_ function if using ulimit -v
|
||||
sc_prohibit_test_ulimit_without_require_:
|
||||
@(git -C $(srcdir) grep -l get_min_ulimit_v_ tests; \
|
||||
git -C $(srcdir) grep -l 'ulimit -v' tests) \
|
||||
| sort | uniq -u | grep . && { echo "$(ME): the above test(s)"\
|
||||
" should match get_min_ulimit_v_ with ulimit -v" 1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that tests call the cleanup_ function if using background processes
|
||||
sc_prohibit_test_background_without_cleanup_:
|
||||
@(git -C $(srcdir) grep -El '( &$$|&[^&]*=\$$!)' tests; \
|
||||
git -C $(srcdir) grep -l 'cleanup_()' tests | sed p) \
|
||||
| sort | uniq -u | grep . && { echo "$(ME): the above test(s)"\
|
||||
" should use cleanup_ for background processes" 1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that tests call the print_ver_ function for programs which are
|
||||
# actually used in that test.
|
||||
sc_prohibit_test_calls_print_ver_with_irrelevant_argument:
|
||||
@git -C $(srcdir) grep -w print_ver_ tests \
|
||||
| sed 's#:print_ver_##' \
|
||||
| { fail=0; \
|
||||
while read file name; do \
|
||||
for i in $$name; do \
|
||||
case "$$i" in install) i=ginstall;; esac; \
|
||||
grep -w "$$i" $$file|grep -vw print_ver_|grep . >/dev/null \
|
||||
|| { fail=1; \
|
||||
echo "*** Test: $$file, offending: $$i." 1>&2; };\
|
||||
done; \
|
||||
done; \
|
||||
test $$fail = 0 || exit 1; \
|
||||
} || { echo "$(ME): the above test(s) call print_ver_ for" \
|
||||
"program(s) they don't use" 1>&2; exit 1; }
|
||||
|
||||
# Exempt the contents of any usage function from the following.
|
||||
_continued_string_col_1 = \
|
||||
s/^usage .*?\n}//ms;/\\\n\w/ and print ("$$ARGV\n"),$$e=1;END{$$e||=0;exit $$e}
|
||||
# Ding any source file that has a continued string with an alphabetic in the
|
||||
# first column of the following line. We prohibit them because they usually
|
||||
# trigger false positives in tools that try to map an arbitrary line number
|
||||
# to the enclosing function name. Of course, very many strings do precisely
|
||||
# this, *when they are part of the usage function*. That is why we exempt
|
||||
# the contents of any function named "usage".
|
||||
sc_prohibit_continued_string_alpha_in_column_1:
|
||||
@perl -0777 -ne '$(_continued_string_col_1)' \
|
||||
$$($(VC_LIST_EXCEPT) | grep '\.[ch]$$') \
|
||||
|| { echo '$(ME): continued string with word in first column' \
|
||||
1>&2; exit 1; } || :
|
||||
# Use this to list offending lines:
|
||||
# git ls-files |grep '\.[ch]$' | xargs \
|
||||
# perl -n -0777 -e 's/^usage.*?\n}//ms;/\\\n\w/ and print "$ARGV\n"' \
|
||||
# | xargs grep -A1 '\\$'|grep '\.[ch][:-][_a-zA-Z]'
|
||||
|
||||
|
||||
###########################################################
|
||||
_p0 = \([^"'/]\|"\([^\"]\|[\].\)*"\|'\([^\']\|[\].\)*'
|
||||
_pre = $(_p0)\|[/][^"'/*]\|[/]"\([^\"]\|[\].\)*"\|[/]'\([^\']\|[\].\)*'\)*
|
||||
_pre_anchored = ^\($(_pre)\)
|
||||
_comment_and_close = [^*]\|[*][^/*]\)*[*][*]*/
|
||||
# help font-lock mode: '
|
||||
|
||||
# A sed expression that removes ANSI C and ISO C99 comments.
|
||||
# Derived from the one in GNU gettext's 'moopp' preprocessor.
|
||||
_sed_remove_comments = \
|
||||
/[/][/*]/{ \
|
||||
ta; \
|
||||
:a; \
|
||||
s,$(_pre_anchored)//.*,\1,; \
|
||||
te; \
|
||||
s,$(_pre_anchored)/[*]\($(_comment_and_close),\1 ,; \
|
||||
ta; \
|
||||
/^$(_pre)[/][*]/{ \
|
||||
s,$(_pre_anchored)/[*].*,\1 ,; \
|
||||
tu; \
|
||||
:u; \
|
||||
n; \
|
||||
s,^\($(_comment_and_close),,; \
|
||||
tv; \
|
||||
s,^.*$$,,; \
|
||||
bu; \
|
||||
:v; \
|
||||
}; \
|
||||
:e; \
|
||||
}
|
||||
# Quote all single quotes.
|
||||
_sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
|
||||
# help font-lock mode: '
|
||||
|
||||
_space_before_paren_exempt =? \\n\\$$
|
||||
_space_before_paren_exempt = \
|
||||
(^ *\#|\\n\\$$|%s\(to %s|(date|group|character)\(s\))
|
||||
# Ensure that there is a space before each open parenthesis in C code.
|
||||
sc_space_before_open_paren:
|
||||
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
|
||||
fail=0; \
|
||||
for c in $$($(VC_LIST_EXCEPT) | grep '\.[ch]$$'); do \
|
||||
sed '$(_sed_rm_comments_q)' $$c 2>/dev/null \
|
||||
| grep -i '[[:alnum:]](' \
|
||||
| grep -vE '$(_space_before_paren_exempt)' \
|
||||
| grep . && { fail=1; echo "*** $$c"; }; \
|
||||
done; \
|
||||
test $$fail = 1 && \
|
||||
{ echo '$(ME): the above files lack a space-before-open-paren' \
|
||||
1>&2; exit 1; } || :; \
|
||||
else :; \
|
||||
fi
|
||||
|
||||
# Similar to the gnulib maint.mk rule for sc_prohibit_strcmp
|
||||
# Use STREQ_LEN or STRPREFIX rather than comparing strncmp == 0, or != 0.
|
||||
sc_prohibit_strncmp:
|
||||
@prohibit='^[^#].*str''ncmp *\(' \
|
||||
halt='use STREQ_LEN or STRPREFIX instead of str''ncmp' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Enforce recommended preprocessor indentation style.
|
||||
sc_preprocessor_indentation:
|
||||
@if cppi --version >/dev/null 2>&1; then \
|
||||
$(VC_LIST_EXCEPT) | grep '\.[ch]$$' | xargs cppi -a -c \
|
||||
|| { echo '$(ME): incorrect preprocessor indentation' 1>&2; \
|
||||
exit 1; }; \
|
||||
else \
|
||||
echo '$(ME): skipping test $@: cppi not installed' 1>&2; \
|
||||
fi
|
||||
|
||||
# THANKS.in is a list of name/email pairs for people who are mentioned in
|
||||
# commit logs (and generated ChangeLog), but who are not also listed as an
|
||||
# author of a commit. Name/email pairs of commit authors are automatically
|
||||
# extracted from the repository. As a very minor factorization, when
|
||||
# someone who was initially listed only in THANKS.in later authors a commit,
|
||||
# this rule detects that their pair may now be removed from THANKS.in.
|
||||
sc_THANKS_in_duplicates:
|
||||
@{ git -C $(srcdir) log --pretty=format:%aN | sort -u; \
|
||||
cut -b-36 $(srcdir)/THANKS.in \
|
||||
| sed '/^$$/,/^$$/!d;/^$$/d;s/ *$$//'; } \
|
||||
| sort | uniq -d | grep . \
|
||||
&& { echo '$(ME): remove the above names from THANKS.in' \
|
||||
1>&2; exit 1; } || :
|
||||
|
||||
# Ensure the contributor list stays sorted. However, if the system's
|
||||
# en_US.UTF-8 locale data is erroneous, give a diagnostic and skip
|
||||
# this test. This affects OS X, up to at least 10.11.6.
|
||||
# Use our sort as other implementations may result in a different order.
|
||||
sc_THANKS_in_sorted:
|
||||
@printf 'a\n.b\n'|LC_ALL=en_US.UTF-8 src/sort -c 2> /dev/null \
|
||||
&& { \
|
||||
sed '/^$$/,/^$$/!d;/^$$/d' $(srcdir)/THANKS.in > $@.1 && \
|
||||
LC_ALL=en_US.UTF-8 src/sort -f -k1,1 $@.1 > $@.2 && \
|
||||
diff -u $@.1 $@.2; diff=$$?; \
|
||||
rm -f $@.1 $@.2; \
|
||||
test "$$diff" = 0 \
|
||||
|| { echo '$(ME): THANKS.in is unsorted' 1>&2; exit 1; }; \
|
||||
} \
|
||||
|| { echo '$(ME): this system has erroneous locale data;' \
|
||||
'skipping $@' 1>&2; }
|
||||
|
||||
# Look for developer diagnostics that are marked for translation.
|
||||
# This won't find any for which devmsg's format string is on a separate line.
|
||||
sc_marked_devdiagnostics:
|
||||
@prohibit='$(begword)devmsg *\(.*_\(' \
|
||||
halt='found marked developer diagnostic(s)' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure we keep hex constants as 4 or 8 bytes for consistency
|
||||
# and so that make src/fs-magic-compare works consistently
|
||||
sc_fs-magic-compare:
|
||||
@sed -n 's|.*/\* \(0x[0-9A-Fa-f]\{1,\}\) .*\*/|\1|p' \
|
||||
$(srcdir)/src/stat.c | grep -Ev '^0x([0-9A-F]{4}){1,2}$$' \
|
||||
&& { echo '$(ME): Constants in src/stat.c should be 4 or 8' \
|
||||
'upper-case chars' 1>&2; exit 1; } || :
|
||||
|
||||
# Ensure gnulib generated files are ignored
|
||||
# TODO: Perhaps augment gnulib-tool to do this in lib/.gitignore?
|
||||
sc_gitignore_missing:
|
||||
@{ sed -n '/^\/lib\/.*\.h$$/{p;p}' $(srcdir)/.gitignore; \
|
||||
find lib -name '*.in*' ! -name '*~' ! -name 'sys_*' | \
|
||||
sed 's|^|/|; s|_\(.*in\.h\)|/\1|; s/\.in//'; } | \
|
||||
sort | uniq -u | grep . && { echo '$(ME): Add above' \
|
||||
'entries to .gitignore' >&2; exit 1; } || :
|
||||
|
||||
# Flag redundant entries in .gitignore
|
||||
# Disabled for now as too aggressive flagging
|
||||
# entries like /lib/arg-nonnull.h
|
||||
#sc_gitignore_redundant:
|
||||
# @{ grep ^/lib $(srcdir)/.gitignore; \
|
||||
# sed 's|^|/lib|' $(srcdir)/lib/.gitignore; } | \
|
||||
# sort | uniq -d | grep . && { echo '$(ME): Remove above' \
|
||||
# 'entries from .gitignore' >&2; exit 1; } || :
|
||||
|
||||
# Ensure gl/ files are distributed
|
||||
sc_gldist_missing:
|
||||
@cd $(srcdir); \
|
||||
grep '^gl/' gl/local.mk > $@.a; \
|
||||
find gl '(' -name Makefile.am ')' -prune -o -type f \
|
||||
'!' '(' -name '*.orig' -or -name '*~' -or \
|
||||
-name 'ChangeLog.*' ')' -printf '%p\n' | \
|
||||
LC_ALL=C sort | tr '\012' @ | sed 's/@$$/%/;s/@/ \\@/g' | \
|
||||
tr @% '\012\012' > $@.e; \
|
||||
diff -u $@.a $@.e; diff=$$?; \
|
||||
rm -f $@.a $@.e; \
|
||||
test "$$diff" = 0 \
|
||||
|| { echo '$(ME): Inconsistent EXTRA_DIST in gl/local.mk'>&2; \
|
||||
exit 1; }
|
||||
|
||||
sc_prohibit-form-feed:
|
||||
@prohibit=$$'\f' \
|
||||
in_vc_files='\.[chly]$$' \
|
||||
halt='Form Feed (^L) detected' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Override the default Cc: used in generating an announcement.
|
||||
announcement_Cc_ = $(translation_project_), \
|
||||
coreutils@gnu.org, coreutils-announce@gnu.org
|
||||
|
||||
-include $(srcdir)/dist-check.mk
|
||||
|
||||
update-copyright-env = \
|
||||
UPDATE_COPYRIGHT_FORCE=1 \
|
||||
UPDATE_COPYRIGHT_USE_INTERVALS=2 \
|
||||
UPDATE_COPYRIGHT_MAX_LINE_LENGTH=79
|
||||
|
||||
# List syntax-check exemptions.
|
||||
exclude_file_name_regexp--sc_space_tab = \
|
||||
^(tests/pr/|tests/misc/nl\.sh$$|gl/.*\.diff$$|man/help2man$$)
|
||||
exclude_file_name_regexp--sc_bindtextdomain = \
|
||||
^(gl/.*|lib/euidaccess-stat|src/make-prime-list|src/cksum)\.c$$
|
||||
exclude_file_name_regexp--sc_trailing_blank = \
|
||||
^(tests/pr/|gl/.*\.diff$$|man/help2man)
|
||||
exclude_file_name_regexp--sc_system_h_headers = \
|
||||
^src/((system|copy|chown-core|find-mount-point)\.h|make-prime-list\.c)$$
|
||||
|
||||
_src := (false|lbracket|chown-(chgrp|chown)
|
||||
_src := $(_src)|ls-(dir|ls|vdir)|tac-pipe|uname-(arch|uname))
|
||||
_gl_src = (xdecto.max|cl-strtold)
|
||||
exclude_file_name_regexp--sc_require_config_h_first = \
|
||||
(^lib/buffer-lcm\.c|gl/lib/$(_gl_src)\.c|src/$(_src)\.c)$$
|
||||
exclude_file_name_regexp--sc_require_config_h = \
|
||||
$(exclude_file_name_regexp--sc_require_config_h_first)
|
||||
|
||||
exclude_file_name_regexp--sc_po_check = ^(gl/|man/help2man)
|
||||
exclude_file_name_regexp--sc_prohibit_always-defined_macros = \
|
||||
^src/(seq|remove)\.c$$
|
||||
exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = ^tests/pr/
|
||||
exclude_file_name_regexp--sc_program_name = \
|
||||
^(gl/.*|lib/euidaccess-stat|src/make-prime-list)\.c$$
|
||||
exclude_file_name_regexp--sc_file_system = \
|
||||
NEWS|^(init\.cfg|src/df\.c|tests/df/df-P\.sh|tests/df/df-output\.sh)$$
|
||||
exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \
|
||||
^m4/stat-prog\.m4$$
|
||||
exclude_file_name_regexp--sc_prohibit_fail_0 = \
|
||||
(^.*/git-hooks/commit-msg|^tests/init\.sh|Makefile\.am|\.mk|.*\.texi)$$
|
||||
exclude_file_name_regexp--sc_prohibit_test_minus_ao = doc/.*\.texi$$
|
||||
exclude_file_name_regexp--sc_prohibit_atoi_atof = ^lib/euidaccess-stat\.c$$
|
||||
|
||||
# longlong.h is maintained elsewhere.
|
||||
_ll = ^src/longlong\.h$$
|
||||
exclude_file_name_regexp--sc_useless_cpp_parens = $(_ll)
|
||||
exclude_file_name_regexp--sc_space_before_open_paren = $(_ll)
|
||||
|
||||
tbi_1 = ^tests/pr/|(\.mk|^man/help2man)$$
|
||||
tbi_2 = ^scripts/git-hooks/(pre-commit|pre-applypatch|applypatch-msg)$$
|
||||
tbi_3 = (GNU)?[Mm]akefile(\.am)?$$|$(_ll)
|
||||
exclude_file_name_regexp--sc_prohibit_tab_based_indentation = \
|
||||
$(tbi_1)|$(tbi_2)|$(tbi_3)
|
||||
|
||||
exclude_file_name_regexp--sc_preprocessor_indentation = \
|
||||
^(gl/lib/rand-isaac\.[ch]|gl/tests/test-rand-isaac\.c)$$|$(_ll)
|
||||
exclude_file_name_regexp--sc_prohibit_stat_st_blocks = \
|
||||
^(src/system\.h|tests/du/2g\.sh)$$
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_continued_string_alpha_in_column_1 = \
|
||||
^src/(system\.h|od\.c|printf\.c|getlimits\.c)$$
|
||||
|
||||
_cksum = ^tests/cksum/cksum-base64\.pl$$
|
||||
exclude_file_name_regexp--sc_prohibit_test_backticks = \
|
||||
^tests/(local\.mk|(init|misc/stdbuf|factor/create-test)\.sh)$$|$(_cksum)
|
||||
|
||||
# Exempt test.c, since it's nominally shared, and relatively static.
|
||||
exclude_file_name_regexp--sc_prohibit_operator_at_end_of_line = \
|
||||
^src/(ptx|test|head)\.c$$
|
||||
|
||||
exclude_file_name_regexp--sc_error_message_uppercase = ^src/factor\.c$$
|
||||
exclude_file_name_regexp--sc_prohibit_atoi_atof = ^src/make-prime-list\.c$$
|
||||
|
||||
# Exception here as we don't want __attribute elided on non GCC
|
||||
exclude_file_name_regexp--sc_prohibit-gl-attributes = ^src/libstdbuf\.c$$
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_uppercase_id_est = \.diff$$
|
||||
exclude_file_name_regexp--sc_ensure_dblspace_after_dot_before_id_est = \.diff$$
|
||||
exclude_file_name_regexp--sc_ensure_comma_after_id_est = \.diff|$(_ll)$$
|
||||
exclude_file_name_regexp--sc_long_lines = \.diff$$|$(_ll)|$(_cksum)|bootstrap
|
||||
|
||||
# `grep . -q` is not exactly equivalent to `grep . >/dev/null`
|
||||
# and this difference is significant in the NEWS description
|
||||
exclude_file_name_regexp--sc_unportable_grep_q = NEWS
|
||||
|
||||
# Augment AM_CFLAGS to include our per-directory options:
|
||||
AM_CFLAGS += $($(@D)_CFLAGS)
|
||||
|
||||
src_CFLAGS = $(WARN_CFLAGS)
|
||||
lib_CFLAGS = $(GNULIB_WARN_CFLAGS)
|
||||
gnulib-tests_CFLAGS = $(GNULIB_TEST_WARN_CFLAGS)
|
||||
|
||||
# Configuration to make the tight-scope syntax-check rule work with
|
||||
# non-recursive make.
|
||||
# Note _gl_TS_headers use _single line_ extern function declarations,
|
||||
# while *_SOURCES use the _two line_ form.
|
||||
export _gl_TS_headers = $(noinst_HEADERS)
|
||||
# Add exceptions for --enable-single-binary renamed functions.
|
||||
_gl_TS_unmarked_extern_functions = main usage
|
||||
_gl_TS_unmarked_extern_functions += single_binary_main_.* _usage_.*
|
||||
# Headers to search for single line extern _data_ declarations.
|
||||
_gl_TS_other_headers = $(srcdir)/src/*.h src/*.h
|
||||
# Avoid tight_scope rule stating these should be static
|
||||
# as there is no way to achieve that with the way these are defined.
|
||||
_gl_TS_unmarked_extern_vars = ptr_MD5_.*
|
||||
# Other tight_scope settings
|
||||
_gl_TS_dir = .
|
||||
_gl_TS_obj_files = src/*.$(OBJEXT)
|
||||
# Settings for running codespell.
|
||||
csiwl_1 = debbugs,clen,te,bu,shs,linke,fo,souch,inout,outin
|
||||
csiwl_2 = kno,ois,afile,whats,hda,indx,ot,nam
|
||||
codespell_ignore_words_list = $(csiwl_1),$(csiwl_2)
|
||||
exclude_file_name_regexp--sc_codespell = \
|
||||
^(THANKS\.in|tests/pr/.*(F|tn?|l(o|m|i)|bl))$$
|
902
configure.ac
Normal file
902
configure.ac
Normal file
|
@ -0,0 +1,902 @@
|
|||
# -*- autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
# Copyright (C) 1991-2025 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/>.
|
||||
|
||||
dnl Written by Jim Meyering.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
# Make inter-release version strings look like, e.g., v6.9-219-g58ddd, which
|
||||
# indicates that it is built from the 219th delta (in _some_ repository)
|
||||
# following the v6.9 tag, and that 58ddd is a prefix of the commit SHA1.
|
||||
# The explicit URL can be removed when autoconf > 2.69 is released.
|
||||
AC_INIT([GNU coreutils],
|
||||
m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||
[bug-coreutils@gnu.org],
|
||||
[coreutils],
|
||||
[https://www.gnu.org/software/coreutils/])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/ls.c])
|
||||
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([lib/config.h:lib/config.hin])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11.2 dist-xz color-tests parallel-tests subdir-objects])
|
||||
AM_SILENT_RULES([yes]) # make --enable-silent-rules the default.
|
||||
|
||||
dnl POSIXCHECK is worthwhile for maintainers, but adds several seconds
|
||||
dnl (more than 10% execution time) to ./configure, with no benefit for
|
||||
dnl most users. Using it to look for bugs requires:
|
||||
dnl GNULIB_POSIXCHECK=1 autoreconf -f
|
||||
dnl ./configure
|
||||
dnl make
|
||||
dnl make -C src clean
|
||||
dnl make CFLAGS=-DGNULIB_POSIXCHECK=1
|
||||
dnl FIXME: Once we figure out how to avoid false positives, we should
|
||||
dnl have 'make my-distcheck' in dist-check.mk exercise this.
|
||||
m4_syscmd([test "${GNULIB_POSIXCHECK+set}" = set])
|
||||
m4_if(m4_sysval, [0], [], [dnl
|
||||
gl_ASSERT_NO_GNULIB_POSIXCHECK])
|
||||
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CPP
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_LN_S
|
||||
gl_EARLY
|
||||
gl_SET_CRYPTO_CHECK_DEFAULT([auto-gpl-compat])
|
||||
gl_INIT
|
||||
coreutils_MACROS
|
||||
|
||||
# These are safe, since 'sort', coreutils's only multithreaded app,
|
||||
# does not use the relevant modules.
|
||||
AC_DEFINE([GNULIB_EXCLUDE_SINGLE_THREAD], [1],
|
||||
[Define to 1 if apps call 'exclude' functions from a single thread.])
|
||||
AC_DEFINE([GNULIB_REGEX_SINGLE_THREAD], [1],
|
||||
[Define to 1 if apps call 'regex' functions from a single thread.])
|
||||
# Although 'sort' is multithreaded and can use these functions,
|
||||
# it uses them only from the main thread.
|
||||
AC_DEFINE([GNULIB_MBRTOWC_SINGLE_THREAD], [1],
|
||||
[Define to 1 if apps call mbrtowc, mbrtoc32, and 'regex' functions
|
||||
from a single thread.])
|
||||
# This is safe, since all apps set locale early.
|
||||
AC_DEFINE([GNULIB_WCHAR_SINGLE_LOCALE], [1],
|
||||
[Define to 1 if apps don't set the locale after calling
|
||||
locale-sensitive functions like mbrtowc and wcwidth.])
|
||||
|
||||
AC_DEFINE([GNULIB_MBRTOC32_REGULAR], [1],
|
||||
[Do not worry about rare encodings like CP864, EBCDIC, Johab, and Shift JIS
|
||||
that glibc does not support.])
|
||||
|
||||
# The test suite needs to know if we have a working perl.
|
||||
AM_CONDITIONAL([HAVE_PERL], [test "$gl_cv_prog_perl" != no])
|
||||
|
||||
# gl_GCC_VERSION_IFELSE([major], [minor], [run-if-found], [run-if-not-found])
|
||||
# ------------------------------------------------
|
||||
# If $CPP is gcc-MAJOR.MINOR or newer, then run RUN-IF-FOUND.
|
||||
# Otherwise, run RUN-IF-NOT-FOUND.
|
||||
AC_DEFUN([gl_GCC_VERSION_IFELSE],
|
||||
[AC_PREPROC_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#if ($1) < __GNUC__ || (($1) == __GNUC__ && ($2) <= __GNUC_MINOR__)
|
||||
/* ok */
|
||||
#else
|
||||
# error "your version of gcc is older than $1.$2"
|
||||
#endif
|
||||
]]),
|
||||
], [$3], [$4])
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([single-binary],
|
||||
[AS_HELP_STRING([--enable-single-binary=[shebangs|symlinks]],
|
||||
[Compile all the tools in a single binary, reducing the overall size.
|
||||
When compiled this way, shebangs (default when enabled) or symlinks are
|
||||
installed for each tool that points to the single binary.])],
|
||||
[gl_single_binary=no ;
|
||||
case $enableval in
|
||||
yes) gl_single_binary=shebangs ;;
|
||||
no|shebangs|symlinks) gl_single_binary=$enableval ;;
|
||||
*) AC_MSG_ERROR([bad value $enableval for single-binary option.
|
||||
Options are: symlinks, shebangs, no.]) ;;
|
||||
esac],
|
||||
[gl_single_binary=no]
|
||||
)
|
||||
AC_ARG_ENABLE([single-binary-exceptions],
|
||||
[AS_HELP_STRING([--enable-single-binary-exceptions=PROG_LIST],
|
||||
[When used with --enable-single-binary, exclude the PROG_LIST from
|
||||
it, so these programs are compiled as separated files
|
||||
(comma-separated, default none))])],
|
||||
[gl_single_binary_exceptions=$enableval],
|
||||
[gl_single_binary_exceptions=]
|
||||
)
|
||||
if test "$gl_single_binary" = 'symlinks'; then
|
||||
if ! test "`echo ls | sed \"$program_transform_name\"`" = 'ls'; then
|
||||
AC_MSG_ERROR([program name transformations are not currently supported
|
||||
with --enable-single-binary=symlinks.])
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([SINGLE_BINARY], [test "$gl_single_binary" != no])
|
||||
|
||||
AC_ARG_ENABLE([bold-man-page-references],
|
||||
[AS_HELP_STRING([--disable-bold-man-page-references],
|
||||
[When generating man pages, do not apply bold style around any
|
||||
references like name(1) etc.])],
|
||||
[gl_bold_manpages=yes ;
|
||||
case $enableval in
|
||||
no|yes) gl_bold_manpages=$enableval ;;
|
||||
*) AC_MSG_ERROR([bad value $enableval for bold-man-page-references.
|
||||
Options are: yes, no.]) ;;
|
||||
esac],
|
||||
[gl_bold_manpages=yes]
|
||||
)
|
||||
AM_CONDITIONAL([BOLD_MAN_REFS], [test "$gl_bold_manpages" != no])
|
||||
|
||||
AC_ARG_ENABLE([gcc-warnings],
|
||||
[AS_HELP_STRING([--enable-gcc-warnings@<:@=TYPE@:>@],
|
||||
[control generation of GCC warnings. The TYPE 'no' disables
|
||||
warnings (default for non-developer builds); 'yes' generates
|
||||
cheap warnings if available (default for developer builds);
|
||||
'expensive' in addition generates expensive-to-compute warnings
|
||||
if available.])],
|
||||
[case $enableval in
|
||||
no|yes|expensive) ;;
|
||||
*) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;;
|
||||
esac
|
||||
gl_gcc_warnings=$enableval],
|
||||
[
|
||||
# GCC provides fine-grained control over diagnostics which
|
||||
# is used in gnulib for example to suppress warnings from
|
||||
# certain sections of code. So if this is available and
|
||||
# we're running from a git repo, then auto enable the warnings.
|
||||
gl_gcc_warnings=no
|
||||
gl_GCC_VERSION_IFELSE([4], [6],
|
||||
[test -d "$srcdir"/.git \
|
||||
&& ! test -f "$srcdir"/.tarball-version \
|
||||
&& gl_gcc_warnings=yes])]
|
||||
)
|
||||
|
||||
# clang is unduly picky about some things, even by default.
|
||||
if test "$gl_cv_compiler_clang" = yes; then
|
||||
gl_WARN_ADD([-Wno-format-extra-args])
|
||||
gl_WARN_ADD([-Wno-implicit-const-int-float-conversion])
|
||||
gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare])
|
||||
fi
|
||||
|
||||
if test $gl_gcc_warnings != no; then
|
||||
gl_WARN_ADD([-Werror], [WERROR_CFLAGS])
|
||||
AC_SUBST([WERROR_CFLAGS])
|
||||
|
||||
ew=
|
||||
AS_IF([test $gl_gcc_warnings != expensive],
|
||||
[# -fanalyzer and related options slow GCC considerably.
|
||||
ew="$ew -fanalyzer -Wno-analyzer-malloc-leak"])
|
||||
|
||||
# This, $nw, is the list of warnings we disable.
|
||||
nw=$ew
|
||||
nw="$nw -Wdeclaration-after-statement" # too useful to forbid
|
||||
nw="$nw -Waggregate-return" # anachronistic
|
||||
nw="$nw -Wlong-long" # C90 is anachronistic (lib/gethrxtime.h)
|
||||
nw="$nw -Wc++-compat" # We don't care about C++ compilers
|
||||
nw="$nw -Wundef" # Warns on '#if GNULIB_FOO' etc in gnulib
|
||||
nw="$nw -Wtraditional" # Warns on #elif which we use often
|
||||
nw="$nw -Wcast-qual" # Too many warnings for now
|
||||
nw="$nw -Wconversion" # Too many warnings for now
|
||||
nw="$nw -Wsign-conversion" # Too many warnings for now
|
||||
nw="$nw -Wtraditional-conversion" # Too many warnings for now
|
||||
nw="$nw -Wunreachable-code" # Too many warnings for now
|
||||
nw="$nw -Wpadded" # Our structs are not padded
|
||||
nw="$nw -Wredundant-decls" # openat.h declares e.g., mkdirat
|
||||
nw="$nw -Wformat-nonliteral" # who.c and pinky.c strftime uses
|
||||
nw="$nw -Wnested-externs" # use of XARGMATCH/verify_function__
|
||||
nw="$nw -Wstack-protector" # not worth working around
|
||||
nw="$nw -Wformat-overflow=2" # False alarms due to GCC bug 110333
|
||||
nw="$nw -Wformat-truncation=2" # False alarm in ls.c, probably related
|
||||
# things I might fix soon:
|
||||
nw="$nw -Wfloat-equal" # sort.c, seq.c
|
||||
nw="$nw -Wmissing-format-attribute" # copy.c
|
||||
nw="$nw -Wunsafe-loop-optimizations" # a few src/*.c
|
||||
nw="$nw -Winline" # system.h's readdir_ignoring_dot_and_dotdot
|
||||
nw="$nw -Wvector-operation-performance" # warns about randperm.c
|
||||
|
||||
# Suppress noreturn warnings with single binaries; otherwise
|
||||
# GCC complains about the renamed 'main' not being declared noreturn
|
||||
# because 'main_exit' calls 'exit' when linting.
|
||||
if test "$gl_single_binary" != no; then
|
||||
nw="$nw -Wsuggest-attribute=noreturn"
|
||||
fi
|
||||
|
||||
# Using -Wstrict-overflow is a pain, but the alternative is worse.
|
||||
# For an example, see the code that provoked this report:
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33498
|
||||
# Code like that still infloops with gcc-4.6.0 and -O2. Scary indeed.
|
||||
|
||||
gl_MANYWARN_ALL_GCC([ws])
|
||||
AS_VAR_APPEND([ws], [' -Wswitch-enum'])
|
||||
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
|
||||
for w in $ws; do
|
||||
gl_WARN_ADD([$w])
|
||||
done
|
||||
gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now
|
||||
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
|
||||
gl_WARN_ADD([-Wno-format-nonliteral])
|
||||
|
||||
gl_WARN_ADD([-fdiagnostics-show-option])
|
||||
gl_WARN_ADD([-funit-at-a-time])
|
||||
|
||||
AC_SUBST([WARN_CFLAGS])
|
||||
|
||||
AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
|
||||
AH_VERBATIM([FORTIFY_SOURCE],
|
||||
[/* Enable compile-time and run-time bounds-checking, and some warnings,
|
||||
without upsetting glibc 2.15+. */
|
||||
#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__
|
||||
# define _FORTIFY_SOURCE 2
|
||||
#endif
|
||||
])
|
||||
AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks])
|
||||
|
||||
# We use a slightly smaller set of warning options for lib/.
|
||||
# Remove the following and save the result in GNULIB_WARN_CFLAGS.
|
||||
nw=$ew
|
||||
nw="$nw -Wduplicated-branches" # Too many false alarms
|
||||
nw="$nw -Wformat-truncation=2"
|
||||
nw="$nw -Wmissing-variable-declarations"
|
||||
nw="$nw -Wstrict-overflow"
|
||||
nw="$nw -Wuninitialized"
|
||||
nw="$nw -Wunused-macros"
|
||||
nw="$nw -Wmissing-prototypes"
|
||||
nw="$nw -Wold-style-definition"
|
||||
# FIXME: it may be easy to remove this, since it affects only one file:
|
||||
# the snprintf call at ftoastr.c:132.
|
||||
nw="$nw -Wdouble-promotion"
|
||||
|
||||
# FIXME: remove this line when gcc improves
|
||||
# FP in careadlinkat.c w/gcc 10.0.1 20200205
|
||||
gl_WARN_ADD([-Wno-return-local-addr])
|
||||
|
||||
# FIXME: remove this line when gcc improves
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88443
|
||||
gl_WARN_ADD([-Wno-stringop-overflow])
|
||||
|
||||
gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
|
||||
AC_SUBST([GNULIB_WARN_CFLAGS])
|
||||
|
||||
# For gnulib-tests, the set is slightly smaller still.
|
||||
nw=
|
||||
nw="$nw -Wstrict-prototypes"
|
||||
# It's not worth being this picky about test programs.
|
||||
nw="$nw -Wsuggest-attribute=cold"
|
||||
nw="$nw -Wsuggest-attribute=const"
|
||||
nw="$nw -Wsuggest-attribute=format"
|
||||
nw="$nw -Wsuggest-attribute=pure"
|
||||
gl_MANYWARN_COMPLEMENT([GNULIB_TEST_WARN_CFLAGS],
|
||||
[$GNULIB_WARN_CFLAGS], [$nw])
|
||||
AC_SUBST([GNULIB_TEST_WARN_CFLAGS])
|
||||
fi
|
||||
|
||||
AC_FUNC_FORK
|
||||
|
||||
optional_bin_progs=
|
||||
AC_CHECK_FUNCS([chroot],
|
||||
gl_ADD_PROG([optional_bin_progs], [chroot]))
|
||||
AC_CHECK_FUNCS([gethostid],
|
||||
gl_ADD_PROG([optional_bin_progs], [hostid]))
|
||||
AC_CHECK_FUNCS([sigsuspend],
|
||||
gl_ADD_PROG([optional_bin_progs], [timeout]))
|
||||
|
||||
gl_WINSIZE_IN_PTEM
|
||||
|
||||
AC_MSG_CHECKING([whether localtime caches TZ])
|
||||
AC_CACHE_VAL([utils_cv_localtime_cache],
|
||||
[if test x$ac_cv_func_tzset = xyes; then
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <time.h>
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
extern char **environ;
|
||||
void unset_TZ (void)
|
||||
{
|
||||
char **from, **to;
|
||||
for (to = from = environ; (*to = *from); from++)
|
||||
if (! (to[0][0] == 'T' && to[0][1] == 'Z' && to[0][2] == '='))
|
||||
to++;
|
||||
}
|
||||
int
|
||||
main ()
|
||||
{
|
||||
time_t now = time ((time_t *) 0);
|
||||
int hour_GMT0, hour_unset;
|
||||
if (putenv ("TZ=GMT0") != 0)
|
||||
return 1;
|
||||
hour_GMT0 = localtime (&now)->tm_hour;
|
||||
unset_TZ ();
|
||||
hour_unset = localtime (&now)->tm_hour;
|
||||
if (putenv ("TZ=PST8") != 0)
|
||||
return 1;
|
||||
if (localtime (&now)->tm_hour == hour_GMT0)
|
||||
return 1;
|
||||
unset_TZ ();
|
||||
if (localtime (&now)->tm_hour != hour_unset)
|
||||
return 1;
|
||||
return 0;
|
||||
}]])],
|
||||
[utils_cv_localtime_cache=no],
|
||||
[utils_cv_localtime_cache=yes],
|
||||
[# If we have tzset, assume the worst when cross-compiling.
|
||||
utils_cv_localtime_cache=yes])
|
||||
else
|
||||
# If we lack tzset, report that localtime does not cache TZ,
|
||||
# since we can't invalidate the cache if we don't have tzset.
|
||||
utils_cv_localtime_cache=no
|
||||
fi])dnl
|
||||
AC_MSG_RESULT([$utils_cv_localtime_cache])
|
||||
if test $utils_cv_localtime_cache = yes; then
|
||||
AC_DEFINE([LOCALTIME_CACHE], [1], [FIXME])
|
||||
fi
|
||||
|
||||
# Find the library for dynamic loading of shared libraries.
|
||||
AC_SEARCH_LIBS([dlopen], [dl])
|
||||
AS_CASE([$ac_cv_search_dlopen],
|
||||
[no | 'none required'],
|
||||
[LIB_DL=],
|
||||
[*],
|
||||
[LIB_DL="$ac_cv_search_dlopen"])
|
||||
AC_SUBST([LIB_DL])
|
||||
|
||||
# Should 'sort' link libcrypto dynamically?
|
||||
AS_CASE([$LIB_CRYPTO],
|
||||
[-lcrypto],
|
||||
[# Check for dlopen and libcrypto dynamic linking in one program,
|
||||
# as there's little point to checking them separately.
|
||||
AC_CACHE_CHECK([for dlopen and whether libcrypto is linked dynamically],
|
||||
[utils_cv_libcrypto_soname],
|
||||
[utils_cv_libcrypto_soname=no
|
||||
saved_LIBS=$LIBS
|
||||
LIBS="$LIBS $LIB_DL $LIB_CRYPTO"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <dlfcn.h>
|
||||
#include <openssl/sha.h>
|
||||
/* Use SHA512 rather than MD5 here to avoid deprecation warnings.
|
||||
So need to check HAVE_OPENSSL_MD5.. with DLOPEN_LIBCRYPTO. */
|
||||
]],
|
||||
[[return !(dlopen ("libcrypto.so", RTLD_LAZY | RTLD_GLOBAL)
|
||||
&& SHA512 (0, 0, 0));]])],
|
||||
[# readelf works with cross-builds; ldd works on more platforms.
|
||||
LIBCRYPTO_SONAME="`(readelf -d conftest$EXEEXT || ldd conftest$EXEEXT
|
||||
) 2>/dev/null |
|
||||
sed -n 's/.*\(libcrypto\.so\.[[.0-9]]*\).*/\1/p'`"
|
||||
AS_CASE([$LIBCRYPTO_SONAME],
|
||||
[*libcrypto*],
|
||||
[utils_cv_libcrypto_soname=$LIBCRYPTO_SONAME])])
|
||||
LIBS=$saved_LIBS])
|
||||
AS_CASE([$utils_cv_libcrypto_soname],
|
||||
[*libcrypto*],
|
||||
[AC_DEFINE([DLOPEN_LIBCRYPTO], [1],
|
||||
[Define to 1 if dlopen exists and libcrypto is
|
||||
linked dynamically.])
|
||||
AC_DEFINE_UNQUOTED([LIBCRYPTO_SONAME], ["$utils_cv_libcrypto_soname"],
|
||||
[versioned libcrypto])
|
||||
])])
|
||||
|
||||
# macOS >= 10.12
|
||||
AC_CHECK_FUNCS([fclonefileat])
|
||||
|
||||
# Assume that if getattrat exists, it's compatible with Solaris 11.
|
||||
AC_CHECK_FUNCS([getattrat])
|
||||
if test $ac_cv_func_getattrat = yes; then
|
||||
LIB_NVPAIR=-lnvpair
|
||||
AC_SUBST([LIB_NVPAIR])
|
||||
fi
|
||||
|
||||
# glibc >= 2.28 and linux kernel >= 4.11
|
||||
AC_CHECK_FUNCS([statx])
|
||||
|
||||
# SCO-ODT-3.0 is reported to need -los to link programs using initgroups
|
||||
AC_CHECK_FUNCS([initgroups])
|
||||
if test $ac_cv_func_initgroups = no; then
|
||||
AC_CHECK_LIB([os], [initgroups])
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS([syslog])
|
||||
if test $ac_cv_func_syslog = no; then
|
||||
# syslog is not in the default libraries. See if it's in some other.
|
||||
for lib in bsd socket inet; do
|
||||
AC_CHECK_LIB([$lib], [syslog], [AC_DEFINE([HAVE_SYSLOG], [1], [FIXME])
|
||||
LIBS="$LIBS -l$lib"; break])
|
||||
done
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for 3-argument setpriority function],
|
||||
[utils_cv_func_setpriority],
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
]],
|
||||
[[setpriority (0, 0, 0);]])],
|
||||
[utils_cv_func_setpriority=yes],
|
||||
[utils_cv_func_setpriority=no])])
|
||||
if test $utils_cv_func_setpriority = no; then
|
||||
AC_CHECK_FUNCS([nice])
|
||||
fi
|
||||
case $utils_cv_func_setpriority,$ac_cv_func_nice in
|
||||
*yes*)
|
||||
gl_ADD_PROG([optional_bin_progs], [nice])
|
||||
esac
|
||||
|
||||
if test "$cross_compiling" = yes || test -c /dev/stdin <.; then
|
||||
AC_DEFINE([DEV_FD_MIGHT_BE_CHR], [1],
|
||||
[Define to 1 if /dev/std{in,out,err} and /dev/fd/N, if they exist, might be
|
||||
character-special devices whose minor device number is the file
|
||||
descriptor number, such as on Solaris. Leave undefined if they are
|
||||
definitely the actual files. This determination should be done after any
|
||||
symbolic links are followed.])
|
||||
fi
|
||||
|
||||
AC_DEFUN([coreutils_DUMMY_1],
|
||||
[
|
||||
AC_REQUIRE([gl_READUTMP])
|
||||
if test $ac_cv_header_utmp_h = yes || test $ac_cv_header_utmpx_h = yes; then
|
||||
gl_ADD_PROG([optional_bin_progs], [who])
|
||||
gl_ADD_PROG([optional_bin_progs], [users])
|
||||
gl_ADD_PROG([optional_bin_progs], [pinky])
|
||||
fi
|
||||
])
|
||||
coreutils_DUMMY_1
|
||||
|
||||
AC_SYS_POSIX_TERMIOS()
|
||||
gl_HEADER_TIOCGWINSZ_NEEDS_SYS_IOCTL
|
||||
|
||||
if test $ac_cv_sys_posix_termios = yes; then
|
||||
gl_ADD_PROG([optional_bin_progs], [stty])
|
||||
|
||||
AC_MSG_CHECKING([whether termios.h needs _XOPEN_SOURCE])
|
||||
AC_CACHE_VAL([su_cv_sys_termios_needs_xopen_source],
|
||||
[AC_EGREP_CPP([yes], [#include <termios.h>
|
||||
#ifdef IUCLC
|
||||
yes
|
||||
#endif], su_cv_sys_termios_needs_xopen_source=no,
|
||||
AC_EGREP_CPP([yes], [#define _XOPEN_SOURCE
|
||||
#include <termios.h>
|
||||
#ifdef IUCLC
|
||||
yes
|
||||
#endif], su_cv_sys_termios_needs_xopen_source=yes,
|
||||
su_cv_sys_termios_needs_xopen_source=no))])
|
||||
AC_MSG_RESULT([$su_cv_sys_termios_needs_xopen_source])
|
||||
test $su_cv_sys_termios_needs_xopen_source = yes &&
|
||||
AC_DEFINE([TERMIOS_NEEDS_XOPEN_SOURCE], [1], [FIXME])
|
||||
|
||||
AC_MSG_CHECKING([c_line in struct termios])
|
||||
AC_CACHE_VAL([su_cv_sys_c_line_in_termios],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if TERMIOS_NEEDS_XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
struct termios t;
|
||||
int s = sizeof t.c_line;]])],
|
||||
[su_cv_sys_c_line_in_termios=yes],
|
||||
[su_cv_sys_c_line_in_termios=no])])
|
||||
AC_MSG_RESULT([$su_cv_sys_c_line_in_termios])
|
||||
test $su_cv_sys_c_line_in_termios = yes \
|
||||
&& AC_DEFINE([HAVE_C_LINE], [1], [FIXME])
|
||||
fi
|
||||
|
||||
# FIXME: note that this macro appears above, too.
|
||||
# I'm leaving it here for now. This whole thing needs to be modernized...
|
||||
gl_WINSIZE_IN_PTEM
|
||||
|
||||
gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H
|
||||
|
||||
if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \
|
||||
test $gl_cv_sys_tiocgwinsz_needs_sys_ioctl_h = no; then
|
||||
AC_MSG_CHECKING([TIOCGWINSZ in sys/pty.h])
|
||||
AC_CACHE_VAL([su_cv_sys_tiocgwinsz_in_sys_pty_h],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||
#ifdef WINSIZE_IN_PTEM
|
||||
# include <sys/stream.h>
|
||||
# include <sys/ptem.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/pty.h>]], [[int x = TIOCGWINSZ;]])],
|
||||
[su_cv_sys_tiocgwinsz_in_sys_pty_h=yes],
|
||||
[su_cv_sys_tiocgwinsz_in_sys_pty_h=no])])
|
||||
AC_MSG_RESULT([$su_cv_sys_tiocgwinsz_in_sys_pty_h])
|
||||
|
||||
test $su_cv_sys_tiocgwinsz_in_sys_pty_h = yes \
|
||||
&& AC_DEFINE([GWINSZ_IN_SYS_PTY], [1],
|
||||
[Define if your system defines TIOCGWINSZ in sys/pty.h.])
|
||||
fi
|
||||
|
||||
# Build df only if there's a point to it.
|
||||
if test $gl_cv_list_mounted_fs = yes && test $gl_cv_fs_space = yes; then
|
||||
gl_ADD_PROG([optional_bin_progs], [df])
|
||||
fi
|
||||
|
||||
# Build stdbuf only if supported
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
ac_save_LDFLAGS=$LDFLAGS
|
||||
cu_save_c_werror_flag=$ac_c_werror_flag
|
||||
AC_LANG_WERROR
|
||||
# Detect warnings about ignored "constructor" attributes.
|
||||
gl_WARN_ADD([-Werror], [CFLAGS])
|
||||
gl_WARN_ADD([-errwarn], [CFLAGS])
|
||||
# Put this message here, after gl_WARN_ADD's chatter.
|
||||
AC_MSG_CHECKING([whether this system supports stdbuf])
|
||||
CFLAGS="-fPIC $CFLAGS"
|
||||
LDFLAGS="-shared $LDFLAGS"
|
||||
AC_CACHE_VAL([utils_cv_stdbuf_supported],[
|
||||
utils_cv_stdbuf_supported=no
|
||||
# Note we only LINK here rather than RUN to support cross compilation
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[
|
||||
static int stdbuf = 0;
|
||||
|
||||
void __attribute__ ((constructor))
|
||||
stdbuf_init (void)
|
||||
{
|
||||
stdbuf = 1;
|
||||
}]],[[
|
||||
if (stdbuf != 1)
|
||||
return 1;]])
|
||||
],
|
||||
[utils_cv_stdbuf_supported=yes])])
|
||||
AC_MSG_RESULT([$utils_cv_stdbuf_supported])
|
||||
if test "$utils_cv_stdbuf_supported" = "yes" && test -z "$EXEEXT"; then
|
||||
gl_ADD_PROG([optional_bin_progs], [stdbuf])
|
||||
fi
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
LDFLAGS=$ac_save_LDFLAGS
|
||||
ac_c_werror_flag=$cu_save_c_werror_flag
|
||||
|
||||
# Test compiler support for half precision floating point types (for od)
|
||||
AC_MSG_CHECKING([IEEE 16 bit floating point])
|
||||
AC_CACHE_VAL([utils_cv_ieee_16_bit_supported],[
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
volatile _Float16 hf = 1;
|
||||
float f = hf; /* Ensure compiler can promote to float. */
|
||||
return !(f == 1.0f);
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_ieee_16_bit_supported=yes
|
||||
],[
|
||||
utils_cv_ieee_16_bit_supported=no
|
||||
],[
|
||||
utils_cv_ieee_16_bit_supported=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_ieee_16_bit_supported])
|
||||
if test $utils_cv_ieee_16_bit_supported = yes; then
|
||||
AC_DEFINE([FLOAT16_SUPPORTED], [1], [IEEE 16 bit float supported])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([Brain 16 bit floating point])
|
||||
AC_CACHE_VAL([utils_cv_brain_16_bit_supported],[
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
volatile __bf16 hf = 1;
|
||||
float f = hf; /* Ensure compiler can promote to float. */
|
||||
return !(f == 1.0f);
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_brain_16_bit_supported=yes
|
||||
],[
|
||||
utils_cv_brain_16_bit_supported=no
|
||||
],[
|
||||
utils_cv_brain_16_bit_supported=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_brain_16_bit_supported])
|
||||
if test $utils_cv_brain_16_bit_supported = yes; then
|
||||
AC_DEFINE([BF16_SUPPORTED], [1], [Brain 16 bit float supported])
|
||||
fi
|
||||
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
CFLAGS="-march=armv8-a+crypto $CFLAGS"
|
||||
AC_MSG_CHECKING([if vmull intrinsic exists])
|
||||
AC_CACHE_VAL([utils_cv_vmull_intrinsic_exists],[
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <stdio.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <arm_neon.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
uint64x2_t a;
|
||||
poly64_t shift64 = vget_lane_p64(vcreate_p64(0xB8BC6765), 0);
|
||||
a = vreinterpretq_u64_p128(vmull_p64(shift64, vreinterpretq_p128_u64(a)));
|
||||
return (getauxval(AT_HWCAP) & HWCAP_PMULL) > 0;
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_vmull_intrinsic_exists=yes
|
||||
],[
|
||||
utils_cv_vmull_intrinsic_exists=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_vmull_intrinsic_exists])
|
||||
if test $utils_cv_vmull_intrinsic_exists = yes; then
|
||||
AC_DEFINE([USE_VMULL_CRC32], [1],
|
||||
[CRC32 calculation by vmull hardware instruction enabled])
|
||||
fi
|
||||
AM_CONDITIONAL([USE_VMULL_CRC32],
|
||||
[test $utils_cv_vmull_intrinsic_exists = yes])
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
CFLAGS="-mavx -mpclmul $CFLAGS"
|
||||
AC_MSG_CHECKING([if pclmul intrinsic exists])
|
||||
AC_CACHE_VAL([utils_cv_pclmul_intrinsic_exists],[
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <x86intrin.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
__m128i a, b;
|
||||
a = _mm_clmulepi64_si128 (a, b, 0x00);
|
||||
a = _mm_shuffle_epi8 (a, b);
|
||||
return __builtin_cpu_supports ("pclmul");
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_pclmul_intrinsic_exists=yes
|
||||
],[
|
||||
utils_cv_pclmul_intrinsic_exists=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_pclmul_intrinsic_exists])
|
||||
if test $utils_cv_pclmul_intrinsic_exists = yes; then
|
||||
AC_DEFINE([USE_PCLMUL_CRC32], [1],
|
||||
[CRC32 calculation by pclmul hardware instruction enabled])
|
||||
fi
|
||||
AM_CONDITIONAL([USE_PCLMUL_CRC32],
|
||||
[test $utils_cv_pclmul_intrinsic_exists = yes])
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
CFLAGS=" -mavx2 -mvpclmulqdq $CFLAGS"
|
||||
AC_MSG_CHECKING([if avx2 pclmul intrinsic exists])
|
||||
AC_CACHE_VAL([utils_cv_avx2_pclmul_intrinsic_exists],[
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <x86intrin.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
__m256i a, b;
|
||||
a = _mm256_clmulepi64_epi128 (a, b, 0x00);
|
||||
a = _mm256_shuffle_epi8 (a, b);
|
||||
return __builtin_cpu_supports ("avx2") &&
|
||||
__builtin_cpu_supports ("vpclmulqdq");
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_avx2_pclmul_intrinsic_exists=yes
|
||||
],[
|
||||
utils_cv_avx2_pclmul_intrinsic_exists=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_avx2_pclmul_intrinsic_exists])
|
||||
if test $utils_cv_avx2_pclmul_intrinsic_exists = yes; then
|
||||
AC_DEFINE([USE_AVX2_CRC32], [1],
|
||||
[CRC32 calculation by avx2 hardware instructions enabled])
|
||||
fi
|
||||
AM_CONDITIONAL([USE_AVX2_CRC32],
|
||||
[test $utils_cv_avx2_pclmul_intrinsic_exists = yes])
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
CFLAGS=" -mavx512bw -mavx512f -mvpclmulqdq $CFLAGS"
|
||||
AC_MSG_CHECKING([if avx512 pclmul intrinsic exists])
|
||||
AC_CACHE_VAL([utils_cv_avx512_pclmul_intrinsic_exists],[
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <x86intrin.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
__m512i a, b;
|
||||
a = _mm512_set_epi8 (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
a = _mm512_clmulepi64_epi128 (a, b, 0x00);
|
||||
a = _mm512_shuffle_epi8 (a, b);
|
||||
return __builtin_cpu_supports ("avx512bw") &&
|
||||
__builtin_cpu_supports ("avx512f");
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_avx512_pclmul_intrinsic_exists=yes
|
||||
],[
|
||||
utils_cv_avx512_pclmul_intrinsic_exists=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_avx512_pclmul_intrinsic_exists])
|
||||
if test $utils_cv_avx512_pclmul_intrinsic_exists = yes; then
|
||||
AC_DEFINE([USE_AVX512_CRC32], [1],
|
||||
[CRC32 calculation by avx512 hardware instructions enabled])
|
||||
fi
|
||||
AM_CONDITIONAL([USE_AVX512_CRC32],
|
||||
[test $utils_cv_avx512_pclmul_intrinsic_exists = yes])
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
|
||||
CFLAGS="-mavx2 $CFLAGS"
|
||||
AC_MSG_CHECKING([for avx2 intrinsics])
|
||||
AC_CACHE_VAL([utils_cv_avx2_intrinsic_exists],[
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <x86intrin.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
__m256i matches = _mm256_setzero_si256 ();
|
||||
int mask = _mm256_movemask_epi8 (matches);
|
||||
int lines = __builtin_popcount (mask);
|
||||
return __builtin_cpu_supports ("avx2");
|
||||
}
|
||||
]])
|
||||
],[
|
||||
utils_cv_avx2_intrinsic_exists=yes
|
||||
],[
|
||||
utils_cv_avx2_intrinsic_exists=no
|
||||
])])
|
||||
AC_MSG_RESULT([$utils_cv_avx2_intrinsic_exists])
|
||||
if test $utils_cv_avx2_intrinsic_exists = yes; then
|
||||
AC_DEFINE([USE_AVX2_WC_LINECOUNT], [1], [Counting lines with AVX2 enabled])
|
||||
fi
|
||||
AM_CONDITIONAL([USE_AVX2_WC_LINECOUNT],
|
||||
[test $utils_cv_avx2_intrinsic_exists = yes])
|
||||
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
|
||||
############################################################################
|
||||
|
||||
dnl Autogenerated by the 'gen-lists-of-programs.sh' auxiliary script.
|
||||
dnl Issue proper calls to the macros gl_INCLUDE_EXCLUDE_PROG and
|
||||
dnl gl_ADD_PROG (updating $optional_bin_progs), and generate the list
|
||||
dnl of coreutils programs to be built only upon explicit user request,
|
||||
dnl saving that list in the $no_install_progs_default shell variable.
|
||||
m4_include([m4/cu-progs.m4])
|
||||
|
||||
# Now that we know which programs will actually be built, determine
|
||||
# which optional helper progs should be compiled.
|
||||
# Note it adding to pkglibexec_PROGRAMS, $(transform) in src/local.mk
|
||||
# may need to be updated accordingly.
|
||||
case " $optional_bin_progs " in
|
||||
*' stdbuf '*) pkglibexec_PROGRAMS='src/libstdbuf.so';;
|
||||
*) pkglibexec_PROGRAMS='';;
|
||||
esac
|
||||
|
||||
man1_MANS=`
|
||||
for p in $optional_bin_progs; do
|
||||
# Change "ginstall.1" to "install.1".
|
||||
test $p = ginstall && p=install
|
||||
# Ignore the "[" program, since writing a portable make rule to
|
||||
# generate its manpage is not practical.
|
||||
dnl Use the autoconf-provided quadrigraph to represent "[",
|
||||
dnl otherwise we will incur in dreadful quoting issues.
|
||||
test x$p = x'@<:@' && continue
|
||||
echo "man/$p.1"
|
||||
done`
|
||||
|
||||
# Not installed by "make install", but must be built when creating
|
||||
# a distribution tarball.
|
||||
EXTRA_MANS=`for p in $no_install_progs_default $gl_no_install_prog; do
|
||||
echo man/$p.1
|
||||
done`
|
||||
|
||||
# Replace all the programs by the single binary and symlinks if specified.
|
||||
single_binary_progs=
|
||||
single_binary_libs=
|
||||
single_binary_deps=
|
||||
single_binary_install_type=
|
||||
if test "$gl_single_binary" != no; then
|
||||
man1_MANS="$man1_MANS man/coreutils.1"
|
||||
# Convert the list to a space separated list
|
||||
gl_single_binary_exceptions=`echo $gl_single_binary_exceptions | tr ',' ' '`
|
||||
|
||||
single_binary_progs=`echo $optional_bin_progs`
|
||||
optional_bin_progs="coreutils"
|
||||
for prog in $gl_single_binary_exceptions; do
|
||||
# Fail if requested to exclude a program than was not part of coreutils.
|
||||
case " $single_binary_progs " in
|
||||
*" $prog "*)
|
||||
gl_REMOVE_PROG([single_binary_progs], [$prog]) ;
|
||||
gl_ADD_PROG([optional_bin_progs], [$prog]) ;;
|
||||
*) AC_MSG_ERROR(['$prog' is not being compiled.]) ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# single_binary_libs holds the list of libs required by the selected
|
||||
# programs, such as for example -lrt.
|
||||
single_binary_libs=`
|
||||
for p in $single_binary_progs; do
|
||||
# Convert '[' to '_'
|
||||
test x"$p" = x'@<:@' && p='_'
|
||||
printf '$(src_libsinglebin_%s_a_ldadd) ' "$p"
|
||||
done`
|
||||
# single_binary_deps holds the list of libsinglebin_*.a files that have the
|
||||
# compiled code of each selected program in a "library" format.
|
||||
single_binary_deps=`
|
||||
for p in $single_binary_progs; do
|
||||
# Convert '[' to '_'
|
||||
test x"$p" = x'@<:@' && p='_'
|
||||
printf 'src/libsinglebin_%s.a ' "$p"
|
||||
done`
|
||||
single_binary_install_type="$gl_single_binary"
|
||||
fi
|
||||
AC_SUBST([single_binary_progs], [$single_binary_progs])
|
||||
AC_SUBST([single_binary_libs], [$single_binary_libs])
|
||||
AC_SUBST([single_binary_deps], [$single_binary_deps])
|
||||
AC_SUBST([single_binary_install_type], [$single_binary_install_type])
|
||||
|
||||
|
||||
# The programs built and installed by "make && make install".
|
||||
# Since this is AC_SUBST'd, Automake won't be able to perform rewrite
|
||||
# with $(EXEEXT) appending on it, so we have to do it ourselves -- in
|
||||
# this case, only for $(bin_PROGRAMS).
|
||||
bin_PROGRAMS=`
|
||||
for p in $optional_bin_progs; do echo src/"$p"'$(EXEEXT)'; done`
|
||||
|
||||
# Normalize whitespace.
|
||||
man1_MANS=`echo $man1_MANS`
|
||||
EXTRA_MANS=`echo $EXTRA_MANS`
|
||||
bin_PROGRAMS=`echo $bin_PROGRAMS`
|
||||
pkglibexec_PROGS=`echo $pkglibexec_PROGRAMS`
|
||||
|
||||
AC_SUBST([bin_PROGRAMS]) AM_SUBST_NOTMAKE([bin_PROGRAMS])
|
||||
AC_SUBST([pkglibexec_PROGRAMS]) AM_SUBST_NOTMAKE([pkglibexec_PROGRAMS])
|
||||
AC_SUBST([man1_MANS]) AM_SUBST_NOTMAKE([man1_MANS])
|
||||
AC_SUBST([EXTRA_MANS]) AM_SUBST_NOTMAKE([EXTRA_MANS])
|
||||
|
||||
AC_SUBST([built_programs], [$optional_bin_progs])
|
||||
|
||||
AM_CONDITIONAL([CROSS_COMPILING], [test "$cross_compiling" = yes])
|
||||
|
||||
############################################################################
|
||||
|
||||
# As long as "grep 'PRI[diouxX]' po/*.pot" reports matches in
|
||||
# translatable strings, we must use need-formatstring-macros here.
|
||||
AM_GNU_GETTEXT([external], [need-formatstring-macros])
|
||||
AM_GNU_GETTEXT_VERSION([0.19.2])
|
||||
|
||||
# For a test of uniq: it uses the $LOCALE_FR envvar.
|
||||
gt_LOCALE_FR
|
||||
|
||||
AC_CONFIG_FILES(
|
||||
Makefile
|
||||
po/Makefile.in
|
||||
gnulib-tests/Makefile
|
||||
)
|
||||
AC_OUTPUT
|
133
dist-check.mk
Normal file
133
dist-check.mk
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Most of this is probably too coreutils-centric to be useful to other packages.
|
||||
|
||||
bin=bin-$$$$
|
||||
|
||||
write_loser = printf '\#!%s\necho $$0: bad path 1>&2; exit 1\n' '$(SHELL)'
|
||||
|
||||
tmpdir = $(abs_top_builddir)/tests/torture
|
||||
|
||||
t=$(tmpdir)/$(PACKAGE)/test
|
||||
pfx=$(t)/i
|
||||
|
||||
built_programs := $(sort $(patsubst src/%$(EXEEXT),%,$(bin_PROGRAMS)))
|
||||
|
||||
# More than once, tainted build and source directory names would
|
||||
# have caused at least one "make check" test to apply "chmod 700"
|
||||
# to all directories under $HOME. Make sure it doesn't happen again.
|
||||
tp = $(tmpdir)/taint
|
||||
t_prefix = $(tp)/a
|
||||
t_taint = '$(t_prefix) b'
|
||||
fake_home = $(tp)/home
|
||||
|
||||
# When extracting from a distribution tarball, extract using the fastest
|
||||
# method possible. With dist-xz, that means using the *.xz file.
|
||||
ifneq ('', $(filter *.xz, $(DIST_ARCHIVES)))
|
||||
tar_decompress_opt_ = J
|
||||
suffix_ = xz
|
||||
else
|
||||
ifneq ('', $(filter *.gz, $(DIST_ARCHIVES)))
|
||||
tar_decompress_opt_ = z
|
||||
suffix_ = gz
|
||||
else
|
||||
tar_decompress_opt_ = j
|
||||
suffix_ = bz2
|
||||
endif
|
||||
endif
|
||||
amtar_extract_ = $(AMTAR) -$(tar_decompress_opt_)xf
|
||||
preferred_tarball_ = $(distdir).tar.$(suffix_)
|
||||
|
||||
# Ensure that tests run from tainted build and src dir names work,
|
||||
# and don't affect anything in $HOME. Create witness files in $HOME,
|
||||
# record their attributes, and build/test. Then ensure that the
|
||||
# witnesses were not affected.
|
||||
# Skip this test when using libtool, since libtool-generated scripts
|
||||
# cannot deal with a space-tainted srcdir.
|
||||
ALL_RECURSIVE_TARGETS += taint-distcheck
|
||||
taint-distcheck: $(DIST_ARCHIVES)
|
||||
grep '^[ ]*LT_INIT' configure.ac >/dev/null && exit 0 || :
|
||||
test -d $(t_taint) && chmod -R 700 $(t_taint) || :
|
||||
-rm -rf $(t_taint) $(fake_home)
|
||||
mkdir -p $(t_prefix) $(t_taint) $(fake_home)
|
||||
$(amtar_extract_) $(preferred_tarball_) -C $(t_taint)
|
||||
mkfifo $(fake_home)/fifo
|
||||
touch $(fake_home)/f
|
||||
mkdir -p $(fake_home)/d/e
|
||||
ls -lR $(fake_home) $(t_prefix) > $(tp)/.ls-before
|
||||
HOME=$(fake_home); export HOME; \
|
||||
cd $(t_taint)/$(distdir) \
|
||||
&& ./configure \
|
||||
&& $(MAKE) \
|
||||
&& $(MAKE) check \
|
||||
&& ls -lR $(fake_home) $(t_prefix) > $(tp)/.ls-after \
|
||||
&& diff $(tp)/.ls-before $(tp)/.ls-after \
|
||||
&& test -d $(t_prefix)
|
||||
rm -rf $(tp)
|
||||
|
||||
# Verify that a twisted use of --program-transform-name=PROGRAM works.
|
||||
define install-transform-check
|
||||
echo running install-transform-check \
|
||||
&& rm -rf $(pfx) \
|
||||
&& $(MAKE) program_transform_name='s/.*/zyx/' \
|
||||
prefix=$(pfx) install \
|
||||
&& test "$$(echo $(pfx)/bin/*)" = "$(pfx)/bin/zyx" \
|
||||
&& test "$$(find $(pfx)/share/man -type f|sed 's,.*/,,;s,\..*,,')" = "zyx"
|
||||
endef
|
||||
|
||||
# Install, then verify that all binaries and man pages are in place.
|
||||
# Note that neither the binary, ginstall, nor the [.1 man page is installed.
|
||||
define my-instcheck
|
||||
echo running my-instcheck; \
|
||||
$(MAKE) prefix=$(pfx) install \
|
||||
&& test ! -f $(pfx)/bin/ginstall \
|
||||
&& { fail=0; \
|
||||
for i in $(built_programs); do \
|
||||
test "$$i" = ginstall && i=install; \
|
||||
for j in "$(pfx)/bin/$$i" \
|
||||
"$(pfx)/share/man/man1/$$i.1"; do \
|
||||
case $$j in *'[.1') continue;; esac; \
|
||||
test -f "$$j" && : \
|
||||
|| { echo "$$j not installed"; fail=1; }; \
|
||||
done; \
|
||||
done; \
|
||||
test $$fail = 1 && exit 1 || :; \
|
||||
}
|
||||
endef
|
||||
|
||||
# Use this to make sure we don't run these programs when building
|
||||
# from a virgin compressed tarball file, below.
|
||||
null_AM_MAKEFLAGS ?= \
|
||||
ACLOCAL=false \
|
||||
AUTOCONF=false \
|
||||
AUTOMAKE=false \
|
||||
AUTOHEADER=false \
|
||||
GPERF=false \
|
||||
MAKEINFO=false
|
||||
|
||||
ALL_RECURSIVE_TARGETS += my-distcheck
|
||||
my-distcheck: $(DIST_ARCHIVES) $(local-check)
|
||||
$(MAKE) syntax-check
|
||||
$(MAKE) check
|
||||
-rm -rf $(t)
|
||||
mkdir -p $(t)
|
||||
$(amtar_extract_) $(preferred_tarball_) -C $(t)
|
||||
(set -e; cd $(t)/$(distdir); \
|
||||
./configure --quiet --enable-gcc-warnings --disable-nls; \
|
||||
$(MAKE) AM_MAKEFLAGS='$(null_AM_MAKEFLAGS)'; \
|
||||
$(MAKE) dvi; \
|
||||
$(install-transform-check); \
|
||||
$(my-instcheck); \
|
||||
$(MAKE) distclean \
|
||||
)
|
||||
(cd $(t) && mv $(distdir) $(distdir).old \
|
||||
&& $(amtar_extract_) - ) < $(preferred_tarball_)
|
||||
# With post-v1.15 automake, "distclean" would fail to remove .deps
|
||||
# directories, leading to a spurious failure of the following recursive diff.
|
||||
# FIXME: remove this, once automake is fixed.
|
||||
find $(t)/$(distdir).old $(t)/$(distdir) -name .deps | xargs -r rmdir
|
||||
diff -ur $(t)/$(distdir).old $(t)/$(distdir)
|
||||
-rm -rf $(t)
|
||||
rmdir $(tmpdir)/$(PACKAGE) $(tmpdir)
|
||||
@echo "========================"; \
|
||||
echo "ready for distribution:"; \
|
||||
for i in $(DIST_ARCHIVES); do echo " $$i"; done; \
|
||||
echo "========================"
|
2
doc/constants.texi
Normal file
2
doc/constants.texi
Normal file
|
@ -0,0 +1,2 @@
|
|||
@set DEFAULT_MAX_N_UNCHANGED_STATS_BETWEEN_OPENS 5
|
||||
@set SHRED_DEFAULT_PASSES 3
|
22165
doc/coreutils.info
Normal file
22165
doc/coreutils.info
Normal file
File diff suppressed because it is too large
Load diff
20362
doc/coreutils.texi
Normal file
20362
doc/coreutils.texi
Normal file
File diff suppressed because it is too large
Load diff
505
doc/fdl.texi
Normal file
505
doc/fdl.texi
Normal file
|
@ -0,0 +1,505 @@
|
|||
@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 Free Software Foundation, Inc.
|
||||
@uref{https://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{https://www.gnu.org/licenses/}.
|
||||
|
||||
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:
|
132
doc/local.mk
Normal file
132
doc/local.mk
Normal file
|
@ -0,0 +1,132 @@
|
|||
# Make coreutils documentation. -*-Makefile-*-
|
||||
# This is included by the top-level Makefile.am.
|
||||
|
||||
# Copyright (C) 1995-2025 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/>.
|
||||
|
||||
info_TEXINFOS = doc/coreutils.texi
|
||||
|
||||
doc_coreutils_TEXINFOS = \
|
||||
doc/perm.texi \
|
||||
doc/parse-datetime.texi \
|
||||
doc/constants.texi \
|
||||
doc/fdl.texi \
|
||||
doc/sort-version.texi
|
||||
|
||||
# The customization variable CHECK_NORMAL_MENU_STRUCTURE is necessary with
|
||||
# makeinfo versions ≥ 6.8.
|
||||
MAKEINFO = @MAKEINFO@ -c CHECK_NORMAL_MENU_STRUCTURE=1
|
||||
|
||||
# The following is necessary if the package name is 8 characters or longer.
|
||||
# If the info documentation would be split into 10 or more separate files,
|
||||
# then this is necessary even if the package name is 7 characters long.
|
||||
#
|
||||
# Tell makeinfo to put everything in a single info file: <package>.info.
|
||||
# Otherwise, it would also generate files with names like <package>.info-[123],
|
||||
# and those names all map to one 14-byte name (<package>.info-) on some crufty
|
||||
# old systems.
|
||||
AM_MAKEINFOFLAGS = --no-split
|
||||
|
||||
doc/constants.texi: $(top_srcdir)/src/tail.c $(top_srcdir)/src/shred.c
|
||||
$(AM_V_GEN)LC_ALL=C; export LC_ALL; \
|
||||
$(MKDIR_P) doc && \
|
||||
{ sed -n -e 's/^#define \(DEFAULT_MAX[_A-Z]*\) \(.*\)/@set \1 \2/p' \
|
||||
$(top_srcdir)/src/tail.c && \
|
||||
sed -n -e \
|
||||
's/.*\(DEFAULT_PASSES\)[ =]* \([0-9]*\).*/@set SHRED_\1 \2/p'\
|
||||
$(top_srcdir)/src/shred.c; } > $@-t \
|
||||
&& { cmp $@-t $@ >/dev/null 2>&1 || mv $@-t $@; rm -f $@-t; }
|
||||
|
||||
MAINTAINERCLEANFILES += doc/constants.texi
|
||||
|
||||
# Extended regular expressions to match word starts and ends.
|
||||
_W = (^|[^A-Za-z0-9_])
|
||||
W_ = ([^A-Za-z0-9_]|$$)
|
||||
|
||||
syntax_checks = \
|
||||
sc-avoid-builtin \
|
||||
sc-avoid-io \
|
||||
sc-avoid-non-zero \
|
||||
sc-avoid-path \
|
||||
sc-avoid-timezone \
|
||||
sc-avoid-zeroes \
|
||||
sc-exponent-grouping \
|
||||
sc-lower-case-var
|
||||
|
||||
texi_files = $(srcdir)/doc/*.texi
|
||||
|
||||
.PHONY: $(syntax_checks) check-texinfo
|
||||
|
||||
# List words/regexps here that should not appear in the texinfo documentation.
|
||||
check-texinfo: $(syntax_checks)
|
||||
$(AM_V_GEN)fail=0; \
|
||||
grep '@url{' $(texi_files) && fail=1; \
|
||||
grep '\$$@"' $(texi_files) && fail=1; \
|
||||
grep -n '[^[:punct:]]@footnote' $(texi_files) && fail=1; \
|
||||
grep -n filename $(texi_files) \
|
||||
| $(EGREP) -v 'setfilename|[{]filename[}]' \
|
||||
&& fail=1; \
|
||||
exit $$fail
|
||||
|
||||
sc-avoid-builtin:
|
||||
$(AM_V_GEN)$(EGREP) -i '$(_W)builtins?$(W_)' $(texi_files) \
|
||||
&& exit 1 || :
|
||||
|
||||
sc-avoid-path:
|
||||
$(AM_V_GEN)fail=0; \
|
||||
$(EGREP) -i '$(_W)path(name)?s?$(W_)' $(texi_files) \
|
||||
| $(EGREP) -v \
|
||||
'PATH=|path search|search path|@vindex PATH$$|@env[{]PATH[}]' \
|
||||
&& fail=1; \
|
||||
exit $$fail
|
||||
|
||||
# Use "time zone", not "timezone".
|
||||
sc-avoid-timezone:
|
||||
$(AM_V_GEN)$(EGREP) timezone $(texi_files) && exit 1 || :
|
||||
|
||||
# Check for insufficient exponent grouping, e.g.,
|
||||
# @math{2^64} should be @math{2^{64}}.
|
||||
sc-exponent-grouping:
|
||||
$(AM_V_GEN)$(EGREP) '\{.*\^[0-9][0-9]' $(texi_files) && exit 1 || :
|
||||
|
||||
# Say I/O, not IO.
|
||||
sc-avoid-io:
|
||||
$(AM_V_GEN)$(EGREP) '$(_W)IO$(W_)' $(texi_files) && exit 1 || :
|
||||
|
||||
# I prefer nonzero over non-zero.
|
||||
sc-avoid-non-zero:
|
||||
$(AM_V_GEN)$(EGREP) non-zero $(texi_files) && exit 1 || :
|
||||
|
||||
# Use "zeros", not "zeroes" (nothing wrong with "zeroes"; just be consistent).
|
||||
sc-avoid-zeroes:
|
||||
$(AM_V_GEN)$(EGREP) -i '$(_W)zeroes$(W_)' $(texi_files) \
|
||||
&& exit 1 || :
|
||||
|
||||
# The quantity inside @var{...} should not contain upper case letters.
|
||||
# The leading backslash exemption is to permit in-macro uses like
|
||||
# @var{\varName\} where the upper case letter is part of a parameter name.
|
||||
find_upper_case_var = \
|
||||
'/\@var\{/ or next; \
|
||||
while (/\@var\{(.+?)}/g) \
|
||||
{ \
|
||||
$$v = $$1; \
|
||||
$$v =~ /[A-Z]/ && $$v !~ /^\\/ and (print "$$ARGV:$$.:$$_"), $$m = 1 \
|
||||
} \
|
||||
END {$$m and (warn "$@: do not use upper case in \@var{...}\n"), exit 1}'
|
||||
sc-lower-case-var:
|
||||
$(AM_V_GEN)$(PERL) -e 1 || { echo $@: skipping test; exit 0; }; \
|
||||
$(PERL) -lne $(find_upper_case_var) $(texi_files)
|
||||
|
||||
check-local: check-texinfo
|
618
doc/parse-datetime.texi
Normal file
618
doc/parse-datetime.texi
Normal file
|
@ -0,0 +1,618 @@
|
|||
@c GNU date syntax documentation
|
||||
|
||||
@c Copyright (C) 1994--2006, 2009--2025 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:: @samp{14 Nov 2022}
|
||||
* Time of day items:: @samp{9:02pm}
|
||||
* Time zone items:: @samp{UTC}, @samp{-0700}, @samp{+0900}, @dots{}
|
||||
* Combined date and time of day items:: @samp{2022-11-14T21:02:42,000000-0500}
|
||||
* Day of week items:: @samp{Monday} and others
|
||||
* Relative items in date strings:: @samp{next tuesday, 2 years ago}
|
||||
* Pure numbers in date strings:: @samp{20221114}, @samp{2102}
|
||||
* Seconds since the Epoch:: @samp{@@1668477762}
|
||||
* Specifying time zone rules:: @samp{TZ="America/New_York"}, @samp{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 Nov 15 02:02:42 UTC 2022
|
||||
$ TZ=UTC0 date +'%Y-%m-%d %H:%M:%SZ'
|
||||
2022-11-15 02:02:42Z
|
||||
$ date --rfc-3339=ns # --rfc-3339 is a GNU extension.
|
||||
2022-11-14 21:02:42.000000000-05:00
|
||||
$ date --rfc-email # a GNU extension
|
||||
Mon, 14 Nov 2022 21:02:42 -0500
|
||||
$ date +'%Y-%m-%d %H:%M:%S %z' # %z is a GNU extension.
|
||||
2022-11-14 21:02:42 -0500
|
||||
$ date +'@@%s.%N' # %s and %N are GNU extensions.
|
||||
@@1668477762.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{2022-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
|
||||
2022-11-14 # ISO 8601.
|
||||
22-11-14 # Assume 19xx for 69 through 99,
|
||||
# 20xx for 00 through 68 (not recommended).
|
||||
11/14/2022 # Common U.S. writing.
|
||||
14 November 2022
|
||||
14 Nov 2022 # Three-letter abbreviations always allowed.
|
||||
November 14, 2022
|
||||
14-nov-2022
|
||||
14nov2022
|
||||
@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
|
||||
11/14
|
||||
nov 14
|
||||
@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 obsolete
|
||||
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
|
||||
2022-09-24T20:02:00.052-05:00
|
||||
2022-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{2022-12-31 -1 month} might evaluate to 2022-12-01,
|
||||
because 2022-11-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 Dec 2022 13:02:39 -0400
|
||||
$ date --date='-1 month' +'Last month was %B?'
|
||||
Last month was December?
|
||||
$ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
|
||||
Last month was November!
|
||||
@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, 2022?'' 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" 2022-10-31 06:30'
|
||||
Mon Oct 31 01:30:00 EDT 2022
|
||||
@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{2022-11-14
|
||||
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 2022, 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{Africa/Abidjan} to @samp{Pacific/Tongatapu}, 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.
|
||||
The previously-mentioned POSIX rule @samp{UTC0} says that the time zone
|
||||
abbreviation is @samp{UTC}, the zone is zero hours away from
|
||||
Greenwich, and there is no daylight saving time.
|
||||
POSIX rules can also specify nonzero Greenwich offsets.
|
||||
For example, the following shell transcript answers the question
|
||||
``What time is it five and a half hours east of Greenwich when a clock
|
||||
seven hours west of Greenwich shows 9:50pm on July 12, 2022?''
|
||||
|
||||
@example
|
||||
$ TZ="<+0530>-5:30" date --date='TZ="<-07>+7" 2022-07-12 21:50'
|
||||
Wed Jul 13 10:20:00 +0530 2022
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
This example uses the somewhat-confusing POSIX convention for rules.
|
||||
@samp{TZ="<-07>+7"} says that the time zone abbreviation is @samp{-07}
|
||||
and the time zone is 7 hours west of Greenwich, and
|
||||
@samp{TZ="<+0530>-5:30"} says that the time zone abbreviation is @samp{+0530}
|
||||
and the time zone is 5 hours 30 minutes east of Greenwich.
|
||||
(One should never use a setting like @samp{TZ="UTC-5"}, since
|
||||
this would incorrectly imply that local time is five hours east of
|
||||
Greenwich and the time zone is called ``UTC''.)
|
||||
Although trickier POSIX @env{TZ} settings like
|
||||
@samp{TZ="<-05>+5<-04>,M3.2.0/2,M11.1.0/2"} can specify some daylight
|
||||
saving regimes, location-based settings like
|
||||
@samp{TZ="America/New_York"} are typically simpler and more accurate
|
||||
historically. @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}).
|
641
doc/perm.texi
Normal file
641
doc/perm.texi
Normal file
|
@ -0,0 +1,641 @@
|
|||
@c File mode bits
|
||||
|
||||
@c Copyright (C) 1994--2025 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, with no Front-Cover Texts, and with no Back-Cover
|
||||
@c Texts. A copy of the license is included in the ``GNU Free
|
||||
@c Documentation License'' file as part of this distribution.
|
||||
|
||||
Each file has a set of @dfn{file mode bits} that control the kinds of
|
||||
access that users have to that file. They can be represented either in
|
||||
symbolic form or as an octal number.
|
||||
|
||||
@menu
|
||||
* Mode Structure:: Structure of file mode bits.
|
||||
* Symbolic Modes:: Mnemonic representation of file mode bits.
|
||||
* Numeric Modes:: File mode bits as octal numbers.
|
||||
* Operator Numeric Modes:: ANDing, ORing, and setting modes octally.
|
||||
* Directory Setuid and Setgid:: Set-user-ID and set-group-ID on directories.
|
||||
@end menu
|
||||
|
||||
@node Mode Structure
|
||||
@section Structure of File Mode Bits
|
||||
|
||||
The file mode bits have two parts: the @dfn{file permission bits},
|
||||
which control ordinary access to the file, and @dfn{special mode
|
||||
bits}, which affect only some files.
|
||||
|
||||
There are three kinds of permissions that a user can have for a file:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
@cindex read permission
|
||||
permission to read the file. For directories, this means permission to
|
||||
list the contents of the directory.
|
||||
@item
|
||||
@cindex write permission
|
||||
permission to write to (change) the file. For directories, this means
|
||||
permission to create and remove files in the directory.
|
||||
@item
|
||||
@cindex execute/search permission
|
||||
permission to execute the file (run it as a program). For directories,
|
||||
this means permission to access files in the directory.
|
||||
@end enumerate
|
||||
|
||||
There are three categories of users who may have different permissions
|
||||
to perform any of the above operations on a file:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
the file's owner;
|
||||
@item
|
||||
other users who are in the file's group;
|
||||
@item
|
||||
everyone else.
|
||||
@end enumerate
|
||||
|
||||
@cindex owner, default
|
||||
@cindex group owner, default
|
||||
Files are given an owner and group when they are created. Usually the
|
||||
owner is the current user and the group is the group of the directory
|
||||
the file is in, but this varies with the operating system, the
|
||||
file system the file is created on, and the way the file is created. You
|
||||
can change the owner and group of a file by using the @command{chown} and
|
||||
@command{chgrp} commands.
|
||||
|
||||
In addition to the three sets of three permissions listed above, the
|
||||
file mode bits have three special components, which affect only
|
||||
executable files (programs) and, on most systems, directories:
|
||||
|
||||
@table @asis
|
||||
@item The @dfn{set-user-ID bit} (@dfn{setuid bit}).
|
||||
@cindex set-user-ID
|
||||
@cindex setuid
|
||||
On execution, set the process's effective user ID to that of the file.
|
||||
For directories on a few systems, give files created in the directory
|
||||
the same owner as the directory, no matter who creates them, and set
|
||||
the set-user-ID bit of newly-created subdirectories.
|
||||
|
||||
@item The @dfn{set-group-ID bit} (@dfn{setgid bit}).
|
||||
@cindex set-group-ID
|
||||
@cindex setgid
|
||||
On execution, set the process's effective group ID to that of the file.
|
||||
For directories on most systems, give files created in the directory
|
||||
the same group as the directory, no matter what group the user who
|
||||
creates them is in, and set the set-group-ID bit of newly-created
|
||||
subdirectories.
|
||||
|
||||
@item The @dfn{restricted deletion flag} or @dfn{sticky bit}.
|
||||
@cindex sticky
|
||||
@cindex swap space, saving text image in
|
||||
@cindex text image, saving in swap space
|
||||
@cindex restricted deletion flag
|
||||
Prevent unprivileged users from removing or renaming a file in a directory
|
||||
unless they own the file or the directory; this is commonly
|
||||
found on world-writable directories like @file{/tmp}.
|
||||
For regular files on some older systems, save the program's text image on the
|
||||
swap device so it will load more quickly when run, so that the image
|
||||
is ``sticky''.
|
||||
@end table
|
||||
|
||||
In addition to the file mode bits listed above, there may be file attributes
|
||||
specific to the file system, e.g., access control lists (ACLs), whether a
|
||||
file is compressed, whether a file can be modified (immutability), and whether
|
||||
a file can be dumped. These are usually set using programs
|
||||
specific to the file system. For example:
|
||||
@c should probably say a lot more about ACLs... someday
|
||||
|
||||
@table @asis
|
||||
@item ext2
|
||||
On GNU and GNU/Linux the file attributes specific to
|
||||
the ext2 file system are set using @command{chattr}.
|
||||
|
||||
@item FFS
|
||||
On FreeBSD the file flags specific to the FFS
|
||||
file system are set using @command{chflags}.
|
||||
@end table
|
||||
|
||||
Even if a file's mode bits allow an operation on that file,
|
||||
that operation may still fail, because:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
the file-system-specific attributes or flags do not permit it; or
|
||||
|
||||
@item
|
||||
the file system is mounted as read-only.
|
||||
@end itemize
|
||||
|
||||
For example, if the immutable attribute is set on a file,
|
||||
it cannot be modified, regardless of the fact that you
|
||||
may have just run @code{chmod a+w FILE}.
|
||||
|
||||
@node Symbolic Modes
|
||||
@section Symbolic Modes
|
||||
|
||||
@cindex symbolic modes
|
||||
@dfn{Symbolic modes} represent changes to files' mode bits as
|
||||
operations on single-character symbols. They allow you to modify either
|
||||
all or selected parts of files' mode bits, optionally based on
|
||||
their previous values, and perhaps on the current @code{umask} as well
|
||||
(@pxref{Umask and Protection}).
|
||||
|
||||
The format of symbolic modes is:
|
||||
|
||||
@example
|
||||
@r{[}ugoa@dots{}@r{][}-+=@r{]}@var{perms}@dots{}@r{[},@dots{}@r{]}
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
where @var{perms} is either zero or more letters from the set
|
||||
@samp{rwxXst}, or a single letter from the set @samp{ugo}.
|
||||
|
||||
The following sections describe the operators and other details of
|
||||
symbolic modes.
|
||||
|
||||
@menu
|
||||
* Setting Permissions:: Basic operations on permissions.
|
||||
* Copying Permissions:: Copying existing permissions.
|
||||
* Changing Special Mode Bits:: Special mode bits.
|
||||
* Conditional Executability:: Conditionally affecting executability.
|
||||
* Multiple Changes:: Making multiple changes.
|
||||
* Umask and Protection:: The effect of the umask.
|
||||
@end menu
|
||||
|
||||
@node Setting Permissions
|
||||
@subsection Setting Permissions
|
||||
|
||||
The basic symbolic operations on a file's permissions are adding,
|
||||
removing, and setting the permission that certain users have to read,
|
||||
write, and execute or search the file. These operations have the following
|
||||
format:
|
||||
|
||||
@example
|
||||
@var{users} @var{operation} @var{permissions}
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
The spaces between the three parts above are shown for readability only;
|
||||
symbolic modes cannot contain spaces.
|
||||
|
||||
The @var{users} part tells which users' access to the file is changed.
|
||||
It consists of one or more of the following letters (or it can be empty;
|
||||
@pxref{Umask and Protection}, for a description of what happens then). When
|
||||
more than one of these letters is given, the order that they are in does
|
||||
not matter.
|
||||
|
||||
@table @code
|
||||
@item u
|
||||
@cindex owner of file, permissions for
|
||||
the user who owns the file;
|
||||
@item g
|
||||
@cindex group, permissions for
|
||||
other users who are in the file's group;
|
||||
@item o
|
||||
@cindex other permissions
|
||||
all other users;
|
||||
@item a
|
||||
all users; the same as @samp{ugo}.
|
||||
@end table
|
||||
|
||||
The @var{operation} part tells how to change the affected users' access
|
||||
to the file, and is one of the following symbols:
|
||||
|
||||
@table @code
|
||||
@item +
|
||||
@cindex adding permissions
|
||||
to add the @var{permissions} to whatever permissions the @var{users}
|
||||
already have for the file;
|
||||
@item -
|
||||
@cindex removing permissions
|
||||
@cindex subtracting permissions
|
||||
to remove the @var{permissions} from whatever permissions the
|
||||
@var{users} already have for the file;
|
||||
@item =
|
||||
@cindex setting permissions
|
||||
to make the @var{permissions} the only permissions that the @var{users}
|
||||
have for the file.
|
||||
@end table
|
||||
|
||||
The @var{permissions} part tells what kind of access to the file should
|
||||
be changed; it is normally zero or more of the following letters. As with the
|
||||
@var{users} part, the order does not matter when more than one letter is
|
||||
given. Omitting the @var{permissions} part is useful only with the
|
||||
@samp{=} operation, where it gives the specified @var{users} no access
|
||||
at all to the file.
|
||||
|
||||
@table @code
|
||||
@item r
|
||||
@cindex read permission, symbolic
|
||||
the permission the @var{users} have to read the file;
|
||||
@item w
|
||||
@cindex write permission, symbolic
|
||||
the permission the @var{users} have to write to the file;
|
||||
@item x
|
||||
@cindex execute/search permission, symbolic
|
||||
the permission the @var{users} have to execute the file,
|
||||
or search it if it is a directory.
|
||||
@end table
|
||||
|
||||
For example, to give everyone permission to read and write a regular file,
|
||||
but not to execute it, use:
|
||||
|
||||
@example
|
||||
a=rw
|
||||
@end example
|
||||
|
||||
To remove write permission for all users other than the file's
|
||||
owner, use:
|
||||
|
||||
@example
|
||||
go-w
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
The above command does not affect the access that the owner of
|
||||
the file has to it, nor does it affect whether other users can
|
||||
read or execute the file.
|
||||
|
||||
To give everyone except a file's owner no permission to do anything with
|
||||
that file, use the mode below. Other users could still remove the file,
|
||||
if they have write permission on the directory it is in.
|
||||
|
||||
@example
|
||||
go=
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Another way to specify the same thing is:
|
||||
|
||||
@example
|
||||
og-rwx
|
||||
@end example
|
||||
|
||||
@node Copying Permissions
|
||||
@subsection Copying Existing Permissions
|
||||
|
||||
@cindex copying existing permissions
|
||||
@cindex permissions, copying existing
|
||||
You can base a file's permissions on its existing permissions. To do
|
||||
this, instead of using a series of @samp{r}, @samp{w}, or @samp{x}
|
||||
letters after the
|
||||
operator, you use the letter @samp{u}, @samp{g}, or @samp{o}. For
|
||||
example, the mode
|
||||
|
||||
@example
|
||||
o+g
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
adds the permissions for users who are in a file's group to the
|
||||
permissions that other users have for the file. Thus, if the file
|
||||
started out as mode 664 (@samp{rw-rw-r--}), the above mode would change
|
||||
it to mode 666 (@samp{rw-rw-rw-}). If the file had started out as mode
|
||||
741 (@samp{rwxr----x}), the above mode would change it to mode 745
|
||||
(@samp{rwxr--r-x}). The @samp{-} and @samp{=} operations work
|
||||
analogously.
|
||||
|
||||
@node Changing Special Mode Bits
|
||||
@subsection Changing Special Mode Bits
|
||||
|
||||
@cindex changing special mode bits
|
||||
In addition to changing a file's read, write, and execute/search permissions,
|
||||
you can change its special mode bits. @xref{Mode Structure}, for a
|
||||
summary of these special mode bits.
|
||||
|
||||
To change the file mode bits to set the user ID on execution, use
|
||||
@samp{u} in the @var{users} part of the symbolic mode and
|
||||
@samp{s} in the @var{permissions} part.
|
||||
|
||||
To change the file mode bits to set the group ID on execution, use
|
||||
@samp{g} in the @var{users} part of the symbolic mode and
|
||||
@samp{s} in the @var{permissions} part.
|
||||
|
||||
To set both user and group ID on execution, omit the @var{users} part
|
||||
of the symbolic mode (or use @samp{a}) and use @samp{s} in the
|
||||
@var{permissions} part.
|
||||
|
||||
To change the file mode bits to set the restricted deletion flag or sticky bit,
|
||||
omit the @var{users} part of the symbolic mode (or use @samp{a}) and use
|
||||
@samp{t} in the @var{permissions} part.
|
||||
|
||||
For example, to set the set-user-ID mode bit of a program,
|
||||
you can use the mode:
|
||||
|
||||
@example
|
||||
u+s
|
||||
@end example
|
||||
|
||||
To remove both set-user-ID and set-group-ID mode bits from
|
||||
it, you can use the mode:
|
||||
|
||||
@example
|
||||
a-s
|
||||
@end example
|
||||
|
||||
To set the restricted deletion flag or sticky bit, you can use
|
||||
the mode:
|
||||
|
||||
@example
|
||||
+t
|
||||
@end example
|
||||
|
||||
The combination @samp{o+s} has no effect. On GNU systems
|
||||
the combinations @samp{u+t} and @samp{g+t} have no effect, and
|
||||
@samp{o+t} acts like plain @samp{+t}.
|
||||
|
||||
The @samp{=} operator is not very useful with special mode bits.
|
||||
For example, the mode:
|
||||
|
||||
@example
|
||||
o=t
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
does set the restricted deletion flag or sticky bit, but it also
|
||||
removes all read, write, and execute/search permissions that users not in the
|
||||
file's group might have had for it.
|
||||
|
||||
@xref{Directory Setuid and Setgid}, for additional rules concerning
|
||||
set-user-ID and set-group-ID bits and directories.
|
||||
|
||||
@node Conditional Executability
|
||||
@subsection Conditional Executability
|
||||
|
||||
@cindex conditional executability
|
||||
There is one more special type of symbolic permission: if you use
|
||||
@samp{X} instead of @samp{x}, execute/search permission is affected only if the
|
||||
file is a directory or already had execute permission.
|
||||
|
||||
For example, this mode:
|
||||
|
||||
@example
|
||||
a+X
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
gives all users permission to search directories, or to execute files if
|
||||
anyone could execute them before.
|
||||
|
||||
@node Multiple Changes
|
||||
@subsection Making Multiple Changes
|
||||
|
||||
@cindex multiple changes to permissions
|
||||
The format of symbolic modes is actually more complex than described
|
||||
above (@pxref{Setting Permissions}). It provides two ways to make
|
||||
multiple changes to files' mode bits.
|
||||
|
||||
The first way is to specify multiple @var{operation} and
|
||||
@var{permissions} parts after a @var{users} part in the symbolic mode.
|
||||
|
||||
For example, the mode:
|
||||
|
||||
@example
|
||||
og+rX-w
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
gives users other than the owner of the file read permission and, if
|
||||
it is a directory or if someone already had execute permission
|
||||
to it, gives them execute/search permission; and it also denies them write
|
||||
permission to the file. It does not affect the permission that the
|
||||
owner of the file has for it. The above mode is equivalent to
|
||||
the two modes:
|
||||
|
||||
@example
|
||||
og+rX
|
||||
og-w
|
||||
@end example
|
||||
|
||||
The second way to make multiple changes is to specify more than one
|
||||
simple symbolic mode, separated by commas. For example, the mode:
|
||||
|
||||
@example
|
||||
a+r,go-w
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
gives everyone permission to read the file and removes write
|
||||
permission on it for all users except its owner. Another example:
|
||||
|
||||
@example
|
||||
u=rwx,g=rx,o=
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
sets all of the permission bits for the file explicitly. (It
|
||||
gives users who are not in the file's group no permission at all for
|
||||
it.)
|
||||
|
||||
The two methods can be combined. The mode:
|
||||
|
||||
@example
|
||||
a+r,g+x-w
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
gives all users permission to read the file, and gives users who are in
|
||||
the file's group permission to execute/search it as well, but not permission
|
||||
to write to it. The above mode could be written in several different
|
||||
ways; another is:
|
||||
|
||||
@example
|
||||
u+r,g+rx,o+r,g-w
|
||||
@end example
|
||||
|
||||
@node Umask and Protection
|
||||
@subsection The Umask and Protection
|
||||
|
||||
@cindex umask and modes
|
||||
@cindex modes and umask
|
||||
If the @var{users} part of a symbolic mode is omitted, it defaults to
|
||||
@samp{a} (affect all users), except that any permissions that are
|
||||
@emph{set} in the system variable @code{umask} are @emph{not affected}.
|
||||
The value of @code{umask} can be set using the
|
||||
@code{umask} command. Its default value varies from system to system.
|
||||
|
||||
@cindex giving away permissions
|
||||
Omitting the @var{users} part of a symbolic mode is generally not useful
|
||||
with operations other than @samp{+}. It is useful with @samp{+} because
|
||||
it allows you to use @code{umask} as an easily customizable protection
|
||||
against giving away more permission to files than you intended to.
|
||||
|
||||
As an example, if @code{umask} has the value 2, which removes write
|
||||
permission for users who are not in the file's group, then the mode:
|
||||
|
||||
@example
|
||||
+w
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
adds permission to write to the file to its owner and to other users who
|
||||
are in the file's group, but @emph{not} to other users. In contrast,
|
||||
the mode:
|
||||
|
||||
@example
|
||||
a+w
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
ignores @code{umask}, and @emph{does} give write permission for
|
||||
the file to all users.
|
||||
|
||||
@node Numeric Modes
|
||||
@section Numeric Modes
|
||||
|
||||
@cindex numeric modes
|
||||
@cindex file mode bits, numeric
|
||||
@cindex octal numbers for file modes
|
||||
As an
|
||||
alternative to giving a symbolic mode, you can give an octal (base 8)
|
||||
number that represents the mode.
|
||||
|
||||
The permissions granted to the user,
|
||||
to other users in the file's group,
|
||||
and to other users not in the file's group each require three
|
||||
bits: one bit for read, one for write, and one for execute/search permission.
|
||||
These three bits are represented as one octal digit;
|
||||
for example, if all three are present, the resulting 111 (in binary)
|
||||
is represented as the digit 7 (in octal). The three special
|
||||
mode bits also require one bit each, and they are as a group
|
||||
represented as another octal digit. Here is how the bits are arranged,
|
||||
starting with the highest valued bit:
|
||||
|
||||
@example
|
||||
Value in Corresponding
|
||||
Mode Mode Bit
|
||||
|
||||
Special mode bits:
|
||||
4000 Set user ID
|
||||
2000 Set group ID
|
||||
1000 Restricted deletion flag or sticky bit
|
||||
|
||||
The file's owner:
|
||||
400 Read
|
||||
200 Write
|
||||
100 Execute/search
|
||||
|
||||
Other users in the file's group:
|
||||
40 Read
|
||||
20 Write
|
||||
10 Execute/search
|
||||
|
||||
Other users not in the file's group:
|
||||
4 Read
|
||||
2 Write
|
||||
1 Execute/search
|
||||
@end example
|
||||
|
||||
For example, numeric mode @samp{4751} corresponds to symbolic mode
|
||||
@samp{u=srwx,g=rx,o=x}, and numeric mode @samp{664} corresponds to symbolic mode
|
||||
@samp{ug=rw,o=r}. Numeric mode @samp{0} corresponds to symbolic mode
|
||||
@samp{a=}.
|
||||
|
||||
A numeric mode is usually shorter than the corresponding symbolic
|
||||
mode, but it is limited in that normally it cannot take into account the
|
||||
previous file mode bits; it can only set them absolutely.
|
||||
The set-user-ID and set-group-ID bits of directories are an exception
|
||||
to this general limitation. @xref{Directory Setuid and Setgid}.
|
||||
Also, operator numeric modes can take previous file mode bits into
|
||||
account. @xref{Operator Numeric Modes}.
|
||||
|
||||
Numeric modes are always interpreted in octal; you do not have to add a
|
||||
leading @samp{0}, as you do in C@. Mode @samp{0055} is the same as
|
||||
mode @samp{55}. However, modes of five digits or more, such as
|
||||
@samp{00055}, are sometimes special (@pxref{Directory Setuid and Setgid}).
|
||||
|
||||
@node Operator Numeric Modes
|
||||
@section Operator Numeric Modes
|
||||
|
||||
An operator numeric mode is a numeric mode that is prefixed by a
|
||||
@samp{-}, @samp{+}, or @samp{=} operator, which has the same
|
||||
interpretation as in symbolic modes. For example, @samp{+440} enables
|
||||
read permission for the file's owner and group, @samp{-1} disables
|
||||
execute permission for other users, and @samp{=600} clears all
|
||||
permissions except for enabling read-write permissions for the file's
|
||||
owner. Operator numeric modes can be combined with symbolic modes by
|
||||
separating them with a comma; for example, @samp{=0,u+r} clears all
|
||||
permissions except for enabling read permission for the file's owner.
|
||||
|
||||
The commands @samp{chmod =755 @var{dir}} and @samp{chmod 755
|
||||
@var{dir}} differ in that the former clears the directory @var{dir}'s
|
||||
setuid and setgid bits, whereas the latter preserves them.
|
||||
@xref{Directory Setuid and Setgid}.
|
||||
|
||||
Operator numeric modes are a GNU extension.
|
||||
|
||||
@node Directory Setuid and Setgid
|
||||
@section Directories and the Set-User-ID and Set-Group-ID Bits
|
||||
|
||||
On most systems, if a directory's set-group-ID bit is set, newly
|
||||
created subfiles inherit the same group as the directory, and newly
|
||||
created subdirectories inherit the set-group-ID bit of the parent
|
||||
directory. On a few systems, a directory's set-user-ID bit has a
|
||||
similar effect on the ownership of new subfiles and the set-user-ID
|
||||
bits of new subdirectories. These mechanisms let users share files
|
||||
more easily, by lessening the need to use @command{chmod} or
|
||||
@command{chown} to share new files.
|
||||
|
||||
These convenience mechanisms rely on the set-user-ID and set-group-ID
|
||||
bits of directories. If commands like @command{chmod} and
|
||||
@command{mkdir} routinely cleared these bits on directories, the
|
||||
mechanisms would be less convenient and it would be harder to share
|
||||
files. Therefore, a command like @command{chmod} does not affect the
|
||||
set-user-ID or set-group-ID bits of a directory unless the user
|
||||
specifically mentions them in a symbolic mode, or uses an operator
|
||||
numeric mode such as @samp{=755}, or sets them in a numeric mode, or
|
||||
clears them in a numeric mode that has five or more octal digits.
|
||||
For example, on systems that support
|
||||
set-group-ID inheritance:
|
||||
|
||||
@example
|
||||
# These commands leave the set-user-ID and
|
||||
# set-group-ID bits of the subdirectories alone,
|
||||
# so that they retain their default values.
|
||||
mkdir A B C
|
||||
chmod 755 A
|
||||
chmod 0755 B
|
||||
chmod u=rwx,go=rx C
|
||||
mkdir -m 755 D
|
||||
mkdir -m 0755 E
|
||||
mkdir -m u=rwx,go=rx F
|
||||
@end example
|
||||
|
||||
If you want to try to set these bits, you must mention them
|
||||
explicitly in the symbolic or numeric modes, e.g.:
|
||||
|
||||
@example
|
||||
# These commands try to set the set-user-ID
|
||||
# and set-group-ID bits of the subdirectories.
|
||||
mkdir G
|
||||
chmod 6755 G
|
||||
chmod +6000 G
|
||||
chmod u=rwx,go=rx,a+s G
|
||||
mkdir -m 6755 H
|
||||
mkdir -m +6000 I
|
||||
mkdir -m u=rwx,go=rx,a+s J
|
||||
@end example
|
||||
|
||||
If you want to try to clear these bits, you must mention them
|
||||
explicitly in a symbolic mode, or use an operator numeric mode, or
|
||||
specify a numeric mode with five or more octal digits, e.g.:
|
||||
|
||||
@example
|
||||
# These commands try to clear the set-user-ID
|
||||
# and set-group-ID bits of the directory D.
|
||||
chmod a-s D
|
||||
chmod -6000 D
|
||||
chmod =755 D
|
||||
chmod 00755 D
|
||||
@end example
|
||||
|
||||
This behavior is a GNU extension. Portable scripts should
|
||||
not rely on requests to set or clear these bits on directories, as
|
||||
POSIX allows implementations to ignore these requests.
|
||||
The GNU behavior with numeric modes of four or fewer digits
|
||||
is intended for scripts portable to systems that preserve these bits;
|
||||
the behavior with numeric modes of five or more digits is for scripts
|
||||
portable to systems that do not preserve the bits.
|
909
doc/sort-version.texi
Normal file
909
doc/sort-version.texi
Normal file
|
@ -0,0 +1,909 @@
|
|||
@c GNU Version-sort ordering documentation
|
||||
|
||||
@c Copyright (C) 2019--2025 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
|
||||
@c Texts. A copy of the license is included in the ``GNU Free
|
||||
@c Documentation License'' file as part of this distribution.
|
||||
|
||||
@c Written by Assaf Gordon
|
||||
|
||||
@node Version sort ordering
|
||||
@chapter Version sort ordering
|
||||
|
||||
|
||||
|
||||
@node Version sort overview
|
||||
@section Version sort overview
|
||||
|
||||
@dfn{Version sort} puts items such as file names and lines of
|
||||
text in an order that feels natural to people, when the text
|
||||
contains a mixture of letters and digits.
|
||||
|
||||
Lexicographic sorting usually does not produce the order that one expects
|
||||
because comparisons are made on a character-by-character basis.
|
||||
|
||||
Compare the sorting of the following items:
|
||||
|
||||
@example
|
||||
Lexicographic sort: Version Sort:
|
||||
|
||||
a1 a1
|
||||
a120 a2
|
||||
a13 a13
|
||||
a2 a120
|
||||
@end example
|
||||
|
||||
Version sort functionality in GNU Coreutils is available in the @samp{ls -v},
|
||||
@samp{ls --sort=version}, @samp{sort -V}, and
|
||||
@samp{sort --version-sort} commands.
|
||||
|
||||
|
||||
|
||||
@node Using version sort in GNU Coreutils
|
||||
@subsection Using version sort in GNU Coreutils
|
||||
|
||||
Two GNU Coreutils programs use version sort: @command{ls} and @command{sort}.
|
||||
|
||||
To list files in version sort order, use @command{ls}
|
||||
with the @option{-v} or @option{--sort=version} option:
|
||||
|
||||
@example
|
||||
default sort: version sort:
|
||||
|
||||
$ ls -1 $ ls -1 -v
|
||||
a1 a1
|
||||
a100 a1.4
|
||||
a1.13 a1.13
|
||||
a1.4 a1.40
|
||||
a1.40 a2
|
||||
a2 a100
|
||||
@end example
|
||||
|
||||
To sort text files in version sort order, use @command{sort} with
|
||||
the @option{-V} or @option{--version-sort} option:
|
||||
|
||||
@example
|
||||
$ cat input
|
||||
b3
|
||||
b11
|
||||
b1
|
||||
b20
|
||||
|
||||
|
||||
lexicographic order: version sort order:
|
||||
|
||||
$ sort input $ sort -V input
|
||||
b1 b1
|
||||
b11 b3
|
||||
b20 b11
|
||||
b3 b20
|
||||
@end example
|
||||
|
||||
To sort a specific field in a file, use @option{-k/--key} with
|
||||
@samp{V} type sorting, which is often combined with @samp{b} to
|
||||
ignore leading blanks in the field:
|
||||
|
||||
@example
|
||||
$ cat input2
|
||||
100 b3 apples
|
||||
2000 b11 oranges
|
||||
3000 b1 potatoes
|
||||
4000 b20 bananas
|
||||
$ sort -k 2bV,2 input2
|
||||
3000 b1 potatoes
|
||||
100 b3 apples
|
||||
2000 b11 oranges
|
||||
4000 b20 bananas
|
||||
@end example
|
||||
|
||||
@node Version sort and natural sort
|
||||
@subsection Version sort and natural sort
|
||||
|
||||
In GNU Coreutils, the name @dfn{version sort} was chosen because it is based
|
||||
on Debian GNU/Linux's algorithm of sorting packages' versions.
|
||||
|
||||
Its goal is to answer questions like
|
||||
``Which package is newer, @file{firefox-60.7.2} or @file{firefox-60.12.3}?''
|
||||
|
||||
In Coreutils this algorithm was slightly modified to work on more
|
||||
general input such as textual strings and file names
|
||||
(see @ref{Differences from Debian version sort}).
|
||||
|
||||
In other contexts, such as other programs and other programming
|
||||
languages, a similar sorting functionality is called
|
||||
@uref{https://en.wikipedia.org/wiki/Natural_sort_order,natural sort}.
|
||||
|
||||
|
||||
@node Variations in version sort order
|
||||
@subsection Variations in version sort order
|
||||
|
||||
Currently there is no standard for version sort.
|
||||
|
||||
That is: there is no one correct way or universally agreed-upon way to
|
||||
order items. Each program and each programming language can decide its
|
||||
own ordering algorithm and call it ``version sort'', ``natural sort'',
|
||||
or other names.
|
||||
|
||||
See @ref{Other version/natural sort implementations} for many examples of
|
||||
differing sorting possibilities, each with its own rules and variations.
|
||||
|
||||
If you find a bug in the Coreutils implementation of version-sort, please
|
||||
report it. @xref{Reporting version sort bugs}.
|
||||
|
||||
|
||||
@node Version sort implementation
|
||||
@section Version sort implementation
|
||||
|
||||
GNU Coreutils version sort is based on the ``upstream version''
|
||||
part of
|
||||
@uref{https://www.debian.org/doc/debian-policy/ch-controlfields.html#version,
|
||||
Debian's versioning scheme}.
|
||||
|
||||
This section describes the GNU Coreutils sort ordering rules.
|
||||
|
||||
The next section (@ref{Differences from Debian version
|
||||
sort}) describes some differences between GNU Coreutils
|
||||
and Debian version sort.
|
||||
|
||||
|
||||
@node Version-sort ordering rules
|
||||
@subsection Version-sort ordering rules
|
||||
|
||||
The version sort ordering rules are:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
The strings are compared from left to right.
|
||||
|
||||
@item
|
||||
First the initial part of each string consisting entirely of non-digit
|
||||
bytes is determined.
|
||||
|
||||
@enumerate A
|
||||
@item
|
||||
These two parts (either of which may be empty) are compared lexically.
|
||||
If a difference is found it is returned.
|
||||
|
||||
@item
|
||||
The lexical comparison is a lexicographic comparison of byte strings,
|
||||
except that:
|
||||
|
||||
@enumerate a
|
||||
@item
|
||||
ASCII letters sort before other bytes.
|
||||
@item
|
||||
A tilde sorts before anything, even an empty string.
|
||||
@end enumerate
|
||||
@end enumerate
|
||||
|
||||
@item
|
||||
Then the initial part of the remainder of each string that contains
|
||||
all the leading digits is determined. The numerical values represented by
|
||||
these two parts are compared, and any difference found is returned as
|
||||
the result of the comparison.
|
||||
|
||||
@enumerate A
|
||||
@item
|
||||
For these purposes an empty string (which can only occur at the end of
|
||||
one or both version strings being compared) counts as zero.
|
||||
|
||||
@item
|
||||
Because the numerical value is used, non-identical strings can compare
|
||||
equal. For example, @samp{123} compares equal to @samp{00123}, and
|
||||
the empty string compares equal to @samp{0}.
|
||||
@end enumerate
|
||||
|
||||
@item
|
||||
These two steps (comparing and removing initial non-digit strings and
|
||||
initial digit strings) are repeated until a difference is found or
|
||||
both strings are exhausted.
|
||||
@end enumerate
|
||||
|
||||
Consider the version-sort comparison of two file names:
|
||||
@file{foo07.7z} and @file{foo7a.7z}. The two strings will be broken
|
||||
down to the following parts, and the parts compared respectively from
|
||||
each string:
|
||||
|
||||
@example
|
||||
foo @r{vs} foo @r{(rule 2, non-digits)}
|
||||
07 @r{vs} 7 @r{(rule 3, digits)}
|
||||
. @r{vs} a. @r{(rule 2)}
|
||||
7 @r{vs} 7 @r{(rule 3)}
|
||||
z @r{vs} z @r{(rule 2)}
|
||||
@end example
|
||||
|
||||
Comparison flow based on above algorithm:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
The first parts (@samp{foo}) are identical.
|
||||
|
||||
@item
|
||||
The second parts (@samp{07} and @samp{7}) are compared numerically,
|
||||
and compare equal.
|
||||
|
||||
@item
|
||||
The third parts (@samp{.} vs @samp{a.}) are compared
|
||||
lexically by ASCII value (rule 2.B).
|
||||
|
||||
@item
|
||||
The first byte of the first string (@samp{.}) is compared
|
||||
to the first byte of the second string (@samp{a}).
|
||||
|
||||
@item
|
||||
Rule 2.B.a says letters sorts before non-letters.
|
||||
Hence, @samp{a} comes before @samp{.}.
|
||||
|
||||
@item
|
||||
The returned result is that @file{foo7a.7z} comes before @file{foo07.7z}.
|
||||
@end enumerate
|
||||
|
||||
Result when using sort:
|
||||
|
||||
@example
|
||||
$ cat input3
|
||||
foo07.7z
|
||||
foo7a.7z
|
||||
$ sort -V input3
|
||||
foo7a.7z
|
||||
foo07.7z
|
||||
@end example
|
||||
|
||||
See @ref{Differences from Debian version sort} for
|
||||
additional rules that extend the Debian algorithm in Coreutils.
|
||||
|
||||
|
||||
@node Version sort is not the same as numeric sort
|
||||
@subsection Version sort is not the same as numeric sort
|
||||
|
||||
Consider the following text file:
|
||||
|
||||
@example
|
||||
$ cat input4
|
||||
8.10
|
||||
8.5
|
||||
8.1
|
||||
8.01
|
||||
8.010
|
||||
8.100
|
||||
8.49
|
||||
|
||||
Numerical Sort: Version Sort:
|
||||
|
||||
$ sort -n input4 $ sort -V input4
|
||||
8.01 8.01
|
||||
8.010 8.1
|
||||
8.1 8.5
|
||||
8.10 8.010
|
||||
8.100 8.10
|
||||
8.49 8.49
|
||||
8.5 8.100
|
||||
@end example
|
||||
|
||||
Numeric sort (@samp{sort -n}) treats the entire string as a single numeric
|
||||
value, and compares it to other values. For example, @samp{8.1}, @samp{8.10} and
|
||||
@samp{8.100} are numerically equivalent, and are ordered together. Similarly,
|
||||
@samp{8.49} is numerically less than @samp{8.5}, and appears before first.
|
||||
|
||||
Version sort (@samp{sort -V}) first breaks down the string into digit and
|
||||
non-digit parts, and only then compares each part (see annotated
|
||||
example in @ref{Version-sort ordering rules}).
|
||||
|
||||
Comparing the string @samp{8.1} to @samp{8.01}, first the
|
||||
@samp{8}s are compared (and are identical), then the
|
||||
dots (@samp{.}) are compared and are identical, and lastly the
|
||||
remaining digits are compared numerically (@samp{1} and @samp{01}) --
|
||||
which are numerically equal. Hence, @samp{8.01} and @samp{8.1}
|
||||
are grouped together.
|
||||
|
||||
Similarly, comparing @samp{8.5} to @samp{8.49} -- the @samp{8}
|
||||
and @samp{.} parts are identical, then the numeric values @samp{5} and
|
||||
@samp{49} are compared. The resulting @samp{5} appears before @samp{49}.
|
||||
|
||||
This sorting order (where @samp{8.5} comes before @samp{8.49}) is common when
|
||||
assigning versions to computer programs (while perhaps not intuitive
|
||||
or ``natural'' for people).
|
||||
|
||||
@node Version sort punctuation
|
||||
@subsection Version sort punctuation
|
||||
|
||||
Punctuation is sorted by ASCII order (rule 2.B).
|
||||
|
||||
@example
|
||||
$ touch 1.0.5_src.tar.gz 1.0_src.tar.gz
|
||||
$ ls -v -1
|
||||
1.0.5_src.tar.gz
|
||||
1.0_src.tar.gz
|
||||
@end example
|
||||
|
||||
Why is @file{1.0.5_src.tar.gz} listed before @file{1.0_src.tar.gz}?
|
||||
|
||||
Based on the version-sort ordering rules, the strings are broken down
|
||||
into the following parts:
|
||||
|
||||
@example
|
||||
1 @r{vs} 1 @r{(rule 3, all digits)}
|
||||
. @r{vs} . @r{(rule 2, all non-digits)}
|
||||
0 @r{vs} 0 @r{(rule 3)}
|
||||
. @r{vs} _src.tar.gz @r{(rule 2)}
|
||||
5 @r{vs} empty string @r{(no more bytes in the file name)}
|
||||
_src.tar.gz @r{vs} empty string
|
||||
@end example
|
||||
|
||||
The fourth parts (@samp{.} and @samp{_src.tar.gz}) are compared
|
||||
lexically by ASCII order. The @samp{.} (ASCII value 46) is
|
||||
less than @samp{_} (ASCII value 95) -- and should be listed before it.
|
||||
|
||||
Hence, @file{1.0.5_src.tar.gz} is listed first.
|
||||
|
||||
If a different byte appears instead of the underscore (for
|
||||
example, percent sign @samp{%} ASCII value 37, which is less
|
||||
than dot's ASCII value of 46), that file will be listed first:
|
||||
|
||||
@example
|
||||
$ touch 1.0.5_src.tar.gz 1.0%zzzzz.gz
|
||||
1.0%zzzzz.gz
|
||||
1.0.5_src.tar.gz
|
||||
@end example
|
||||
|
||||
The same reasoning applies to the following example, as @samp{.} with
|
||||
ASCII value 46 is less than @samp{/} with ASCII value 47:
|
||||
|
||||
@example
|
||||
$ cat input5
|
||||
3.0/
|
||||
3.0.5
|
||||
$ sort -V input5
|
||||
3.0.5
|
||||
3.0/
|
||||
@end example
|
||||
|
||||
|
||||
@node Punctuation vs letters
|
||||
@subsection Punctuation vs letters
|
||||
|
||||
Rule 2.B.a says letters sort before non-letters
|
||||
(after breaking down a string to digit and non-digit parts).
|
||||
|
||||
@example
|
||||
$ cat input6
|
||||
a%
|
||||
az
|
||||
$ sort -V input6
|
||||
az
|
||||
a%
|
||||
@end example
|
||||
|
||||
The input strings consist entirely of non-digits, and based on the
|
||||
above algorithm have only one part, all non-digits
|
||||
(@samp{a%} vs @samp{az}).
|
||||
|
||||
Each part is then compared lexically,
|
||||
byte-by-byte; @samp{a} compares identically in both
|
||||
strings.
|
||||
|
||||
Rule 2.B.a says a letter like @samp{z} sorts before
|
||||
a non-letter like @samp{%} -- hence @samp{az} appears first (despite
|
||||
@samp{z} having ASCII value of 122, much larger than @samp{%}
|
||||
with ASCII value 37).
|
||||
|
||||
@node The tilde @samp{~}
|
||||
@subsection The tilde @samp{~}
|
||||
|
||||
Rule 2.B.b says the tilde @samp{~} (ASCII 126) sorts
|
||||
before other bytes, and before an empty string.
|
||||
|
||||
@example
|
||||
$ cat input7
|
||||
1
|
||||
1%
|
||||
1.2
|
||||
1~
|
||||
~
|
||||
$ sort -V input7
|
||||
~
|
||||
1~
|
||||
1
|
||||
1%
|
||||
1.2
|
||||
@end example
|
||||
|
||||
The sorting algorithm starts by breaking down the string into
|
||||
non-digit (rule 2) and digit parts (rule 3).
|
||||
|
||||
In the above input file, only the last line in the input file starts
|
||||
with a non-digit (@samp{~}). This is the first part. All other lines
|
||||
in the input file start with a digit -- their first non-digit part is
|
||||
empty.
|
||||
|
||||
Based on rule 2.B.b, tilde @samp{~} sorts before other bytes
|
||||
and before the empty string -- hence it comes before all other strings,
|
||||
and is listed first in the sorted output.
|
||||
|
||||
The remaining lines (@samp{1}, @samp{1%}, @samp{1.2}, @samp{1~})
|
||||
follow similar logic: The digit part is extracted (1 for all strings)
|
||||
and compares equal. The following extracted parts for the remaining
|
||||
input lines are: empty part, @samp{%}, @samp{.}, @samp{~}.
|
||||
|
||||
Tilde sorts before all others, hence the line @samp{1~} appears next.
|
||||
|
||||
The remaining lines (@samp{1}, @samp{1%}, @samp{1.2}) are sorted based
|
||||
on previously explained rules.
|
||||
|
||||
@node Version sort ignores locale
|
||||
@subsection Version sort ignores locale
|
||||
|
||||
In version sort, Unicode characters are compared byte-by-byte according
|
||||
to their binary representation, ignoring their Unicode value or the
|
||||
current locale.
|
||||
|
||||
Most commonly, Unicode characters are encoded as UTF-8 bytes; for
|
||||
example, GREEK SMALL LETTER ALPHA (U+03B1, @samp{α}) is encoded as the
|
||||
UTF-8 sequence @samp{0xCE 0xB1}). The encoding is compared
|
||||
byte-by-byte, e.g., first @samp{0xCE} (decimal value 206) then
|
||||
@samp{0xB1} (decimal value 177).
|
||||
|
||||
@example
|
||||
$ touch aa az "a%" "aα"
|
||||
$ ls -1 -v
|
||||
aa
|
||||
az
|
||||
a%
|
||||
aα
|
||||
@end example
|
||||
|
||||
Ignoring the first letter (@samp{a}) which is identical in all
|
||||
strings, the compared values are:
|
||||
|
||||
@samp{a} and @samp{z} are letters, and sort before
|
||||
all other non-digits.
|
||||
|
||||
Then, percent sign @samp{%} (ASCII value 37) is compared to the
|
||||
first byte of the UTF-8 sequence of @samp{α}, which is 0xCE or 206). The
|
||||
value 37 is smaller, hence @samp{a%} is listed before @samp{aα}.
|
||||
|
||||
@node Differences from Debian version sort
|
||||
@section Differences from Debian version sort
|
||||
|
||||
GNU Coreutils version sort differs slightly from the
|
||||
official Debian algorithm, in order to accommodate more general usage
|
||||
and file name listing.
|
||||
|
||||
|
||||
@node Hyphen-minus and colon
|
||||
@subsection Hyphen-minus @samp{-} and colon @samp{:}
|
||||
|
||||
In Debian's version string syntax the version consists of three parts:
|
||||
@example
|
||||
[epoch:]upstream_version[-debian_revision]
|
||||
@end example
|
||||
The @samp{epoch} and @samp{debian_revision} parts are optional.
|
||||
|
||||
Example of such version strings:
|
||||
|
||||
@example
|
||||
60.7.2esr-1~deb9u1
|
||||
52.9.0esr-1~deb9u1
|
||||
1:2.3.4-1+b2
|
||||
327-2
|
||||
1:1.0.13-3
|
||||
2:1.19.2-1+deb9u5
|
||||
@end example
|
||||
|
||||
If the @samp{debian_revision part} is not present,
|
||||
hyphens @samp{-} are not allowed.
|
||||
If epoch is not present, colons @samp{:} are not allowed.
|
||||
|
||||
If these parts are present, hyphen and/or colons can appear only once
|
||||
in valid Debian version strings.
|
||||
|
||||
In GNU Coreutils, such restrictions are not reasonable (a file name can
|
||||
have many hyphens, a line of text can have many colons).
|
||||
|
||||
As a result, in GNU Coreutils hyphens and colons are treated exactly
|
||||
like all other punctuation, i.e., they are sorted after
|
||||
letters. @xref{Version sort punctuation}.
|
||||
|
||||
In Debian, these characters are treated differently than in Coreutils:
|
||||
a version string with hyphen will sort before similar strings without
|
||||
hyphens.
|
||||
|
||||
Compare:
|
||||
|
||||
@example
|
||||
$ touch 1ab-cd 1abb
|
||||
$ ls -v -1
|
||||
1abb
|
||||
1ab-cd
|
||||
$ if dpkg --compare-versions 1abb lt 1ab-cd
|
||||
> then echo sorted
|
||||
> else echo out of order
|
||||
> fi
|
||||
out of order
|
||||
@end example
|
||||
|
||||
For further details, see @ref{Comparing two strings using Debian's
|
||||
algorithm} and @uref{https://bugs.gnu.org/35939,GNU Bug 35939}.
|
||||
|
||||
@node Special priority in GNU Coreutils version sort
|
||||
@subsection Special priority in GNU Coreutils version sort
|
||||
|
||||
In GNU Coreutils version sort, the following items have
|
||||
special priority and sort before all other strings (listed in order):
|
||||
|
||||
@enumerate
|
||||
@item The empty string
|
||||
|
||||
@item The string @samp{.} (a single dot, ASCII 46)
|
||||
|
||||
@item The string @samp{..} (two dots)
|
||||
|
||||
@item Strings starting with dot (@samp{.}) sort before
|
||||
strings starting with any other byte.
|
||||
@end enumerate
|
||||
|
||||
Example:
|
||||
|
||||
@example
|
||||
$ printf '%s\n' a "" b "." c ".." ".d20" ".d3" | sort -V
|
||||
.
|
||||
..
|
||||
.d3
|
||||
.d20
|
||||
a
|
||||
b
|
||||
c
|
||||
@end example
|
||||
|
||||
These priorities make perfect sense for @samp{ls -v}: The special
|
||||
files dot @samp{.} and dot-dot @samp{..} will be listed
|
||||
first, followed by any hidden files (files starting with a dot),
|
||||
followed by non-hidden files.
|
||||
|
||||
For @samp{sort -V} these priorities might seem arbitrary. However,
|
||||
because the sorting code is shared between the @command{ls} and @command{sort}
|
||||
program, the ordering rules are the same.
|
||||
|
||||
@node Special handling of file extensions
|
||||
@subsection Special handling of file extensions
|
||||
|
||||
GNU Coreutils version sort implements specialized handling
|
||||
of strings that look like file names with extensions.
|
||||
This enables slightly more natural ordering of file
|
||||
names.
|
||||
|
||||
The following additional rules apply when comparing two strings where
|
||||
both begin with non-@samp{.}. They also apply when comparing two
|
||||
strings where both begin with @samp{.} but neither is @samp{.} or @samp{..}.
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
A suffix (i.e., a file extension) is defined as: a dot, followed by an
|
||||
ASCII letter or tilde, followed by zero or more ASCII letters, digits,
|
||||
or tildes; all repeated zero or more times, and ending at string end.
|
||||
This is equivalent to matching the extended regular expression
|
||||
@code{(\.[A-Za-z~][A-Za-z0-9~]*)*$} in the C locale.
|
||||
The longest such match is used, except that a suffix is not
|
||||
allowed to match an entire nonempty string.
|
||||
|
||||
@item
|
||||
The suffixes are temporarily removed, and the strings are compared
|
||||
without them, using version sort (see @ref{Version-sort ordering
|
||||
rules}) without special priority (see @ref{Special priority in GNU
|
||||
Coreutils version sort}).
|
||||
|
||||
@item
|
||||
If the suffix-less strings do not compare equal, this comparison
|
||||
result is used and the suffixes are effectively ignored.
|
||||
|
||||
@item
|
||||
If the suffix-less strings compare equal, the suffixes are restored
|
||||
and the entire strings are compared using version sort.
|
||||
@end enumerate
|
||||
|
||||
Examples for rule 1:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
@samp{hello-8.txt}: the suffix is @samp{.txt}
|
||||
|
||||
@item
|
||||
@samp{hello-8.2.txt}: the suffix is @samp{.txt}
|
||||
(@samp{.2} is not included because the dot is not followed by a letter)
|
||||
|
||||
@item
|
||||
@samp{hello-8.0.12.tar.gz}: the suffix is @samp{.tar.gz} (@samp{.0.12}
|
||||
is not included)
|
||||
|
||||
@item
|
||||
@samp{hello-8.2}: no suffix (suffix is an empty string)
|
||||
|
||||
@item
|
||||
@samp{hello.foobar65}: the suffix is @samp{.foobar65}
|
||||
|
||||
@item
|
||||
@samp{gcc-c++-10.8.12-0.7rc2.fc9.tar.bz2}: the suffix is
|
||||
@samp{.fc9.tar.bz2} (@samp{.7rc2} is not included as it begins with a digit)
|
||||
|
||||
@item
|
||||
@samp{.autom4te.cfg}: the suffix is the entire string.
|
||||
@end itemize
|
||||
|
||||
Examples for rule 2:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Comparing @samp{hello-8.txt} to @samp{hello-8.2.12.txt}, the
|
||||
@samp{.txt} suffix is temporarily removed from both strings.
|
||||
|
||||
@item
|
||||
Comparing @samp{foo-10.3.tar.gz} to @samp{foo-10.tar.xz}, the suffixes
|
||||
@samp{.tar.gz} and @samp{.tar.xz} are temporarily removed from the
|
||||
strings.
|
||||
@end itemize
|
||||
|
||||
Example for rule 3:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Comparing @samp{hello.foobar65} to @samp{hello.foobar4}, the suffixes
|
||||
(@samp{.foobar65} and @samp{.foobar4}) are temporarily removed. The
|
||||
remaining strings are identical (@samp{hello}). The suffixes are then
|
||||
restored, and the entire strings are compared (@samp{hello.foobar4} comes
|
||||
first).
|
||||
@end itemize
|
||||
|
||||
Examples for rule 4:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
When comparing the strings @samp{hello-8.2.txt} and @samp{hello-8.10.txt}, the
|
||||
suffixes (@samp{.txt}) are temporarily removed. The remaining strings
|
||||
(@samp{hello-8.2} and @samp{hello-8.10}) are compared as previously described
|
||||
(@samp{hello-8.2} comes first).
|
||||
@slanted{(In this case the suffix removal algorithm
|
||||
does not have a noticeable effect on the resulting order.)}
|
||||
@end itemize
|
||||
|
||||
@b{How does the suffix-removal algorithm effect ordering results?}
|
||||
|
||||
Consider the comparison of hello-8.txt and hello-8.2.txt.
|
||||
|
||||
Without the suffix-removal algorithm, the strings will be broken down
|
||||
to the following parts:
|
||||
|
||||
@example
|
||||
hello- @r{vs} hello- @r{(rule 2, all non-digits)}
|
||||
8 @r{vs} 8 @r{(rule 3, all digits)}
|
||||
.txt @r{vs} . @r{(rule 2)}
|
||||
empty @r{vs} 2
|
||||
empty @r{vs} .txt
|
||||
@end example
|
||||
|
||||
The comparison of the third parts (@samp{.} vs
|
||||
@samp{.txt}) will determine that the shorter string comes first --
|
||||
resulting in @file{hello-8.2.txt} appearing first.
|
||||
|
||||
Indeed this is the order in which Debian's @command{dpkg} compares the strings.
|
||||
|
||||
A more natural result is that @file{hello-8.txt} should come before
|
||||
@file{hello-8.2.txt}, and this is where the suffix-removal comes into play:
|
||||
|
||||
The suffixes (@samp{.txt}) are removed, and the remaining strings are
|
||||
broken down into the following parts:
|
||||
|
||||
@example
|
||||
hello- @r{vs} hello- @r{(rule 2, all non-digits)}
|
||||
8 @r{vs} 8 @r{(rule 3, all digits)}
|
||||
empty @r{vs} . @r{(rule 2)}
|
||||
empty @r{vs} 2
|
||||
@end example
|
||||
|
||||
As empty strings sort before non-empty strings, the result is @samp{hello-8}
|
||||
being first.
|
||||
|
||||
A real-world example would be listing files such as:
|
||||
@file{gcc_10.fc9.tar.gz}
|
||||
and @file{gcc_10.8.12.7rc2.fc9.tar.bz2}: Debian's algorithm would list
|
||||
@file{gcc_10.8.12.7rc2.fc9.tar.bz2} first, while @samp{ls -v} will list
|
||||
@file{gcc_10.fc9.tar.gz} first.
|
||||
|
||||
These priorities make sense for @samp{ls -v}:
|
||||
Versioned files will be listed in a more natural order.
|
||||
|
||||
For @samp{sort -V} these priorities might seem arbitrary. However,
|
||||
because the sorting code is shared between the @command{ls} and @command{sort}
|
||||
program, the ordering rules are the same.
|
||||
|
||||
|
||||
@node Comparing two strings using Debian's algorithm
|
||||
@subsection Comparing two strings using Debian's algorithm
|
||||
|
||||
The Debian program @command{dpkg} (available on all Debian and Ubuntu
|
||||
installations) can compare two strings using the @option{--compare-versions}
|
||||
option.
|
||||
|
||||
To use it, create a helper shell function (simply copy & paste the
|
||||
following snippet to your shell command-prompt):
|
||||
|
||||
@example
|
||||
compver() @{
|
||||
if dpkg --compare-versions "$1" lt "$2"
|
||||
then printf '%s\n' "$1" "$2"
|
||||
else printf '%s\n' "$2" "$1"
|
||||
fi
|
||||
@}
|
||||
@end example
|
||||
|
||||
Then compare two strings by calling @command{compver}:
|
||||
|
||||
@example
|
||||
$ compver 8.49 8.5
|
||||
8.5
|
||||
8.49
|
||||
@end example
|
||||
|
||||
Note that @command{dpkg} will warn if the strings have invalid syntax:
|
||||
|
||||
@example
|
||||
$ compver "foo07.7z" "foo7a.7z"
|
||||
dpkg: warning: version 'foo07.7z' has bad syntax:
|
||||
version number does not start with digit
|
||||
dpkg: warning: version 'foo7a.7z' has bad syntax:
|
||||
version number does not start with digit
|
||||
foo7a.7z
|
||||
foo07.7z
|
||||
$ compver "3.0/" "3.0.5"
|
||||
dpkg: warning: version '3.0/' has bad syntax:
|
||||
invalid character in version number
|
||||
3.0.5
|
||||
3.0/
|
||||
@end example
|
||||
|
||||
To illustrate the different handling of hyphens between Debian and
|
||||
Coreutils algorithms (see
|
||||
@ref{Hyphen-minus and colon}):
|
||||
|
||||
@example
|
||||
$ compver abb ab-cd 2>/dev/null $ printf 'abb\nab-cd\n' | sort -V
|
||||
ab-cd abb
|
||||
abb ab-cd
|
||||
@end example
|
||||
|
||||
To illustrate the different handling of file extension: (see @ref{Special
|
||||
handling of file extensions}):
|
||||
|
||||
@example
|
||||
$ compver hello-8.txt hello-8.2.txt 2>/dev/null
|
||||
hello-8.2.txt
|
||||
hello-8.txt
|
||||
$ printf '%s\n' hello-8.txt hello-8.2.txt | sort -V
|
||||
hello-8.txt
|
||||
hello-8.2.txt
|
||||
@end example
|
||||
|
||||
|
||||
@node Advanced version sort topics
|
||||
@section Advanced Topics
|
||||
|
||||
|
||||
@node Reporting version sort bugs
|
||||
@subsection Reporting version sort bugs
|
||||
|
||||
If you suspect a bug in GNU Coreutils version sort (i.e., in the
|
||||
output of @samp{ls -v} or @samp{sort -V}), please first check the following:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
Is the result consistent with Debian's own ordering (using @command{dpkg}, see
|
||||
@ref{Comparing two strings using Debian's algorithm})? If it is, then this
|
||||
is not a bug -- please do not report it.
|
||||
|
||||
@item
|
||||
If the result differs from Debian's, is it explained by one of the
|
||||
sections in @ref{Differences from Debian version sort}? If it is,
|
||||
then this is not a bug -- please do not report it.
|
||||
|
||||
@item
|
||||
If you have a question about specific ordering which is not explained
|
||||
here, please write to @email{coreutils@@gnu.org}, and provide a
|
||||
concise example that will help us diagnose the issue.
|
||||
|
||||
@item
|
||||
If you still suspect a bug which is not explained by the above, please
|
||||
write to @email{bug-coreutils@@gnu.org} with a concrete example of the
|
||||
suspected incorrect output, with details on why you think it is
|
||||
incorrect.
|
||||
|
||||
@end enumerate
|
||||
|
||||
@node Other version/natural sort implementations
|
||||
@subsection Other version/natural sort implementations
|
||||
|
||||
As previously mentioned, there are multiple variations on
|
||||
version/natural sort, each with its own rules. Some examples are:
|
||||
|
||||
@itemize
|
||||
|
||||
@item
|
||||
Natural Sorting variants in
|
||||
@uref{https://rosettacode.org/wiki/Natural_sorting,Rosetta Code}.
|
||||
|
||||
@item
|
||||
Python's @uref{https://pypi.org/project/natsort/,natsort package}
|
||||
(includes detailed description of their sorting rules:
|
||||
@uref{https://natsort.readthedocs.io/en/master/howitworks.html,
|
||||
natsort -- how it works}).
|
||||
|
||||
@item
|
||||
Ruby's @uref{https://github.com/github/version_sorter,version_sorter}.
|
||||
|
||||
@item
|
||||
Perl has multiple packages for natural and version sorts
|
||||
(each likely with its own rules and nuances):
|
||||
@uref{https://metacpan.org/pod/Sort::Naturally,Sort::Naturally},
|
||||
@uref{https://metacpan.org/pod/Sort::Versions,Sort::Versions},
|
||||
@uref{https://metacpan.org/pod/CPAN::Version,CPAN::Version}.
|
||||
|
||||
@item
|
||||
PHP has a built-in function
|
||||
@uref{https://www.php.net/manual/en/function.natsort.php,natsort}.
|
||||
|
||||
@item
|
||||
NodeJS's @uref{https://www.npmjs.com/package/natural-sort,natural-sort package}.
|
||||
|
||||
@item
|
||||
In zsh, the
|
||||
@uref{http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers,
|
||||
glob modifier} @samp{*(n)} will expand to files in natural sort order.
|
||||
|
||||
@item
|
||||
When writing C programs, the GNU libc library (@samp{glibc})
|
||||
provides the
|
||||
@uref{https://man7.org/linux/man-pages/man3/strverscmp.3.html,
|
||||
strverscmp(3)} function to compare two strings, and
|
||||
@uref{https://man7.org/linux/man-pages/man3/versionsort.3.html,versionsort(3)}
|
||||
function to compare two directory entries (despite the names, they are
|
||||
not identical to GNU Coreutils version sort ordering).
|
||||
|
||||
@item
|
||||
Using Debian's sorting algorithm in:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
python: @uref{https://stackoverflow.com/a/4957741,
|
||||
Stack Overflow Example #4957741}.
|
||||
|
||||
@item
|
||||
NodeJS: @uref{https://www.npmjs.com/package/deb-version-compare,
|
||||
deb-version-compare}.
|
||||
@end itemize
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Related source code
|
||||
@subsection Related source code
|
||||
|
||||
@itemize
|
||||
|
||||
@item
|
||||
Debian's code which splits a version string into
|
||||
@code{epoch/upstream_version/debian_revision} parts:
|
||||
@uref{https://git.dpkg.org/cgit/dpkg/dpkg.git/tree/lib/dpkg/parsehelp.c#n191,
|
||||
parsehelp.c:parseversion()}.
|
||||
|
||||
@item
|
||||
Debian's code which performs the @code{upstream_version} comparison:
|
||||
@uref{https://git.dpkg.org/cgit/dpkg/dpkg.git/tree/lib/dpkg/version.c#n140,
|
||||
version.c}.
|
||||
|
||||
@item
|
||||
Gnulib code (used by GNU Coreutils) which performs the version comparison:
|
||||
@uref{https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/filevercmp.c,
|
||||
filevercmp.c}.
|
||||
@end itemize
|
4
doc/stamp-vti
Normal file
4
doc/stamp-vti
Normal file
|
@ -0,0 +1,4 @@
|
|||
@set UPDATED 7 April 2025
|
||||
@set UPDATED-MONTH April 2025
|
||||
@set EDITION 9.7
|
||||
@set VERSION 9.7
|
4
doc/version.texi
Normal file
4
doc/version.texi
Normal file
|
@ -0,0 +1,4 @@
|
|||
@set UPDATED 7 April 2025
|
||||
@set UPDATED-MONTH April 2025
|
||||
@set EDITION 9.7
|
||||
@set VERSION 9.7
|
59
gl/lib/buffer-lcm.c
Normal file
59
gl/lib/buffer-lcm.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* buffer-lcm.c - compute a good buffer size for dealing with two files
|
||||
|
||||
Copyright (C) 2002-2025 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 "buffer-lcm.h"
|
||||
|
||||
/* Return a buffer size suitable for doing I/O with files whose block
|
||||
sizes are A and B. However, never return a value greater than
|
||||
LCM_MAX. */
|
||||
|
||||
size_t
|
||||
buffer_lcm (size_t a, size_t b, size_t lcm_max)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
/* Use reasonable values if buffer sizes are zero. */
|
||||
if (!a)
|
||||
size = b ? b : 8 * 1024;
|
||||
else
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
/* Return lcm (A, B) if it is in range; otherwise, fall back
|
||||
on A. */
|
||||
|
||||
size_t lcm, m, n, q, r;
|
||||
|
||||
/* N = gcd (A, B). */
|
||||
for (m = a, n = b; (r = m % n) != 0; m = n, n = r)
|
||||
continue;
|
||||
|
||||
/* LCM = lcm (A, B), if in range. */
|
||||
q = a / n;
|
||||
lcm = q * b;
|
||||
if (lcm <= lcm_max && lcm / b == q)
|
||||
return lcm;
|
||||
}
|
||||
|
||||
size = a;
|
||||
}
|
||||
|
||||
return size <= lcm_max ? size : lcm_max;
|
||||
}
|
2
gl/lib/buffer-lcm.h
Normal file
2
gl/lib/buffer-lcm.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include <stddef.h>
|
||||
size_t buffer_lcm (size_t, size_t, size_t) _GL_ATTRIBUTE_CONST;
|
76
gl/lib/cl-strtod.c
Normal file
76
gl/lib/cl-strtod.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Convert string to double in the current locale, falling back on the C locale.
|
||||
|
||||
Copyright 2019-2025 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 "cl-strtod.h"
|
||||
|
||||
#include <c-strtod.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if LONG
|
||||
# define CL_STRTOD cl_strtold
|
||||
# define DOUBLE long double
|
||||
# define C_STRTOD c_strtold
|
||||
# define STRTOD strtold
|
||||
#else
|
||||
# define CL_STRTOD cl_strtod
|
||||
# define DOUBLE double
|
||||
# define C_STRTOD c_strtod
|
||||
# define STRTOD strtod
|
||||
#endif
|
||||
|
||||
/* This function acts like strtod or strtold, except that it falls
|
||||
back on the C locale if the initial prefix is not parsable in
|
||||
the current locale. If the prefix is parsable in both locales,
|
||||
it uses the longer parse, breaking ties in favor of the current locale.
|
||||
|
||||
Parse the initial prefix of NPTR as a floating-point number in the
|
||||
current locale or in the C locale (preferring the locale that
|
||||
yields the longer parse, or the current locale if there is a tie).
|
||||
If ENDPTR is non-null, set *ENDPTR to the first unused byte, or to
|
||||
NPTR if the prefix cannot be parsed.
|
||||
|
||||
If successful, return a number without changing errno.
|
||||
If the prefix cannot be parsed, return 0 and possibly set errno to EINVAL.
|
||||
If the number overflows, return an extreme value and set errno to ERANGE.
|
||||
If the number underflows, return a value close to 0 and set errno to ERANGE.
|
||||
If there is some other error, return 0 and set errno. */
|
||||
|
||||
DOUBLE
|
||||
CL_STRTOD (char const *nptr, char **restrict endptr)
|
||||
{
|
||||
char *end;
|
||||
DOUBLE d = STRTOD (nptr, &end);
|
||||
if (*end)
|
||||
{
|
||||
int strtod_errno = errno;
|
||||
char *c_end;
|
||||
DOUBLE c = C_STRTOD (nptr, &c_end);
|
||||
if (end < c_end)
|
||||
d = c, end = c_end;
|
||||
else
|
||||
errno = strtod_errno;
|
||||
}
|
||||
if (endptr)
|
||||
*endptr = end;
|
||||
return d;
|
||||
}
|
4
gl/lib/cl-strtod.h
Normal file
4
gl/lib/cl-strtod.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
double cl_strtod (char const *, char **restrict)
|
||||
_GL_ATTRIBUTE_NONNULL ((1));
|
||||
long double cl_strtold (char const *, char **restrict)
|
||||
_GL_ATTRIBUTE_NONNULL ((1));
|
2
gl/lib/cl-strtold.c
Normal file
2
gl/lib/cl-strtold.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define LONG 1
|
||||
#include "cl-strtod.c"
|
3
gl/lib/dtimespec-bound.c
Normal file
3
gl/lib/dtimespec-bound.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include <config.h>
|
||||
#define DTIMESPEC_BOUND_INLINE _GL_EXTERN_INLINE
|
||||
#include "dtimespec-bound.h"
|
76
gl/lib/dtimespec-bound.h
Normal file
76
gl/lib/dtimespec-bound.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Compute a timespec-related bound for floating point.
|
||||
|
||||
Copyright 2025 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 DTIMESPEC_BOUND_H
|
||||
# define DTIMESPEC_BOUND_H 1
|
||||
|
||||
/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */
|
||||
# if !_GL_CONFIG_H_INCLUDED
|
||||
# error "Please include config.h first."
|
||||
# endif
|
||||
|
||||
# include <errno.h>
|
||||
# include <float.h>
|
||||
# include <math.h>
|
||||
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
# ifndef DTIMESPEC_BOUND_INLINE
|
||||
# define DTIMESPEC_BOUND_INLINE _GL_INLINE
|
||||
# endif
|
||||
|
||||
/* If C is positive and finite, return the least floating point value
|
||||
greater than C. However, if 0 < C < (2 * DBL_TRUE_MIN) / (DBL_EPSILON**2),
|
||||
return a positive value less than 1e-9.
|
||||
|
||||
If C is +0.0, return a positive value < 1e-9 if ERR == ERANGE, C otherwise.
|
||||
If C is +Inf, return C.
|
||||
If C is negative, return -timespec_roundup(-C).
|
||||
If C is a NaN, return a NaN.
|
||||
|
||||
Assume round-to-even.
|
||||
|
||||
This function can be useful if some floating point operation
|
||||
rounded to C but we want a nearby bound on the true value, where
|
||||
the bound can be converted to struct timespec. If the operation
|
||||
underflowed to zero, ERR should be ERANGE a la strtod. */
|
||||
|
||||
DTIMESPEC_BOUND_INLINE double
|
||||
dtimespec_bound (double c, int err)
|
||||
{
|
||||
/* Do not use copysign or nextafter, as they link to -lm in GNU/Linux. */
|
||||
|
||||
/* Use DBL_TRUE_MIN for the special case of underflowing to zero;
|
||||
any positive value less than 1e-9 will do. */
|
||||
if (err == ERANGE && c == 0)
|
||||
return signbit (c) ? -DBL_TRUE_MIN : DBL_TRUE_MIN;
|
||||
|
||||
/* This is the first part of Algorithm 2 of:
|
||||
Rump SM, Zimmermann P, Boldo S, Melquiond G.
|
||||
Computing predecessor and successor in rounding to nearest.
|
||||
BIT Numerical Mathematics. 2009;49(419-431).
|
||||
<https://doi.org/10.1007/s10543-009-0218-z>
|
||||
The rest of Algorithm 2 is not needed because numbers less than
|
||||
the predecessor of 1e-9 merely need to stay less than 1e-9. */
|
||||
double phi = DBL_EPSILON / 2 * (1 + DBL_EPSILON);
|
||||
return c + phi * c;
|
||||
}
|
||||
|
||||
_GL_INLINE_HEADER_END
|
||||
|
||||
#endif
|
37
gl/lib/fadvise.c
Normal file
37
gl/lib/fadvise.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* Declare an access pattern hint for files.
|
||||
Copyright (C) 2010-2025 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 "fadvise.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include "ignore-value.h"
|
||||
|
||||
void
|
||||
fdadvise (int fd, off_t offset, off_t len, fadvice_t advice)
|
||||
{
|
||||
#if HAVE_POSIX_FADVISE
|
||||
ignore_value (posix_fadvise (fd, offset, len, advice));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
fadvise (FILE *fp, fadvice_t advice)
|
||||
{
|
||||
if (fp)
|
||||
fdadvise (fileno (fp), 0, 0, advice);
|
||||
}
|
71
gl/lib/fadvise.h
Normal file
71
gl/lib/fadvise.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Declare an access pattern hint for files.
|
||||
Copyright (C) 2010-2025 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 <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* There are a few hints one can provide, which have the
|
||||
following characteristics on Linux 2.6.31 at least.
|
||||
|
||||
POSIX_FADV_SEQUENTIAL
|
||||
Doubles the size of read ahead done for file
|
||||
POSIX_FADV_WILLNEED
|
||||
_synchronously_ prepopulate the buffer cache with the file
|
||||
POSIX_FADV_NOREUSE
|
||||
Could lower priority of data in buffer caches,
|
||||
but currently does nothing.
|
||||
POSIX_FADV_DONTNEED
|
||||
Drop the file from cache.
|
||||
Note this is automatically done when files are unlinked.
|
||||
|
||||
We use this enum "type" both to make it explicit that
|
||||
these options are mutually exclusive, and to discourage
|
||||
the passing of the possibly undefined POSIX_FADV_... values.
|
||||
Note we could #undef the POSIX_FADV_ values, but that would
|
||||
preclude using the posix_fadvise() function with its standard
|
||||
constants. Using posix_fadvise() might be required if the return
|
||||
value is needed, but it must be guarded by appropriate #ifdefs. */
|
||||
|
||||
#if HAVE_POSIX_FADVISE
|
||||
typedef enum {
|
||||
FADVISE_NORMAL = POSIX_FADV_NORMAL,
|
||||
FADVISE_SEQUENTIAL = POSIX_FADV_SEQUENTIAL,
|
||||
FADVISE_NOREUSE = POSIX_FADV_NOREUSE,
|
||||
FADVISE_DONTNEED = POSIX_FADV_DONTNEED,
|
||||
FADVISE_WILLNEED = POSIX_FADV_WILLNEED,
|
||||
FADVISE_RANDOM = POSIX_FADV_RANDOM
|
||||
} fadvice_t;
|
||||
#else
|
||||
typedef enum {
|
||||
FADVISE_NORMAL,
|
||||
FADVISE_SEQUENTIAL,
|
||||
FADVISE_NOREUSE,
|
||||
FADVISE_DONTNEED,
|
||||
FADVISE_WILLNEED,
|
||||
FADVISE_RANDOM
|
||||
} fadvice_t;
|
||||
#endif
|
||||
|
||||
/* We ignore any errors as these hints are only advisory.
|
||||
There is the chance one can pass invalid ADVICE, which will
|
||||
not be indicated, but given the simplicity of the interface
|
||||
this is unlikely. Also not returning errors allows the
|
||||
unconditional passing of descriptors to non standard files,
|
||||
which will just be ignored if unsupported. */
|
||||
|
||||
void fdadvise (int fd, off_t offset, off_t len, fadvice_t advice);
|
||||
void fadvise (FILE *fp, fadvice_t advice);
|
46
gl/lib/fd-reopen.c
Normal file
46
gl/lib/fd-reopen.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Invoke open, but return either a desired file descriptor or -1.
|
||||
|
||||
Copyright (C) 2005-2025 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 "fd-reopen.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Open a file to a particular file descriptor. This is like standard
|
||||
'open', except it always returns DESIRED_FD if successful. */
|
||||
|
||||
int
|
||||
fd_reopen (int desired_fd, char const *file, int flags, mode_t mode)
|
||||
{
|
||||
int fd = open (file, flags, mode);
|
||||
|
||||
if (fd == desired_fd || fd < 0)
|
||||
return fd;
|
||||
else
|
||||
{
|
||||
int fd2 = dup2 (fd, desired_fd);
|
||||
int saved_errno = errno;
|
||||
close (fd);
|
||||
errno = saved_errno;
|
||||
return fd2;
|
||||
}
|
||||
}
|
22
gl/lib/fd-reopen.h
Normal file
22
gl/lib/fd-reopen.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* Invoke open, but return either a desired file descriptor or -1.
|
||||
|
||||
Copyright (C) 2005-2025 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 <sys/types.h>
|
||||
|
||||
int fd_reopen (int, char const *, int, mode_t) _GL_ATTRIBUTE_NONNULL ();
|
150
gl/lib/heap.c
Normal file
150
gl/lib/heap.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* Barebones heap implementation supporting only insert and pop.
|
||||
|
||||
Copyright (C) 2010-2025 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/>. */
|
||||
|
||||
/* Full implementation: GDSL (http://gna.org/projects/gdsl/) by Nicolas
|
||||
Darnis <ndarnis@free.fr>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "heap.h"
|
||||
#include "stdlib--.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
static int heap_default_compare (void const *, void const *);
|
||||
static void heapify_down (void **, idx_t, idx_t,
|
||||
int (*) (void const *, void const *));
|
||||
static void heapify_up (void **, idx_t,
|
||||
int (*) (void const *, void const *));
|
||||
|
||||
struct heap
|
||||
{
|
||||
void **array; /* array[0] is not used */
|
||||
idx_t capacity; /* Array size */
|
||||
idx_t count; /* Used as index to last element. Also is num of items. */
|
||||
int (*compare) (void const *, void const *);
|
||||
};
|
||||
|
||||
/* Allocate memory for the heap. */
|
||||
|
||||
struct heap *
|
||||
heap_alloc (int (*compare) (void const *, void const *), idx_t n_reserve)
|
||||
{
|
||||
struct heap *heap = xmalloc (sizeof *heap);
|
||||
|
||||
if (n_reserve == 0)
|
||||
n_reserve = 1;
|
||||
|
||||
heap->array = xnmalloc (n_reserve, sizeof *(heap->array));
|
||||
|
||||
heap->array[0] = nullptr;
|
||||
heap->capacity = n_reserve;
|
||||
heap->count = 0;
|
||||
heap->compare = compare ? compare : heap_default_compare;
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
heap_default_compare (void const *a, void const *b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
heap_free (struct heap *heap)
|
||||
{
|
||||
free (heap->array);
|
||||
free (heap);
|
||||
}
|
||||
|
||||
/* Insert element into heap. */
|
||||
|
||||
int
|
||||
heap_insert (struct heap *heap, void *item)
|
||||
{
|
||||
if (heap->capacity - 1 <= heap->count)
|
||||
heap->array = xpalloc (heap->array, &heap->capacity, 1, -1,
|
||||
sizeof heap->array[0]);
|
||||
|
||||
heap->array[++heap->count] = item;
|
||||
heapify_up (heap->array, heap->count, heap->compare);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pop top element off heap. */
|
||||
|
||||
void *
|
||||
heap_remove_top (struct heap *heap)
|
||||
{
|
||||
void *top;
|
||||
|
||||
if (heap->count == 0)
|
||||
return nullptr;
|
||||
|
||||
top = heap->array[1];
|
||||
heap->array[1] = heap->array[heap->count--];
|
||||
heapify_down (heap->array, heap->count, 1, heap->compare);
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
/* Move element down into appropriate position in heap. */
|
||||
|
||||
static void
|
||||
heapify_down (void **array, idx_t count, idx_t initial,
|
||||
int (*compare) (void const *, void const *))
|
||||
{
|
||||
void *element = array[initial];
|
||||
|
||||
idx_t parent = initial;
|
||||
while (parent <= count >> 1)
|
||||
{
|
||||
idx_t child = 2 * parent;
|
||||
|
||||
if (child < count && compare (array[child], array[child + 1]) < 0)
|
||||
child++;
|
||||
|
||||
if (compare (array[child], element) <= 0)
|
||||
break;
|
||||
|
||||
array[parent] = array[child];
|
||||
parent = child;
|
||||
}
|
||||
|
||||
array[parent] = element;
|
||||
}
|
||||
|
||||
/* Move element up into appropriate position in heap. */
|
||||
|
||||
static void
|
||||
heapify_up (void **array, idx_t count,
|
||||
int (*compare) (void const *, void const *))
|
||||
{
|
||||
idx_t k = count;
|
||||
void *new_element = array[k];
|
||||
|
||||
while (k != 1 && compare (array[k >> 1], new_element) <= 0)
|
||||
{
|
||||
array[k] = array[k >> 1];
|
||||
k >>= 1;
|
||||
}
|
||||
|
||||
array[k] = new_element;
|
||||
}
|
34
gl/lib/heap.h
Normal file
34
gl/lib/heap.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Barebones heap implementation supporting only insert and pop.
|
||||
|
||||
Copyright (C) 2010-2025 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/>. */
|
||||
|
||||
/* Full implementation: GDSL (http://gna.org/projects/gdsl/) by Nicolas
|
||||
Darnis <ndarnis@free.fr>. Adapted by Gene Auyeung. */
|
||||
|
||||
#include "idx.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct heap;
|
||||
|
||||
void heap_free (struct heap *) _GL_ATTRIBUTE_NONNULL ();
|
||||
|
||||
struct heap *heap_alloc (int (*) (void const *, void const *), idx_t)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (heap_free, 1)
|
||||
_GL_ATTRIBUTE_RETURNS_NONNULL;
|
||||
|
||||
int heap_insert (struct heap *heap, void *item) _GL_ATTRIBUTE_NONNULL ();
|
||||
void *heap_remove_top (struct heap *heap) _GL_ATTRIBUTE_NONNULL ();
|
273
gl/lib/rand-isaac.c
Normal file
273
gl/lib/rand-isaac.c
Normal file
|
@ -0,0 +1,273 @@
|
|||
/* Bob Jenkins's cryptographic random number generators, ISAAC and ISAAC64.
|
||||
|
||||
Copyright (C) 1999-2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 1999 Colin Plumb.
|
||||
|
||||
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 Colin Plumb and Paul Eggert. */
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* We need a source of random numbers for some data.
|
||||
* Cryptographically secure is desirable, but it's not life-or-death
|
||||
* so I can be a little bit experimental in the choice of RNGs here.
|
||||
*
|
||||
* This generator is based somewhat on RC4, but has analysis
|
||||
* <https://burtleburtle.net/bob/rand/isaacafa.html>
|
||||
* pointing to it actually being better. I like it because it's nice
|
||||
* and fast, and because the author did good work analyzing it.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
#include "rand-isaac.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
/* If the platform supports unaligned access,
|
||||
then don't have -fsanitize=undefined warn about it. */
|
||||
#undef ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED
|
||||
#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) \
|
||||
|| __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9)
|
||||
# define ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED /* empty */
|
||||
#else
|
||||
# define ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED \
|
||||
__attribute__ ((__no_sanitize_undefined__))
|
||||
#endif
|
||||
|
||||
/* A if 32-bit ISAAC, B if 64-bit. This is a macro, not an inline
|
||||
function, to prevent undefined behavior if the unused argument
|
||||
shifts by more than a word width. */
|
||||
#define IF32(a, b) (ISAAC_BITS == 32 ? (a) : (b))
|
||||
|
||||
/* Discard bits outside the desired range. On typical machines, any
|
||||
decent compiler should optimize this function call away to nothing.
|
||||
But machines with pad bits in integers may need to do more work. */
|
||||
static inline isaac_word
|
||||
just (isaac_word a)
|
||||
{
|
||||
isaac_word desired_bits = ((isaac_word) 1 << 1 << (ISAAC_BITS - 1)) - 1;
|
||||
return a & desired_bits;
|
||||
}
|
||||
|
||||
/* The index operation. */
|
||||
static inline isaac_word
|
||||
ind (isaac_word const *m, isaac_word x)
|
||||
{
|
||||
if (sizeof *m * CHAR_BIT == ISAAC_BITS)
|
||||
{
|
||||
/* The typical case, where words are exactly the right size.
|
||||
Optimize this to a mask, an addition, and an indirect
|
||||
load. */
|
||||
void const *void_m = m;
|
||||
char const *base_p = void_m;
|
||||
void const *word_p = base_p + (x & ((ISAAC_WORDS - 1) * sizeof *m));
|
||||
isaac_word const *p = word_p;
|
||||
return *p;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Atypical machines need more work. */
|
||||
return m[(x / (ISAAC_BITS / CHAR_BIT)) & (ISAAC_WORDS - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
/* Use and update *S to generate random data to fill RESULT. */
|
||||
void ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED
|
||||
isaac_refill (struct isaac_state *s, isaac_word result[ISAAC_WORDS])
|
||||
{
|
||||
/* Caches of S->a and S->b. */
|
||||
isaac_word a = s->a;
|
||||
isaac_word b = s->b + (++s->c);
|
||||
|
||||
/* Pointers into state array and into result. */
|
||||
isaac_word *m = s->m;
|
||||
isaac_word *r = result;
|
||||
|
||||
enum { HALF = ISAAC_WORDS / 2 };
|
||||
|
||||
/* The central step. S->m is the whole state array, while M is a
|
||||
pointer to the current word. OFF is the offset from M to the
|
||||
word ISAAC_WORDS/2 words away in the SM array, i.e., +/-
|
||||
ISAAC_WORDS/2. A and B are state variables, and R the result.
|
||||
This updates A, B, M[I], and R[I]. */
|
||||
#define ISAAC_STEP(i, off, mix) \
|
||||
{ \
|
||||
isaac_word x, y; \
|
||||
a = (IF32 (a, 0) ^ (mix)) + m[off + (i)]; \
|
||||
x = m[i]; \
|
||||
m[i] = y = ind (s->m, x) + a + b; \
|
||||
r[i] = b = just (ind (s->m, y >> ISAAC_WORDS_LOG) + x); \
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ISAAC_STEP (0, HALF, IF32 ( a << 13, ~ (a ^ (a << 21))));
|
||||
ISAAC_STEP (1, HALF, IF32 (just (a) >> 6, a ^ (just (a) >> 5)));
|
||||
ISAAC_STEP (2, HALF, IF32 ( a << 2, a ^ ( a << 12)));
|
||||
ISAAC_STEP (3, HALF, IF32 (just (a) >> 16, a ^ (just (a) >> 33)));
|
||||
r += 4;
|
||||
}
|
||||
while ((m += 4) < s->m + HALF);
|
||||
|
||||
do
|
||||
{
|
||||
ISAAC_STEP (0, -HALF, IF32 ( a << 13, ~ (a ^ (a << 21))));
|
||||
ISAAC_STEP (1, -HALF, IF32 (just (a) >> 6, a ^ (just (a) >> 5)));
|
||||
ISAAC_STEP (2, -HALF, IF32 ( a << 2, a ^ ( a << 12)));
|
||||
ISAAC_STEP (3, -HALF, IF32 (just (a) >> 16, a ^ (just (a) >> 33)));
|
||||
r += 4;
|
||||
}
|
||||
while ((m += 4) < s->m + ISAAC_WORDS);
|
||||
|
||||
s->a = a;
|
||||
s->b = b;
|
||||
}
|
||||
|
||||
/*
|
||||
* The basic seed-scrambling step for initialization, based on Bob
|
||||
* Jenkins' 256-bit hash.
|
||||
*/
|
||||
#if ISAAC_BITS == 32
|
||||
#define mix(a, b, c, d, e, f, g, h) \
|
||||
{ \
|
||||
a ^= b << 11; d += a; \
|
||||
b += c; b ^= just (c) >> 2; e += b; \
|
||||
c += d; c ^= d << 8; f += c; \
|
||||
d += e; d ^= just (e) >> 16; g += d; \
|
||||
e += f; e ^= f << 10; h += e; \
|
||||
f += g; f ^= just (g) >> 4; a += f; \
|
||||
g += h; g ^= h << 8; b += g; \
|
||||
h += a; h ^= just (a) >> 9; c += h; \
|
||||
a += b; \
|
||||
}
|
||||
#else
|
||||
#define mix(a, b, c, d, e, f, g, h) \
|
||||
{ \
|
||||
a -= e; f ^= just (h) >> 9; h += a; \
|
||||
b -= f; g ^= a << 9; a += b; \
|
||||
c -= g; h ^= just (b) >> 23; b += c; \
|
||||
d -= h; a ^= c << 15; c += d; \
|
||||
e -= a; b ^= just (d) >> 14; d += e; \
|
||||
f -= b; c ^= e << 20; e += f; \
|
||||
g -= c; d ^= just (f) >> 17; f += g; \
|
||||
h -= d; e ^= g << 14; g += h; \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* The basic ISAAC initialization pass. */
|
||||
#define ISAAC_MIX(s, a, b, c, d, e, f, g, h, seed) \
|
||||
{ \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < ISAAC_WORDS; i += 8) \
|
||||
{ \
|
||||
a += seed[i]; \
|
||||
b += seed[i + 1]; \
|
||||
c += seed[i + 2]; \
|
||||
d += seed[i + 3]; \
|
||||
e += seed[i + 4]; \
|
||||
f += seed[i + 5]; \
|
||||
g += seed[i + 6]; \
|
||||
h += seed[i + 7]; \
|
||||
mix (a, b, c, d, e, f, g, h); \
|
||||
s->m[i] = a; \
|
||||
s->m[i + 1] = b; \
|
||||
s->m[i + 2] = c; \
|
||||
s->m[i + 3] = d; \
|
||||
s->m[i + 4] = e; \
|
||||
s->m[i + 5] = f; \
|
||||
s->m[i + 6] = g; \
|
||||
s->m[i + 7] = h; \
|
||||
} \
|
||||
}
|
||||
|
||||
#if 0 /* Provided for reference only; not used in this code */
|
||||
/*
|
||||
* Initialize the ISAAC RNG with the given seed material.
|
||||
* Its size MUST be a multiple of ISAAC_BYTES, and may be
|
||||
* stored in the s->m array.
|
||||
*
|
||||
* This is a generalization of the original ISAAC initialization code
|
||||
* to support larger seed sizes. For seed sizes of 0 and ISAAC_BYTES,
|
||||
* it is identical.
|
||||
*/
|
||||
static void
|
||||
isaac_init (struct isaac_state *s, isaac_word const *seed, size_t seedsize)
|
||||
{
|
||||
isaac_word a, b, c, d, e, f, g, h;
|
||||
|
||||
a = b = c = d = e = f = g = h = /* the golden ratio */
|
||||
IF32 (UINT32_C (0x9e3779b9), UINT64_C (0x9e3779b97f4a7c13));
|
||||
for (int i = 0; i < 4; i++) /* scramble it */
|
||||
mix (a, b, c, d, e, f, g, h);
|
||||
s->a = s->b = s->c = 0;
|
||||
|
||||
if (seedsize)
|
||||
{
|
||||
/* First pass (as in reference ISAAC code) */
|
||||
ISAAC_MIX (s, a, b, c, d, e, f, g, h, seed);
|
||||
/* Second and subsequent passes (extension to ISAAC) */
|
||||
while (seedsize -= ISAAC_BYTES)
|
||||
{
|
||||
seed += ISAAC_WORDS;
|
||||
for (i = 0; i < ISAAC_WORDS; i++)
|
||||
s->m[i] += seed[i];
|
||||
ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The no seed case (as in reference ISAAC code) */
|
||||
for (i = 0; i < ISAAC_WORDS; i++)
|
||||
s->m[i] = 0;
|
||||
}
|
||||
|
||||
/* Final pass */
|
||||
ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize *S to a somewhat-random value, derived from a seed
|
||||
stored in S->m. */
|
||||
void
|
||||
isaac_seed (struct isaac_state *s)
|
||||
{
|
||||
isaac_word a = IF32 (UINT32_C (0x1367df5a), UINT64_C (0x647c4677a2884b7c));
|
||||
isaac_word b = IF32 (UINT32_C (0x95d90059), UINT64_C (0xb9f8b322c73ac862));
|
||||
isaac_word c = IF32 (UINT32_C (0xc3163e4b), UINT64_C (0x8c0ea5053d4712a0));
|
||||
isaac_word d = IF32 (UINT32_C (0x0f421ad8), UINT64_C (0xb29b2e824a595524));
|
||||
isaac_word e = IF32 (UINT32_C (0xd92a4a78), UINT64_C (0x82f053db8355e0ce));
|
||||
isaac_word f = IF32 (UINT32_C (0xa51a3c49), UINT64_C (0x48fe4a0fa5a09315));
|
||||
isaac_word g = IF32 (UINT32_C (0xc4efea1b), UINT64_C (0xae985bf2cbfc89ed));
|
||||
isaac_word h = IF32 (UINT32_C (0x30609119), UINT64_C (0x98f5704f6c44c0ab));
|
||||
|
||||
#if 0
|
||||
/* The initialization of a through h is a precomputed form of: */
|
||||
a = b = c = d = e = f = g = h = /* the golden ratio */
|
||||
IF32 (UINT32_C (0x9e3779b9), UINT64_C (0x9e3779b97f4a7c13));
|
||||
for (int i = 0; i < 4; i++) /* scramble it */
|
||||
mix (a, b, c, d, e, f, g, h);
|
||||
#endif
|
||||
|
||||
/* Mix S->m so that every part of the seed affects every part of the
|
||||
state. */
|
||||
ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m);
|
||||
ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m);
|
||||
|
||||
s->a = s->b = s->c = 0;
|
||||
}
|
66
gl/lib/rand-isaac.h
Normal file
66
gl/lib/rand-isaac.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Bob Jenkins's cryptographic random number generators, ISAAC and ISAAC64.
|
||||
|
||||
Copyright (C) 1999-2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 1999 Colin Plumb.
|
||||
|
||||
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 Colin Plumb and Paul Eggert. */
|
||||
|
||||
#ifndef _GL_RAND_ISAAC_H
|
||||
#define _GL_RAND_ISAAC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Log base 2 of the number of useful bits in an ISAAC word. It must
|
||||
be either 5 or 6. By default, this uses a value that should be
|
||||
faster for this architecture. */
|
||||
#ifndef ISAAC_BITS_LOG
|
||||
#if SIZE_MAX >> 31 >> 31 < 3 /* SIZE_MAX < 2**64 - 1 */
|
||||
#define ISAAC_BITS_LOG 5
|
||||
#else
|
||||
#define ISAAC_BITS_LOG 6
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The number of bits in an ISAAC word. */
|
||||
#define ISAAC_BITS (1 << ISAAC_BITS_LOG)
|
||||
|
||||
#if ISAAC_BITS == 32
|
||||
typedef uint_least32_t isaac_word;
|
||||
#else
|
||||
typedef uint_least64_t isaac_word;
|
||||
#endif
|
||||
|
||||
/* Size of the state tables to use. ISAAC_WORDS_LOG should be at least 3,
|
||||
and smaller values give less security. */
|
||||
#define ISAAC_WORDS_LOG 8
|
||||
#define ISAAC_WORDS (1 << ISAAC_WORDS_LOG)
|
||||
#define ISAAC_BYTES (ISAAC_WORDS * sizeof (isaac_word))
|
||||
|
||||
/* State variables for the random number generator. The M member
|
||||
should be seeded with nonce data before calling isaac_seed. The
|
||||
other members are private. */
|
||||
struct isaac_state
|
||||
{
|
||||
isaac_word m[ISAAC_WORDS]; /* Main state array */
|
||||
isaac_word a, b, c; /* Extra variables */
|
||||
};
|
||||
|
||||
void isaac_seed (struct isaac_state *) _GL_ATTRIBUTE_NONNULL ();
|
||||
void isaac_refill (struct isaac_state *, isaac_word[ISAAC_WORDS])
|
||||
_GL_ATTRIBUTE_NONNULL ();
|
||||
|
||||
#endif
|
216
gl/lib/randint.c
Normal file
216
gl/lib/randint.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/* Generate random integers.
|
||||
|
||||
Copyright (C) 2006-2025 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 "randint.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#if TEST
|
||||
# include <inttypes.h>
|
||||
# include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
randint i;
|
||||
randint n = strtoumax (argv[1], nullptr, 10);
|
||||
randint choices = strtoumax (argv[2], nullptr, 10);
|
||||
char const *name = argv[3];
|
||||
struct randint_source *ints = randint_all_new (name, SIZE_MAX);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
printf ("%ju\n", randint_choose (ints, choices));
|
||||
|
||||
return (randint_all_free (ints) == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
/* A source of random data for generating random integers. */
|
||||
struct randint_source
|
||||
{
|
||||
/* The source of random bytes. */
|
||||
struct randread_source *source;
|
||||
|
||||
/* RANDNUM is a buffered random integer, whose information has not
|
||||
yet been delivered to the caller. It is uniformly distributed in
|
||||
the range 0 <= RANDNUM <= RANDMAX. If RANDMAX is zero, then
|
||||
RANDNUM must be zero (and in some sense it is not really
|
||||
"random"). */
|
||||
randint randnum;
|
||||
randint randmax;
|
||||
};
|
||||
|
||||
/* Create a new randint_source from SOURCE. */
|
||||
|
||||
struct randint_source *
|
||||
randint_new (struct randread_source *source)
|
||||
{
|
||||
struct randint_source *s = xmalloc (sizeof *s);
|
||||
s->source = source;
|
||||
s->randnum = s->randmax = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Create a new randint_source by creating a randread_source from
|
||||
NAME and ESTIMATED_BYTES. Return nullptr (setting errno) if
|
||||
unsuccessful. */
|
||||
|
||||
struct randint_source *
|
||||
randint_all_new (char const *name, size_t bytes_bound)
|
||||
{
|
||||
struct randread_source *source = randread_new (name, bytes_bound);
|
||||
return (source ? randint_new (source) : nullptr);
|
||||
}
|
||||
|
||||
/* Return the random data source of *S. */
|
||||
|
||||
struct randread_source *
|
||||
randint_get_source (struct randint_source const *s)
|
||||
{
|
||||
return s->source;
|
||||
}
|
||||
|
||||
/* HUGE_BYTES is true on hosts hosts where randint and unsigned char
|
||||
have the same width and where shifting by the word size therefore
|
||||
has undefined behavior. */
|
||||
enum { HUGE_BYTES = RANDINT_MAX == UCHAR_MAX };
|
||||
|
||||
/* Return X shifted left by CHAR_BIT bits. */
|
||||
static inline randint shift_left (randint x)
|
||||
{
|
||||
return HUGE_BYTES ? 0 : x << CHAR_BIT;
|
||||
}
|
||||
|
||||
|
||||
/* Consume random data from *S to generate a random number in the range
|
||||
0 .. GENMAX. */
|
||||
|
||||
randint
|
||||
randint_genmax (struct randint_source *s, randint genmax)
|
||||
{
|
||||
struct randread_source *source = s->source;
|
||||
randint randnum = s->randnum;
|
||||
randint randmax = s->randmax;
|
||||
randint choices = genmax + 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (randmax < genmax)
|
||||
{
|
||||
/* Calculate how many input bytes will be needed, and read
|
||||
the bytes. */
|
||||
|
||||
size_t i = 0;
|
||||
randint rmax = randmax;
|
||||
unsigned char buf[sizeof randnum];
|
||||
|
||||
do
|
||||
{
|
||||
rmax = shift_left (rmax) + UCHAR_MAX;
|
||||
i++;
|
||||
}
|
||||
while (rmax < genmax);
|
||||
|
||||
randread (source, buf, i);
|
||||
|
||||
/* Increase RANDMAX by appending random bytes to RANDNUM and
|
||||
UCHAR_MAX to RANDMAX until RANDMAX is no less than
|
||||
GENMAX. This may lose up to CHAR_BIT bits of information
|
||||
if (HUGE_BYTES ? 0 : RANDINT_MAX >> CHAR_BIT) < GENMAX,
|
||||
but it is not worth the programming hassle of saving
|
||||
these bits since GENMAX is rarely that large in practice. */
|
||||
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
randnum = shift_left (randnum) + buf[i];
|
||||
randmax = shift_left (randmax) + UCHAR_MAX;
|
||||
i++;
|
||||
}
|
||||
while (randmax < genmax);
|
||||
}
|
||||
|
||||
if (randmax == genmax)
|
||||
{
|
||||
s->randnum = s->randmax = 0;
|
||||
return randnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* GENMAX < RANDMAX, so attempt to generate a random number
|
||||
by taking RANDNUM modulo GENMAX+1. This will choose
|
||||
fairly so long as RANDNUM falls within an integral
|
||||
multiple of GENMAX+1; otherwise, LAST_USABLE_CHOICE < RANDNUM,
|
||||
so discard this attempt and try again.
|
||||
|
||||
Since GENMAX cannot be RANDINT_MAX, CHOICES cannot be
|
||||
zero and there is no need to worry about dividing by
|
||||
zero. */
|
||||
|
||||
randint excess_choices = randmax - genmax;
|
||||
randint unusable_choices = excess_choices % choices;
|
||||
randint last_usable_choice = randmax - unusable_choices;
|
||||
randint reduced_randnum = randnum % choices;
|
||||
|
||||
if (randnum <= last_usable_choice)
|
||||
{
|
||||
s->randnum = randnum / choices;
|
||||
s->randmax = excess_choices / choices;
|
||||
return reduced_randnum;
|
||||
}
|
||||
|
||||
/* Retry, but retain the randomness from the fact that RANDNUM fell
|
||||
into the range LAST_USABLE_CHOICE+1 .. RANDMAX. */
|
||||
randnum = reduced_randnum;
|
||||
randmax = unusable_choices - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear *S so that it no longer contains undelivered random data. */
|
||||
|
||||
void
|
||||
randint_free (struct randint_source *s)
|
||||
{
|
||||
explicit_bzero (s, sizeof *s);
|
||||
free (s);
|
||||
}
|
||||
|
||||
/* Likewise, but also clear the underlying randread object. Return
|
||||
0 if successful, -1 (setting errno) otherwise. */
|
||||
|
||||
int
|
||||
randint_all_free (struct randint_source *s)
|
||||
{
|
||||
int r = randread_free (s->source);
|
||||
int e = errno;
|
||||
randint_free (s);
|
||||
errno = e;
|
||||
return r;
|
||||
}
|
55
gl/lib/randint.h
Normal file
55
gl/lib/randint.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* Generate random integers.
|
||||
|
||||
Copyright (C) 2006-2025 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 RANDINT_H
|
||||
|
||||
# define RANDINT_H 1
|
||||
|
||||
# include <stdint.h>
|
||||
|
||||
# include "randread.h"
|
||||
|
||||
/* An unsigned integer type, used for random integers, and its maximum
|
||||
value. */
|
||||
typedef uintmax_t randint;
|
||||
# define RANDINT_MAX UINTMAX_MAX
|
||||
|
||||
struct randint_source;
|
||||
|
||||
void randint_free (struct randint_source *) _GL_ATTRIBUTE_NONNULL ();
|
||||
int randint_all_free (struct randint_source *) _GL_ATTRIBUTE_NONNULL ();
|
||||
struct randint_source *randint_new (struct randread_source *)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (randint_free, 1)
|
||||
_GL_ATTRIBUTE_NONNULL () _GL_ATTRIBUTE_RETURNS_NONNULL;
|
||||
struct randint_source *randint_all_new (char const *, size_t)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (randint_all_free, 1);
|
||||
struct randread_source *randint_get_source (struct randint_source const *)
|
||||
_GL_ATTRIBUTE_NONNULL () _GL_ATTRIBUTE_PURE;
|
||||
randint randint_genmax (struct randint_source *, randint genmax)
|
||||
_GL_ATTRIBUTE_NONNULL ();
|
||||
|
||||
/* Consume random data from *S to generate a random number in the range
|
||||
0 .. CHOICES-1. CHOICES must be nonzero. */
|
||||
static inline randint
|
||||
randint_choose (struct randint_source *s, randint choices)
|
||||
{
|
||||
return randint_genmax (s, choices - 1);
|
||||
}
|
||||
|
||||
#endif
|
231
gl/lib/randperm.c
Normal file
231
gl/lib/randperm.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/* Generate random permutations.
|
||||
|
||||
Copyright (C) 2006-2025 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 "randperm.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbit.h>
|
||||
#include <stdckdint.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "attribute.h"
|
||||
#include "hash.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return an upper bound on the number of random bytes needed to
|
||||
generate the first H elements of a random permutation of N
|
||||
elements. H must not exceed N. */
|
||||
|
||||
size_t
|
||||
randperm_bound (size_t h, size_t n)
|
||||
{
|
||||
/* Upper bound on number of bits needed to generate the first number
|
||||
of the permutation. */
|
||||
unsigned int lg_n = stdc_bit_width (n) + 1;
|
||||
|
||||
/* Upper bound on number of bits needed to generate the first H elements. */
|
||||
uintmax_t ar;
|
||||
if (ckd_mul (&ar, lg_n, h))
|
||||
return SIZE_MAX;
|
||||
|
||||
/* Convert the bit count to a byte count. */
|
||||
size_t bound = ar / CHAR_BIT + (ar % CHAR_BIT != 0);
|
||||
|
||||
return bound;
|
||||
}
|
||||
|
||||
/* Swap elements I and J in array V. */
|
||||
|
||||
static void
|
||||
swap (size_t *v, size_t i, size_t j)
|
||||
{
|
||||
size_t t = v[i];
|
||||
v[i] = v[j];
|
||||
v[j] = t;
|
||||
}
|
||||
|
||||
/* Structures and functions for a sparse_map abstract data type that's
|
||||
used to effectively swap elements I and J in array V like swap(),
|
||||
but in a more memory efficient manner (when the number of permutations
|
||||
performed is significantly less than the size of the input). */
|
||||
|
||||
struct sparse_ent_
|
||||
{
|
||||
size_t index;
|
||||
size_t val;
|
||||
};
|
||||
|
||||
static size_t
|
||||
sparse_hash_ (void const *x, size_t table_size)
|
||||
{
|
||||
struct sparse_ent_ const *ent = x;
|
||||
return ent->index % table_size;
|
||||
}
|
||||
|
||||
static bool
|
||||
sparse_cmp_ (void const *x, void const *y)
|
||||
{
|
||||
struct sparse_ent_ const *ent1 = x;
|
||||
struct sparse_ent_ const *ent2 = y;
|
||||
return ent1->index == ent2->index;
|
||||
}
|
||||
|
||||
typedef Hash_table sparse_map;
|
||||
|
||||
/* Initialize the structure for the sparse map,
|
||||
when a best guess as to the number of entries
|
||||
specified with SIZE_HINT. */
|
||||
|
||||
static sparse_map *
|
||||
sparse_new (size_t size_hint)
|
||||
{
|
||||
return hash_initialize (size_hint, nullptr, sparse_hash_, sparse_cmp_, free);
|
||||
}
|
||||
|
||||
/* Swap the values for I and J. If a value is not already present
|
||||
then assume it's equal to the index. Update the value for
|
||||
index I in array V. */
|
||||
|
||||
static void
|
||||
sparse_swap (sparse_map *sv, size_t *v, size_t i, size_t j)
|
||||
{
|
||||
struct sparse_ent_ *v1 = hash_remove (sv, &(struct sparse_ent_) {i,0});
|
||||
struct sparse_ent_ *v2 = hash_remove (sv, &(struct sparse_ent_) {j,0});
|
||||
|
||||
/* FIXME: reduce the frequency of these mallocs. */
|
||||
if (!v1)
|
||||
{
|
||||
v1 = xmalloc (sizeof *v1);
|
||||
v1->index = v1->val = i;
|
||||
}
|
||||
if (!v2)
|
||||
{
|
||||
v2 = xmalloc (sizeof *v2);
|
||||
v2->index = v2->val = j;
|
||||
}
|
||||
|
||||
size_t t = v1->val;
|
||||
v1->val = v2->val;
|
||||
v2->val = t;
|
||||
if (!hash_insert (sv, v1))
|
||||
xalloc_die ();
|
||||
if (!hash_insert (sv, v2))
|
||||
xalloc_die ();
|
||||
|
||||
v[i] = v1->val;
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_free (sparse_map *sv)
|
||||
{
|
||||
hash_free (sv);
|
||||
}
|
||||
|
||||
|
||||
/* From R, allocate and return a malloc'd array of the first H elements
|
||||
of a random permutation of N elements. H must not exceed N.
|
||||
Return nullptr if H is zero. */
|
||||
|
||||
size_t *
|
||||
randperm_new (struct randint_source *r, size_t h, size_t n)
|
||||
{
|
||||
size_t *v;
|
||||
|
||||
switch (h)
|
||||
{
|
||||
case 0:
|
||||
v = nullptr;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
v = xmalloc (sizeof *v);
|
||||
v[0] = randint_choose (r, n);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
/* The algorithm is essentially the same in both
|
||||
the sparse and non sparse case. In the sparse case we use
|
||||
a hash to implement sparse storage for the set of n numbers
|
||||
we're shuffling. When to use the sparse method was
|
||||
determined with the help of this script:
|
||||
|
||||
#!/bin/sh
|
||||
for n in $(seq 2 32); do
|
||||
for h in $(seq 2 32); do
|
||||
test $h -gt $n && continue
|
||||
for s in o n; do
|
||||
test $s = o && shuf=shuf || shuf=./shuf
|
||||
num=$(env time -f "$s:${h},${n} = %e,%M" \
|
||||
$shuf -i0-$((2**$n-2)) -n$((2**$h-2)) | wc -l)
|
||||
test $num = $((2**$h-2)) || echo "$s:${h},${n} = failed" >&2
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
This showed that if sparseness = n/h, then:
|
||||
|
||||
sparseness = 128 => .125 mem used, and about same speed
|
||||
sparseness = 64 => .25 mem used, but 1.5 times slower
|
||||
sparseness = 32 => .5 mem used, but 2 times slower
|
||||
|
||||
Also the memory usage was only significant when n > 128Ki
|
||||
*/
|
||||
bool sparse = (n >= (128 * 1024)) && (n / h >= 32);
|
||||
|
||||
size_t i;
|
||||
sparse_map *sv;
|
||||
|
||||
if (sparse)
|
||||
{
|
||||
sv = sparse_new (h * 2);
|
||||
if (sv == nullptr)
|
||||
xalloc_die ();
|
||||
v = xnmalloc (h, sizeof *v);
|
||||
}
|
||||
else
|
||||
{
|
||||
sv = nullptr; /* To placate GCC's -Wuninitialized. */
|
||||
v = xnmalloc (n, sizeof *v);
|
||||
for (i = 0; i < n; i++)
|
||||
v[i] = i;
|
||||
}
|
||||
|
||||
for (i = 0; i < h; i++)
|
||||
{
|
||||
size_t j = i + randint_choose (r, n - i);
|
||||
if (sparse)
|
||||
sparse_swap (sv, v, i, j);
|
||||
else
|
||||
swap (v, i, j);
|
||||
}
|
||||
|
||||
if (sparse)
|
||||
sparse_free (sv);
|
||||
else
|
||||
v = xnrealloc (v, h, sizeof *v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
6
gl/lib/randperm.h
Normal file
6
gl/lib/randperm.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "randint.h"
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
size_t randperm_bound (size_t, size_t) _GL_ATTRIBUTE_CONST;
|
||||
size_t *randperm_new (struct randint_source *, size_t, size_t)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
|
329
gl/lib/randread.c
Normal file
329
gl/lib/randread.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/* Generate buffers of random data.
|
||||
|
||||
Copyright (C) 2006-2025 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. */
|
||||
|
||||
/* FIXME: Improve performance by adding support for the RDRAND machine
|
||||
instruction if available (e.g., Ivy Bridge processors). */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "randread.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <exitfail.h>
|
||||
#include <fcntl.h>
|
||||
#include <quote.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
#include "assure.h"
|
||||
#include "minmax.h"
|
||||
#include "rand-isaac.h"
|
||||
#include "stdio-safer.h"
|
||||
#include "unlocked-io.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#if _STRING_ARCH_unaligned || _STRING_INLINE_unaligned
|
||||
# define POINTER_IS_ALIGNED(ptr, type) true
|
||||
#else
|
||||
# define POINTER_IS_ALIGNED(ptr, type) ((size_t) (ptr) % alignof (type) == 0)
|
||||
#endif
|
||||
|
||||
/* The maximum buffer size used for reads of random data. Using the
|
||||
value 2 * ISAAC_BYTES makes this the largest power of two that
|
||||
would not otherwise cause struct randread_source to grow. */
|
||||
#define RANDREAD_BUFFER_SIZE (2 * ISAAC_BYTES)
|
||||
|
||||
/* A source of random data for generating random buffers. */
|
||||
struct randread_source
|
||||
{
|
||||
/* Stream to read random bytes from. If null, the current
|
||||
implementation uses an internal PRNG (ISAAC). */
|
||||
FILE *source;
|
||||
|
||||
/* Function to call, and its argument, if there is an input error or
|
||||
end of file when reading from the stream; errno is nonzero if
|
||||
there was an error. If this function returns, it should fix the
|
||||
problem before returning. The default handler assumes that
|
||||
handler_arg is the file name of the source. */
|
||||
void (*handler) (void const *);
|
||||
void const *handler_arg;
|
||||
|
||||
/* The buffer for SOURCE. It's kept here to simplify storage
|
||||
allocation and to make it easier to clear out buffered random
|
||||
data. */
|
||||
union
|
||||
{
|
||||
/* The stream buffer, if SOURCE is not null. */
|
||||
char c[RANDREAD_BUFFER_SIZE];
|
||||
|
||||
/* The buffered ISAAC pseudorandom buffer, if SOURCE is null. */
|
||||
struct isaac
|
||||
{
|
||||
/* The number of bytes that are buffered at the end of data.b. */
|
||||
size_t buffered;
|
||||
|
||||
/* State of the ISAAC generator. */
|
||||
struct isaac_state state;
|
||||
|
||||
/* Up to a buffer's worth of pseudorandom data. */
|
||||
union
|
||||
{
|
||||
isaac_word w[ISAAC_WORDS];
|
||||
unsigned char b[ISAAC_BYTES];
|
||||
} data;
|
||||
} isaac;
|
||||
} buf;
|
||||
};
|
||||
|
||||
|
||||
/* The default error handler. */
|
||||
|
||||
static void
|
||||
randread_error (void const *file_name)
|
||||
{
|
||||
affirm (exit_failure);
|
||||
error (exit_failure, errno,
|
||||
errno == 0 ? _("%s: end of file") : _("%s: read error"),
|
||||
quote (file_name));
|
||||
}
|
||||
|
||||
/* Simply return a new randread_source object with the default error
|
||||
handler. */
|
||||
|
||||
static struct randread_source *
|
||||
simple_new (FILE *source, void const *handler_arg)
|
||||
{
|
||||
struct randread_source *s = xmalloc (sizeof *s);
|
||||
s->source = source;
|
||||
s->handler = randread_error;
|
||||
s->handler_arg = handler_arg;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Put a nonce value into BUFFER, with size BUFSIZE.
|
||||
Return true on success, false (setting errno) on failure. */
|
||||
|
||||
static bool
|
||||
get_nonce (void *buffer, size_t bufsize)
|
||||
{
|
||||
char *buf = buffer, *buflim = buf + bufsize;
|
||||
while (buf < buflim)
|
||||
{
|
||||
#if defined __sun
|
||||
# define MAX_GETRANDOM 1024
|
||||
#else
|
||||
# define MAX_GETRANDOM SIZE_MAX
|
||||
#endif
|
||||
size_t max_bytes = MIN (buflim - buf, MAX_GETRANDOM);
|
||||
ssize_t nbytes = getrandom (buf, max_bytes, 0);
|
||||
if (0 <= nbytes)
|
||||
buf += nbytes;
|
||||
else if (errno != EINTR)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Body of randread_free, broken out to pacify gcc -Wmismatched-dealloc. */
|
||||
|
||||
static int
|
||||
randread_free_body (struct randread_source *s)
|
||||
{
|
||||
FILE *source = s->source;
|
||||
explicit_bzero (s, sizeof *s);
|
||||
free (s);
|
||||
return source ? fclose (source) : 0;
|
||||
}
|
||||
|
||||
/* Create and initialize a random data source from NAME, or use a
|
||||
reasonable default source if NAME is null. BYTES_BOUND is an upper
|
||||
bound on the number of bytes that will be needed. If zero, it is a
|
||||
hard bound; otherwise it is just an estimate.
|
||||
|
||||
If NAME is not null, NAME is saved for use as the argument of the
|
||||
default handler. Unless a non-default handler is used, NAME's
|
||||
lifetime should be at least that of the returned value.
|
||||
|
||||
Return nullptr (setting errno) on failure. */
|
||||
|
||||
struct randread_source *
|
||||
randread_new (char const *name, size_t bytes_bound)
|
||||
{
|
||||
if (bytes_bound == 0)
|
||||
return simple_new (nullptr, nullptr);
|
||||
else
|
||||
{
|
||||
FILE *source = nullptr;
|
||||
struct randread_source *s;
|
||||
|
||||
if (name)
|
||||
if (! (source = fopen_safer (name, "rb")))
|
||||
return nullptr;
|
||||
|
||||
s = simple_new (source, name);
|
||||
|
||||
if (source)
|
||||
setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound));
|
||||
else
|
||||
{
|
||||
/* Fill the ISAAC buffer. Although it is tempting to read at
|
||||
most BYTES_BOUND bytes, this is incorrect for two reasons.
|
||||
First, BYTES_BOUND is just an estimate.
|
||||
Second, even if the estimate is correct
|
||||
ISAAC64 poorly randomizes when BYTES_BOUND is small
|
||||
and just the first few bytes of s->buf.isaac.state.m
|
||||
are random while the other bytes are all zero. See:
|
||||
Aumasson J-P. On the pseudo-random generator ISAAC.
|
||||
Cryptology ePrint Archive. 2006;438.
|
||||
<https://eprint.iacr.org/2006/438>. */
|
||||
s->buf.isaac.buffered = 0;
|
||||
if (! get_nonce (s->buf.isaac.state.m,
|
||||
sizeof s->buf.isaac.state.m))
|
||||
{
|
||||
int e = errno;
|
||||
randread_free_body (s);
|
||||
errno = e;
|
||||
return nullptr;
|
||||
}
|
||||
isaac_seed (&s->buf.isaac.state);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set S's handler and its argument. HANDLER (HANDLER_ARG) is called
|
||||
when there is a read error or end of file from the random data
|
||||
source; errno is nonzero if there was an error. If HANDLER
|
||||
returns, it should fix the problem before returning. The default
|
||||
handler assumes that handler_arg is the file name of the source; it
|
||||
does not return. */
|
||||
|
||||
void
|
||||
randread_set_handler (struct randread_source *s, void (*handler) (void const *))
|
||||
{
|
||||
s->handler = handler;
|
||||
}
|
||||
|
||||
void
|
||||
randread_set_handler_arg (struct randread_source *s, void const *handler_arg)
|
||||
{
|
||||
s->handler_arg = handler_arg;
|
||||
}
|
||||
|
||||
|
||||
/* Place SIZE random bytes into the buffer beginning at P, using
|
||||
the stream in S. */
|
||||
|
||||
static void
|
||||
readsource (struct randread_source *s, unsigned char *p, size_t size)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
size_t inbytes = fread (p, sizeof *p, size, s->source);
|
||||
int fread_errno = errno;
|
||||
p += inbytes;
|
||||
size -= inbytes;
|
||||
if (size == 0)
|
||||
break;
|
||||
errno = (ferror (s->source) ? fread_errno : 0);
|
||||
s->handler (s->handler_arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Place SIZE pseudorandom bytes into the buffer beginning at P, using
|
||||
the buffered ISAAC generator in ISAAC. */
|
||||
|
||||
static void
|
||||
readisaac (struct isaac *isaac, void *p, size_t size)
|
||||
{
|
||||
size_t inbytes = isaac->buffered;
|
||||
|
||||
while (true)
|
||||
{
|
||||
char *char_p = p;
|
||||
|
||||
if (size <= inbytes)
|
||||
{
|
||||
memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size);
|
||||
isaac->buffered = inbytes - size;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes);
|
||||
p = char_p + inbytes;
|
||||
size -= inbytes;
|
||||
|
||||
/* If P is aligned, write to *P directly to avoid the overhead
|
||||
of copying from the buffer. */
|
||||
if (POINTER_IS_ALIGNED (p, isaac_word))
|
||||
{
|
||||
isaac_word *wp = p;
|
||||
while (ISAAC_BYTES <= size)
|
||||
{
|
||||
isaac_refill (&isaac->state, wp);
|
||||
wp += ISAAC_WORDS;
|
||||
size -= ISAAC_BYTES;
|
||||
if (size == 0)
|
||||
{
|
||||
isaac->buffered = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
p = wp;
|
||||
}
|
||||
|
||||
isaac_refill (&isaac->state, isaac->data.w);
|
||||
inbytes = ISAAC_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Consume random data from *S to generate a random buffer BUF of size
|
||||
SIZE. */
|
||||
|
||||
void
|
||||
randread (struct randread_source *s, void *buf, size_t size)
|
||||
{
|
||||
if (s->source)
|
||||
readsource (s, buf, size);
|
||||
else
|
||||
readisaac (&s->buf.isaac, buf, size);
|
||||
}
|
||||
|
||||
|
||||
/* Clear *S so that it no longer contains undelivered random data, and
|
||||
deallocate any system resources associated with *S. Return 0 if
|
||||
successful, a negative number (setting errno) if not (this is rare,
|
||||
but can occur in theory if there is an input error). */
|
||||
|
||||
int
|
||||
randread_free (struct randread_source *s)
|
||||
{
|
||||
return randread_free_body (s);
|
||||
}
|
37
gl/lib/randread.h
Normal file
37
gl/lib/randread.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* Generate buffers of random data.
|
||||
|
||||
Copyright (C) 2006-2025 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 RANDREAD_H
|
||||
# define RANDREAD_H 1
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
struct randread_source;
|
||||
|
||||
int randread_free (struct randread_source *) _GL_ATTRIBUTE_NONNULL ();
|
||||
struct randread_source *randread_new (char const *, size_t)
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (randread_free, 1);
|
||||
void randread (struct randread_source *, void *, size_t)
|
||||
_GL_ATTRIBUTE_NONNULL ();
|
||||
void randread_set_handler (struct randread_source *, void (*) (void const *))
|
||||
_GL_ATTRIBUTE_NONNULL ();
|
||||
void randread_set_handler_arg (struct randread_source *, void const *)
|
||||
_GL_ATTRIBUTE_NONNULL ((1));
|
||||
|
||||
#endif
|
37
gl/lib/root-dev-ino.c
Normal file
37
gl/lib/root-dev-ino.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* root-dev-ino.c -- get the device and inode numbers for '/'.
|
||||
Copyright (C) 2003-2025 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 "root-dev-ino.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Call lstat to get the device and inode numbers for '/'.
|
||||
Upon failure, return nullptr. Otherwise, set the members of
|
||||
*ROOT_D_I accordingly and return ROOT_D_I. */
|
||||
struct dev_ino *
|
||||
get_root_dev_ino (struct dev_ino *root_d_i)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if (lstat ("/", &statbuf))
|
||||
return nullptr;
|
||||
root_d_i->st_ino = statbuf.st_ino;
|
||||
root_d_i->st_dev = statbuf.st_dev;
|
||||
return root_d_i;
|
||||
}
|
47
gl/lib/root-dev-ino.h
Normal file
47
gl/lib/root-dev-ino.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* Root device and inode number checking.
|
||||
|
||||
Copyright (C) 2003-2025 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 ROOT_DEV_INO_H
|
||||
# define ROOT_DEV_INO_H 1
|
||||
|
||||
# include "dev-ino.h"
|
||||
# include "same-inode.h"
|
||||
|
||||
struct dev_ino *
|
||||
get_root_dev_ino (struct dev_ino *root_d_i) _GL_ATTRIBUTE_NONNULL ();
|
||||
|
||||
/* These macros are common to the programs that support the
|
||||
--preserve-root and --no-preserve-root options. */
|
||||
|
||||
# define ROOT_DEV_INO_CHECK(Root_dev_ino, Dir_statbuf) \
|
||||
(Root_dev_ino && PSAME_INODE (Dir_statbuf, Root_dev_ino))
|
||||
|
||||
# define ROOT_DEV_INO_WARN(Dirname) \
|
||||
do \
|
||||
{ \
|
||||
if (STREQ (Dirname, "/")) \
|
||||
error (0, 0, _("it is dangerous to operate recursively on %s"), \
|
||||
quoteaf (Dirname)); \
|
||||
else \
|
||||
error (0, 0, \
|
||||
_("it is dangerous to operate recursively on %s (same as %s)"), \
|
||||
quoteaf_n (0, Dirname), quoteaf_n (1, "/")); \
|
||||
error (0, 0, _("use --no-preserve-root to override this failsafe")); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#endif
|
3
gl/lib/skipchars.c
Normal file
3
gl/lib/skipchars.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include <config.h>
|
||||
#define SKIPCHARS_INLINE _GL_EXTERN_INLINE
|
||||
#include <skipchars.h>
|
56
gl/lib/skipchars.h
Normal file
56
gl/lib/skipchars.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Skipping sequences of characters satisfying a predicate
|
||||
|
||||
Copyright 2023-2025 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 "mcel.h"
|
||||
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef SKIPCHARS_INLINE
|
||||
# define SKIPCHARS_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
/* Return the address just past the leading sequence of possibly
|
||||
multi-byte characters or encoding errors G in STR that satisfy
|
||||
PREDICATE (G) if OK is true, or that do not satisfy the predicate
|
||||
call if OK is false. */
|
||||
|
||||
SKIPCHARS_INLINE char *
|
||||
skip_str_matching (char const *str, bool (*predicate) (mcel_t), bool ok)
|
||||
{
|
||||
char const *s = str;
|
||||
for (mcel_t g; *s && predicate (g = mcel_scanz (s)) == ok;
|
||||
s += g.len)
|
||||
continue;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
/* Return the address just past the leading sequence of possibly
|
||||
multi-byte characters or encoding errors G in BUF (which ends at LIM)
|
||||
that satisfy PREDICATE (G) if OK is true, or that do not satisfy
|
||||
the predicate call if OK is false. */
|
||||
|
||||
SKIPCHARS_INLINE char *
|
||||
skip_buf_matching (char const *buf, char const *lim,
|
||||
bool (*predicate) (mcel_t), bool ok)
|
||||
{
|
||||
char const *s = buf;
|
||||
for (mcel_t g; s < lim && predicate (g = mcel_scan (s, lim)) == ok;
|
||||
s += g.len)
|
||||
continue;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
_GL_INLINE_HEADER_END
|
44
gl/lib/smack.h
Normal file
44
gl/lib/smack.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Include and determine availability of smack routines
|
||||
Copyright (C) 2013-2025 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/>. */
|
||||
|
||||
/* Here we replace or wrap the most common smack functions used by coreutils.
|
||||
Others will need to be protected by HAVE_SMACK. */
|
||||
|
||||
#ifdef HAVE_SMACK
|
||||
# include <sys/smack.h>
|
||||
#else
|
||||
static inline ssize_t
|
||||
smack_new_label_from_self (char **label)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
smack_set_label_for_self (char const *label)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
is_smack_enabled (void)
|
||||
{
|
||||
#ifdef HAVE_SMACK
|
||||
return smack_smackfs_path () != nullptr;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
34
gl/lib/strintcmp.c
Normal file
34
gl/lib/strintcmp.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Compare integer strings.
|
||||
|
||||
Copyright (C) 2005-2025 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 "strnumcmp-in.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* Compare strings A and B as integers without explicitly converting
|
||||
them to machine numbers, to avoid overflow problems and perhaps
|
||||
improve performance. */
|
||||
|
||||
int
|
||||
strintcmp (char const *a, char const *b)
|
||||
{
|
||||
return numcompare (a, b, CHAR_MAX + 1, CHAR_MAX + 1);
|
||||
}
|
235
gl/lib/strnumcmp-in.h
Normal file
235
gl/lib/strnumcmp-in.h
Normal file
|
@ -0,0 +1,235 @@
|
|||
/* Compare numeric strings. This is an internal include file.
|
||||
|
||||
Copyright (C) 1988-2025 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 Mike Haertel. */
|
||||
|
||||
#ifndef STRNUMCMP_IN_H
|
||||
# define STRNUMCMP_IN_H 1
|
||||
|
||||
# include "strnumcmp.h"
|
||||
|
||||
# include "c-ctype.h"
|
||||
# include <stddef.h>
|
||||
|
||||
# define NEGATION_SIGN '-'
|
||||
# define NUMERIC_ZERO '0'
|
||||
|
||||
/* Compare strings A and B containing decimal fractions < 1.
|
||||
DECIMAL_POINT is the decimal point. Each string
|
||||
should begin with a decimal point followed immediately by the digits
|
||||
of the fraction. Strings not of this form are treated as zero. */
|
||||
|
||||
/* The goal here, is to take two numbers a and b... compare these
|
||||
in parallel. Instead of converting each, and then comparing the
|
||||
outcome. Most likely stopping the comparison before the conversion
|
||||
is complete. The algorithm used, in the old "sort" utility:
|
||||
|
||||
Algorithm: fraccompare
|
||||
Action : compare two decimal fractions
|
||||
accepts : char *a, char *b
|
||||
returns : -1 if a<b, 0 if a=b, 1 if a>b.
|
||||
implement:
|
||||
|
||||
if *a == decimal_point AND *b == decimal_point
|
||||
find first character different in a and b.
|
||||
if both are digits, return the difference *a - *b.
|
||||
if *a is a digit
|
||||
skip past zeros
|
||||
if digit return 1, else 0
|
||||
if *b is a digit
|
||||
skip past zeros
|
||||
if digit return -1, else 0
|
||||
if *a is a decimal_point
|
||||
skip past decimal_point and zeros
|
||||
if digit return 1, else 0
|
||||
if *b is a decimal_point
|
||||
skip past decimal_point and zeros
|
||||
if digit return -1, else 0
|
||||
return 0 */
|
||||
|
||||
static inline int _GL_ATTRIBUTE_PURE
|
||||
fraccompare (char const *a, char const *b, char decimal_point)
|
||||
{
|
||||
if (*a == decimal_point && *b == decimal_point)
|
||||
{
|
||||
while (*++a == *++b)
|
||||
if (! c_isdigit (*a))
|
||||
return 0;
|
||||
if (c_isdigit (*a) && c_isdigit (*b))
|
||||
return *a - *b;
|
||||
if (c_isdigit (*a))
|
||||
goto a_trailing_nonzero;
|
||||
if (c_isdigit (*b))
|
||||
goto b_trailing_nonzero;
|
||||
return 0;
|
||||
}
|
||||
else if (*a++ == decimal_point)
|
||||
{
|
||||
a_trailing_nonzero:
|
||||
while (*a == NUMERIC_ZERO)
|
||||
a++;
|
||||
return c_isdigit (*a);
|
||||
}
|
||||
else if (*b++ == decimal_point)
|
||||
{
|
||||
b_trailing_nonzero:
|
||||
while (*b == NUMERIC_ZERO)
|
||||
b++;
|
||||
return - c_isdigit (*b);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compare strings A and B as numbers without explicitly converting
|
||||
them to machine numbers, to avoid overflow problems and perhaps
|
||||
improve performance. DECIMAL_POINT is the decimal point and
|
||||
THOUSANDS_SEP the thousands separator. A DECIMAL_POINT outside
|
||||
'char' range causes comparisons to act as if there is no decimal point
|
||||
character, and likewise for THOUSANDS_SEP. */
|
||||
|
||||
static inline int _GL_ATTRIBUTE_PURE
|
||||
numcompare (char const *a, char const *b,
|
||||
int decimal_point, int thousands_sep)
|
||||
{
|
||||
char tmpa = *a;
|
||||
char tmpb = *b;
|
||||
int tmp;
|
||||
size_t log_a;
|
||||
size_t log_b;
|
||||
|
||||
if (tmpa == NEGATION_SIGN)
|
||||
{
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep);
|
||||
if (tmpb != NEGATION_SIGN)
|
||||
{
|
||||
if (tmpa == decimal_point)
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == NUMERIC_ZERO);
|
||||
if (c_isdigit (tmpa))
|
||||
return -1;
|
||||
while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep)
|
||||
tmpb = *++b;
|
||||
if (tmpb == decimal_point)
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == NUMERIC_ZERO);
|
||||
return - c_isdigit (tmpb);
|
||||
}
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep);
|
||||
|
||||
while (tmpa == tmpb && c_isdigit (tmpa))
|
||||
{
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == thousands_sep);
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == thousands_sep);
|
||||
}
|
||||
|
||||
if ((tmpa == decimal_point && !c_isdigit (tmpb))
|
||||
|| (tmpb == decimal_point && !c_isdigit (tmpa)))
|
||||
return fraccompare (b, a, decimal_point);
|
||||
|
||||
tmp = tmpb - tmpa;
|
||||
|
||||
for (log_a = 0; c_isdigit (tmpa); ++log_a)
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == thousands_sep);
|
||||
|
||||
for (log_b = 0; c_isdigit (tmpb); ++log_b)
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == thousands_sep);
|
||||
|
||||
if (log_a != log_b)
|
||||
return log_a < log_b ? 1 : -1;
|
||||
|
||||
if (!log_a)
|
||||
return 0;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
else if (tmpb == NEGATION_SIGN)
|
||||
{
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep);
|
||||
if (tmpb == decimal_point)
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == NUMERIC_ZERO);
|
||||
if (c_isdigit (tmpb))
|
||||
return 1;
|
||||
while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep)
|
||||
tmpa = *++a;
|
||||
if (tmpa == decimal_point)
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == NUMERIC_ZERO);
|
||||
return c_isdigit (tmpa);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep)
|
||||
tmpa = *++a;
|
||||
while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep)
|
||||
tmpb = *++b;
|
||||
|
||||
while (tmpa == tmpb && c_isdigit (tmpa))
|
||||
{
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == thousands_sep);
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == thousands_sep);
|
||||
}
|
||||
|
||||
if ((tmpa == decimal_point && !c_isdigit (tmpb))
|
||||
|| (tmpb == decimal_point && !c_isdigit (tmpa)))
|
||||
return fraccompare (a, b, decimal_point);
|
||||
|
||||
tmp = tmpa - tmpb;
|
||||
|
||||
for (log_a = 0; c_isdigit (tmpa); ++log_a)
|
||||
do
|
||||
tmpa = *++a;
|
||||
while (tmpa == thousands_sep);
|
||||
|
||||
for (log_b = 0; c_isdigit (tmpb); ++log_b)
|
||||
do
|
||||
tmpb = *++b;
|
||||
while (tmpb == thousands_sep);
|
||||
|
||||
if (log_a != log_b)
|
||||
return log_a < log_b ? -1 : 1;
|
||||
|
||||
if (!log_a)
|
||||
return 0;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
31
gl/lib/strnumcmp.c
Normal file
31
gl/lib/strnumcmp.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Compare numeric strings.
|
||||
|
||||
Copyright (C) 2005-2025 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 "strnumcmp-in.h"
|
||||
|
||||
/* Externally-visible name for numcompare. */
|
||||
|
||||
int
|
||||
strnumcmp (char const *a, char const *b,
|
||||
int decimal_point, int thousands_sep)
|
||||
{
|
||||
return numcompare (a, b, decimal_point, thousands_sep);
|
||||
}
|
4
gl/lib/strnumcmp.h
Normal file
4
gl/lib/strnumcmp.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
int strintcmp (char const *, char const *)
|
||||
_GL_ATTRIBUTE_NONNULL () _GL_ATTRIBUTE_PURE;
|
||||
int strnumcmp (char const *, char const *, int, int)
|
||||
_GL_ATTRIBUTE_NONNULL () _GL_ATTRIBUTE_PURE;
|
118
gl/lib/targetdir.c
Normal file
118
gl/lib/targetdir.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* Target directory operands for coreutils
|
||||
|
||||
Copyright 2004-2025 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>
|
||||
|
||||
#define TARGETDIR_INLINE _GL_EXTERN_INLINE
|
||||
#include <targetdir.h>
|
||||
|
||||
#include <attribute.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef O_PATH
|
||||
enum { O_PATHSEARCH = O_PATH };
|
||||
#else
|
||||
enum { O_PATHSEARCH = O_SEARCH };
|
||||
#endif
|
||||
|
||||
/* Must F designate the working directory? */
|
||||
|
||||
ATTRIBUTE_PURE static bool
|
||||
must_be_working_directory (char const *f)
|
||||
{
|
||||
/* Return true for ".", "./.", ".///./", etc. */
|
||||
while (*f++ == '.')
|
||||
{
|
||||
if (*f != '/')
|
||||
return !*f;
|
||||
while (*++f == '/')
|
||||
continue;
|
||||
if (!*f)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return a file descriptor open to FILE, for use in openat.
|
||||
As an optimization, return AT_FDCWD if FILE must be the working directory.
|
||||
As a side effect, possibly set *ST to the file's status.
|
||||
Fail and set errno if FILE is not a directory.
|
||||
On failure return -2 if AT_FDCWD is -1, -1 otherwise. */
|
||||
|
||||
int
|
||||
target_directory_operand (char const *file, struct stat *st)
|
||||
{
|
||||
if (must_be_working_directory (file))
|
||||
return AT_FDCWD;
|
||||
|
||||
int fd = -1;
|
||||
int try_to_open = 1;
|
||||
int stat_result;
|
||||
|
||||
/* On old systems without O_DIRECTORY, like Solaris 10, check with
|
||||
stat first lest we try to open a fifo for example and hang. */
|
||||
if (!O_DIRECTORY)
|
||||
{
|
||||
stat_result = stat (file, st);
|
||||
if (stat_result == 0)
|
||||
{
|
||||
try_to_open = S_ISDIR (st->st_mode);
|
||||
errno = ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* On EOVERFLOW failure, give up on checking, as there is no
|
||||
easy way to check. This should be rare. */
|
||||
try_to_open = errno == EOVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
if (try_to_open)
|
||||
{
|
||||
fd = open (file, O_PATHSEARCH | O_DIRECTORY);
|
||||
|
||||
/* On platforms lacking O_PATH, using O_SEARCH | O_DIRECTORY to
|
||||
open an overly-protected non-directory can fail with either
|
||||
EACCES or ENOTDIR. Prefer ENOTDIR as it makes for better
|
||||
diagnostics. */
|
||||
if (O_PATHSEARCH == O_SEARCH && fd < 0 && errno == EACCES)
|
||||
errno = (((O_DIRECTORY ? stat (file, st) : stat_result) == 0
|
||||
&& !S_ISDIR (st->st_mode))
|
||||
? ENOTDIR : EACCES);
|
||||
}
|
||||
|
||||
if (!O_DIRECTORY && 0 <= fd)
|
||||
{
|
||||
/* On old systems like Solaris 10 double check type,
|
||||
to ensure we've opened a directory. */
|
||||
int err;
|
||||
if (fstat (fd, st) == 0
|
||||
? !S_ISDIR (st->st_mode) && (err = ENOTDIR, true)
|
||||
: (err = errno) != EOVERFLOW)
|
||||
{
|
||||
close (fd);
|
||||
errno = err;
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd - (AT_FDCWD == -1 && fd < 0);
|
||||
}
|
43
gl/lib/targetdir.h
Normal file
43
gl/lib/targetdir.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* Target directory operands for coreutils
|
||||
|
||||
Copyright 2022-2025 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 <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _GL_INLINE_HEADER_BEGIN
|
||||
# error "Please include config.h first."
|
||||
#endif
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef TARGETDIR_INLINE
|
||||
# define TARGETDIR_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
/* Return a file descriptor open to FILE, for use in openat.
|
||||
As an optimization, return AT_FDCWD if FILE must be the working directory.
|
||||
As a side effect, possibly set *ST to the file's status.
|
||||
Fail and set errno if FILE is not a directory.
|
||||
On failure return -2 if AT_FDCWD is -1, -1 otherwise. */
|
||||
extern int target_directory_operand (char const *file, struct stat *st);
|
||||
|
||||
/* Return true if FD represents success for target_directory_operand. */
|
||||
TARGETDIR_INLINE _GL_ATTRIBUTE_PURE bool
|
||||
target_dirfd_valid (int fd)
|
||||
{
|
||||
return fd != -1 - (AT_FDCWD == -1);
|
||||
}
|
||||
|
||||
_GL_INLINE_HEADER_END
|
5
gl/lib/xdectoimax.c
Normal file
5
gl/lib/xdectoimax.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define __xdectoint xdectoimax
|
||||
#define __xnumtoint xnumtoimax
|
||||
#define __xdectoint_t intmax_t
|
||||
#define __xstrtol xstrtoimax
|
||||
#include "xdectoint.c"
|
96
gl/lib/xdectoint.c
Normal file
96
gl/lib/xdectoint.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* Convert decimal strings with bounds checking and exit on error.
|
||||
|
||||
Copyright (C) 2014-2025 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 "xdectoint.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <error.h>
|
||||
#include <quote.h>
|
||||
#include <xstrtol.h>
|
||||
|
||||
/* Parse numeric string N_STR of base BASE, and return the value.
|
||||
The value is between MIN and MAX.
|
||||
Strings can have multiplicative SUFFIXES if specified.
|
||||
On a parse error or out-of-range number, diagnose with N_STR and ERR, and
|
||||
exit with status ERR_EXIT if nonzero, EXIT_FAILURE otherwise.
|
||||
However, if FLAGS & XTOINT_MIN_QUIET, do not diagnose or exit
|
||||
for too-low numbers; return MIN and set errno instead.
|
||||
Similarly for XTOINT_MAX_QUIET and too-high numbers and MAX.
|
||||
The errno value and diagnostic for out-of-range values depend on
|
||||
whether FLAGS & XTOINT_MIN_RANGE and FLAGS & XTOINT_MAX_RANGE are set. */
|
||||
|
||||
__xdectoint_t
|
||||
__xnumtoint (char const *n_str, int base, __xdectoint_t min, __xdectoint_t max,
|
||||
char const *suffixes, char const *err, int err_exit,
|
||||
int flags)
|
||||
{
|
||||
__xdectoint_t tnum, r;
|
||||
strtol_error s_err = __xstrtol (n_str, nullptr, base, &tnum, suffixes);
|
||||
|
||||
/* Errno value to report if there is an overflow. */
|
||||
int overflow_errno;
|
||||
|
||||
if (s_err != LONGINT_INVALID)
|
||||
{
|
||||
if (tnum < min)
|
||||
{
|
||||
r = min;
|
||||
overflow_errno = flags & XTOINT_MIN_RANGE ? ERANGE : EOVERFLOW;
|
||||
if (s_err == LONGINT_OK)
|
||||
s_err = LONGINT_OVERFLOW;
|
||||
}
|
||||
else if (max < tnum)
|
||||
{
|
||||
r = max;
|
||||
overflow_errno = flags & XTOINT_MAX_RANGE ? ERANGE : EOVERFLOW;
|
||||
if (s_err == LONGINT_OK)
|
||||
s_err = LONGINT_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = tnum;
|
||||
overflow_errno = EOVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
int e = s_err == LONGINT_OVERFLOW ? overflow_errno : 0;
|
||||
|
||||
if (! (s_err == LONGINT_OK
|
||||
|| (s_err == LONGINT_OVERFLOW
|
||||
&& flags & (tnum < 0 ? XTOINT_MIN_QUIET : XTOINT_MAX_QUIET))))
|
||||
error (err_exit ? err_exit : EXIT_FAILURE, e, "%s: %s", err, quote (n_str));
|
||||
|
||||
errno = e;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Parse decimal string N_STR, and return the value.
|
||||
Exit on parse error or if MIN or MAX are exceeded.
|
||||
Strings can have multiplicative SUFFIXES if specified.
|
||||
ERR is printed along with N_STR on error. */
|
||||
|
||||
__xdectoint_t
|
||||
__xdectoint (char const *n_str, __xdectoint_t min, __xdectoint_t max,
|
||||
char const *suffixes, char const *err, int err_exit)
|
||||
{
|
||||
return __xnumtoint (n_str, 10, min, max, suffixes, err, err_exit, 0);
|
||||
}
|
57
gl/lib/xdectoint.h
Normal file
57
gl/lib/xdectoint.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* Convert decimal strings with bounds checking and exit on error.
|
||||
|
||||
Copyright (C) 2014-2025 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 XDECTOINT_H_
|
||||
# define XDECTOINT_H_ 1
|
||||
|
||||
# include <inttypes.h>
|
||||
|
||||
/* Flags for xnumtoimax and xnumtoumax. They can be ORed togethar. */
|
||||
enum
|
||||
{
|
||||
/* If the number is less than MIN, do not diagnose the problem;
|
||||
instead, return MIN and set errno to EOVERFLOW or ERANGE. */
|
||||
XTOINT_MIN_QUIET = 1 << 0,
|
||||
|
||||
/* Likewise for the MAX argument. */
|
||||
XTOINT_MAX_QUIET = 1 << 1,
|
||||
|
||||
/* The MIN argument is imposed by the caller, not by the type of
|
||||
the result. This causes the function to use ERANGE rather
|
||||
than EOVERFLOW behavior when issuing diagnostics or setting errno. */
|
||||
XTOINT_MIN_RANGE = 1 << 2,
|
||||
|
||||
/* Likewise for the MAX argument. */
|
||||
XTOINT_MAX_RANGE = 1 << 3
|
||||
};
|
||||
|
||||
# define _DECLARE_XDECTOINT(name, type) \
|
||||
type name (char const *n_str, type min, type max, \
|
||||
char const *suffixes, char const *err, int err_exit) \
|
||||
_GL_ATTRIBUTE_NONNULL ((1, 5));
|
||||
# define _DECLARE_XNUMTOINT(name, type) \
|
||||
type name (char const *n_str, int base, type min, type max, \
|
||||
char const *suffixes, char const *err, int err_exit, int flags) \
|
||||
_GL_ATTRIBUTE_NONNULL ((1, 6));
|
||||
|
||||
_DECLARE_XDECTOINT (xdectoimax, intmax_t)
|
||||
_DECLARE_XDECTOINT (xdectoumax, uintmax_t)
|
||||
|
||||
_DECLARE_XNUMTOINT (xnumtoimax, intmax_t)
|
||||
_DECLARE_XNUMTOINT (xnumtoumax, uintmax_t)
|
||||
|
||||
#endif /* not XDECTOINT_H_ */
|
5
gl/lib/xdectoumax.c
Normal file
5
gl/lib/xdectoumax.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define __xdectoint xdectoumax
|
||||
#define __xnumtoint xnumtoumax
|
||||
#define __xdectoint_t uintmax_t
|
||||
#define __xstrtol xstrtoumax
|
||||
#include "xdectoint.c"
|
64
gl/lib/xfts.c
Normal file
64
gl/lib/xfts.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* xfts.c -- a wrapper for fts_open
|
||||
|
||||
Copyright (C) 2003-2025 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 <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "assure.h"
|
||||
#include "xalloc.h"
|
||||
#include "xfts.h"
|
||||
|
||||
/* Fail with a proper diagnostic if fts_open fails. */
|
||||
|
||||
FTS *
|
||||
xfts_open (char * const *argv, int options,
|
||||
int (*compar) (const FTSENT **, const FTSENT **))
|
||||
{
|
||||
FTS *fts = fts_open (argv, options | FTS_CWDFD, compar);
|
||||
if (fts == nullptr)
|
||||
{
|
||||
/* This can fail in two ways: out of memory or with errno==EINVAL,
|
||||
which indicates it was called with invalid bit_flags. */
|
||||
affirm (errno != EINVAL);
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
return fts;
|
||||
}
|
||||
|
||||
/* When fts_read returns FTS_DC to indicate a directory cycle,
|
||||
it may or may not indicate a real problem. When a program like
|
||||
chgrp performs a recursive traversal that requires traversing
|
||||
symbolic links, it is *not* a problem. However, when invoked
|
||||
with "-P -R", it deserves a warning. The fts_options member
|
||||
records the options that control this aspect of fts's behavior,
|
||||
so test that. */
|
||||
bool
|
||||
cycle_warning_required (FTS const *fts, FTSENT const *ent)
|
||||
{
|
||||
#define ISSET(Fts,Opt) ((Fts)->fts_options & (Opt))
|
||||
/* When dereferencing no symlinks, or when dereferencing only
|
||||
those listed on the command line and we're not processing
|
||||
a command-line argument, then a cycle is a serious problem. */
|
||||
return ((ISSET (fts, FTS_PHYSICAL) && !ISSET (fts, FTS_COMFOLLOW))
|
||||
|| (ISSET (fts, FTS_PHYSICAL) && ISSET (fts, FTS_COMFOLLOW)
|
||||
&& ent->fts_level != FTS_ROOTLEVEL));
|
||||
}
|
11
gl/lib/xfts.h
Normal file
11
gl/lib/xfts.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "fts_.h"
|
||||
|
||||
FTS *
|
||||
xfts_open (char * const *, int options,
|
||||
int (*) (const FTSENT **, const FTSENT **))
|
||||
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (fts_close, 1)
|
||||
_GL_ATTRIBUTE_NONNULL ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL;
|
||||
|
||||
bool
|
||||
cycle_warning_required (FTS const *fts, FTSENT const *ent)
|
||||
_GL_ATTRIBUTE_NONNULL () _GL_ATTRIBUTE_PURE;
|
81
gl/local.mk
Normal file
81
gl/local.mk
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Make coreutils programs. -*-Makefile-*-
|
||||
# This is included by the top-level Makefile.am.
|
||||
|
||||
## Copyright (C) 2024-2025 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/>.
|
||||
|
||||
EXTRA_DIST += \
|
||||
gl/lib/buffer-lcm.c \
|
||||
gl/lib/buffer-lcm.h \
|
||||
gl/lib/cl-strtod.c \
|
||||
gl/lib/cl-strtod.h \
|
||||
gl/lib/cl-strtold.c \
|
||||
gl/lib/dtimespec-bound.c \
|
||||
gl/lib/dtimespec-bound.h \
|
||||
gl/lib/fadvise.c \
|
||||
gl/lib/fadvise.h \
|
||||
gl/lib/fd-reopen.c \
|
||||
gl/lib/fd-reopen.h \
|
||||
gl/lib/heap.c \
|
||||
gl/lib/heap.h \
|
||||
gl/lib/rand-isaac.c \
|
||||
gl/lib/rand-isaac.h \
|
||||
gl/lib/randint.c \
|
||||
gl/lib/randint.h \
|
||||
gl/lib/randperm.c \
|
||||
gl/lib/randperm.h \
|
||||
gl/lib/randread.c \
|
||||
gl/lib/randread.h \
|
||||
gl/lib/root-dev-ino.c \
|
||||
gl/lib/root-dev-ino.h \
|
||||
gl/lib/skipchars.c \
|
||||
gl/lib/skipchars.h \
|
||||
gl/lib/smack.h \
|
||||
gl/lib/strintcmp.c \
|
||||
gl/lib/strnumcmp-in.h \
|
||||
gl/lib/strnumcmp.c \
|
||||
gl/lib/strnumcmp.h \
|
||||
gl/lib/targetdir.c \
|
||||
gl/lib/targetdir.h \
|
||||
gl/lib/xdectoimax.c \
|
||||
gl/lib/xdectoint.c \
|
||||
gl/lib/xdectoint.h \
|
||||
gl/lib/xdectoumax.c \
|
||||
gl/lib/xfts.c \
|
||||
gl/lib/xfts.h \
|
||||
gl/local.mk \
|
||||
gl/modules/buffer-lcm \
|
||||
gl/modules/cl-strtod \
|
||||
gl/modules/cl-strtold \
|
||||
gl/modules/dtimespec-bound \
|
||||
gl/modules/fadvise \
|
||||
gl/modules/fadvise-tests \
|
||||
gl/modules/fd-reopen \
|
||||
gl/modules/heap \
|
||||
gl/modules/link-tests.diff \
|
||||
gl/modules/randint \
|
||||
gl/modules/randperm \
|
||||
gl/modules/randread \
|
||||
gl/modules/randread-tests \
|
||||
gl/modules/rename-tests.diff \
|
||||
gl/modules/root-dev-ino \
|
||||
gl/modules/skipchars \
|
||||
gl/modules/smack \
|
||||
gl/modules/strnumcmp \
|
||||
gl/modules/targetdir \
|
||||
gl/modules/xdectoint \
|
||||
gl/modules/xfts \
|
||||
gl/tests/test-fadvise.c \
|
||||
gl/tests/test-rand-isaac.c
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue