supermin-4.1.6/ 0000775 0001750 0001750 00000000000 12255776504 010404 5 0000000 0000000 supermin-4.1.6/README 0000644 0001750 0001750 00000004650 12240365064 011174 0000000 0000000 supermin - Tool for creating supermin appliances
by Richard W.M. Jones (rjones@redhat.com)
http://people.redhat.com/~rjones/supermin
----------------------------------------------------------------------
Supermin is a tool for building supermin appliances. These are tiny
appliances [similar to virtual machines], usually around 100KB in
size, which get fully instantiated on-the-fly in a fraction of a
second when you need to boot one of them.
A complete description is in the supermin(1) man page.
IMPORTANT NOTE FOR USERS OF FEBOOTSTRAP 3.x:
supermin 4.x is just an evolution of febootstrap 3.x (really we just
renamed it). The previous febootstrap program is now called
supermin. The previous febootstrap-supermin-helper program is now
called supermin-helper. Apart from that they are identical, although
they will evolve and add features over time.
IMPORTANT NOTE FOR USERS OF FEBOOTSTRAP 2.x:
febootstrap 3.x is a complete rewrite. febootstrap 2.x could only
build Fedora distributions. This version can build many varieties
of Linux distros. 3.x only builds supermin appliances, it does not
build chroots. 3.x does not build cross-distro, cross-release or
cross-architecture systems. If you want febootstrap 2.x, please use
the 'febootstrap-2.x' branch from the git repository.
Requirements
------------
ocaml
ocaml findlib ("ocamlfind" program)
perldoc
- This is just used to generate the manpage.
bash
gcc
gawk
libcom_err
libext2fs
/sbin/mke2fs
- These are part of e2fsprogs.
For Fedora/RHEL:
rpm
yum
yumdownloader
For Debian/Ubuntu:
dpkg
aptitude
Optional
--------
ocaml inifiles library (needed for zypper only)
These are only needed if you plan to boot the supermin appliances you
are building:
qemu >= 0.13
kernel >= 2.6.36
zlib (statically linked) - if your kernel uses gzipped modules
xz (statically linked) - if your kernel uses xz-compressed modules
Building and installing
-----------------------
./configure
make
sudo make install
Tests
-----
make check
Note that the tests require a network connection. If you don't
have a network connection (eg. for distro package building) then
try doing:
./configure --disable-network-tests
Examples
--------
See the examples/ subdirectory.
Feedback and bugs
-----------------
Send feedback to libguestfs@redhat.com. You can file bugs in
https://bugzilla.redhat.com/ (under "Fedora", "supermin")
supermin-4.1.6/src/ 0000775 0001750 0001750 00000000000 12255776503 011172 5 0000000 0000000 supermin-4.1.6/src/supermin_debian.ml 0000664 0001750 0001750 00000016365 12175443777 014630 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* Debian support. *)
open Unix
open Printf
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let debian_detect () =
file_exists "/etc/debian_version" &&
Config.aptitude <> "no" && Config.apt_cache <> "no" && Config.dpkg <> "no"
let installed_pkgs = ref []
let debian_init () =
installed_pkgs :=
run_command_get_lines "dpkg-query --show --showformat='${Package}\\n'"
let get_installed_pkgs () =
match !installed_pkgs with
| [] -> assert false
| pkgs -> pkgs
(* Select which dependencies will be installed. See apt-cache(8) for
* complete details. Using "-i" means only Depends and Pre-depends
* are installed, which is stricter (fewer packages) than ordinary
* 'apt-get install'. Otherwise, enable everything, then selectively
* disable what you don't want, to make it behave more like
* 'apt-get install'.
*)
let which_dependencies = "-i"
(*let which_dependencies = "--no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances"*)
let rec debian_resolve_dependencies_and_download names mode =
let which_dependencies =
if mode == PkgNames then which_dependencies ^ " --recurse"
else which_dependencies in
let cmd =
sprintf "%s depends %s %s | grep -v '^[<[:space:]]' | grep -Ev ':\\w+\\b'"
Config.apt_cache which_dependencies
(String.concat " " (List.map Filename.quote names)) in
let pkgs = run_command_get_lines cmd in
let pkgs =
if Config.apt_cache_depends_recurse_broken then
workaround_broken_apt_cache_depends_recurse (sort_uniq pkgs)
else
sort_uniq pkgs in
(* Exclude packages matching [--exclude] regexps on the command line. *)
let pkgs =
List.filter (
fun name ->
not (List.exists (fun re -> Str.string_match re name 0) excludes)
) pkgs in
let present_pkgs, download_pkgs =
if not use_installed then
[], pkgs
else
List.partition (
fun pkg -> List.exists ((=) pkg) (get_installed_pkgs ())
) pkgs in
debug "packages already present: %s" (String.concat " " present_pkgs);
debug "wanted packages to download: %s" (String.concat " " download_pkgs);
(* Download the packages. *)
if (List.length download_pkgs > 0)
then (
let cmd =
sprintf "umask 0000; cd %s && %s download %s"
(Filename.quote tmpdir)
Config.aptitude
(String.concat " " (List.map Filename.quote download_pkgs)) in
run_command cmd
);
(* Find out what aptitude downloaded. *)
let files = Sys.readdir tmpdir in
let download_pkgs = List.map (
fun pkg ->
(* Look for 'pkg_*.deb' in the list of files. *)
let pre = pkg ^ "_" in
let r = ref "" in
try
for i = 0 to Array.length files - 1 do
if string_prefix pre files.(i) then (
r := files.(i);
files.(i) <- "";
raise Exit
)
done;
eprintf "supermin: aptitude: error: no file was downloaded corresponding to package %s\n" pkg;
exit 1
with
Exit -> tmpdir // !r
) download_pkgs in
List.sort compare (List.append present_pkgs download_pkgs)
(* On Ubuntu 10.04 LTS, apt-cache depends --recurse is broken. It
* doesn't return the full list of dependencies. Therefore recurse
* into these dependencies one by one until we reach a fixpoint.
*)
and workaround_broken_apt_cache_depends_recurse names =
debug "workaround for broken 'apt-cache depends --recurse' command:\n %s"
(String.concat " " names);
let names' =
List.map (
fun name ->
let cmd =
sprintf "%s depends --recurse -i %s | grep -v '^[<[:space:]]'"
Config.apt_cache (Filename.quote name) in
run_command_get_lines cmd
) names in
let names' = List.flatten names' in
let names' = sort_uniq names' in
if names <> names' then
workaround_broken_apt_cache_depends_recurse names'
else
names
let debian_list_files_downloaded pkg =
debug "unpacking %s ..." pkg;
(* We actually need to extract the file in order to get the
* information about modes etc.
*)
let pkgdir = tmpdir // Filename.basename pkg ^ ".d" in
mkdir pkgdir 0o755;
let cmd =
sprintf "umask 0000; dpkg-deb --fsys-tarfile %s | (cd %s && tar xf -)"
pkg pkgdir in
run_command cmd;
let cmd = sprintf "cd %s && find ." pkgdir in
let lines = run_command_get_lines cmd in
let files = List.map (
fun path ->
assert (path.[0] = '.');
(* No leading '.' *)
let path =
if path = "." then "/"
else String.sub path 1 (String.length path - 1) in
(* Find out what it is and get the canonical filename. *)
let statbuf = lstat (pkgdir // path) in
let is_dir = statbuf.st_kind = S_DIR in
(* No per-file metadata like in RPM, but we can synthesize it
* from the path.
*)
let config = statbuf.st_kind = S_REG && string_prefix "/etc/" path in
let mode = statbuf.st_perm in
(path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
ft_ghost = false; ft_size = statbuf.st_size })
) lines in
files
let debian_list_files_installed pkg =
debug "using installed package %s ..." pkg;
let cmd = sprintf "dpkg-query --listfiles %s" pkg in
let lines = run_command_get_lines cmd in
(* filter out lines not directly describing fs objects such as
"package diverts others to: /path/to/..." *)
let lines = List.filter (
fun l -> l.[0] = '/' && l.[1] != '.'
) lines in
let files = List.map (
fun path ->
let statbuf = lstat path in
let is_dir = statbuf.st_kind = S_DIR in
let config = statbuf.st_kind = S_REG && string_prefix "/etc/" path in
let mode = statbuf.st_perm in
(path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
ft_ghost = false; ft_size = statbuf.st_size })
) lines in
files
let debian_list_files pkg =
if use_installed && List.exists ((=) pkg) (get_installed_pkgs ()) then
debian_list_files_installed pkg
else
debian_list_files_downloaded pkg
(* Easy because we already unpacked the archive above. *)
let debian_get_file_from_package pkg file =
if use_installed && List.exists (fun p -> p = pkg) (get_installed_pkgs ())
then
file
else
tmpdir // Filename.basename pkg ^ ".d" // file
let () =
let ph = {
ph_detect = debian_detect;
ph_init = debian_init;
ph_resolve_dependencies_and_download =
debian_resolve_dependencies_and_download;
ph_list_files = debian_list_files;
ph_get_file_from_package = debian_get_file_from_package;
} in
register_package_handler "debian" ph
supermin-4.1.6/src/supermin_cmdline.mli 0000664 0001750 0001750 00000004174 12175443777 015165 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2010 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(** Command line parsing. *)
val debug : ('a, unit, string, unit) format4 -> 'a
(** Print string (like printf), but only if --verbose was given on
the command line. *)
type mode = (** --names/--names-only flag *)
| PkgFiles (** no flag *)
| PkgNames (** --names *)
| PkgNamesOnly (** --names-only *)
val excludes : Str.regexp list
(** List of package regexps to exclude. *)
val mode : mode
(** How to interpret {!packages}:
If [mode = PkgFiles] then it's a list of filenames.
If [mode = PkgNames] then it's a list of package names.
If [mode = PkgNamesOnly] then it's a list of package names
and no dependencies are to be loaded. *)
val outputdir : string
(** Output directory. *)
val packages : string list
(** List of packages or package names as supplied on the command line. *)
val save_temps : bool
(** True if [--save-temps] was given on the command line. *)
val use_installed : bool
(** True if [--use-installed] was given on the command line *)
val verbose : bool
(** True if [--verbose] was given on the command line.
See also {!debug}. *)
val warnings : bool
(** If true, print warnings. [--no-warnings] sets this to false. *)
val packager_config : string option
(** Package manager configuration file. *)
supermin-4.1.6/src/supermin.1 0000664 0001750 0001750 00000036131 12240365305 013026 0000000 0000000 .\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.20)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
. if \nF \{
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "SUPERMIN 1"
.TH SUPERMIN 1 "2013-11-12" "supermin-4.1.5" "Virtualization Support"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
supermin \- Tool for creating supermin appliances
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 2
\& supermin [\-o OUTPUTDIR] \-\-names LIST OF PKGS ...
\& supermin [\-o OUTPUTDIR] PKG FILE NAMES ...
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
Supermin is a tool for building supermin appliances. These are
tiny appliances (similar to virtual machines), usually around 100KB in
size, which get fully instantiated on-the-fly in a fraction of a
second when you need to boot one of them.
.PP
Originally \*(L"fe\*(R" in \*(L"febootstrap\*(R" stood for \*(L"Fedora\*(R", but this tool is
now distro-independent and can build supermin appliances for several
popular Linux distros, and adding support for others is reasonably
easy. For this reason, starting with version 4, we have renamed the
tool \*(L"supermin\*(R".
.PP
Note that this manual page documents supermin 4.x which is a complete
rewrite and quite different from febootstrap 2.x. If you are looking
for the febootstrap 2.x tools, then this is not the right place.
.SS "\s-1BASIC OPERATION\s0"
.IX Subsection "BASIC OPERATION"
There are two modes for using supermin. With the \fI\-\-names\fR
parameter, supermin takes a list of package names and creates a
supermin appliance containing those packages and all dependencies that
those packages require. In this mode supermin usually needs
network access because it may need to consult package repositories in
order to work out dependencies and download packages.
.PP
Without \fI\-\-names\fR, supermin takes a list of packages (ie.
filenames of locally available packages). This package set must be
complete and consistent with no dependencies outside the set of
packages you provide. In this mode supermin does not require any
network access. It works by looking at the package files themselves.
.PP
By \*(L"package\*(R" we mean the \s-1RPM, DEB, \s0(etc.) package. A package name
might be the fully qualified name (eg. \f(CW\*(C`coreutils\-8.5\-7.fc14.x86_64\*(C'\fR)
or some abbreviation (eg. \f(CW\*(C`coreutils\*(C'\fR). The precise format of the
name and what abbreviations are allowed depends on the package
manager.
.PP
The supermin appliance that supermin writes consists of two files
called \f(CW\*(C`hostfiles\*(C'\fR and \f(CW\*(C`base.img\*(C'\fR (see \*(L"\s-1SUPERMIN APPLIANCES\*(R"\s0
below). By default these are written to the current directory. If
you specify the \fI\-o \s-1OUTPUTDIR\s0\fR option then these files are written to
the named directory instead (traditionally this directory is named
\&\f(CW\*(C`supermin.d\*(C'\fR but you can call it whatever you want).
.PP
In all cases supermin can only build a supermin appliance which is
identical in distro, version and architecture to the host. It does
\&\fInot\fR do cross-builds.
.SH "OPTIONS"
.IX Header "OPTIONS"
.IP "\fB\-\-help\fR" 4
.IX Item "--help"
Display brief command line usage, and exit.
.IP "\fB\-\-exclude \s-1REGEXP\s0\fR" 4
.IX Item "--exclude REGEXP"
After doing dependency resolution, exclude packages which match the
regular expression.
.Sp
This option is only used with \fI\-\-names\fR, and it can be given multiple
times on the command line.
.IP "\fB\-\-names\fR" 4
.IX Item "--names"
Provide a list of package names, instead of providing packages
directly. In this mode supermin may require network access. See
\&\*(L"\s-1BASIC OPERATION\*(R"\s0 above.
.IP "\fB\-\-no\-warnings\fR" 4
.IX Item "--no-warnings"
Don't print warnings about packaging problems.
.IP "\fB\-o outputdir\fR" 4
.IX Item "-o outputdir"
Select the output directory where the two supermin appliance files are
written (\f(CW\*(C`hostfiles\*(C'\fR and \f(CW\*(C`base.img\*(C'\fR). The default directory is the
current directory. Note that if this files exist already in the
output directory then they will be overwritten.
.IP "\fB\-\-packager\-config \s-1CONFIGFILE\s0\fR" 4
.IX Item "--packager-config CONFIGFILE"
Set the configuration file for the package manager. This allows you
to specify alternate software repositories.
.Sp
For ArchLinux, this sets the pacman configuration file (default
\&\f(CW\*(C`/etc/pacman.conf\*(C'\fR). See \fIpacman.conf\fR\|(5).
.Sp
For Yum/RPM distributions, this sets the yum configuration file
(default \f(CW\*(C`/etc/yum.conf\*(C'\fR). See \fIyum.conf\fR\|(5).
.IP "\fB\-\-save\-temps\fR" 4
.IX Item "--save-temps"
Don't remove temporary files and directories on exit. This is useful
for debugging.
.IP "\fB\-\-use\-installed\fR" 4
.IX Item "--use-installed"
If packages are already installed, use the contents (from the local
filesystem) instead of downloading them.
.Sp
Note that this can cause malformed appliances if local files have been
changed from what was originally in the package. This is particularly
a problem for configuration files.
.Sp
However this option is useful in some controlled situations: for
example when using supermin inside a freshly installed chroot.
.IP "\fB\-v\fR" 4
.IX Item "-v"
.PD 0
.IP "\fB\-\-verbose\fR" 4
.IX Item "--verbose"
.PD
Enable verbose messages.
.IP "\fB\-V\fR" 4
.IX Item "-V"
.PD 0
.IP "\fB\-\-version\fR" 4
.IX Item "--version"
.PD
Print the package name and version number, and exit.
.IP "\fB\-\-yum\-config \s-1CONFIGFILE\s0\fR" 4
.IX Item "--yum-config CONFIGFILE"
This is a deprecated alias for \fI\-\-packager\-config \s-1CONFIGFILE\s0\fR.
.SH "SUPERMIN APPLIANCES"
.IX Header "SUPERMIN APPLIANCES"
Supermin appliances consist of just enough information to be able to
build an appliance containing the same operating system (Linux
version, distro, release etc) as the host \s-1OS. \s0 Since the host and
appliance share many common files such as \f(CW\*(C`/bin/bash\*(C'\fR and
\&\f(CW\*(C`/lib/libc.so\*(C'\fR there is no reason to ship these files in the
appliance. They can simply be read from the host on demand when the
appliance is launched. Therefore to save space we just store the
names of the host files that we want.
.PP
There are some files which cannot just be copied from the host in this
way. These include configuration files which the host admin might
have edited. So along with the list of host files, we also store a
skeleton base image which contains these files and the outline
directory structure.
.PP
Therefore the supermin appliance normally consists of at least two
control files:
.IP "\fBhostfiles\fR" 4
.IX Item "hostfiles"
The list of files that are to be copied from the host. This is a
plain text file with one pathname per line. Directories are included
in this file.
.Sp
Paths can contain wildcards, which are expanded when the appliance
is created, eg:
.Sp
.Vb 1
\& /etc/yum.repos.d/*.repo
.Ve
.Sp
would copy all of the \f(CW\*(C`*.repo\*(C'\fR files into the appliance.
.Sp
Each pathname in the file should start with a \f(CW\*(C`/\*(C'\fR character. (In
older versions of febootstrap, paths started with \f(CW\*(C`./\*(C'\fR and were
relative to the root directory, but you should not do that in new
files).
.IP "\fBbase.img\fR" 4
.IX Item "base.img"
This uncompressed cpio file contains the skeleton filesystem. Mostly
it contains directories and a few configuration files.
.Sp
All paths in the cpio file should be relative to the root directory of
the appliance.
.Sp
Note that unlike \f(CW\*(C`hostfiles\*(C'\fR, paths and directories in the base image
don't need to have any relationship to the host filesystem.
.IP "\fBbase.img.gz\fR" 4
.IX Item "base.img.gz"
Since supermin ≥ 4.1.4, any cpio image files may be
gzip-compressed to save disk space. \f(CW\*(C`hostfiles\*(C'\fR cannot be
compressed. The supermin program won't create these files. You need
to compress the output yourself, eg by doing:
.Sp
.Vb 1
\& gzip \-9 supermin.d/*.img
.Ve
.SS "\s-1RECONSTRUCTING THE APPLIANCE\s0"
.IX Subsection "RECONSTRUCTING THE APPLIANCE"
The separate tool \fIsupermin\-helper\fR\|(1) is used to
reconstruct an appliance from the hostfiles and base image files.
.PP
This program in fact iterates recursively over the files and
directories passed to it. A common layout is:
.PP
.Vb 4
\& supermin.d/
\& supermin.d/base.img
\& supermin.d/extra.img
\& supermin.d/hostfiles
.Ve
.PP
and then invoking supermin-helper with just the
\&\f(CW\*(C`supermin.d\*(C'\fR directory path as an argument.
.PP
In this way extra files can be added to the appliance just by creating
another cpio file (\f(CW\*(C`extra.img\*(C'\fR in the example above) and dropping it
into the directory. When the appliance is constructed, the extra
files will appear in the appliance.
.PP
\fI\s-1DIRECTORIES BEFORE FILES\s0\fR
.IX Subsection "DIRECTORIES BEFORE FILES"
.PP
In order for supermin-helper to run quickly, it does not
know how to create directories automatically. Inside hostfiles and
the cpio files, directories must be specified before any files that
they contain. For example:
.PP
.Vb 3
\& /usr
\& /usr/sbin
\& /usr/sbin/serviced
.Ve
.PP
It is fine to list the same directory name multiple times.
.PP
\fI\s-1LEXICOGRAPHICAL ORDER\s0\fR
.IX Subsection "LEXICOGRAPHICAL ORDER"
.PP
supermin-helper visits the supermin control files in
lexicographical order. Thus in the example above, in the order
\&\f(CW\*(C`base.img\*(C'\fR \-> \f(CW\*(C`extra.img\*(C'\fR \-> \f(CW\*(C`hostfiles\*(C'\fR.
.PP
This has an important effect: files contained in later cpio files
overwrite earlier files, and directories do not need to be specified
if they have already been created in earlier control files.
.PP
\fI\s-1EXAMPLE OF CREATING EXTRA CPIO FILE\s0\fR
.IX Subsection "EXAMPLE OF CREATING EXTRA CPIO FILE"
.PP
You can create a file like \f(CW\*(C`extra.img\*(C'\fR very easily using a shell
snippet similar to this one:
.PP
.Vb 6
\& cd $tmpdir
\& mkdir \-p usr/sbin
\& cp /path/to/serviced usr/sbin/
\& echo \-e "usr\enusr/sbin\enusr/sbin/serviced" |
\& cpio \-\-quiet \-o \-H newc > extra.img
\& rm \-rf usr
.Ve
.PP
Notice how we instruct cpio to create intermediate directories.
.SS "\s-1MINIMIZING THE SUPERMIN APPLIANCE\s0"
.IX Subsection "MINIMIZING THE SUPERMIN APPLIANCE"
You may want to \*(L"minimize\*(R" the supermin appliance in order to save
time and space when it is instantiated. Typically you might want to
remove documentation, info files, man pages and locales. We used to
provide a separate tool called \f(CW\*(C`febootstrap\-minimize\*(C'\fR for this
purpose, but it is no longer provided. Instead you can post-process
\&\f(CW\*(C`hostfiles\*(C'\fR yourself to remove any files or directories that you
don't want (by removing lines from the file). Be careful what you
remove because files may be necessary for correct operation of the
appliance.
.PP
For example:
.PP
.Vb 5
\& < supermin.d/hostfiles \e
\& grep \-v \*(Aq^/usr/share/man/\*(Aq |
\& grep \-v \*(Aq^/usr/share/doc/\*(Aq |
\& grep \-v \*(Aq^/usr/share/info/\*(Aq > supermin.d/hostfiles\-t
\& mv supermin.d/hostfiles\-t supermin.d/hostfiles
.Ve
.SS "\s-1KERNEL AND KERNEL MODULES\s0"
.IX Subsection "KERNEL AND KERNEL MODULES"
Usually the kernel and kernel modules are \fInot\fR included in the
supermin appliance. When the appliance is instantiated, the kernel
modules from the host kernel are copied in, and it is booted using the
host kernel.
.PP
supermin-helper is able to choose the best host kernel
available to boot the appliance. Users can override this by setting
environment variables (see \fIsupermin\-helper\fR\|(1)).
.SS "\s-1BOOTING AND CACHING THE SUPERMIN APPLIANCE\s0"
.IX Subsection "BOOTING AND CACHING THE SUPERMIN APPLIANCE"
For fastest boot times you should cache the output of
supermin-helper. See the libguestfs source file
\&\f(CW\*(C`src/appliance.c\*(C'\fR for an example of how this is done.
.SS "\s-1ENFORCING AVAILABILITY OF HOSTFILES\s0"
.IX Subsection "ENFORCING AVAILABILITY OF HOSTFILES"
supermin-helper builds the appliance by copying in host
files as listed in \f(CW\*(C`hostfiles\*(C'\fR. For this to work those host files
must be available. We usually enforce this by adding requirements
(eg. \s-1RPM \s0\f(CW\*(C`Requires:\*(C'\fR lines) on the package that uses the supermin
appliance, so that package cannot be installed without pulling in the
dependent packages and thus making sure the host files are available.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fIsupermin\-helper\fR\|(1),
,
\&\fIguestfs\fR\|(3),
.
.SH "AUTHORS"
.IX Header "AUTHORS"
.IP "\(bu" 4
Richard W.M. Jones
.IP "\(bu" 4
Matthew Booth mbooth@redhat.com
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright (C) 2009\-2011 Red Hat Inc.
.PP
This program is free software; you can redistribute it and/or modify
it under the terms of the \s-1GNU\s0 General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.PP
This program is distributed in the hope that it will be useful,
but \s-1WITHOUT ANY WARRANTY\s0; without even the implied warranty of
\&\s-1MERCHANTABILITY\s0 or \s-1FITNESS FOR A PARTICULAR PURPOSE. \s0 See the
\&\s-1GNU\s0 General Public License for more details.
.PP
You should have received a copy of the \s-1GNU\s0 General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, \s-1MA 02139, USA.\s0
supermin-4.1.6/src/supermin_pacman.ml 0000664 0001750 0001750 00000010746 12175443777 014642 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* ArchLinux support. *)
open Unix
open Printf
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let pacman_detect () =
file_exists "/etc/arch-release" &&
Config.pacman <> "no"
let pacman_init () =
if use_installed then
failwith "pacman driver doesn't support --use-installed"
let pacman_resolve_dependencies_and_download names mode =
if mode = PkgNamesOnly then (
eprintf "supermin: pacman: --names-only flag is not implemented\n";
exit 1
);
let cmd =
sprintf "(for p in %s; do pactree -u $p; done) | awk '{print $1}' | sort -u"
(String.concat " " (List.map Filename.quote names)) in
let pkgs = run_command_get_lines cmd in
(* Exclude packages matching [--exclude] regexps on the command line. *)
let pkgs =
List.filter (
fun name ->
not (List.exists (fun re -> Str.string_match re name 0) excludes)
) pkgs in
(* Download the packages. I could use wget `pacman -Sp`, but this
* narrows the pacman -Sy window
*)
List.iter (
fun pkg ->
let cmd =
sprintf "umask 0000; cd %s && mkdir -p var/lib/pacman && fakeroot pacman%s -Syw --noconfirm --cachedir=$(pwd) --root=$(pwd) %s"
(Filename.quote tmpdir)
(match packager_config with
| None -> ""
| Some filename -> " --config " ^ filename)
pkg in
if Sys.command cmd <> 0 then (
(* The package is not in the main repos, check the aur *)
let cmd =
sprintf "umask 0000; cd %s && wget https://aur.archlinux.org/packages/%s/%s/%s.tar.gz && tar xf %s.tar.gz && cd %s && makepkg && mv %s-*.pkg.tar.xz %s"
(Filename.quote tmpdir)
(String.sub pkg 0 2)
pkg
pkg
pkg
pkg
pkg
(Filename.quote tmpdir) in
run_command cmd;
)
) pkgs;
List.sort compare pkgs
let pacman_list_files pkg =
debug "unpacking %s ..." pkg;
(* We actually need to extract the file in order to get the
* information about modes etc.
*)
let pkgdir = tmpdir // pkg ^ ".d" in
mkdir pkgdir 0o755;
let cmd =
sprintf "ls -1 %s/%s-*.pkg.* | awk '/\\/%s-[^/-]*-[^/-]*-[^/-]*$/ { print $0 }'"
tmpdir pkg pkg in
let pkgfile = List.hd (run_command_get_lines cmd) in
let cmd = sprintf "umask 0000; fakeroot tar -xf %s -C %s"
(Filename.quote pkgfile) (Filename.quote pkgdir) in
run_command cmd;
let cmd = sprintf "cd %s && find ." pkgdir in
let lines = run_command_get_lines cmd in
let files = List.map (
fun path ->
assert (path.[0] = '.');
(* No leading '.' *)
let path =
if path = "." then "/"
else String.sub path 1 (String.length path - 1) in
(* Find out what it is and get the canonical filename. *)
let statbuf = lstat (pkgdir // path) in
let is_dir = statbuf.st_kind = S_DIR in
(* No per-file metadata like in RPM, but we can synthesize it
* from the path.
*)
let config = statbuf.st_kind = S_REG && string_prefix "/etc/" path in
let mode = statbuf.st_perm in
(path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
ft_ghost = false; ft_size = statbuf.st_size })
) lines in
files
(* Easy because we already unpacked the archive above. *)
let pacman_get_file_from_package pkg file =
tmpdir // pkg ^ ".d" // file
let () =
let ph = {
ph_detect = pacman_detect;
ph_init = pacman_init;
ph_resolve_dependencies_and_download =
pacman_resolve_dependencies_and_download;
ph_list_files = pacman_list_files;
ph_get_file_from_package = pacman_get_file_from_package;
} in
register_package_handler "pacman" ph
supermin-4.1.6/src/supermin_cmdline.ml 0000664 0001750 0001750 00000007574 12240365137 015005 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
open Printf
type mode = (* --names/--names-only flag *)
| PkgFiles (* no flag *)
| PkgNames (* --names *)
| PkgNamesOnly (* --names-only *)
let excludes = ref []
let mode = ref PkgFiles
let outputdir = ref "."
let packages = ref []
let save_temps = ref false
let use_installed = ref false
let verbose = ref false
let warnings = ref true
let packager_config = ref None
let print_version () =
printf "%s %s\n" Config.package_name Config.package_version;
exit 0
let add_exclude re =
excludes := Str.regexp re :: !excludes
let set_packager_config filename =
(* Need to check that the file exists, and make the path absolute. *)
let filename =
if Filename.is_relative filename then
Filename.concat (Sys.getcwd ()) filename
else filename in
if not (Sys.file_exists filename) then (
eprintf "supermin: --packager-config: %s: file does not exist\n"
filename;
exit 1
);
packager_config := Some filename
let argspec = Arg.align [
"--exclude", Arg.String add_exclude,
"regexp Exclude packages matching regexp";
"--names", Arg.Unit (fun () -> mode := PkgNames),
" Specify set of root package names on command line";
"--names-only", Arg.Unit (fun () -> mode := PkgNamesOnly),
" Specify exact set of package names on command line";
"--no-warnings", Arg.Clear warnings,
" Suppress warnings";
"-o", Arg.Set_string outputdir,
"outputdir Set output directory (default: \".\")";
"--packager-config", Arg.String set_packager_config,
"file Set alternate package manager configuration file";
"--save-temp", Arg.Set save_temps,
" Don't delete temporary files and directories on exit";
"--save-temps", Arg.Set save_temps,
" Don't delete temporary files and directories on exit";
"--use-installed", Arg.Set use_installed,
" Use already installed packages for package contents";
"-v", Arg.Set verbose,
" Enable verbose output";
"--verbose", Arg.Set verbose,
" Enable verbose output";
"-V", Arg.Unit print_version,
" Print package name and version, and exit";
"--version", Arg.Unit print_version,
" Print package name and version, and exit";
"--yum-config", Arg.String set_packager_config,
"file Deprecated alias for `--packager-config file'";
]
let anon_fn str =
packages := str :: !packages
let usage_msg =
"\
supermin - tool for creating supermin appliances
Copyright (C) 2009-2013 Red Hat Inc.
Usage:
supermin [-o OUTPUTDIR] --names LIST OF PKGS ...
supermin [-o OUTPUTDIR] PKG FILE NAMES ...
For full instructions see the supermin(1) man page.
Options:\n"
let () =
Arg.parse argspec anon_fn usage_msg;
if !packages = [] then (
eprintf "supermin: no packages listed on the command line\n";
exit 1
)
let excludes = List.rev !excludes
let mode = !mode
let outputdir = !outputdir
let packages = List.rev !packages
let save_temps = !save_temps
let use_installed = !use_installed
let verbose = !verbose
let warnings = !warnings
let packager_config = !packager_config
let debug fs = ksprintf (fun str -> if verbose then print_endline str) fs
supermin-4.1.6/src/config.ml.in 0000664 0001750 0001750 00000002317 12233731404 013304 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat Inc.
* @configure_input@
*
* 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
let package_name = "@PACKAGE_NAME@"
let package_version = "@PACKAGE_VERSION@"
let zypper = "@ZYPPER@"
let yum = "@YUM@"
let urpmi = "@URPMI@"
let rpm = "@RPM@"
let yumdownloader = "@YUMDOWNLOADER@"
let aptitude = "@APTITUDE@"
let apt_cache = "@APT_CACHE@"
let dpkg = "@DPKG@"
let apt_cache_depends_recurse_broken = @APT_CACHE_DEPENDS_RECURSE_BROKEN@
let pacman = "@PACMAN@"
let pacman_g2 = "@PACMAN_G2@"
let host_cpu = "@host_cpu@"
supermin-4.1.6/src/supermin.pod 0000664 0001750 0001750 00000026035 12240365127 013454 0000000 0000000 =encoding utf8
=head1 NAME
supermin - Tool for creating supermin appliances
=head1 SYNOPSIS
supermin [-o OUTPUTDIR] --names LIST OF PKGS ...
supermin [-o OUTPUTDIR] PKG FILE NAMES ...
=head1 DESCRIPTION
Supermin is a tool for building supermin appliances. These are
tiny appliances (similar to virtual machines), usually around 100KB in
size, which get fully instantiated on-the-fly in a fraction of a
second when you need to boot one of them.
Originally "fe" in "febootstrap" stood for "Fedora", but this tool is
now distro-independent and can build supermin appliances for several
popular Linux distros, and adding support for others is reasonably
easy. For this reason, starting with version 4, we have renamed the
tool "supermin".
Note that this manual page documents supermin 4.x which is a complete
rewrite and quite different from febootstrap 2.x. If you are looking
for the febootstrap 2.x tools, then this is not the right place.
=head2 BASIC OPERATION
There are two modes for using supermin. With the I<--names>
parameter, supermin takes a list of package names and creates a
supermin appliance containing those packages and all dependencies that
those packages require. In this mode supermin usually needs
network access because it may need to consult package repositories in
order to work out dependencies and download packages.
Without I<--names>, supermin takes a list of packages (ie.
filenames of locally available packages). This package set must be
complete and consistent with no dependencies outside the set of
packages you provide. In this mode supermin does not require any
network access. It works by looking at the package files themselves.
By "package" we mean the RPM, DEB, (etc.) package. A package name
might be the fully qualified name (eg. C)
or some abbreviation (eg. C). The precise format of the
name and what abbreviations are allowed depends on the package
manager.
The supermin appliance that supermin writes consists of two files
called C and C (see L
below). By default these are written to the current directory. If
you specify the I<-o OUTPUTDIR> option then these files are written to
the named directory instead (traditionally this directory is named
C but you can call it whatever you want).
In all cases supermin can only build a supermin appliance which is
identical in distro, version and architecture to the host. It does
I do cross-builds.
=head1 OPTIONS
=over 4
=item B<--help>
Display brief command line usage, and exit.
=item B<--exclude REGEXP>
After doing dependency resolution, exclude packages which match the
regular expression.
This option is only used with I<--names>, and it can be given multiple
times on the command line.
=item B<--names>
Provide a list of package names, instead of providing packages
directly. In this mode supermin may require network access. See
L above.
=item B<--no-warnings>
Don't print warnings about packaging problems.
=item B<-o outputdir>
Select the output directory where the two supermin appliance files are
written (C and C). The default directory is the
current directory. Note that if this files exist already in the
output directory then they will be overwritten.
=item B<--packager-config CONFIGFILE>
Set the configuration file for the package manager. This allows you
to specify alternate software repositories.
For ArchLinux, this sets the pacman configuration file (default
C). See L.
For Yum/RPM distributions, this sets the yum configuration file
(default C). See L.
=item B<--save-temps>
Don't remove temporary files and directories on exit. This is useful
for debugging.
=item B<--use-installed>
If packages are already installed, use the contents (from the local
filesystem) instead of downloading them.
Note that this can cause malformed appliances if local files have been
changed from what was originally in the package. This is particularly
a problem for configuration files.
However this option is useful in some controlled situations: for
example when using supermin inside a freshly installed chroot.
=item B<-v>
=item B<--verbose>
Enable verbose messages.
=item B<-V>
=item B<--version>
Print the package name and version number, and exit.
=item B<--yum-config CONFIGFILE>
This is a deprecated alias for I<--packager-config CONFIGFILE>.
=back
=head1 SUPERMIN APPLIANCES
Supermin appliances consist of just enough information to be able to
build an appliance containing the same operating system (Linux
version, distro, release etc) as the host OS. Since the host and
appliance share many common files such as C and
C there is no reason to ship these files in the
appliance. They can simply be read from the host on demand when the
appliance is launched. Therefore to save space we just store the
names of the host files that we want.
There are some files which cannot just be copied from the host in this
way. These include configuration files which the host admin might
have edited. So along with the list of host files, we also store a
skeleton base image which contains these files and the outline
directory structure.
Therefore the supermin appliance normally consists of at least two
control files:
=over 4
=item B
The list of files that are to be copied from the host. This is a
plain text file with one pathname per line. Directories are included
in this file.
Paths can contain wildcards, which are expanded when the appliance
is created, eg:
/etc/yum.repos.d/*.repo
would copy all of the C<*.repo> files into the appliance.
Each pathname in the file should start with a C> character. (In
older versions of febootstrap, paths started with C<./> and were
relative to the root directory, but you should not do that in new
files).
=item B
This uncompressed cpio file contains the skeleton filesystem. Mostly
it contains directories and a few configuration files.
All paths in the cpio file should be relative to the root directory of
the appliance.
Note that unlike C, paths and directories in the base image
don't need to have any relationship to the host filesystem.
=item B
Since supermin E 4.1.4, any cpio image files may be
gzip-compressed to save disk space. C cannot be
compressed. The supermin program won't create these files. You need
to compress the output yourself, eg by doing:
gzip -9 supermin.d/*.img
=back
=head2 RECONSTRUCTING THE APPLIANCE
The separate tool L is used to
reconstruct an appliance from the hostfiles and base image files.
This program in fact iterates recursively over the files and
directories passed to it. A common layout is:
supermin.d/
supermin.d/base.img
supermin.d/extra.img
supermin.d/hostfiles
and then invoking supermin-helper with just the
C directory path as an argument.
In this way extra files can be added to the appliance just by creating
another cpio file (C in the example above) and dropping it
into the directory. When the appliance is constructed, the extra
files will appear in the appliance.
=head3 DIRECTORIES BEFORE FILES
In order for supermin-helper to run quickly, it does not
know how to create directories automatically. Inside hostfiles and
the cpio files, directories must be specified before any files that
they contain. For example:
/usr
/usr/sbin
/usr/sbin/serviced
It is fine to list the same directory name multiple times.
=head3 LEXICOGRAPHICAL ORDER
supermin-helper visits the supermin control files in
lexicographical order. Thus in the example above, in the order
C -E C -E C.
This has an important effect: files contained in later cpio files
overwrite earlier files, and directories do not need to be specified
if they have already been created in earlier control files.
=head3 EXAMPLE OF CREATING EXTRA CPIO FILE
You can create a file like C very easily using a shell
snippet similar to this one:
cd $tmpdir
mkdir -p usr/sbin
cp /path/to/serviced usr/sbin/
echo -e "usr\nusr/sbin\nusr/sbin/serviced" |
cpio --quiet -o -H newc > extra.img
rm -rf usr
Notice how we instruct cpio to create intermediate directories.
=head2 MINIMIZING THE SUPERMIN APPLIANCE
You may want to "minimize" the supermin appliance in order to save
time and space when it is instantiated. Typically you might want to
remove documentation, info files, man pages and locales. We used to
provide a separate tool called C for this
purpose, but it is no longer provided. Instead you can post-process
C yourself to remove any files or directories that you
don't want (by removing lines from the file). Be careful what you
remove because files may be necessary for correct operation of the
appliance.
For example:
< supermin.d/hostfiles \
grep -v '^/usr/share/man/' |
grep -v '^/usr/share/doc/' |
grep -v '^/usr/share/info/' > supermin.d/hostfiles-t
mv supermin.d/hostfiles-t supermin.d/hostfiles
=head2 KERNEL AND KERNEL MODULES
Usually the kernel and kernel modules are I included in the
supermin appliance. When the appliance is instantiated, the kernel
modules from the host kernel are copied in, and it is booted using the
host kernel.
supermin-helper is able to choose the best host kernel
available to boot the appliance. Users can override this by setting
environment variables (see L).
=head2 BOOTING AND CACHING THE SUPERMIN APPLIANCE
For fastest boot times you should cache the output of
supermin-helper. See the libguestfs source file
C for an example of how this is done.
=head2 ENFORCING AVAILABILITY OF HOSTFILES
supermin-helper builds the appliance by copying in host
files as listed in C. For this to work those host files
must be available. We usually enforce this by adding requirements
(eg. RPM C lines) on the package that uses the supermin
appliance, so that package cannot be installed without pulling in the
dependent packages and thus making sure the host files are available.
=head1 SEE ALSO
L,
L,
L,
L.
=head1 AUTHORS
=over 4
=item *
Richard W.M. Jones L
=item *
Matthew Booth L
=back
=head1 COPYRIGHT
Copyright (C) 2009-2011 Red Hat 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 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
supermin-4.1.6/src/supermin_utils.mli 0000664 0001750 0001750 00000005756 12175443777 014721 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(** Utilities. *)
val file_exists : string -> bool
(** Return [true] iff file exists. *)
val dir_exists : string -> bool
(** Return [true] iff dir exists. *)
val uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list
(** Uniquify a list (the list must be sorted first). *)
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list
(** Sort and uniquify a list. *)
val input_all_lines : in_channel -> string list
(** Input all lines from a channel, returning a list of lines. *)
val run_command_get_lines : string -> string list
(** Run the command and read the list of lines that it prints to stdout. *)
val run_command : string -> unit
(** Run a command using {!Sys.command} and exit if it fails. Be careful
when constructing the command to properly quote any arguments
(using {!Filename.quote}). *)
val run_shell : string -> string list -> unit
(** [run_shell code args] runs shell [code] with arguments [args].
This does not return anything, but exits with an error message
if the shell code returns an error. *)
val run_python : string -> string list -> unit
(** [run_python code args] runs Python [code] with arguments [args].
This does not return anything, but exits with an error message
if the Python code returns an error. *)
val tmpdir : unit -> string
(** [tmpdir ()] returns a newly created temporary directory. The
tmp directory is automatically removed when the program exits.
Note that a fresh temporary directory is returned each time you
call this function. *)
val (//) : string -> string -> string
(** [x // y] concatenates file paths [x] and [y] into a single path. *)
val find : string -> string -> int
(** [find str sub] searches for [sub] in [str], returning the index
or -1 if not found. *)
val string_split : string -> string -> string list
(** [string_split sep str] splits [str] at [sep]. *)
val string_prefix : string -> string -> bool
(** [string_prefix prefix str] returns true iff [str] starts with [prefix]. *)
val path_prefix : string -> string -> bool
(** [path_prefix prefix path] returns true iff [path] is [prefix] or
[path] starts with [prefix/]. *)
val filter_map : ('a -> 'b option) -> 'a list -> 'b list
(** map + filter *)
supermin-4.1.6/src/supermin.ml 0000664 0001750 0001750 00000035323 12200004503 013262 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
open Unix
open Printf
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let () =
debug "%s %s" Config.package_name Config.package_version;
(* Instead of printing out warnings as we go along, accumulate them
* in lists and print them all out at the end.
*)
let warn_unreadable = ref [] in
(* Determine which package manager this system uses. *)
check_system ();
let ph = get_package_handler () in
debug "selected package handler: %s" (get_package_handler_name ());
(* Not --names: check files exist. *)
if mode = PkgFiles then (
List.iter (
fun pkg ->
if not (file_exists pkg) then (
eprintf "supermin: %s: no such file (did you miss out the --names option?)\n" pkg;
exit 1
)
) packages
);
(* --names: resolve the package list to a full list of package names
* (including dependencies).
*)
let packages =
if mode <> PkgFiles then (
let packages = ph.ph_resolve_dependencies_and_download packages mode in
debug "resolved packages: %s" (String.concat " " packages);
packages
)
else packages in
(* Get the list of files. *)
let files =
List.flatten (
List.map (
fun pkg ->
let files = ph.ph_list_files pkg in
List.map (fun (filename, ft) -> filename, ft, pkg) files
) packages
) in
(* Canonicalize the name of directories, so that /a and /a/ are the same. *)
let files =
List.map (
fun (filename, ft, pkg) ->
let len = String.length filename in
let filename =
if len > 1 (* don't rewrite "/" *) && ft.ft_dir
&& filename.[len-1] = '/' then
String.sub filename 0 (len-1)
else
filename in
(filename, ft, pkg)
) files in
(* Sort and combine duplicate files. *)
let files =
let files = List.sort compare files in
let combine (name1, ft1, pkg1) (name2, ft2, pkg2) =
(* Rules for combining files. *)
if ft1.ft_config || ft2.ft_config then (
(* It's a fairly frequent bug in Fedora for two packages to
* incorrectly list the same config file. Allow this, provided
* the size of both files is 0; or one is a ghost file and the
* other is not.
*)
if ft1.ft_size = 0 && ft2.ft_size = 0 then
(name1, ft1, pkg1)
else if not ft1.ft_ghost && ft2.ft_ghost then
(name1, ft1, pkg1)
else if ft1.ft_ghost && not ft2.ft_ghost then
(name2, ft2, pkg2)
else (
eprintf "supermin: error: %s is a config file which is listed in two packages (%s, %s)\n"
name1 pkg1 pkg2;
exit 1
)
)
else if (ft1.ft_dir || ft2.ft_dir) && (not (ft1.ft_dir && ft2.ft_dir)) then (
eprintf "supermin: error: %s appears as both directory and ordinary file (%s, %s)\n"
name1 pkg1 pkg2;
exit 1
)
else if ft1.ft_ghost then
(name2, ft2, pkg2)
else
(name1, ft1, pkg1)
in
let rec loop = function
| [] -> []
| (name1, _, _ as f1) :: (name2, _, _ as f2) :: fs when name1 = name2 ->
let f = combine f1 f2 in loop (f :: fs)
| f :: fs -> f :: loop fs
in
loop files in
(* Ignore %ghost non-regular files. RPMs in Fedora 20 contain these.
* It's not clear what they are meant to signify. XXX
*)
let files = List.filter (
function
| name, { ft_dir = false; ft_ghost = true; ft_mode = mode }, pkg ->
if (mode land 0o170_000) = 0o100_000 then
true
else (
debug "ignoring ghost non-regular file %s (mode 0%o) from package %s"
name mode pkg;
false
)
| _ -> true
) files in
(* Because we may have excluded some packages, and also because of
* distribution packaging errors, it's not necessarily true that a
* directory is created before each file in that directory.
* Determine those missing directories and add them now.
*)
let files =
let insert_dir, dir_seen =
let h = Hashtbl.create (List.length files) in
let insert_dir dir = Hashtbl.replace h dir true in
let dir_seen dir = Hashtbl.mem h dir in
insert_dir, dir_seen
in
let files =
List.map (
fun (path, { ft_dir = is_dir }, _ as f) ->
if is_dir then
insert_dir path;
let rec loop path =
let parent = Filename.dirname path in
if dir_seen parent then []
else (
insert_dir parent;
let newdir = (parent, { ft_dir = true; ft_config = false;
ft_ghost = false; ft_mode = 0o40755;
ft_size = 0 },
"") in
newdir :: loop parent
)
in
List.rev (f :: loop path)
) files in
List.flatten files in
(* Debugging. *)
debug "%d files and directories" (List.length files);
if false then (
List.iter (
fun (name, { ft_dir = dir; ft_ghost = ghost; ft_config = config;
ft_mode = mode; ft_size = size }, pkg) ->
printf "%s [%s%s%s%o %d] from %s\n" name
(if dir then "dir " else "")
(if ghost then "ghost " else "")
(if config then "config " else "")
mode size
pkg
) files
);
(* Split the list of files into ones for hostfiles and ones for base image. *)
let p_hmac = Str.regexp "^\\..*\\.hmac$" in
let hostfiles = ref []
and baseimgfiles = ref [] in
List.iter (
fun (path, {ft_dir = dir; ft_ghost = ghost; ft_config = config} ,_ as f) ->
let file = Filename.basename path in
(* Ignore boot files, kernel, kernel modules. Supermin appliances
* are booted from external kernel and initrd, and
* supermin-helper copies the host kernel modules.
* Note we want to keep the /boot and /lib/modules directory entries.
*)
if string_prefix "/boot/" path then ()
else if string_prefix "/lib/modules/" path then ()
(* Always write directory names to both output files. *)
else if dir then (
hostfiles := f :: !hostfiles;
baseimgfiles := f :: !baseimgfiles;
)
(* Timezone configuration is config, but copy it from host system. *)
else if path = "/etc/localtime" then
hostfiles := f :: !hostfiles
(* Ignore FIPS files (.*.hmac) (RHBZ#654638). *)
else if Str.string_match p_hmac file 0 then ()
(* Ghost files are created empty in the base image. *)
else if ghost then
baseimgfiles := f :: !baseimgfiles
(* For config files we can't rely on the host-installed copy
* since the admin may have modified then. We have to get the
* original file from the package and put it in the base image.
*)
else if config then
baseimgfiles := f :: !baseimgfiles
(* Anything else comes from the host. *)
else
hostfiles := f :: !hostfiles
) files;
let hostfiles = List.rev !hostfiles
and baseimgfiles = List.rev !baseimgfiles in
(* Write hostfiles. *)
(* Regexps used below. *)
let p_ld_so = Str.regexp "^ld-[.0-9]+\\.so$" in
let p_libbfd = Str.regexp "^libbfd-.*\\.so$" in
let p_libgcc = Str.regexp "^libgcc_s-.*\\.so\\.\\([0-9]+\\)$" in
let p_libntfs3g = Str.regexp "^libntfs-3g\\.so\\..*$" in
let p_lib123so = Str.regexp "^lib\\(.*\\)-[-.0-9]+\\.so$" in
let p_lib123so123 =
Str.regexp "^lib\\(.*\\)-[-.0-9]+\\.so\\.\\([0-9]+\\)\\." in
let p_libso123 = Str.regexp "^lib\\(.*\\)\\.so\\.\\([0-9]+\\)\\." in
let ntfs3g_once = ref false in
let chan = open_out (tmpdir // "hostfiles") in
List.iter (
fun (path, {ft_dir = is_dir; ft_ghost = ghost; ft_config = config;
ft_mode = mode }, _) ->
let dir = Filename.dirname path in
let file = Filename.basename path in
if is_dir then
fprintf chan "%s\n" path
(* Warn about hostfiles which are unreadable by non-root. We
* won't be able to add those to the appliance at run time, but
* there's not much else we can do about it except get the
* distros to fix this nonsense.
*)
else if mode land 0o004 = 0 then
warn_unreadable := path :: !warn_unreadable
(* Replace fixed numbers in some library names by wildcards. *)
else if Str.string_match p_ld_so file 0 then
fprintf chan "%s/ld-*.so\n" dir
(* Special case for libbfd. *)
else if Str.string_match p_libbfd file 0 then
fprintf chan "%s/libbfd-*.so\n" dir
(* Special case for libgcc_s--.so.N *)
else if Str.string_match p_libgcc file 0 then
fprintf chan "%s/libgcc_s-*.so.%s\n" dir (Str.matched_group 1 file)
(* Special case for libntfs-3g.so.* *)
else if Str.string_match p_libntfs3g file 0 then (
if not !ntfs3g_once then (
fprintf chan "%s/libntfs-3g.so.*\n" dir;
ntfs3g_once := true
)
)
(* libfoo-1.2.3.so *)
else if Str.string_match p_lib123so file 0 then
fprintf chan "%s/lib%s-*.so\n" dir (Str.matched_group 1 file)
(* libfoo-1.2.3.so.123 (but NOT '*.so.N') *)
else if Str.string_match p_lib123so123 file 0 then
fprintf chan "%s/lib%s-*.so.%s.*\n" dir
(Str.matched_group 1 file) (Str.matched_group 2 file)
(* libfoo.so.1.2.3 (but NOT '*.so.N') *)
else if Str.string_match p_libso123 file 0 then
fprintf chan "%s/lib%s.so.%s.*\n" dir
(Str.matched_group 1 file) (Str.matched_group 2 file)
(* Anything else comes from the host. *)
else
fprintf chan "%s\n" path
) hostfiles;
close_out chan;
(* Write base.img.
*
* We have to create directories and copy files to tmpdir/root
* and then call out to cpio to construct the initrd.
*)
let rootdir = tmpdir // "root" in
mkdir rootdir 0o755;
List.iter (
fun (path, { ft_dir = is_dir; ft_ghost = ghost; ft_config = config;
ft_mode = mode }, pkg) ->
(* Always write directory names to both output files. *)
if is_dir then (
(* Directory permissions are fixed up below. *)
if path <> "/" then mkdir (rootdir // path) 0o755
)
(* Ghost files are just touched with the correct perms. *)
else if ghost then (
let chan = open_out (rootdir // path) in
close_out chan;
chmod (rootdir // path) (mode land 0o777 lor 0o400)
)
(* For config files we can't rely on the host-installed copy
* since the admin may have modified it. We have to get the
* original file from the package.
*)
else if config then (
let outfile = ph.ph_get_file_from_package pkg path in
(* Note that the output config file might not be a regular file. *)
let statbuf = lstat outfile in
let destfile = rootdir // path in
(* Depending on the file type, copy it to destination. *)
match statbuf.st_kind with
| S_REG ->
(* Unreadable files (eg. /etc/gshadow). Make readable. *)
if statbuf.st_perm = 0 then chmod outfile 0o400;
let cmd =
sprintf "cp %s %s"
(Filename.quote outfile) (Filename.quote destfile) in
run_command cmd;
chmod destfile (mode land 0o777 lor 0o400)
| S_LNK ->
let link = readlink outfile in
symlink link destfile
| S_DIR -> assert false
| S_CHR
| S_BLK
| S_FIFO
| S_SOCK ->
eprintf "supermin: error: %s: don't know how to handle this type of file\n" path;
exit 1
)
else
assert false (* should not be reached *)
) baseimgfiles;
(* Fix up directory permissions, in reverse order. Since we don't
* want to have a read-only directory that we can't write into above.
*)
List.iter (
fun (path, { ft_dir = is_dir; ft_mode = mode }, _) ->
if is_dir then chmod (rootdir // path) (mode land 0o3777 lor 0o700)
) (List.rev baseimgfiles);
(* Construct the 'base.img' initramfs. Feed in the list of filenames
* partly because we conveniently have them, and partly because
* this results in a nice alphabetical ordering in the cpio file.
*)
(*let cmd = sprintf "ls -lR %s" rootdir in
ignore (Sys.command cmd);*)
let cmd =
sprintf "(cd %s && cpio --quiet -o -0 -H newc) > %s"
rootdir (tmpdir // "base.img") in
let chan = open_process_out cmd in
List.iter (fun (path, _, _) -> fprintf chan ".%s\000" path) baseimgfiles;
let stat = close_process_out chan in
(match stat with
| WEXITED 0 -> ()
| WEXITED i ->
eprintf "supermin: command '%s' failed (returned %d), see earlier error messages\n" cmd i;
exit i
| WSIGNALED i ->
eprintf "supermin: command '%s' killed by signal %d" cmd i;
exit 1
| WSTOPPED i ->
eprintf "supermin: command '%s' stopped by signal %d" cmd i;
exit 1
);
(* Undo directory permissions, because rm -rf can't delete files in
* unreadable directories.
*)
List.iter (
fun (path, { ft_dir = is_dir; ft_mode = mode }, _) ->
if is_dir then chmod (rootdir // path) 0o755
) (List.rev baseimgfiles);
(* Print warnings. *)
if warnings then (
(match !warn_unreadable with
| [] -> ()
| paths ->
eprintf "supermin: warning: some host files are unreadable by non-root\n";
eprintf "supermin: warning: get your distro to fix these files:\n";
List.iter
(fun path -> eprintf "\t%s\n%!" path)
(List.sort compare paths)
);
);
(* Near-atomically copy files to the final output directory. *)
debug "writing %s ..." (outputdir // "base.img");
let cmd =
sprintf "mv %s %s"
(Filename.quote (tmpdir // "base.img"))
(Filename.quote (outputdir // "base.img")) in
run_command cmd;
debug "writing %s ..." (outputdir // "hostfiles");
let cmd =
sprintf "mv %s %s"
(Filename.quote (tmpdir // "hostfiles"))
(Filename.quote (outputdir // "hostfiles")) in
run_command cmd
supermin-4.1.6/src/Makefile.in 0000664 0001750 0001750 00000142167 12255775676 013204 0000000 0000000 # Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in 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.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# supermin Makefile.am
# (C) Copyright 2009-2013 Red Hat 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 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Written by Richard W.M. Jones
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@HAVE_OCAML_INIFILES_TRUE@am__append_1 = \
@HAVE_OCAML_INIFILES_TRUE@ supermin_zypp_rpm.ml
@HAVE_OCAML_INIFILES_TRUE@am__append_2 = \
@HAVE_OCAML_INIFILES_TRUE@ supermin_zypp_rpm.ml
@HAVE_OCAML_INIFILES_TRUE@am__append_3 = -package inifiles
subdir = src
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/config.ml.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
$(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/chdir-long.m4 \
$(top_srcdir)/m4/close.m4 $(top_srcdir)/m4/closedir.m4 \
$(top_srcdir)/m4/cycle-check.m4 $(top_srcdir)/m4/d-ino.m4 \
$(top_srcdir)/m4/d-type.m4 $(top_srcdir)/m4/dirent-safer.m4 \
$(top_srcdir)/m4/dirent_h.m4 $(top_srcdir)/m4/dirfd.m4 \
$(top_srcdir)/m4/dirname.m4 \
$(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup.m4 \
$(top_srcdir)/m4/dup2.m4 $(top_srcdir)/m4/errno_h.m4 \
$(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exponentd.m4 \
$(top_srcdir)/m4/extensions.m4 \
$(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \
$(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl-safer.m4 \
$(top_srcdir)/m4/fcntl.m4 $(top_srcdir)/m4/fcntl_h.m4 \
$(top_srcdir)/m4/fdopendir.m4 $(top_srcdir)/m4/filenamecat.m4 \
$(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fstat.m4 \
$(top_srcdir)/m4/fts.m4 $(top_srcdir)/m4/getcwd.m4 \
$(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getopt.m4 \
$(top_srcdir)/m4/gnulib-common.m4 \
$(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/i-ring.m4 \
$(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/intmax_t.m4 \
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
$(top_srcdir)/m4/largefile.m4 $(top_srcdir)/m4/longlong.m4 \
$(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/malloc.m4 \
$(top_srcdir)/m4/memchr.m4 $(top_srcdir)/m4/mempcpy.m4 \
$(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mmap-anon.m4 \
$(top_srcdir)/m4/mode_t.m4 $(top_srcdir)/m4/msvc-inval.m4 \
$(top_srcdir)/m4/msvc-nothrow.m4 $(top_srcdir)/m4/multiarch.m4 \
$(top_srcdir)/m4/nocrash.m4 $(top_srcdir)/m4/ocaml.m4 \
$(top_srcdir)/m4/off_t.m4 $(top_srcdir)/m4/onceonly.m4 \
$(top_srcdir)/m4/open.m4 $(top_srcdir)/m4/openat.m4 \
$(top_srcdir)/m4/opendir.m4 $(top_srcdir)/m4/pathmax.m4 \
$(top_srcdir)/m4/printf.m4 $(top_srcdir)/m4/raise.m4 \
$(top_srcdir)/m4/readdir.m4 $(top_srcdir)/m4/realloc.m4 \
$(top_srcdir)/m4/safe-read.m4 $(top_srcdir)/m4/safe-write.m4 \
$(top_srcdir)/m4/save-cwd.m4 $(top_srcdir)/m4/signal_h.m4 \
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/ssize_t.m4 \
$(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdarg.m4 \
$(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \
$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \
$(top_srcdir)/m4/strdup.m4 $(top_srcdir)/m4/strerror.m4 \
$(top_srcdir)/m4/string_h.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
$(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_types_h.m4 \
$(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/unistd-safer.m4 \
$(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/vasnprintf.m4 \
$(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/warn-on-use.m4 \
$(top_srcdir)/m4/wchar_h.m4 $(top_srcdir)/m4/wchar_t.m4 \
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/write.m4 \
$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xsize.m4 \
$(top_srcdir)/m4/xstrtol.m4 $(top_srcdir)/m4/xvasprintf.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = config.ml
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
SCRIPTS = $(bin_SCRIPTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
man1dir = $(mandir)/man1
NROFF = nroff
MANS = $(man_MANS)
DATA = $(noinst_DATA)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
ALLOCA_H = @ALLOCA_H@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
APTITUDE = @APTITUDE@
APT_CACHE = @APT_CACHE@
APT_CACHE_DEPENDS_RECURSE_BROKEN = @APT_CACHE_DEPENDS_RECURSE_BROKEN@
AR = @AR@
ARFLAGS = @ARFLAGS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@
BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@
BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
COM_ERR_CFLAGS = @COM_ERR_CFLAGS@
COM_ERR_LIBS = @COM_ERR_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DPKG = @DPKG@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
EMULTIHOP_VALUE = @EMULTIHOP_VALUE@
ENOLINK_HIDDEN = @ENOLINK_HIDDEN@
ENOLINK_VALUE = @ENOLINK_VALUE@
EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
ERRNO_H = @ERRNO_H@
EXEEXT = @EXEEXT@
EXT2FS_CFLAGS = @EXT2FS_CFLAGS@
EXT2FS_LIBS = @EXT2FS_LIBS@
FLOAT_H = @FLOAT_H@
GAWK = @GAWK@
GETOPT_H = @GETOPT_H@
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
GNULIB_ATOLL = @GNULIB_ATOLL@
GNULIB_BTOWC = @GNULIB_BTOWC@
GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@
GNULIB_CHDIR = @GNULIB_CHDIR@
GNULIB_CHOWN = @GNULIB_CHOWN@
GNULIB_CLOSE = @GNULIB_CLOSE@
GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@
GNULIB_DIRFD = @GNULIB_DIRFD@
GNULIB_DPRINTF = @GNULIB_DPRINTF@
GNULIB_DUP = @GNULIB_DUP@
GNULIB_DUP2 = @GNULIB_DUP2@
GNULIB_DUP3 = @GNULIB_DUP3@
GNULIB_ENVIRON = @GNULIB_ENVIRON@
GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
GNULIB_FACCESSAT = @GNULIB_FACCESSAT@
GNULIB_FCHDIR = @GNULIB_FCHDIR@
GNULIB_FCHMODAT = @GNULIB_FCHMODAT@
GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@
GNULIB_FCLOSE = @GNULIB_FCLOSE@
GNULIB_FCNTL = @GNULIB_FCNTL@
GNULIB_FDATASYNC = @GNULIB_FDATASYNC@
GNULIB_FDOPEN = @GNULIB_FDOPEN@
GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@
GNULIB_FFLUSH = @GNULIB_FFLUSH@
GNULIB_FFSL = @GNULIB_FFSL@
GNULIB_FFSLL = @GNULIB_FFSLL@
GNULIB_FGETC = @GNULIB_FGETC@
GNULIB_FGETS = @GNULIB_FGETS@
GNULIB_FOPEN = @GNULIB_FOPEN@
GNULIB_FPRINTF = @GNULIB_FPRINTF@
GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
GNULIB_FPURGE = @GNULIB_FPURGE@
GNULIB_FPUTC = @GNULIB_FPUTC@
GNULIB_FPUTS = @GNULIB_FPUTS@
GNULIB_FREAD = @GNULIB_FREAD@
GNULIB_FREOPEN = @GNULIB_FREOPEN@
GNULIB_FSCANF = @GNULIB_FSCANF@
GNULIB_FSEEK = @GNULIB_FSEEK@
GNULIB_FSEEKO = @GNULIB_FSEEKO@
GNULIB_FSTAT = @GNULIB_FSTAT@
GNULIB_FSTATAT = @GNULIB_FSTATAT@
GNULIB_FSYNC = @GNULIB_FSYNC@
GNULIB_FTELL = @GNULIB_FTELL@
GNULIB_FTELLO = @GNULIB_FTELLO@
GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
GNULIB_FUTIMENS = @GNULIB_FUTIMENS@
GNULIB_FWRITE = @GNULIB_FWRITE@
GNULIB_GETC = @GNULIB_GETC@
GNULIB_GETCHAR = @GNULIB_GETCHAR@
GNULIB_GETCWD = @GNULIB_GETCWD@
GNULIB_GETDELIM = @GNULIB_GETDELIM@
GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
GNULIB_GETGROUPS = @GNULIB_GETGROUPS@
GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
GNULIB_GETLINE = @GNULIB_GETLINE@
GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
GNULIB_GETLOGIN = @GNULIB_GETLOGIN@
GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@
GNULIB_GRANTPT = @GNULIB_GRANTPT@
GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@
GNULIB_IMAXABS = @GNULIB_IMAXABS@
GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
GNULIB_ISATTY = @GNULIB_ISATTY@
GNULIB_LCHMOD = @GNULIB_LCHMOD@
GNULIB_LCHOWN = @GNULIB_LCHOWN@
GNULIB_LINK = @GNULIB_LINK@
GNULIB_LINKAT = @GNULIB_LINKAT@
GNULIB_LSEEK = @GNULIB_LSEEK@
GNULIB_LSTAT = @GNULIB_LSTAT@
GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
GNULIB_MBRLEN = @GNULIB_MBRLEN@
GNULIB_MBRTOWC = @GNULIB_MBRTOWC@
GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
GNULIB_MBSCHR = @GNULIB_MBSCHR@
GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
GNULIB_MBSINIT = @GNULIB_MBSINIT@
GNULIB_MBSLEN = @GNULIB_MBSLEN@
GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@
GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@
GNULIB_MBSSEP = @GNULIB_MBSSEP@
GNULIB_MBSSPN = @GNULIB_MBSSPN@
GNULIB_MBSSTR = @GNULIB_MBSSTR@
GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
GNULIB_MBTOWC = @GNULIB_MBTOWC@
GNULIB_MEMCHR = @GNULIB_MEMCHR@
GNULIB_MEMMEM = @GNULIB_MEMMEM@
GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
GNULIB_MKDIRAT = @GNULIB_MKDIRAT@
GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
GNULIB_MKFIFO = @GNULIB_MKFIFO@
GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@
GNULIB_MKNOD = @GNULIB_MKNOD@
GNULIB_MKNODAT = @GNULIB_MKNODAT@
GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@
GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@
GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@
GNULIB_MKTIME = @GNULIB_MKTIME@
GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@
GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@
GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
GNULIB_OPEN = @GNULIB_OPEN@
GNULIB_OPENAT = @GNULIB_OPENAT@
GNULIB_OPENDIR = @GNULIB_OPENDIR@
GNULIB_PCLOSE = @GNULIB_PCLOSE@
GNULIB_PERROR = @GNULIB_PERROR@
GNULIB_PIPE = @GNULIB_PIPE@
GNULIB_PIPE2 = @GNULIB_PIPE2@
GNULIB_POPEN = @GNULIB_POPEN@
GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@
GNULIB_PREAD = @GNULIB_PREAD@
GNULIB_PRINTF = @GNULIB_PRINTF@
GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@
GNULIB_PTSNAME = @GNULIB_PTSNAME@
GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@
GNULIB_PUTC = @GNULIB_PUTC@
GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
GNULIB_PUTENV = @GNULIB_PUTENV@
GNULIB_PUTS = @GNULIB_PUTS@
GNULIB_PWRITE = @GNULIB_PWRITE@
GNULIB_RAISE = @GNULIB_RAISE@
GNULIB_RANDOM = @GNULIB_RANDOM@
GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
GNULIB_READ = @GNULIB_READ@
GNULIB_READDIR = @GNULIB_READDIR@
GNULIB_READLINK = @GNULIB_READLINK@
GNULIB_READLINKAT = @GNULIB_READLINKAT@
GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
GNULIB_REALPATH = @GNULIB_REALPATH@
GNULIB_REMOVE = @GNULIB_REMOVE@
GNULIB_RENAME = @GNULIB_RENAME@
GNULIB_RENAMEAT = @GNULIB_RENAMEAT@
GNULIB_REWINDDIR = @GNULIB_REWINDDIR@
GNULIB_RMDIR = @GNULIB_RMDIR@
GNULIB_RPMATCH = @GNULIB_RPMATCH@
GNULIB_SCANDIR = @GNULIB_SCANDIR@
GNULIB_SCANF = @GNULIB_SCANF@
GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@
GNULIB_SETENV = @GNULIB_SETENV@
GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@
GNULIB_SIGACTION = @GNULIB_SIGACTION@
GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@
GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@
GNULIB_SLEEP = @GNULIB_SLEEP@
GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
GNULIB_STAT = @GNULIB_STAT@
GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@
GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
GNULIB_STPCPY = @GNULIB_STPCPY@
GNULIB_STPNCPY = @GNULIB_STPNCPY@
GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
GNULIB_STRDUP = @GNULIB_STRDUP@
GNULIB_STRERROR = @GNULIB_STRERROR@
GNULIB_STRERROR_R = @GNULIB_STRERROR_R@
GNULIB_STRNCAT = @GNULIB_STRNCAT@
GNULIB_STRNDUP = @GNULIB_STRNDUP@
GNULIB_STRNLEN = @GNULIB_STRNLEN@
GNULIB_STRPBRK = @GNULIB_STRPBRK@
GNULIB_STRPTIME = @GNULIB_STRPTIME@
GNULIB_STRSEP = @GNULIB_STRSEP@
GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
GNULIB_STRSTR = @GNULIB_STRSTR@
GNULIB_STRTOD = @GNULIB_STRTOD@
GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
GNULIB_STRTOLL = @GNULIB_STRTOLL@
GNULIB_STRTOULL = @GNULIB_STRTOULL@
GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
GNULIB_SYMLINK = @GNULIB_SYMLINK@
GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@
GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@
GNULIB_TIMEGM = @GNULIB_TIMEGM@
GNULIB_TIME_R = @GNULIB_TIME_R@
GNULIB_TMPFILE = @GNULIB_TMPFILE@
GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@
GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@
GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
GNULIB_UNLINK = @GNULIB_UNLINK@
GNULIB_UNLINKAT = @GNULIB_UNLINKAT@
GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@
GNULIB_UNSETENV = @GNULIB_UNSETENV@
GNULIB_USLEEP = @GNULIB_USLEEP@
GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@
GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
GNULIB_VFSCANF = @GNULIB_VFSCANF@
GNULIB_VPRINTF = @GNULIB_VPRINTF@
GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
GNULIB_VSCANF = @GNULIB_VSCANF@
GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
GNULIB_WCPCPY = @GNULIB_WCPCPY@
GNULIB_WCPNCPY = @GNULIB_WCPNCPY@
GNULIB_WCRTOMB = @GNULIB_WCRTOMB@
GNULIB_WCSCASECMP = @GNULIB_WCSCASECMP@
GNULIB_WCSCAT = @GNULIB_WCSCAT@
GNULIB_WCSCHR = @GNULIB_WCSCHR@
GNULIB_WCSCMP = @GNULIB_WCSCMP@
GNULIB_WCSCOLL = @GNULIB_WCSCOLL@
GNULIB_WCSCPY = @GNULIB_WCSCPY@
GNULIB_WCSCSPN = @GNULIB_WCSCSPN@
GNULIB_WCSDUP = @GNULIB_WCSDUP@
GNULIB_WCSLEN = @GNULIB_WCSLEN@
GNULIB_WCSNCASECMP = @GNULIB_WCSNCASECMP@
GNULIB_WCSNCAT = @GNULIB_WCSNCAT@
GNULIB_WCSNCMP = @GNULIB_WCSNCMP@
GNULIB_WCSNCPY = @GNULIB_WCSNCPY@
GNULIB_WCSNLEN = @GNULIB_WCSNLEN@
GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@
GNULIB_WCSPBRK = @GNULIB_WCSPBRK@
GNULIB_WCSRCHR = @GNULIB_WCSRCHR@
GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@
GNULIB_WCSSPN = @GNULIB_WCSSPN@
GNULIB_WCSSTR = @GNULIB_WCSSTR@
GNULIB_WCSTOK = @GNULIB_WCSTOK@
GNULIB_WCSWIDTH = @GNULIB_WCSWIDTH@
GNULIB_WCSXFRM = @GNULIB_WCSXFRM@
GNULIB_WCTOB = @GNULIB_WCTOB@
GNULIB_WCTOMB = @GNULIB_WCTOMB@
GNULIB_WCWIDTH = @GNULIB_WCWIDTH@
GNULIB_WMEMCHR = @GNULIB_WMEMCHR@
GNULIB_WMEMCMP = @GNULIB_WMEMCMP@
GNULIB_WMEMCPY = @GNULIB_WMEMCPY@
GNULIB_WMEMMOVE = @GNULIB_WMEMMOVE@
GNULIB_WMEMSET = @GNULIB_WMEMSET@
GNULIB_WRITE = @GNULIB_WRITE@
GNULIB__EXIT = @GNULIB__EXIT@
GREP = @GREP@
HAVE_ALPHASORT = @HAVE_ALPHASORT@
HAVE_ATOLL = @HAVE_ATOLL@
HAVE_BTOWC = @HAVE_BTOWC@
HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@
HAVE_CHOWN = @HAVE_CHOWN@
HAVE_CLOSEDIR = @HAVE_CLOSEDIR@
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@
HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@
HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@
HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@
HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@
HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@
HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@
HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@
HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@
HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@
HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@
HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@
HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@
HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
HAVE_DECL_SETENV = @HAVE_DECL_SETENV@
HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@
HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@
HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@
HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@
HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@
HAVE_DIRENT_H = @HAVE_DIRENT_H@
HAVE_DPRINTF = @HAVE_DPRINTF@
HAVE_DUP2 = @HAVE_DUP2@
HAVE_DUP3 = @HAVE_DUP3@
HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
HAVE_FACCESSAT = @HAVE_FACCESSAT@
HAVE_FCHDIR = @HAVE_FCHDIR@
HAVE_FCHMODAT = @HAVE_FCHMODAT@
HAVE_FCHOWNAT = @HAVE_FCHOWNAT@
HAVE_FCNTL = @HAVE_FCNTL@
HAVE_FDATASYNC = @HAVE_FDATASYNC@
HAVE_FDOPENDIR = @HAVE_FDOPENDIR@
HAVE_FEATURES_H = @HAVE_FEATURES_H@
HAVE_FFSL = @HAVE_FFSL@
HAVE_FFSLL = @HAVE_FFSLL@
HAVE_FSEEKO = @HAVE_FSEEKO@
HAVE_FSTATAT = @HAVE_FSTATAT@
HAVE_FSYNC = @HAVE_FSYNC@
HAVE_FTELLO = @HAVE_FTELLO@
HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
HAVE_FUTIMENS = @HAVE_FUTIMENS@
HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
HAVE_GETGROUPS = @HAVE_GETGROUPS@
HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
HAVE_GETLOGIN = @HAVE_GETLOGIN@
HAVE_GETOPT_H = @HAVE_GETOPT_H@
HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
HAVE_GRANTPT = @HAVE_GRANTPT@
HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
HAVE_LCHMOD = @HAVE_LCHMOD@
HAVE_LCHOWN = @HAVE_LCHOWN@
HAVE_LINK = @HAVE_LINK@
HAVE_LINKAT = @HAVE_LINKAT@
HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
HAVE_LSTAT = @HAVE_LSTAT@
HAVE_MBRLEN = @HAVE_MBRLEN@
HAVE_MBRTOWC = @HAVE_MBRTOWC@
HAVE_MBSINIT = @HAVE_MBSINIT@
HAVE_MBSLEN = @HAVE_MBSLEN@
HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@
HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@
HAVE_MEMCHR = @HAVE_MEMCHR@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
HAVE_MKDIRAT = @HAVE_MKDIRAT@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
HAVE_MKFIFO = @HAVE_MKFIFO@
HAVE_MKFIFOAT = @HAVE_MKFIFOAT@
HAVE_MKNOD = @HAVE_MKNOD@
HAVE_MKNODAT = @HAVE_MKNODAT@
HAVE_MKOSTEMP = @HAVE_MKOSTEMP@
HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@
HAVE_MKSTEMP = @HAVE_MKSTEMP@
HAVE_MKSTEMPS = @HAVE_MKSTEMPS@
HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@
HAVE_NANOSLEEP = @HAVE_NANOSLEEP@
HAVE_OPENAT = @HAVE_OPENAT@
HAVE_OPENDIR = @HAVE_OPENDIR@
HAVE_OS_H = @HAVE_OS_H@
HAVE_PCLOSE = @HAVE_PCLOSE@
HAVE_PIPE = @HAVE_PIPE@
HAVE_PIPE2 = @HAVE_PIPE2@
HAVE_POPEN = @HAVE_POPEN@
HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@
HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@
HAVE_PREAD = @HAVE_PREAD@
HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@
HAVE_PTSNAME = @HAVE_PTSNAME@
HAVE_PTSNAME_R = @HAVE_PTSNAME_R@
HAVE_PWRITE = @HAVE_PWRITE@
HAVE_RAISE = @HAVE_RAISE@
HAVE_RANDOM = @HAVE_RANDOM@
HAVE_RANDOM_H = @HAVE_RANDOM_H@
HAVE_RANDOM_R = @HAVE_RANDOM_R@
HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@
HAVE_READDIR = @HAVE_READDIR@
HAVE_READLINK = @HAVE_READLINK@
HAVE_READLINKAT = @HAVE_READLINKAT@
HAVE_REALPATH = @HAVE_REALPATH@
HAVE_RENAMEAT = @HAVE_RENAMEAT@
HAVE_REWINDDIR = @HAVE_REWINDDIR@
HAVE_RPMATCH = @HAVE_RPMATCH@
HAVE_SCANDIR = @HAVE_SCANDIR@
HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@
HAVE_SETENV = @HAVE_SETENV@
HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@
HAVE_SIGACTION = @HAVE_SIGACTION@
HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@
HAVE_SIGINFO_T = @HAVE_SIGINFO_T@
HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
HAVE_SIGSET_T = @HAVE_SIGSET_T@
HAVE_SLEEP = @HAVE_SLEEP@
HAVE_STDINT_H = @HAVE_STDINT_H@
HAVE_STPCPY = @HAVE_STPCPY@
HAVE_STPNCPY = @HAVE_STPNCPY@
HAVE_STRCASESTR = @HAVE_STRCASESTR@
HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
HAVE_STRPBRK = @HAVE_STRPBRK@
HAVE_STRPTIME = @HAVE_STRPTIME@
HAVE_STRSEP = @HAVE_STRSEP@
HAVE_STRTOD = @HAVE_STRTOD@
HAVE_STRTOLL = @HAVE_STRTOLL@
HAVE_STRTOULL = @HAVE_STRTOULL@
HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@
HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
HAVE_SYMLINK = @HAVE_SYMLINK@
HAVE_SYMLINKAT = @HAVE_SYMLINKAT@
HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
HAVE_TIMEGM = @HAVE_TIMEGM@
HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@
HAVE_UNISTD_H = @HAVE_UNISTD_H@
HAVE_UNLINKAT = @HAVE_UNLINKAT@
HAVE_UNLOCKPT = @HAVE_UNLOCKPT@
HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
HAVE_USLEEP = @HAVE_USLEEP@
HAVE_UTIMENSAT = @HAVE_UTIMENSAT@
HAVE_VASPRINTF = @HAVE_VASPRINTF@
HAVE_VDPRINTF = @HAVE_VDPRINTF@
HAVE_WCHAR_H = @HAVE_WCHAR_H@
HAVE_WCHAR_T = @HAVE_WCHAR_T@
HAVE_WCPCPY = @HAVE_WCPCPY@
HAVE_WCPNCPY = @HAVE_WCPNCPY@
HAVE_WCRTOMB = @HAVE_WCRTOMB@
HAVE_WCSCASECMP = @HAVE_WCSCASECMP@
HAVE_WCSCAT = @HAVE_WCSCAT@
HAVE_WCSCHR = @HAVE_WCSCHR@
HAVE_WCSCMP = @HAVE_WCSCMP@
HAVE_WCSCOLL = @HAVE_WCSCOLL@
HAVE_WCSCPY = @HAVE_WCSCPY@
HAVE_WCSCSPN = @HAVE_WCSCSPN@
HAVE_WCSDUP = @HAVE_WCSDUP@
HAVE_WCSLEN = @HAVE_WCSLEN@
HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@
HAVE_WCSNCAT = @HAVE_WCSNCAT@
HAVE_WCSNCMP = @HAVE_WCSNCMP@
HAVE_WCSNCPY = @HAVE_WCSNCPY@
HAVE_WCSNLEN = @HAVE_WCSNLEN@
HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@
HAVE_WCSPBRK = @HAVE_WCSPBRK@
HAVE_WCSRCHR = @HAVE_WCSRCHR@
HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@
HAVE_WCSSPN = @HAVE_WCSSPN@
HAVE_WCSSTR = @HAVE_WCSSTR@
HAVE_WCSTOK = @HAVE_WCSTOK@
HAVE_WCSWIDTH = @HAVE_WCSWIDTH@
HAVE_WCSXFRM = @HAVE_WCSXFRM@
HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
HAVE_WINT_T = @HAVE_WINT_T@
HAVE_WMEMCHR = @HAVE_WMEMCHR@
HAVE_WMEMCMP = @HAVE_WMEMCMP@
HAVE_WMEMCPY = @HAVE_WMEMCPY@
HAVE_WMEMMOVE = @HAVE_WMEMMOVE@
HAVE_WMEMSET = @HAVE_WMEMSET@
HAVE__BOOL = @HAVE__BOOL@
HAVE__EXIT = @HAVE__EXIT@
INCLUDE_NEXT = @INCLUDE_NEXT@
INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@
INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@
LDFLAGS = @LDFLAGS@
LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
LZMA_STATIC_LIBS = @LZMA_STATIC_LIBS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MKE2FS = @MKE2FS@
NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@
NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@
NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@
NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@
NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@
NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@
NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@
NEXT_AS_FIRST_DIRECTIVE_STDARG_H = @NEXT_AS_FIRST_DIRECTIVE_STDARG_H@
NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@
NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@
NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@
NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@
NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@
NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@
NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@
NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@
NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@
NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@
NEXT_DIRENT_H = @NEXT_DIRENT_H@
NEXT_ERRNO_H = @NEXT_ERRNO_H@
NEXT_FCNTL_H = @NEXT_FCNTL_H@
NEXT_FLOAT_H = @NEXT_FLOAT_H@
NEXT_GETOPT_H = @NEXT_GETOPT_H@
NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
NEXT_SIGNAL_H = @NEXT_SIGNAL_H@
NEXT_STDARG_H = @NEXT_STDARG_H@
NEXT_STDDEF_H = @NEXT_STDDEF_H@
NEXT_STDINT_H = @NEXT_STDINT_H@
NEXT_STDIO_H = @NEXT_STDIO_H@
NEXT_STDLIB_H = @NEXT_STDLIB_H@
NEXT_STRING_H = @NEXT_STRING_H@
NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@
NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@
NEXT_TIME_H = @NEXT_TIME_H@
NEXT_UNISTD_H = @NEXT_UNISTD_H@
NEXT_WCHAR_H = @NEXT_WCHAR_H@
OBJEXT = @OBJEXT@
OCAML = @OCAML@
OCAMLBEST = @OCAMLBEST@
OCAMLBUILD = @OCAMLBUILD@
OCAMLC = @OCAMLC@
OCAMLCDOTOPT = @OCAMLCDOTOPT@
OCAMLDEP = @OCAMLDEP@
OCAMLDOC = @OCAMLDOC@
OCAMLFIND = @OCAMLFIND@
OCAMLLIB = @OCAMLLIB@
OCAMLMKLIB = @OCAMLMKLIB@
OCAMLMKTOP = @OCAMLMKTOP@
OCAMLOPT = @OCAMLOPT@
OCAMLOPTDOTOPT = @OCAMLOPTDOTOPT@
OCAMLVERSION = @OCAMLVERSION@
OCAML_PKG_inifiles = @OCAML_PKG_inifiles@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PACMAN = @PACMAN@
PACMAN_G2 = @PACMAN_G2@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERLDOC = @PERLDOC@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PRAGMA_COLUMNS = @PRAGMA_COLUMNS@
PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
PRIPTR_PREFIX = @PRIPTR_PREFIX@
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@
PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
RANLIB = @RANLIB@
REPLACE_BTOWC = @REPLACE_BTOWC@
REPLACE_CALLOC = @REPLACE_CALLOC@
REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
REPLACE_CHOWN = @REPLACE_CHOWN@
REPLACE_CLOSE = @REPLACE_CLOSE@
REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@
REPLACE_DIRFD = @REPLACE_DIRFD@
REPLACE_DPRINTF = @REPLACE_DPRINTF@
REPLACE_DUP = @REPLACE_DUP@
REPLACE_DUP2 = @REPLACE_DUP2@
REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
REPLACE_FCLOSE = @REPLACE_FCLOSE@
REPLACE_FCNTL = @REPLACE_FCNTL@
REPLACE_FDOPEN = @REPLACE_FDOPEN@
REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@
REPLACE_FFLUSH = @REPLACE_FFLUSH@
REPLACE_FOPEN = @REPLACE_FOPEN@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
REPLACE_FPURGE = @REPLACE_FPURGE@
REPLACE_FREOPEN = @REPLACE_FREOPEN@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
REPLACE_FSTAT = @REPLACE_FSTAT@
REPLACE_FSTATAT = @REPLACE_FSTATAT@
REPLACE_FTELL = @REPLACE_FTELL@
REPLACE_FTELLO = @REPLACE_FTELLO@
REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@
REPLACE_FUTIMENS = @REPLACE_FUTIMENS@
REPLACE_GETCWD = @REPLACE_GETCWD@
REPLACE_GETDELIM = @REPLACE_GETDELIM@
REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@
REPLACE_GETGROUPS = @REPLACE_GETGROUPS@
REPLACE_GETLINE = @REPLACE_GETLINE@
REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@
REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
REPLACE_ISATTY = @REPLACE_ISATTY@
REPLACE_ITOLD = @REPLACE_ITOLD@
REPLACE_LCHOWN = @REPLACE_LCHOWN@
REPLACE_LINK = @REPLACE_LINK@
REPLACE_LINKAT = @REPLACE_LINKAT@
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
REPLACE_LSEEK = @REPLACE_LSEEK@
REPLACE_LSTAT = @REPLACE_LSTAT@
REPLACE_MALLOC = @REPLACE_MALLOC@
REPLACE_MBRLEN = @REPLACE_MBRLEN@
REPLACE_MBRTOWC = @REPLACE_MBRTOWC@
REPLACE_MBSINIT = @REPLACE_MBSINIT@
REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@
REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@
REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@
REPLACE_MBTOWC = @REPLACE_MBTOWC@
REPLACE_MEMCHR = @REPLACE_MEMCHR@
REPLACE_MEMMEM = @REPLACE_MEMMEM@
REPLACE_MKDIR = @REPLACE_MKDIR@
REPLACE_MKFIFO = @REPLACE_MKFIFO@
REPLACE_MKNOD = @REPLACE_MKNOD@
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
REPLACE_MKTIME = @REPLACE_MKTIME@
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
REPLACE_NULL = @REPLACE_NULL@
REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@
REPLACE_OPEN = @REPLACE_OPEN@
REPLACE_OPENAT = @REPLACE_OPENAT@
REPLACE_OPENDIR = @REPLACE_OPENDIR@
REPLACE_PERROR = @REPLACE_PERROR@
REPLACE_POPEN = @REPLACE_POPEN@
REPLACE_PREAD = @REPLACE_PREAD@
REPLACE_PRINTF = @REPLACE_PRINTF@
REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@
REPLACE_PTSNAME = @REPLACE_PTSNAME@
REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@
REPLACE_PUTENV = @REPLACE_PUTENV@
REPLACE_PWRITE = @REPLACE_PWRITE@
REPLACE_RAISE = @REPLACE_RAISE@
REPLACE_RANDOM_R = @REPLACE_RANDOM_R@
REPLACE_READ = @REPLACE_READ@
REPLACE_READLINK = @REPLACE_READLINK@
REPLACE_REALLOC = @REPLACE_REALLOC@
REPLACE_REALPATH = @REPLACE_REALPATH@
REPLACE_REMOVE = @REPLACE_REMOVE@
REPLACE_RENAME = @REPLACE_RENAME@
REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
REPLACE_RMDIR = @REPLACE_RMDIR@
REPLACE_SETENV = @REPLACE_SETENV@
REPLACE_SLEEP = @REPLACE_SLEEP@
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
REPLACE_SPRINTF = @REPLACE_SPRINTF@
REPLACE_STAT = @REPLACE_STAT@
REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@
REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
REPLACE_STPNCPY = @REPLACE_STPNCPY@
REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@
REPLACE_STRDUP = @REPLACE_STRDUP@
REPLACE_STRERROR = @REPLACE_STRERROR@
REPLACE_STRERROR_R = @REPLACE_STRERROR_R@
REPLACE_STRNCAT = @REPLACE_STRNCAT@
REPLACE_STRNDUP = @REPLACE_STRNDUP@
REPLACE_STRNLEN = @REPLACE_STRNLEN@
REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
REPLACE_STRSTR = @REPLACE_STRSTR@
REPLACE_STRTOD = @REPLACE_STRTOD@
REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@
REPLACE_STRTOK_R = @REPLACE_STRTOK_R@
REPLACE_SYMLINK = @REPLACE_SYMLINK@
REPLACE_TIMEGM = @REPLACE_TIMEGM@
REPLACE_TMPFILE = @REPLACE_TMPFILE@
REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@
REPLACE_UNLINK = @REPLACE_UNLINK@
REPLACE_UNLINKAT = @REPLACE_UNLINKAT@
REPLACE_UNSETENV = @REPLACE_UNSETENV@
REPLACE_USLEEP = @REPLACE_USLEEP@
REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@
REPLACE_VASPRINTF = @REPLACE_VASPRINTF@
REPLACE_VDPRINTF = @REPLACE_VDPRINTF@
REPLACE_VFPRINTF = @REPLACE_VFPRINTF@
REPLACE_VPRINTF = @REPLACE_VPRINTF@
REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
REPLACE_WCRTOMB = @REPLACE_WCRTOMB@
REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@
REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@
REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@
REPLACE_WCTOB = @REPLACE_WCTOB@
REPLACE_WCTOMB = @REPLACE_WCTOMB@
REPLACE_WCWIDTH = @REPLACE_WCWIDTH@
REPLACE_WRITE = @REPLACE_WRITE@
RPM = @RPM@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
STDARG_H = @STDARG_H@
STDBOOL_H = @STDBOOL_H@
STDDEF_H = @STDDEF_H@
STDINT_H = @STDINT_H@
STRIP = @STRIP@
SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
URPMI = @URPMI@
VERSION = @VERSION@
WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@
WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@
WINT_T_SUFFIX = @WINT_T_SUFFIX@
YUM = @YUM@
YUMDOWNLOADER = @YUMDOWNLOADER@
ZLIB_LIBS = @ZLIB_LIBS@
ZLIB_STATIC_LIBS = @ZLIB_STATIC_LIBS@
ZYPPER = @ZYPPER@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
gltests_LIBOBJS = @gltests_LIBOBJS@
gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
gltests_WITNESS = @gltests_WITNESS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
EXTRA_DIST = \
.depend \
config.ml \
supermin.1 \
supermin.pod \
supermin.ml \
supermin_cmdline.mli \
supermin_cmdline.ml \
supermin_debian.ml \
supermin_package_handlers.mli \
supermin_package_handlers.ml \
supermin_pacman.ml \
supermin_pacman_g2.ml \
supermin_urpmi_rpm.ml \
supermin_utils.mli \
supermin_utils.ml \
supermin_yum_rpm.ml \
supermin_zypp_rpm.ml
# Note these must be in build dependency order.
SOURCES = config.ml supermin_cmdline.mli supermin_cmdline.ml \
supermin_utils.mli supermin_utils.ml \
supermin_package_handlers.mli supermin_package_handlers.ml \
$(am__append_1) supermin_yum_rpm.ml supermin_urpmi_rpm.ml \
supermin_debian.ml supermin_pacman.ml supermin_pacman_g2.ml \
supermin.ml
# Can't use filter for this because of automake brokenness.
SOURCES_ML = config.ml supermin_cmdline.ml supermin_utils.ml \
supermin_package_handlers.ml $(am__append_2) \
supermin_yum_rpm.ml supermin_urpmi_rpm.ml supermin_debian.ml \
supermin_pacman.ml supermin_pacman_g2.ml supermin.ml
CLEANFILES = *~ *.cmi *.cmo *.cmx *.o supermin
man_MANS = \
supermin.1
bin_SCRIPTS = supermin
BOBJECTS = $(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(SOURCES_ML:.ml=.cmx)
@HAVE_OCAMLOPT_FALSE@OBJECTS = $(BOBJECTS)
@HAVE_OCAMLOPT_TRUE@OBJECTS = $(XOBJECTS)
@HAVE_OCAMLOPT_FALSE@BEST = c
@HAVE_OCAMLOPT_TRUE@BEST = opt
OCAMLPACKAGES = -package unix,str $(am__append_3)
OCAMLFLAGS = -warn-error CDEFLMPSUVXYZ
SUFFIXES = .cmo .cmi .cmx .ml .mli .mll .mly
@HAVE_PERLDOC_TRUE@noinst_DATA = \
@HAVE_PERLDOC_TRUE@ ../html/supermin.1.html
all: all-am
.SUFFIXES:
.SUFFIXES: .cmo .cmi .cmx .ml .mli .mll .mly
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
config.ml: $(top_builddir)/config.status $(srcdir)/config.ml.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
install-binSCRIPTS: $(bin_SCRIPTS)
@$(NORMAL_INSTALL)
@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n' \
-e 'h;s|.*|.|' \
-e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) { files[d] = files[d] " " $$1; \
if (++n[d] == $(am__install_max)) { \
print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
else { print "f", d "/" $$4, $$1 } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binSCRIPTS:
@$(NORMAL_UNINSTALL)
@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 's,.*/,,;$(transform)'`; \
dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
install-man1: $(man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
list2='$(man_MANS)'; \
test -n "$(man1dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.1[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.1[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(SCRIPTS) $(MANS) $(DATA)
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binSCRIPTS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binSCRIPTS uninstall-man
uninstall-man: uninstall-man1
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
cscopelist-am ctags ctags-am distclean distclean-generic \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-binSCRIPTS install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-man1 install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
pdf-am ps ps-am tags tags-am uninstall uninstall-am \
uninstall-binSCRIPTS uninstall-man uninstall-man1
supermin: $(OBJECTS)
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) -linkpkg \
$^ -o $@
.mli.cmi:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmo:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmx:
$(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
depend: .depend
.depend: $(SOURCES)
rm -f $@ $@-t
$(OCAMLFIND) ocamldep $^ | \
$(SED) 's/ *$$//' | \
$(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
$(SED) 's/ :/:/' | \
sort > $@-t
mv $@-t $@
-include .depend
@HAVE_PERLDOC_TRUE@supermin.1: supermin.pod
@HAVE_PERLDOC_TRUE@ pod2man \
@HAVE_PERLDOC_TRUE@ -u \
@HAVE_PERLDOC_TRUE@ --section 1 \
@HAVE_PERLDOC_TRUE@ -c "Virtualization Support" \
@HAVE_PERLDOC_TRUE@ --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \
@HAVE_PERLDOC_TRUE@ $< > $@
@HAVE_PERLDOC_TRUE@../html/supermin.1.html: supermin.pod
@HAVE_PERLDOC_TRUE@ mkdir -p ../html
@HAVE_PERLDOC_TRUE@ pod2html \
@HAVE_PERLDOC_TRUE@ --css 'pod.css' \
@HAVE_PERLDOC_TRUE@ --htmldir ../html \
@HAVE_PERLDOC_TRUE@ --outfile ../html/supermin.1.html \
@HAVE_PERLDOC_TRUE@ supermin.pod
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
supermin-4.1.6/src/supermin_pacman_g2.ml 0000664 0001750 0001750 00000010773 12233731650 015213 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* FrugalWare support. *)
open Unix
open Printf
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let pacman_g2_detect () =
file_exists "/etc/frugalware-release" &&
Config.pacman_g2 <> "no"
let pacman_g2_init () =
if use_installed then
eprintf "supermin: pacman_g2 driver assumes all packages are already installed when called with option --use-installed.\n%!"
let pacman_g2_resolve_dependencies_and_download names mode =
debug "resolving deps";
debug "filtering deps";
(* Exclude packages matching [--exclude] regexps on the command line. *)
let pkgs =
List.filter (
fun name ->
not (List.exists (fun re -> Str.string_match re name 0) excludes)
) names in
if mode = PkgNamesOnly then (
eprintf "supermin: pacman_g2: --names-only flag is not implemented\n";
exit 1
);
(* Download the packages. I could use wget `pacman -Sp`, but this
* narrows the pacman -Sy window
*)
List.iter (
fun pkg ->
let cmd =
sprintf "umask 0000; cd %s && mkdir -p var/cache/pacman-g2/pkg && fakeroot pacman-g2%s -Sy --noconfirm --root=$(pwd) %s"
(Filename.quote tmpdir)
(match packager_config with
| None -> ""
| Some filename -> " --config " ^ filename)
pkg in
run_command cmd;
) pkgs;
let cmd =
sprintf "cd %s && fakeroot pacman-g2%s -Q --root=$(pwd)| cut -d ' ' -f 1"
(Filename.quote tmpdir)
(match packager_config with
| None -> ""
| Some filename -> " --config " ^ filename) in
let pkgs = run_command_get_lines cmd in
List.sort compare pkgs
let pacman_g2_list_files pkg =
debug "unpacking %s ..." pkg;
(* We actually need to extract the file in order to get the
* information about modes etc.
*)
let pkgdir = tmpdir // pkg ^ ".d" in
mkdir pkgdir 0o755;
let cmd =
sprintf "ls -1 %s/var/cache/pacman-g2/pkg/%s-*.fpm"
tmpdir pkg in
let pkgfile = List.hd (run_command_get_lines cmd) in
let cmd = sprintf "umask 0000; fakeroot tar -xf %s -C %s"
(Filename.quote pkgfile) (Filename.quote pkgdir) in
run_command cmd;
let cmd = sprintf "cd %s && find ." pkgdir in
let lines = run_command_get_lines cmd in
let excludes = [Str.regexp "./.CHANGELOG";
Str.regexp "./.FILELIST";
Str.regexp "./.PKGINFO";
Str.regexp "./.INSTALL"] in
let lines =
List.filter (
fun name ->
not (List.exists (fun re -> Str.string_match re name 0) excludes)
) lines in
let files = List.map (
fun path ->
assert (path.[0] = '.');
(* No leading '.' *)
let path =
if path = "." then "/"
else String.sub path 1 (String.length path - 1) in
(* Find out what it is and get the canonical filename. *)
let statbuf = lstat (pkgdir // path) in
let is_dir = statbuf.st_kind = S_DIR in
(* No per-file metadata like in RPM, but we can synthesize it
* from the path.
*)
let config = statbuf.st_kind = S_REG && string_prefix "/etc/" path in
let mode = statbuf.st_perm in
(path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
ft_ghost = false; ft_size = statbuf.st_size })
) lines in
files
(* Easy because we already unpacked the archive above. *)
let pacman_g2_get_file_from_package pkg file =
tmpdir // pkg ^ ".d" // file
let () =
let ph = {
ph_detect = pacman_g2_detect;
ph_init = pacman_g2_init;
ph_resolve_dependencies_and_download = pacman_g2_resolve_dependencies_and_download;
ph_list_files = pacman_g2_list_files;
ph_get_file_from_package = pacman_g2_get_file_from_package;
} in
register_package_handler "pacman-g2" ph
supermin-4.1.6/src/supermin_utils.ml 0000664 0001750 0001750 00000010636 12175443777 014541 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
open Unix
open Printf
let (//) = Filename.concat
let file_exists name =
try access name [F_OK]; true
with Unix_error _ -> false
let dir_exists name =
try (stat name).st_kind = S_DIR
with Unix_error _ -> false
let rec uniq ?(cmp = Pervasives.compare) = function
| [] -> []
| [x] -> [x]
| x :: y :: xs when cmp x y = 0 ->
uniq ~cmp (x :: xs)
| x :: y :: xs ->
x :: uniq ~cmp (y :: xs)
let sort_uniq ?(cmp = Pervasives.compare) xs =
let xs = List.sort cmp xs in
let xs = uniq ~cmp xs in
xs
let rec input_all_lines chan =
try let line = input_line chan in line :: input_all_lines chan
with End_of_file -> []
let run_command_get_lines cmd =
let chan = open_process_in cmd in
let lines = input_all_lines chan in
let stat = close_process_in chan in
(match stat with
| WEXITED 0 -> ()
| WEXITED i ->
eprintf "supermin: command '%s' failed (returned %d), see earlier error messages\n" cmd i;
exit i
| WSIGNALED i ->
eprintf "supermin: command '%s' killed by signal %d" cmd i;
exit 1
| WSTOPPED i ->
eprintf "supermin: command '%s' stopped by signal %d" cmd i;
exit 1
);
lines
let run_command cmd =
if Sys.command cmd <> 0 then (
eprintf "supermin: %s: command failed, see earlier errors\n" cmd;
exit 1
)
let run_shell code args =
let cmd = sprintf "sh -c %s arg0 %s"
(Filename.quote code)
(String.concat " " (List.map Filename.quote args)) in
if Sys.command cmd <> 0 then (
eprintf "supermin: external shell program failed, see earlier error messages\n";
exit 1
)
let run_python code args =
let cmd = sprintf "python -c %s %s"
(Filename.quote code)
(String.concat " " (List.map Filename.quote args)) in
if Sys.command cmd <> 0 then (
eprintf "supermin: external python program failed, see earlier error messages\n";
exit 1
)
let tmpdir () =
let chan = open_in "/dev/urandom" in
let data = String.create 16 in
really_input chan data 0 (String.length data);
close_in chan;
let data = Digest.to_hex (Digest.string data) in
(* Note this is secure, because if the name already exists, even as a
* symlink, mkdir(2) will fail.
*)
let tmpdir = Filename.temp_dir_name // sprintf "supermin%s.tmp" data in
Unix.mkdir tmpdir 0o700;
(* Only remove the directory if --save-temps was *not* specified. *)
if not Supermin_cmdline.save_temps then
at_exit
(fun () ->
let cmd = sprintf "rm -rf %s" (Filename.quote tmpdir) in
ignore (Sys.command cmd));
tmpdir
let rec find s sub =
let len = String.length s in
let sublen = String.length sub in
let rec loop i =
if i <= len-sublen then (
let rec loop2 j =
if j < sublen then (
if s.[i+j] = sub.[j] then loop2 (j+1)
else -1
) else
i (* found *)
in
let r = loop2 0 in
if r = -1 then loop (i+1) else r
) else
-1 (* not found *)
in
loop 0
let rec string_split sep str =
let len = String.length str in
let seplen = String.length sep in
let i = find str sep in
if i = -1 then [str]
else (
let s' = String.sub str 0 i in
let s'' = String.sub str (i+seplen) (len-i-seplen) in
s' :: string_split sep s''
)
let string_prefix p str =
let len = String.length str in
let plen = String.length p in
len >= plen && String.sub str 0 plen = p
let path_prefix p path =
let len = String.length path in
let plen = String.length p in
path = p || (len > plen && String.sub path 0 (plen+1) = (p ^ "/"))
let rec filter_map f = function
| [] -> []
| x :: xs ->
let x = f x in
match x with
| None -> filter_map f xs
| Some x -> x :: filter_map f xs
supermin-4.1.6/src/.depend 0000664 0001750 0001750 00000003354 12255776042 012355 0000000 0000000 config.cmo:
config.cmx:
supermin_cmdline.cmi:
supermin_cmdline.cmo: config.cmo supermin_cmdline.cmi
supermin_cmdline.cmx: config.cmx supermin_cmdline.cmi
supermin.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
supermin.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
supermin_debian.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
supermin_debian.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
supermin_package_handlers.cmi: supermin_cmdline.cmi
supermin_package_handlers.cmo: supermin_utils.cmi supermin_cmdline.cmi supermin_package_handlers.cmi
supermin_package_handlers.cmx: supermin_utils.cmx supermin_cmdline.cmx supermin_package_handlers.cmi
supermin_pacman.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
supermin_pacman.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
supermin_pacman_g2.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
supermin_pacman_g2.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
supermin_urpmi_rpm.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
supermin_urpmi_rpm.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
supermin_utils.cmi:
supermin_utils.cmo: supermin_cmdline.cmi supermin_utils.cmi
supermin_utils.cmx: supermin_cmdline.cmx supermin_utils.cmi
supermin_yum_rpm.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
supermin_yum_rpm.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
supermin-4.1.6/src/supermin_package_handlers.ml 0000664 0001750 0001750 00000004310 12175443777 016644 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
open Unix
open Printf
open Supermin_utils
open Supermin_cmdline
type package_handler = {
ph_detect : unit -> bool;
ph_init : unit -> unit;
ph_resolve_dependencies_and_download : string list -> mode -> string list;
ph_list_files : string -> (string * file_type) list;
ph_get_file_from_package : string -> string -> string
}
and file_type = {
ft_dir : bool;
ft_config : bool;
ft_ghost : bool;
ft_mode : int;
ft_size : int;
}
let tmpdir = tmpdir ()
let handlers = ref []
let register_package_handler name ph =
handlers := (name, ph) :: !handlers
let handler = ref None
let rec check_system () =
try
handler := Some (
List.find (
fun (_, ph) ->
ph.ph_detect ()
) !handlers
);
(get_package_handler ()).ph_init ()
with Not_found ->
eprintf "\
supermin: could not detect package manager used by this system or distro.
If this is a new Linux distro, or not Linux, or a Linux distro that uses
an unusual packaging format then you may need to port supermin. If
you are expecting that supermin should work on this system or distro
then it may be that the package detection code is not working.
";
exit 1
and get_package_handler () =
match !handler with
| Some (_, ph) -> ph
| None ->
check_system ();
get_package_handler ()
and get_package_handler_name () =
match !handler with
| Some (name, _) -> name
| None ->
check_system ();
get_package_handler_name ()
supermin-4.1.6/src/supermin_zypp_rpm.ml 0000664 0001750 0001750 00000021751 12175443777 015261 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2010 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* Zypper and RPM support. *)
(*
* Theory of operation:
* called as root:
* - without --use-installed:
* ->ph_resolve_dependencies_and_download() returns a list of filenames
* Need to download all packages into an empty --root directory so that
* zypper places all dependencies into --pkg-cache-dir
* - with --use-installed:
* ->ph_resolve_dependencies_and_download() returns a list of package names
* Need to work with an empty --root directory so that zypper can list
* all dependencies of "names". This mode assumes that all required packages
* are installed and the system is consistent. Downloading just the missing
* packages is not implemented.
* called as non-root:
* (Due to the usage of --root zypper does not require root permissions.)
* - without --use-installed:
* Same as above.
* - with --use-installed:
* Same as above.
*
* The usage of --packager-config is tricky: If --root is used zypper assumes
* that every config file is below . So the config has to be parsed
* and relevant files/dirs should be copied into so that zypper can
* use the specified config.
*)
open Unix
open Printf
open Inifiles
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let get_repos_dir () =
let zypper_default = "/etc/zypp/repos.d" in
let parse_repos_dir path =
let cfg = new inifile path in
let dir = (try cfg#getval "main" "reposdir" with _ -> zypper_default) in
dir
in
let dir = (match packager_config with None -> zypper_default |
Some filename -> (try parse_repos_dir filename with _ -> zypper_default) ) in
dir
let repos_dir = get_repos_dir ()
let zypp_rpm_detect () =
(file_exists "/etc/SuSE-release") &&
Config.zypper <> "no" && Config.rpm <> "no"
let zypp_rpm_init () =
if use_installed then
eprintf "supermin: zypp_rpm driver assumes all packages are already installed when called with option --use-installed.\n%!"
let zypp_rpm_resolve_dependencies_and_download_no_installed names =
(* Liberate this data from shell. *)
let tmp_pkg_cache_dir = tmpdir // "pkg_cache_dir" in
let tmp_root = tmpdir // "root" in
let sh = sprintf "
%s
unset LANG ${!LC_*}
tmpdir=%S
cache_dir=\"${tmpdir}/cache-dir\"
pkg_cache_dir=%S
time zypper \
%s \
%s \
--root %S --reposd-dir %S \
--cache-dir \"${cache_dir}\" \
--pkg-cache-dir \"${pkg_cache_dir}\" \
--gpg-auto-import-keys \
--no-gpg-checks \
--non-interactive \
install \
--auto-agree-with-licenses \
--download-only \
$@
"
(if verbose then "set -x" else "")
tmpdir
tmp_pkg_cache_dir
(if verbose then "--verbose --verbose" else "--quiet")
(match packager_config with None -> ""
| Some filename -> sprintf "--config %s" filename)
tmp_root
repos_dir
in
run_shell sh names;
(* http://rosettacode.org/wiki/Walk_a_directory/Recursively *)
let walk_directory_tree dir pattern =
let select str = Str.string_match (Str.regexp pattern) str 0 in
let rec walk acc = function
| [] -> (acc)
| dir::tail ->
let contents = Array.to_list (Sys.readdir dir) in
let contents = List.rev_map (Filename.concat dir) contents in
let dirs, files =
List.fold_left (fun (dirs,files) f ->
match (stat f).st_kind with
| S_REG -> (dirs, f::files) (* Regular file *)
| S_DIR -> (f::dirs, files) (* Directory *)
| _ -> (dirs, files)
) ([],[]) contents
in
let matched = List.filter (select) files in
walk (matched @ acc) (dirs @ tail)
in
walk [] [dir]
in
let pkgs = walk_directory_tree tmp_pkg_cache_dir ".*\\.rpm" in
(* Return list of package filenames. *)
pkgs
let zypp_rpm_resolve_dependencies_and_download_use_installed names =
let cmd = sprintf "
%s
unset LANG ${!LC_*}
zypper \
%s \
%s \
--root %S --reposd-dir %S \
--cache-dir %S \
--gpg-auto-import-keys \
--no-gpg-checks \
--non-interactive \
--xml \
install \
--auto-agree-with-licenses \
--dry-run \
%s | \
xml sel -t \
-m \"stream/install-summary/to-install/solvable[@type='package']\" \
-c \"string(@name)\" -n
"
(if verbose then "set -x" else "")
(if verbose then "--verbose --verbose" else "--quiet")
(match packager_config with None -> ""
| Some filename -> sprintf "--config %s" filename)
tmpdir repos_dir tmpdir (String.concat " " (List.map Filename.quote names)) in
let pkg_names = run_command_get_lines cmd in
(* Return list of package names, remove empty lines. *)
List.filter (fun s -> s <> "") pkg_names
let zypp_rpm_resolve_dependencies_and_download names mode =
if mode = PkgNamesOnly then (
eprintf "supermin: zypp-rpm: --names-only flag is not implemented\n";
exit 1
);
if use_installed then
zypp_rpm_resolve_dependencies_and_download_use_installed names
else
zypp_rpm_resolve_dependencies_and_download_no_installed names
let rec zypp_rpm_list_files pkg =
(* Run rpm -qlp with some extra magic. *)
let cmd =
sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' %s %S"
(if use_installed then "" else "-p")
pkg in
let lines = run_command_get_lines cmd in
let files =
filter_map (
fun line ->
match string_split " " line with
| [filename; flags; mode; size] ->
let test_flag = String.contains flags in
let mode = int_of_string mode in
let size = int_of_string size in
if test_flag 'd' then None (* ignore documentation *)
else (
(* Skip unreadable files when called as non-root *)
if Unix.getuid() > 0 &&
(try Unix.access filename [Unix.R_OK]; false with
Unix_error _ -> eprintf "supermin: EPERM %s\n%!" filename; true) then None
else
Some (filename, {
ft_dir = mode land 0o40000 <> 0;
ft_ghost = test_flag 'g'; ft_config = test_flag 'c';
ft_mode = mode; ft_size = size;
})
)
| _ ->
eprintf "supermin: bad output from rpm command: '%s'" line;
exit 1
) lines in
(* I've never understood why the base packages like 'filesystem' don't
* contain any /dev nodes at all. This leaves every program that
* bootstraps RPMs to create a varying set of device nodes themselves.
* This collection was copied from mock/backend.py.
*)
let files =
let b = Filename.basename pkg in
if string_prefix "filesystem-" b then (
let dirs = [ "/proc"; "/sys"; "/dev"; "/dev/pts"; "/dev/shm";
"/dev/mapper" ] in
let dirs =
List.map (fun name ->
name, { ft_dir = true; ft_ghost = false;
ft_config = false; ft_mode = 0o40755;
ft_size = 0 }) dirs in
let devs = [ "/dev/null"; "/dev/full"; "/dev/zero"; "/dev/random";
"/dev/urandom"; "/dev/tty"; "/dev/console";
"/dev/ptmx"; "/dev/stdin"; "/dev/stdout"; "/dev/stderr" ] in
(* No need to set the mode because these will go into hostfiles. *)
let devs =
List.map (fun name ->
name, { ft_dir = false; ft_ghost = false;
ft_config = false; ft_mode = 0o644;
ft_size = 0 }) devs in
dirs @ devs @ files
) else files in
files
let zypp_rpm_get_file_from_package pkg file =
if use_installed then
file
else (
debug "extracting %s from %s ..." file (Filename.basename pkg);
let outfile = tmpdir // file in
let cmd =
sprintf "umask 0000; rpm2cpio %s | (cd %s && cpio --quiet -id .%s)"
(Filename.quote pkg) (Filename.quote tmpdir) (Filename.quote file) in
run_command cmd;
outfile
)
let () =
let ph = {
ph_detect = zypp_rpm_detect;
ph_init = zypp_rpm_init;
ph_resolve_dependencies_and_download =
zypp_rpm_resolve_dependencies_and_download;
ph_list_files = zypp_rpm_list_files;
ph_get_file_from_package = zypp_rpm_get_file_from_package;
} in
register_package_handler "zypp-rpm" ph
supermin-4.1.6/src/supermin_urpmi_rpm.ml 0000664 0001750 0001750 00000011176 12204345562 015375 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* URPMI support. *)
open Unix
open Printf
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let urpmi_rpm_detect () =
(file_exists "/etc/mageia-release") &&
Config.urpmi <> "no" && Config.rpm <> "no"
let urpmi_rpm_init () =
if use_installed then
failwith "urpmi_rpm driver doesn't support --use-installed"
let urpmi_rpm_resolve_dependencies_and_download names mode =
if mode = PkgNamesOnly then (
eprintf "supermin: urpmi-rpm: --names-only flag is not implemented\n";
exit 1
);
let cmd = sprintf "urpmq -rd --whatprovides --sources %s"
(String.concat " " names) in
let lines = run_command_get_lines cmd in
(* Return list of package filenames. *)
let g x =
(Filename.concat tmpdir (Filename.basename x)) in
let f x =
let cmd = sprintf "curl %s -o %s" x (g x) in
run_command cmd in
List.iter f lines;
let uf res e = if List.mem e res then res else e::res in
List.fold_left uf [] (List.map g lines)
let rec urpmi_rpm_list_files pkg =
(* Run rpm -qlp with some extra magic. *)
let cmd =
sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' -p %s"
pkg in
let lines = run_command_get_lines cmd in
let files =
filter_map (
fun line ->
match string_split " " line with
| [filename; flags; mode; size] ->
let test_flag = String.contains flags in
let mode = int_of_string mode in
let size = int_of_string size in
if test_flag 'd' then None (* ignore documentation *)
else
Some (filename, {
ft_dir = mode land 0o40000 <> 0;
ft_ghost = test_flag 'g'; ft_config = test_flag 'c';
ft_mode = mode; ft_size = size;
})
| _ ->
eprintf "supermin: bad output from rpm command: '%s'" line;
exit 1
) lines in
(* I've never understood why the base packages like 'filesystem' don't
* contain any /dev nodes at all. This leaves every program that
* bootstraps RPMs to create a varying set of device nodes themselves.
* This collection was copied from mock/backend.py.
*)
let files =
let b = Filename.basename pkg in
if string_prefix "filesystem-" b then (
let dirs = [ "/proc"; "/sys"; "/dev"; "/dev/pts"; "/dev/shm";
"/dev/mapper" ] in
let dirs =
List.map (fun name ->
name, { ft_dir = true; ft_ghost = false;
ft_config = false; ft_mode = 0o40755;
ft_size = 0 }) dirs in
let devs = [ "/dev/null"; "/dev/full"; "/dev/zero"; "/dev/random";
"/dev/urandom"; "/dev/tty"; "/dev/console";
"/dev/ptmx"; "/dev/stdin"; "/dev/stdout"; "/dev/stderr" ] in
(* No need to set the mode because these will go into hostfiles. *)
let devs =
List.map (fun name ->
name, { ft_dir = false; ft_ghost = false;
ft_config = false; ft_mode = 0o644;
ft_size = 0 }) devs in
dirs @ devs @ files
) else files in
files
let urpmi_rpm_get_file_from_package pkg file =
debug "extracting %s from %s ..." file (Filename.basename pkg);
let outfile = tmpdir // file in
let cmd =
sprintf "umask 0000; rpm2cpio %s | (cd %s && cpio --quiet -id .%s)"
(Filename.quote pkg) (Filename.quote tmpdir) (Filename.quote file) in
run_command cmd;
outfile
let () =
let ph = {
ph_detect = urpmi_rpm_detect;
ph_init = urpmi_rpm_init;
ph_resolve_dependencies_and_download =
urpmi_rpm_resolve_dependencies_and_download;
ph_list_files = urpmi_rpm_list_files;
ph_get_file_from_package = urpmi_rpm_get_file_from_package;
} in
register_package_handler "urpmi-rpm" ph
supermin-4.1.6/src/supermin_package_handlers.mli 0000664 0001750 0001750 00000005704 12175443777 017025 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(** Generic package handler code. *)
type package_handler = {
ph_detect : unit -> bool;
(** Detect if the current system uses this package manager. This is
called in turn on each package handler, until one returns [true]. *)
ph_init : unit -> unit;
(** After a package handler is selected, this function is called
which can optionally do any initialization that is required.
This is only called on the package handler if it has returned
[true] from {!ph_detect}. *)
ph_resolve_dependencies_and_download : string list -> Supermin_cmdline.mode -> string list;
(** [ph_resolve_dependencies_and_download pkgs mode]
Take a list of package names, and using the package manager
resolve those to a list of all the packages that are required
including dependencies. Download the full list of packages and
dependencies into a tmpdir. Return the list of full filenames.
Note this should also process the [excludes] list. *)
ph_list_files : string -> (string * file_type) list;
(** [ph_list_files pkg] lists the files and file metadata in the
package called [pkg] (a package file). *)
ph_get_file_from_package : string -> string -> string;
(** [ph_get_file_from_package pkg file] extracts the
single named file [file] from [pkg]. The path of the
extracted file is returned. *)
}
(* These file types are inspired by the metadata specifically
* stored by RPM. We should look at what other package formats
* can use too.
*)
and file_type = {
ft_dir : bool; (** Is a directory. *)
ft_config : bool; (** Is a configuration file. *)
ft_ghost : bool; (** Is a ghost (created empty) file. *)
ft_mode : int; (** File mode. *)
ft_size : int; (** File size. *)
}
val register_package_handler : string -> package_handler -> unit
(** Register a package handler. *)
val check_system : unit -> unit
(** Check which package manager this system uses. *)
val get_package_handler : unit -> package_handler
(** Get the selected package manager for this system. *)
val get_package_handler_name : unit -> string
(** Get the name of the selected package manager for this system. *)
supermin-4.1.6/src/Makefile.am 0000664 0001750 0001750 00000006436 12255775332 013156 0000000 0000000 # supermin Makefile.am
# (C) Copyright 2009-2013 Red Hat 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 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Written by Richard W.M. Jones
EXTRA_DIST = \
.depend \
config.ml \
supermin.1 \
supermin.pod \
supermin.ml \
supermin_cmdline.mli \
supermin_cmdline.ml \
supermin_debian.ml \
supermin_package_handlers.mli \
supermin_package_handlers.ml \
supermin_pacman.ml \
supermin_pacman_g2.ml \
supermin_urpmi_rpm.ml \
supermin_utils.mli \
supermin_utils.ml \
supermin_yum_rpm.ml \
supermin_zypp_rpm.ml
# Note these must be in build dependency order.
SOURCES = \
config.ml \
supermin_cmdline.mli \
supermin_cmdline.ml \
supermin_utils.mli \
supermin_utils.ml \
supermin_package_handlers.mli \
supermin_package_handlers.ml
# Can't use filter for this because of automake brokenness.
SOURCES_ML = \
config.ml \
supermin_cmdline.ml \
supermin_utils.ml \
supermin_package_handlers.ml
if HAVE_OCAML_INIFILES
SOURCES += \
supermin_zypp_rpm.ml
SOURCES_ML += \
supermin_zypp_rpm.ml
endif
SOURCES += \
supermin_yum_rpm.ml \
supermin_urpmi_rpm.ml \
supermin_debian.ml \
supermin_pacman.ml \
supermin_pacman_g2.ml \
supermin.ml
SOURCES_ML += \
supermin_yum_rpm.ml \
supermin_urpmi_rpm.ml \
supermin_debian.ml \
supermin_pacman.ml \
supermin_pacman_g2.ml \
supermin.ml
CLEANFILES = *~ *.cmi *.cmo *.cmx *.o supermin
man_MANS = \
supermin.1
bin_SCRIPTS = supermin
BOBJECTS = $(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(SOURCES_ML:.ml=.cmx)
if !HAVE_OCAMLOPT
OBJECTS = $(BOBJECTS)
BEST = c
else
OBJECTS = $(XOBJECTS)
BEST = opt
endif
OCAMLPACKAGES = -package unix,str
if HAVE_OCAML_INIFILES
OCAMLPACKAGES += -package inifiles
endif
OCAMLFLAGS = -warn-error CDEFLMPSUVXYZ
supermin: $(OBJECTS)
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) -linkpkg \
$^ -o $@
.mli.cmi:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmo:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmx:
$(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
depend: .depend
.depend: $(SOURCES)
rm -f $@ $@-t
$(OCAMLFIND) ocamldep $^ | \
$(SED) 's/ *$$//' | \
$(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
$(SED) 's/ :/:/' | \
sort > $@-t
mv $@-t $@
-include .depend
SUFFIXES = .cmo .cmi .cmx .ml .mli .mll .mly
if HAVE_PERLDOC
supermin.1: supermin.pod
pod2man \
-u \
--section 1 \
-c "Virtualization Support" \
--release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \
$< > $@
noinst_DATA = \
../html/supermin.1.html
../html/supermin.1.html: supermin.pod
mkdir -p ../html
pod2html \
--css 'pod.css' \
--htmldir ../html \
--outfile ../html/supermin.1.html \
supermin.pod
endif
supermin-4.1.6/src/supermin_yum_rpm.ml 0000664 0001750 0001750 00000020623 12175443777 015066 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* Yum and RPM support. *)
open Unix
open Printf
open Supermin_package_handlers
open Supermin_utils
open Supermin_cmdline
(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()
let yum_rpm_detect () =
(file_exists "/etc/redhat-release" || file_exists "/etc/fedora-release") &&
Config.yum <> "no" && Config.rpm <> "no"
let yum_rpm_init () =
if use_installed then
failwith "yum_rpm driver doesn't support --use-installed"
let yum_rpm_resolve_dependencies_and_download names mode =
if mode = PkgNamesOnly then (
eprintf "supermin: yum-rpm: --names-only flag is not implemented\n";
exit 1
);
(* Liberate this data from python. *)
let tmpfile = tmpdir // "names.tmp" in
let py = sprintf "
import yum
import yum.misc
import sys
verbose = %d
if verbose:
print \"supermin_yum_rpm: running python code to query yum and resolve deps\"
yb = yum.YumBase ()
yb.preconf.debuglevel = verbose
yb.preconf.errorlevel = verbose
try:
yb.prerepoconf.multi_progressbar = None
except:
pass
if %s:
yb.preconf.fn = %S
try:
yb.setCacheDir ()
except AttributeError:
pass
if verbose:
print \"supermin_yum_rpm: looking up the base packages from the command line\"
deps = dict ()
pkgs = yb.pkgSack.returnPackages (patterns=sys.argv[1:])
for pkg in pkgs:
deps[pkg] = False
if verbose:
print \"supermin_yum_rpm: recursively finding all the dependencies\"
stable = False
while not stable:
stable = True
for pkg in deps.keys():
if deps[pkg] == False:
deps[pkg] = []
stable = False
if verbose:
print (\"supermin_yum_rpm: examining deps of %%s\" %%
pkg.name)
for r in pkg.requires:
ps = yb.whatProvides (r[0], r[1], r[2])
best = yb._bestPackageFromList (ps.returnPackages ())
if best and best.name != pkg.name:
deps[pkg].append (best)
if not deps.has_key (best):
deps[best] = False
deps[pkg] = yum.misc.unique (deps[pkg])
# Write it to a file because yum spews garbage on stdout.
f = open (%S, \"w\")
for pkg in deps.keys ():
f.write (\"%%s %%s %%s %%s %%s\\n\" %%
(pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch))
f.close ()
if verbose:
print \"supermin_yum_rpm: finished python code\"
"
(if verbose then 1 else 0)
(match packager_config with None -> "False" | Some _ -> "True")
(match packager_config with None -> "" | Some filename -> filename)
tmpfile in
run_python py names;
let chan = open_in tmpfile in
let lines = input_all_lines chan in
close_in chan;
(* Get fields. *)
let pkgs =
List.map (
fun line ->
match string_split " " line with
| [name; epoch; version; release; arch] ->
name, int_of_string epoch, version, release, arch
| _ ->
eprintf "supermin: bad output from python script: '%s'" line;
exit 1
) lines in
(* Something of a hack for x86_64: exclude all i[3456]86 packages. *)
let pkgs =
if Config.host_cpu = "x86_64" then (
List.filter (
function (_, _, _, _, ("i386"|"i486"|"i586"|"i686")) -> false
| _ -> true
) pkgs
)
else pkgs in
(* Exclude packages matching [--exclude] regexps on the command line. *)
let pkgs =
List.filter (
fun (name, _, _, _, _) ->
not (List.exists (fun re -> Str.string_match re name 0) excludes)
) pkgs in
(* Sort the list of packages, and remove duplicates (by name).
* XXX This is not quite right: we really want to keep the latest
* package if duplicates are found, but that would require a full
* version compare function.
*)
let pkgs = List.sort (fun a b -> compare b a) pkgs in
let pkgs =
let cmp (name1, _, _, _, _) (name2, _, _, _, _) = compare name1 name2 in
uniq ~cmp pkgs in
let pkgs = List.sort compare pkgs in
(* Construct package names. *)
let pkgnames = List.map (
function
| name, 0, version, release, arch ->
sprintf "%s-%s-%s.%s" name version release arch
| name, epoch, version, release, arch ->
sprintf "%d:%s-%s-%s.%s" epoch name version release arch
) pkgs in
if pkgnames = [] then (
eprintf "supermin: yum-rpm: error: no packages to download\n";
exit 1
);
let cmd = sprintf "yumdownloader%s%s --destdir %s %s"
(if verbose then "" else " --quiet")
(match packager_config with None -> ""
| Some filename -> sprintf " -c %s" filename)
(Filename.quote tmpdir)
(String.concat " " (List.map Filename.quote pkgnames)) in
run_command cmd;
(* Return list of package filenames. *)
List.map (
(* yumdownloader doesn't include epoch in the filename *)
fun (name, _, version, release, arch) ->
sprintf "%s/%s-%s-%s.%s.rpm" tmpdir name version release arch
) pkgs
let rec yum_rpm_list_files pkg =
(* Run rpm -qlp with some extra magic. *)
let cmd =
sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' -p %s"
pkg in
let lines = run_command_get_lines cmd in
let files =
filter_map (
fun line ->
match string_split " " line with
| [filename; flags; mode; size] ->
let test_flag = String.contains flags in
let mode = int_of_string mode in
let size = int_of_string size in
if test_flag 'd' then None (* ignore documentation *)
else
Some (filename, {
ft_dir = mode land 0o40000 <> 0;
ft_ghost = test_flag 'g'; ft_config = test_flag 'c';
ft_mode = mode; ft_size = size;
})
| _ ->
eprintf "supermin: bad output from rpm command: '%s'" line;
exit 1
) lines in
(* I've never understood why the base packages like 'filesystem' don't
* contain any /dev nodes at all. This leaves every program that
* bootstraps RPMs to create a varying set of device nodes themselves.
* This collection was copied from mock/backend.py.
*)
let files =
let b = Filename.basename pkg in
if string_prefix "filesystem-" b then (
let dirs = [ "/proc"; "/sys"; "/dev"; "/dev/pts"; "/dev/shm";
"/dev/mapper" ] in
let dirs =
List.map (fun name ->
name, { ft_dir = true; ft_ghost = false;
ft_config = false; ft_mode = 0o40755;
ft_size = 0 }) dirs in
let devs = [ "/dev/null"; "/dev/full"; "/dev/zero"; "/dev/random";
"/dev/urandom"; "/dev/tty"; "/dev/console";
"/dev/ptmx"; "/dev/stdin"; "/dev/stdout"; "/dev/stderr" ] in
(* No need to set the mode because these will go into hostfiles. *)
let devs =
List.map (fun name ->
name, { ft_dir = false; ft_ghost = false;
ft_config = false; ft_mode = 0o644;
ft_size = 0 }) devs in
dirs @ devs @ files
) else files in
files
let yum_rpm_get_file_from_package pkg file =
debug "extracting %s from %s ..." file (Filename.basename pkg);
let outfile = tmpdir // file in
let cmd =
sprintf "umask 0000; rpm2cpio %s | (cd %s && cpio --quiet -id .%s)"
(Filename.quote pkg) (Filename.quote tmpdir) (Filename.quote file) in
run_command cmd;
outfile
let () =
let ph = {
ph_detect = yum_rpm_detect;
ph_init = yum_rpm_init;
ph_resolve_dependencies_and_download =
yum_rpm_resolve_dependencies_and_download;
ph_list_files = yum_rpm_list_files;
ph_get_file_from_package = yum_rpm_get_file_from_package;
} in
register_package_handler "yum-rpm" ph
supermin-4.1.6/src/config.ml 0000664 0001750 0001750 00000002215 12255775775 012723 0000000 0000000 (* supermin 4
* Copyright (C) 2009-2013 Red Hat Inc.
* src/config.ml. Generated from config.ml.in by configure.
*
* 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 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
let package_name = "supermin"
let package_version = "4.1.6"
let zypper = "no"
let yum = "yum"
let urpmi = "no"
let rpm = "rpm"
let yumdownloader = "yumdownloader"
let aptitude = "no"
let apt_cache = "no"
let dpkg = "no"
let apt_cache_depends_recurse_broken = false
let pacman = ""
let pacman_g2 = "no"
let host_cpu = "x86_64"
supermin-4.1.6/test-driver 0000755 0001750 0001750 00000007611 12177156520 012516 0000000 0000000 #! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2012-06-27.10; # UTC
# Copyright (C) 2011-2013 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 .
# 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 or send patches to
# .
# 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 <$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
estatus=1
fi
case $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 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 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
supermin-4.1.6/lib/ 0000775 0001750 0001750 00000000000 12255776503 011151 5 0000000 0000000 supermin-4.1.6/lib/mempcpy.c 0000664 0001750 0001750 00000002002 12177155607 012700 0000000 0000000 /* Copy memory area and return pointer after last written byte.
Copyright (C) 2003, 2007, 2009-2013 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 . */
#include
/* Specification. */
#include
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
last written byte. */
void *
mempcpy (void *dest, const void *src, size_t n)
{
return (char *) memcpy (dest, src, n) + n;
}
supermin-4.1.6/lib/dirent--.h 0000664 0001750 0001750 00000001547 12177155607 012667 0000000 0000000 /* Like dirent.h, but redefine some names to avoid glitches.
Copyright (C) 2009-2013 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 . */
/* Written by Eric Blake. */
#include "dirent-safer.h"
#undef opendir
#define opendir opendir_safer
supermin-4.1.6/lib/getcwd-lgpl.c 0000664 0001750 0001750 00000006042 12177155607 013447 0000000 0000000 /* Copyright (C) 2011-2013 Free Software Foundation, Inc.
This file is part of gnulib.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 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 . */
#include
/* Specification */
#include
#include
#include
#if GNULIB_GETCWD
/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use. */
typedef int dummy;
#else
/* Get the name of the current working directory, and put it in SIZE
bytes of BUF. Returns NULL if the directory couldn't be determined
(perhaps because the absolute name was longer than PATH_MAX, or
because of missing read/search permissions on parent directories)
or SIZE was too small. If successful, returns BUF. If BUF is
NULL, an array is allocated with 'malloc'; the array is SIZE bytes
long, unless SIZE == 0, in which case it is as big as
necessary. */
# undef getcwd
char *
rpl_getcwd (char *buf, size_t size)
{
char *ptr;
char *result;
/* Handle single size operations. */
if (buf)
{
if (!size)
{
errno = EINVAL;
return NULL;
}
return getcwd (buf, size);
}
if (size)
{
buf = malloc (size);
if (!buf)
{
errno = ENOMEM;
return NULL;
}
result = getcwd (buf, size);
if (!result)
{
int saved_errno = errno;
free (buf);
errno = saved_errno;
}
return result;
}
/* Flexible sizing requested. Avoid over-allocation for the common
case of a name that fits within a 4k page, minus some space for
local variables, to be sure we don't skip over a guard page. */
{
char tmp[4032];
size = sizeof tmp;
ptr = getcwd (tmp, size);
if (ptr)
{
result = strdup (ptr);
if (!result)
errno = ENOMEM;
return result;
}
if (errno != ERANGE)
return NULL;
}
/* My what a large directory name we have. */
do
{
size <<= 1;
ptr = realloc (buf, size);
if (ptr == NULL)
{
free (buf);
errno = ENOMEM;
return NULL;
}
buf = ptr;
result = getcwd (buf, size);
}
while (!result && errno == ERANGE);
if (!result)
{
int saved_errno = errno;
free (buf);
errno = saved_errno;
}
else
{
/* Trim to fit, if possible. */
result = realloc (buf, strlen (buf) + 1);
if (!result)
result = buf;
}
return result;
}
#endif
supermin-4.1.6/lib/error.c 0000664 0001750 0001750 00000024070 12177155607 012370 0000000 0000000 /* Error handler for noninteractive utilities
Copyright (C) 1990-1998, 2000-2007, 2009-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
/* Written by David MacKenzie . */
#if !_LIBC
# include
#endif
#include "error.h"
#include
#include
#include
#include
#if !_LIBC && ENABLE_NLS
# include "gettext.h"
# define _(msgid) gettext (msgid)
#endif
#ifdef _LIBC
# include
# include
# include
# include
# define mbsrtowcs __mbsrtowcs
#endif
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifndef _
# define _(String) String
#endif
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
void (*error_print_progname) (void);
/* This variable is incremented each time 'error' is called. */
unsigned int error_message_count;
#ifdef _LIBC
/* In the GNU C library, there is a predefined variable for this. */
# define program_name program_invocation_name
# include
# include
# include
/* In GNU libc we want do not want to use the common name 'error' directly.
Instead make it a weak alias. */
extern void __error (int status, int errnum, const char *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
extern void __error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message,
...)
__attribute__ ((__format__ (__printf__, 5, 6)));;
# define error __error
# define error_at_line __error_at_line
# include
# define fflush(s) INTUSE(_IO_fflush) (s)
# undef putc
# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
# include
#else /* not _LIBC */
# include
# include
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include
/* Get _get_osfhandle. */
# include "msvc-nothrow.h"
# endif
/* The gnulib override of fcntl is not needed in this file. */
# undef fcntl
# if !HAVE_DECL_STRERROR_R
# ifndef HAVE_DECL_STRERROR_R
"this configure-time declaration test was not run"
# endif
# if STRERROR_R_CHAR_P
char *strerror_r ();
# else
int strerror_r ();
# endif
# endif
/* The calling program should define program_name and set it to the
name of the executing program. */
extern char *program_name;
# if HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r
# endif /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */
#if !_LIBC
/* Return non-zero if FD is open. */
static int
is_open (int fd)
{
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* On native Windows: The initial state of unassigned standard file
descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
There is no fcntl, and the gnulib replacement fcntl does not support
F_GETFL. */
return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
# else
# ifndef F_GETFL
# error Please port fcntl to your platform
# endif
return 0 <= fcntl (fd, F_GETFL);
# endif
}
#endif
static void
flush_stdout (void)
{
#if !_LIBC
int stdout_fd;
# if GNULIB_FREOPEN_SAFER
/* Use of gnulib's freopen-safer module normally ensures that
fileno (stdout) == 1
whenever stdout is open. */
stdout_fd = STDOUT_FILENO;
# else
/* POSIX states that fileno (stdout) after fclose is unspecified. But in
practice it is not a problem, because stdout is statically allocated and
the fd of a FILE stream is stored as a field in its allocated memory. */
stdout_fd = fileno (stdout);
# endif
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= stdout_fd && is_open (stdout_fd))
#endif
fflush (stdout);
}
static void
print_errno_message (int errnum)
{
char const *s;
#if defined HAVE_STRERROR_R || _LIBC
char errbuf[1024];
# if STRERROR_R_CHAR_P || _LIBC
s = __strerror_r (errnum, errbuf, sizeof errbuf);
# else
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
s = errbuf;
else
s = 0;
# endif
#else
s = strerror (errnum);
#endif
#if !_LIBC
if (! s)
s = _("Unknown system error");
#endif
#if _LIBC
__fxprintf (NULL, ": %s", s);
#else
fprintf (stderr, ": %s", s);
#endif
}
static void
error_tail (int status, int errnum, const char *message, va_list args)
{
#if _LIBC
if (_IO_fwide (stderr, 0) > 0)
{
# define ALLOCA_LIMIT 2000
size_t len = strlen (message) + 1;
wchar_t *wmessage = NULL;
mbstate_t st;
size_t res;
const char *tmp;
bool use_malloc = false;
while (1)
{
if (__libc_use_alloca (len * sizeof (wchar_t)))
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
else
{
if (!use_malloc)
wmessage = NULL;
wchar_t *p = (wchar_t *) realloc (wmessage,
len * sizeof (wchar_t));
if (p == NULL)
{
free (wmessage);
fputws_unlocked (L"out of memory\n", stderr);
return;
}
wmessage = p;
use_malloc = true;
}
memset (&st, '\0', sizeof (st));
tmp = message;
res = mbsrtowcs (wmessage, &tmp, len, &st);
if (res != len)
break;
if (__builtin_expect (len >= SIZE_MAX / 2, 0))
{
/* This really should not happen if everything is fine. */
res = (size_t) -1;
break;
}
len *= 2;
}
if (res == (size_t) -1)
{
/* The string cannot be converted. */
if (use_malloc)
{
free (wmessage);
use_malloc = false;
}
wmessage = (wchar_t *) L"???";
}
__vfwprintf (stderr, wmessage, args);
if (use_malloc)
free (wmessage);
}
else
#endif
vfprintf (stderr, message, args);
va_end (args);
++error_message_count;
if (errnum)
print_errno_message (errnum);
#if _LIBC
__fxprintf (NULL, "\n");
#else
putc ('\n', stderr);
#endif
fflush (stderr);
if (status)
exit (status);
}
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args.
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status STATUS if it is nonzero. */
void
error (int status, int errnum, const char *message, ...)
{
va_list args;
#if defined _LIBC && defined __libc_ptf_call
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0);
#endif
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
#if _LIBC
__fxprintf (NULL, "%s: ", program_name);
#else
fprintf (stderr, "%s: ", program_name);
#endif
}
va_start (args, message);
error_tail (status, errnum, message, args);
#ifdef _LIBC
_IO_funlockfile (stderr);
# ifdef __libc_ptf_call
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
# endif
#endif
}
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
int error_one_per_line;
void
error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...)
{
va_list args;
if (error_one_per_line)
{
static const char *old_file_name;
static unsigned int old_line_number;
if (old_line_number == line_number
&& (file_name == old_file_name
|| strcmp (old_file_name, file_name) == 0))
/* Simply return and print nothing. */
return;
old_file_name = file_name;
old_line_number = line_number;
}
#if defined _LIBC && defined __libc_ptf_call
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0);
#endif
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
#if _LIBC
__fxprintf (NULL, "%s:", program_name);
#else
fprintf (stderr, "%s:", program_name);
#endif
}
#if _LIBC
__fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number);
#else
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number);
#endif
va_start (args, message);
error_tail (status, errnum, message, args);
#ifdef _LIBC
_IO_funlockfile (stderr);
# ifdef __libc_ptf_call
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
# endif
#endif
}
#ifdef _LIBC
/* Make the weak alias. */
# undef error
# undef error_at_line
weak_alias (__error, error)
weak_alias (__error_at_line, error_at_line)
#endif
supermin-4.1.6/lib/size_max.h 0000664 0001750 0001750 00000002211 12177155607 013054 0000000 0000000 /* size_max.h -- declare SIZE_MAX through system headers
Copyright (C) 2005-2006, 2009-2013 Free Software Foundation, Inc.
Written by Simon Josefsson.
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 . */
#ifndef GNULIB_SIZE_MAX_H
#define GNULIB_SIZE_MAX_H
/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */
# include
/* Get SIZE_MAX declaration on systems like glibc 2. */
# if HAVE_STDINT_H
# include
# endif
/* On systems where these include files don't define it, SIZE_MAX is defined
in config.h. */
#endif /* GNULIB_SIZE_MAX_H */
supermin-4.1.6/lib/fd-hook.h 0000664 0001750 0001750 00000011351 12177155607 012571 0000000 0000000 /* Hook for making making file descriptor functions close(), ioctl() extensible.
Copyright (C) 2009-2013 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 . */
#ifndef FD_HOOK_H
#define FD_HOOK_H
#ifdef __cplusplus
extern "C" {
#endif
/* Currently, this entire code is only needed for the handling of sockets
on native Windows platforms. */
#if WINDOWS_SOCKETS
/* Type of function that closes FD. */
typedef int (*gl_close_fn) (int fd);
/* Type of function that applies a control request to FD. */
typedef int (*gl_ioctl_fn) (int fd, int request, void *arg);
/* An element of the list of file descriptor hooks.
In CLOS (Common Lisp Object System) speak, it consists of an "around"
method for the close() function and an "around" method for the ioctl()
function.
The fields of this structure are considered private. */
struct fd_hook
{
/* Doubly linked list. */
struct fd_hook *private_next;
struct fd_hook *private_prev;
/* Function that treats the types of FD that it knows about and calls
execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback. */
int (*private_close_fn) (const struct fd_hook *remaining_list,
gl_close_fn primary,
int fd);
/* Function that treats the types of FD that it knows about and calls
execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a
fallback. */
int (*private_ioctl_fn) (const struct fd_hook *remaining_list,
gl_ioctl_fn primary,
int fd, int request, void *arg);
};
/* This type of function closes FD, applying special knowledge for the FD
types it knows about, and calls
execute_close_hooks (REMAINING_LIST, PRIMARY, FD)
for the other FD types.
In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
and PRIMARY is the "primary" method for close(). */
typedef int (*close_hook_fn) (const struct fd_hook *remaining_list,
gl_close_fn primary,
int fd);
/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method.
Return 0 or -1, like close() would do. */
extern int execute_close_hooks (const struct fd_hook *remaining_list,
gl_close_fn primary,
int fd);
/* Execute all close hooks, with PRIMARY as "primary" method.
Return 0 or -1, like close() would do. */
extern int execute_all_close_hooks (gl_close_fn primary, int fd);
/* This type of function applies a control request to FD, applying special
knowledge for the FD types it knows about, and calls
execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG)
for the other FD types.
In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
and PRIMARY is the "primary" method for ioctl(). */
typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list,
gl_ioctl_fn primary,
int fd, int request, void *arg);
/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method.
Return 0 or -1, like ioctl() would do. */
extern int execute_ioctl_hooks (const struct fd_hook *remaining_list,
gl_ioctl_fn primary,
int fd, int request, void *arg);
/* Execute all ioctl hooks, with PRIMARY as "primary" method.
Return 0 or -1, like ioctl() would do. */
extern int execute_all_ioctl_hooks (gl_ioctl_fn primary,
int fd, int request, void *arg);
/* Add a function pair to the list of file descriptor hooks.
CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change.
The LINK variable points to a piece of memory which is guaranteed to be
accessible until the corresponding call to unregister_fd_hook. */
extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook,
struct fd_hook *link);
/* Removes a hook from the list of file descriptor hooks. */
extern void unregister_fd_hook (struct fd_hook *link);
#endif
#ifdef __cplusplus
}
#endif
#endif /* FD_HOOK_H */
supermin-4.1.6/lib/close.c 0000664 0001750 0001750 00000002707 12177155607 012347 0000000 0000000 /* close replacement.
Copyright (C) 2008-2013 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 . */
#include
/* Specification. */
#include
#include
#include "fd-hook.h"
#include "msvc-inval.h"
#undef close
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int
close_nothrow (int fd)
{
int result;
TRY_MSVC_INVAL
{
result = close (fd);
}
CATCH_MSVC_INVAL
{
result = -1;
errno = EBADF;
}
DONE_MSVC_INVAL;
return result;
}
#else
# define close_nothrow close
#endif
/* Override close() to call into other gnulib modules. */
int
rpl_close (int fd)
{
#if WINDOWS_SOCKETS
int retval = execute_all_close_hooks (close_nothrow, fd);
#else
int retval = close_nothrow (fd);
#endif
#if REPLACE_FCHDIR
if (retval >= 0)
_gl_unregister_fd (fd);
#endif
return retval;
}
supermin-4.1.6/lib/stdbool.in.h 0000664 0001750 0001750 00000011772 12177155607 013324 0000000 0000000 /* Copyright (C) 2001-2003, 2006-2013 Free Software Foundation, Inc.
Written by Bruno Haible , 2001.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, 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 . */
#ifndef _GL_STDBOOL_H
#define _GL_STDBOOL_H
/* ISO C 99 for platforms that lack it. */
/* Usage suggestions:
Programs that use should be aware of some limitations
and standards compliance issues.
Standards compliance:
- must be #included before 'bool', 'false', 'true'
can be used.
- You cannot assume that sizeof (bool) == 1.
- Programs should not undefine the macros bool, true, and false,
as C99 lists that as an "obsolescent feature".
Limitations of this substitute, when used in a C89 environment:
- must be #included before the '_Bool' type can be used.
- You cannot assume that _Bool is a typedef; it might be a macro.
- Bit-fields of type 'bool' are not supported. Portable code
should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'.
- In C99, casts and automatic conversions to '_Bool' or 'bool' are
performed in such a way that every nonzero value gets converted
to 'true', and zero gets converted to 'false'. This doesn't work
with this substitute. With this substitute, only the values 0 and 1
give the expected result when converted to _Bool' or 'bool'.
- C99 allows the use of (_Bool)0.0 in constant expressions, but
this substitute cannot always provide this property.
Also, it is suggested that programs use 'bool' rather than '_Bool';
this isn't required, but 'bool' is more common. */
/* 7.16. Boolean type and values */
/* BeOS already #defines false 0, true 1. We use the same
definitions below, but temporarily we have to #undef them. */
#if defined __BEOS__ && !defined __HAIKU__
# include /* defines bool but not _Bool */
# undef false
# undef true
#endif
#ifdef __cplusplus
# define _Bool bool
# define bool bool
#else
# if defined __BEOS__ && !defined __HAIKU__
/* A compiler known to have 'bool'. */
/* If the compiler already has both 'bool' and '_Bool', we can assume they
are the same types. */
# if !@HAVE__BOOL@
typedef bool _Bool;
# endif
# else
# if !defined __GNUC__
/* If @HAVE__BOOL@:
Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when
the built-in _Bool type is used. See
http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
Similar bugs are likely with other compilers as well; this file
wouldn't be used if was working.
So we override the _Bool type.
If !@HAVE__BOOL@:
Need to define _Bool ourselves. As 'signed char' or as an enum type?
Use of a typedef, with SunPRO C, leads to a stupid
"warning: _Bool is a keyword in ISO C99".
Use of an enum type, with IRIX cc, leads to a stupid
"warning(1185): enumerated type mixed with another type".
Even the existence of an enum type, without a typedef,
"Invalid enumerator. (badenum)" with HP-UX cc on Tru64.
The only benefit of the enum, debuggability, is not important
with these compilers. So use 'signed char' and no enum. */
# define _Bool signed char
# else
/* With this compiler, trust the _Bool type if the compiler has it. */
# if !@HAVE__BOOL@
/* For the sake of symbolic names in gdb, define true and false as
enum constants, not only as macros.
It is tempting to write
typedef enum { false = 0, true = 1 } _Bool;
so that gdb prints values of type 'bool' symbolically. But then
values of type '_Bool' might promote to 'int' or 'unsigned int'
(see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int'
(see ISO C 99 6.3.1.1.(2)). So add a negative value to the
enum; this ensures that '_Bool' promotes to 'int'. */
typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
# endif
# endif
# endif
# define bool _Bool
#endif
/* The other macros must be usable in preprocessor directives. */
#ifdef __cplusplus
# define false false
# define true true
#else
# define false 0
# define true 1
#endif
#define __bool_true_false_are_defined 1
#endif /* _GL_STDBOOL_H */
supermin-4.1.6/lib/msvc-nothrow.c 0000664 0001750 0001750 00000002434 12177155607 013705 0000000 0000000 /* Wrappers that don't throw invalid parameter notifications
with MSVC runtime libraries.
Copyright (C) 2011-2013 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 . */
#include
/* Specification. */
#include "msvc-nothrow.h"
/* Get declarations of the native Windows API functions. */
#define WIN32_LEAN_AND_MEAN
#include
#include "msvc-inval.h"
#undef _get_osfhandle
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
intptr_t
_gl_nothrow_get_osfhandle (int fd)
{
intptr_t result;
TRY_MSVC_INVAL
{
result = _get_osfhandle (fd);
}
CATCH_MSVC_INVAL
{
result = (intptr_t) INVALID_HANDLE_VALUE;
}
DONE_MSVC_INVAL;
return result;
}
#endif
supermin-4.1.6/lib/getdtablesize.c 0000664 0001750 0001750 00000004763 12177155607 014074 0000000 0000000 /* getdtablesize() function for platforms that don't have it.
Copyright (C) 2008-2013 Free Software Foundation, Inc.
Written by Bruno Haible , 2008.
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 . */
#include
/* Specification. */
#include
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
#include
#include "msvc-inval.h"
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int
_setmaxstdio_nothrow (int newmax)
{
int result;
TRY_MSVC_INVAL
{
result = _setmaxstdio (newmax);
}
CATCH_MSVC_INVAL
{
result = -1;
}
DONE_MSVC_INVAL;
return result;
}
# define _setmaxstdio _setmaxstdio_nothrow
#endif
/* Cache for the previous getdtablesize () result. */
static int dtablesize;
int
getdtablesize (void)
{
if (dtablesize == 0)
{
/* We are looking for the number N such that the valid file descriptors
are 0..N-1. It can be obtained through a loop as follows:
{
int fd;
for (fd = 3; fd < 65536; fd++)
if (dup2 (0, fd) == -1)
break;
return fd;
}
On Windows XP, the result is 2048.
The drawback of this loop is that it allocates memory for a libc
internal array that is never freed.
The number N can also be obtained as the upper bound for
_getmaxstdio (). _getmaxstdio () returns the maximum number of open
FILE objects. The sanity check in _setmaxstdio reveals the maximum
number of file descriptors. This too allocates memory, but it is
freed when we call _setmaxstdio with the original value. */
int orig_max_stdio = _getmaxstdio ();
unsigned int bound;
for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2)
;
_setmaxstdio (orig_max_stdio);
dtablesize = bound;
}
return dtablesize;
}
#endif
supermin-4.1.6/lib/write.c 0000664 0001750 0001750 00000012011 12177155610 012353 0000000 0000000 /* POSIX compatible write() function.
Copyright (C) 2008-2013 Free Software Foundation, Inc.
Written by Bruno Haible , 2008.
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 . */
#include
/* Specification. */
#include
/* On native Windows platforms, SIGPIPE does not exist. When write() is
called on a pipe with no readers, WriteFile() fails with error
GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
error EINVAL. */
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# include
# include
# include
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include
# include "msvc-inval.h"
# include "msvc-nothrow.h"
# undef write
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static ssize_t
write_nothrow (int fd, const void *buf, size_t count)
{
ssize_t result;
TRY_MSVC_INVAL
{
result = write (fd, buf, count);
}
CATCH_MSVC_INVAL
{
result = -1;
errno = EBADF;
}
DONE_MSVC_INVAL;
return result;
}
# else
# define write_nothrow write
# endif
ssize_t
rpl_write (int fd, const void *buf, size_t count)
{
for (;;)
{
ssize_t ret = write_nothrow (fd, buf, count);
if (ret < 0)
{
# if GNULIB_NONBLOCKING
if (errno == ENOSPC)
{
HANDLE h = (HANDLE) _get_osfhandle (fd);
if (GetFileType (h) == FILE_TYPE_PIPE)
{
/* h is a pipe or socket. */
DWORD state;
if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL,
NULL, 0)
&& (state & PIPE_NOWAIT) != 0)
{
/* h is a pipe in non-blocking mode.
We can get here in four situations:
1. When the pipe buffer is full.
2. When count <= pipe_buf_size and the number of
free bytes in the pipe buffer is < count.
3. When count > pipe_buf_size and the number of free
bytes in the pipe buffer is > 0, < pipe_buf_size.
4. When count > pipe_buf_size and the pipe buffer is
entirely empty.
The cases 1 and 2 are POSIX compliant. In cases 3 and
4 POSIX specifies that write() must split the request
and succeed with a partial write. We fix case 4.
We don't fix case 3 because it is not essential for
programs. */
DWORD out_size; /* size of the buffer for outgoing data */
DWORD in_size; /* size of the buffer for incoming data */
if (GetNamedPipeInfo (h, NULL, &out_size, &in_size, NULL))
{
size_t reduced_count = count;
/* In theory we need only one of out_size, in_size.
But I don't know which of the two. The description
is ambiguous. */
if (out_size != 0 && out_size < reduced_count)
reduced_count = out_size;
if (in_size != 0 && in_size < reduced_count)
reduced_count = in_size;
if (reduced_count < count)
{
/* Attempt to write only the first part. */
count = reduced_count;
continue;
}
}
/* Change errno from ENOSPC to EAGAIN. */
errno = EAGAIN;
}
}
}
else
# endif
{
# if GNULIB_SIGPIPE
if (GetLastError () == ERROR_NO_DATA
&& GetFileType ((HANDLE) _get_osfhandle (fd))
== FILE_TYPE_PIPE)
{
/* Try to raise signal SIGPIPE. */
raise (SIGPIPE);
/* If it is currently blocked or ignored, change errno from
EINVAL to EPIPE. */
errno = EPIPE;
}
# endif
}
}
return ret;
}
}
#endif
supermin-4.1.6/lib/closedir.c 0000664 0001750 0001750 00000002642 12177155607 013044 0000000 0000000 /* Stop reading the entries of a directory.
Copyright (C) 2006-2013 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 . */
#include
/* Specification. */
#include
#if REPLACE_FCHDIR
# include
#endif
#if HAVE_CLOSEDIR
/* Override closedir(), to keep track of the open file descriptors.
Needed because there is a function dirfd(). */
#else
# include
# include "dirent-private.h"
#endif
int
closedir (DIR *dirp)
{
# if REPLACE_FCHDIR
int fd = dirfd (dirp);
# endif
int retval;
#if HAVE_CLOSEDIR
# undef closedir
retval = closedir (dirp);
#else
if (dirp->current != INVALID_HANDLE_VALUE)
FindClose (dirp->current);
free (dirp);
retval = 0;
#endif
#if REPLACE_FCHDIR
if (retval >= 0)
_gl_unregister_fd (fd);
#endif
return retval;
}
supermin-4.1.6/lib/stat.c 0000664 0001750 0001750 00000010666 12177155607 012220 0000000 0000000 /* Work around platform bugs in stat.
Copyright (C) 2009-2013 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 . */
/* written by Eric Blake */
/* If the user's config.h happens to include , let it include only
the system's here, so that orig_stat doesn't recurse to
rpl_stat. */
#define __need_system_sys_stat_h
#include
/* Get the original definition of stat. It might be defined as a macro. */
#include
#include
#undef __need_system_sys_stat_h
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# if _GL_WINDOWS_64_BIT_ST_SIZE
# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
# define stat _stati64
# define REPLACE_FUNC_STAT_DIR 1
# undef REPLACE_FUNC_STAT_FILE
# elif REPLACE_FUNC_STAT_FILE
/* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a.
Bypass it. */
# define stat _stat
# define REPLACE_FUNC_STAT_DIR 1
# undef REPLACE_FUNC_STAT_FILE
# endif
#endif
static int
orig_stat (const char *filename, struct stat *buf)
{
return stat (filename, buf);
}
/* Specification. */
/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc
eliminates this include because of the preliminary #include
above. */
#include "sys/stat.h"
#include
#include
#include
#include
#include "dosname.h"
#include "verify.h"
#if REPLACE_FUNC_STAT_DIR
# include "pathmax.h"
/* The only known systems where REPLACE_FUNC_STAT_DIR is needed also
have a constant PATH_MAX. */
# ifndef PATH_MAX
# error "Please port this replacement to your platform"
# endif
#endif
/* Store information about NAME into ST. Work around bugs with
trailing slashes. Mingw has other bugs (such as st_ino always
being 0 on success) which this wrapper does not work around. But
at least this implementation provides the ability to emulate fchdir
correctly. */
int
rpl_stat (char const *name, struct stat *st)
{
int result = orig_stat (name, st);
#if REPLACE_FUNC_STAT_FILE
/* Solaris 9 mistakenly succeeds when given a non-directory with a
trailing slash. */
if (result == 0 && !S_ISDIR (st->st_mode))
{
size_t len = strlen (name);
if (ISSLASH (name[len - 1]))
{
errno = ENOTDIR;
return -1;
}
}
#endif /* REPLACE_FUNC_STAT_FILE */
#if REPLACE_FUNC_STAT_DIR
if (result == -1 && errno == ENOENT)
{
/* Due to mingw's oddities, there are some directories (like
c:\) where stat() only succeeds with a trailing slash, and
other directories (like c:\windows) where stat() only
succeeds without a trailing slash. But we want the two to be
synonymous, since chdir() manages either style. Likewise, Mingw also
reports ENOENT for names longer than PATH_MAX, when we want
ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR.
Fortunately, mingw PATH_MAX is small enough for stack
allocation. */
char fixed_name[PATH_MAX + 1] = {0};
size_t len = strlen (name);
bool check_dir = false;
verify (PATH_MAX <= 4096);
if (PATH_MAX <= len)
errno = ENAMETOOLONG;
else if (len)
{
strcpy (fixed_name, name);
if (ISSLASH (fixed_name[len - 1]))
{
check_dir = true;
while (len && ISSLASH (fixed_name[len - 1]))
fixed_name[--len] = '\0';
if (!len)
fixed_name[0] = '/';
}
else
fixed_name[len++] = '/';
result = orig_stat (fixed_name, st);
if (result == 0 && check_dir && !S_ISDIR (st->st_mode))
{
result = -1;
errno = ENOTDIR;
}
}
}
#endif /* REPLACE_FUNC_STAT_DIR */
return result;
}
supermin-4.1.6/lib/full-write.c 0000664 0001750 0001750 00000004361 12177155607 013332 0000000 0000000 /* An interface to read and write that retries (if necessary) until complete.
Copyright (C) 1993-1994, 1997-2006, 2009-2013 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 . */
#include
/* Specification. */
#ifdef FULL_READ
# include "full-read.h"
#else
# include "full-write.h"
#endif
#include
#ifdef FULL_READ
# include "safe-read.h"
# define safe_rw safe_read
# define full_rw full_read
# undef const
# define const /* empty */
#else
# include "safe-write.h"
# define safe_rw safe_write
# define full_rw full_write
#endif
#ifdef FULL_READ
/* Set errno to zero upon EOF. */
# define ZERO_BYTE_TRANSFER_ERRNO 0
#else
/* Some buggy drivers return 0 when one tries to write beyond
a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
Set errno to ENOSPC so they get a sensible diagnostic. */
# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
#endif
/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
interrupted or if a partial write(read) occurs. Return the number
of bytes transferred.
When writing, set errno if fewer than COUNT bytes are written.
When reading, if fewer than COUNT bytes are read, you must examine
errno to distinguish failure from EOF (errno == 0). */
size_t
full_rw (int fd, const void *buf, size_t count)
{
size_t total = 0;
const char *ptr = (const char *) buf;
while (count > 0)
{
size_t n_rw = safe_rw (fd, ptr, count);
if (n_rw == (size_t) -1)
break;
if (n_rw == 0)
{
errno = ZERO_BYTE_TRANSFER_ERRNO;
break;
}
total += n_rw;
ptr += n_rw;
count -= n_rw;
}
return total;
}
supermin-4.1.6/lib/strerror-override.h 0000664 0001750 0001750 00000003717 12177155610 014742 0000000 0000000 /* strerror-override.h --- POSIX compatible system error routine
Copyright (C) 2010-2013 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 . */
#ifndef _GL_STRERROR_OVERRIDE_H
# define _GL_STRERROR_OVERRIDE_H
# include
# include
/* Reasonable buffer size that should never trigger ERANGE; if this
proves too small, we intentionally abort(), to remind us to fix
this value. */
# define STACKBUF_LEN 256
/* If ERRNUM maps to an errno value defined by gnulib, return a string
describing the error. Otherwise return NULL. */
# if REPLACE_STRERROR_0 \
|| GNULIB_defined_ESOCK \
|| GNULIB_defined_ESTREAMS \
|| GNULIB_defined_EWINSOCK \
|| GNULIB_defined_ENOMSG \
|| GNULIB_defined_EIDRM \
|| GNULIB_defined_ENOLINK \
|| GNULIB_defined_EPROTO \
|| GNULIB_defined_EMULTIHOP \
|| GNULIB_defined_EBADMSG \
|| GNULIB_defined_EOVERFLOW \
|| GNULIB_defined_ENOTSUP \
|| GNULIB_defined_ENETRESET \
|| GNULIB_defined_ECONNABORTED \
|| GNULIB_defined_ESTALE \
|| GNULIB_defined_EDQUOT \
|| GNULIB_defined_ECANCELED \
|| GNULIB_defined_EOWNERDEAD \
|| GNULIB_defined_ENOTRECOVERABLE \
|| GNULIB_defined_EILSEQ
extern const char *strerror_override (int errnum);
# else
# define strerror_override(ignored) NULL
# endif
#endif /* _GL_STRERROR_OVERRIDE_H */
supermin-4.1.6/lib/xstrtol.h 0000664 0001750 0001750 00000004735 12177155610 012763 0000000 0000000 /* A more useful interface to strtol.
Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2013 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 . */
#ifndef XSTRTOL_H_
# define XSTRTOL_H_ 1
# include
# include
# ifndef _STRTOL_ERROR
enum strtol_error
{
LONGINT_OK = 0,
/* These two values can be ORed together, to indicate that both
errors occurred. */
LONGINT_OVERFLOW = 1,
LONGINT_INVALID_SUFFIX_CHAR = 2,
LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR
| LONGINT_OVERFLOW),
LONGINT_INVALID = 4
};
typedef enum strtol_error strtol_error;
# endif
# define _DECLARE_XSTRTOL(name, type) \
strtol_error name (const char *, char **, int, type *, const char *);
_DECLARE_XSTRTOL (xstrtol, long int)
_DECLARE_XSTRTOL (xstrtoul, unsigned long int)
_DECLARE_XSTRTOL (xstrtoimax, intmax_t)
_DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
#if HAVE_LONG_LONG_INT
_DECLARE_XSTRTOL (xstrtoll, long long int)
_DECLARE_XSTRTOL (xstrtoull, unsigned long long int)
#endif
/* Report an error for an invalid integer in an option argument.
ERR is the error code returned by one of the xstrto* functions.
Use OPT_IDX to decide whether to print the short option string "C"
or "-C" or a long option string derived from LONG_OPTION. OPT_IDX
is -2 if the short option "C" was used, without any leading "-"; it
is -1 if the short option "-C" was used; otherwise it is an index
into LONG_OPTIONS, which should have a name preceded by two '-'
characters.
ARG is the option-argument containing the integer.
After reporting an error, exit with a failure status. */
_Noreturn void xstrtol_fatal (enum strtol_error,
int, char, struct option const *,
char const *);
#endif /* not XSTRTOL_H_ */
supermin-4.1.6/lib/filevercmp.c 0000664 0001750 0001750 00000011620 12177155607 013370 0000000 0000000 /*
Copyright (C) 1995 Ian Jackson
Copyright (C) 2001 Anthony Towns
Copyright (C) 2008-2013 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 . */
#include
#include "filevercmp.h"
#include
#include
#include
#include
#include
#include
/* Match a file suffix defined by this regular expression:
/(\.[A-Za-z~][A-Za-z0-9~]*)*$/
Scan the string *STR and return a pointer to the matching suffix, or
NULL if not found. Upon return, *STR points to terminating NUL. */
static const char *
match_suffix (const char **str)
{
const char *match = NULL;
bool read_alpha = false;
while (**str)
{
if (read_alpha)
{
read_alpha = false;
if (!c_isalpha (**str) && '~' != **str)
match = NULL;
}
else if ('.' == **str)
{
read_alpha = true;
if (!match)
match = *str;
}
else if (!c_isalnum (**str) && '~' != **str)
match = NULL;
(*str)++;
}
return match;
}
/* verrevcmp helper function */
static int
order (unsigned char c)
{
if (c_isdigit (c))
return 0;
else if (c_isalpha (c))
return c;
else if (c == '~')
return -1;
else
return (int) c + UCHAR_MAX + 1;
}
/* slightly modified verrevcmp function from dpkg
S1, S2 - compared string
S1_LEN, S2_LEN - length of strings to be scanned
This implements the algorithm for comparison of version strings
specified by Debian and now widely adopted. The detailed
specification can be found in the Debian Policy Manual in the
section on the 'Version' control field. This version of the code
implements that from s5.6.12 of Debian Policy v3.8.0.1
http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */
static int _GL_ATTRIBUTE_PURE
verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
{
size_t s1_pos = 0;
size_t s2_pos = 0;
while (s1_pos < s1_len || s2_pos < s2_len)
{
int first_diff = 0;
while ((s1_pos < s1_len && !c_isdigit (s1[s1_pos]))
|| (s2_pos < s2_len && !c_isdigit (s2[s2_pos])))
{
int s1_c = (s1_pos == s1_len) ? 0 : order (s1[s1_pos]);
int s2_c = (s2_pos == s2_len) ? 0 : order (s2[s2_pos]);
if (s1_c != s2_c)
return s1_c - s2_c;
s1_pos++;
s2_pos++;
}
while (s1[s1_pos] == '0')
s1_pos++;
while (s2[s2_pos] == '0')
s2_pos++;
while (c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos]))
{
if (!first_diff)
first_diff = s1[s1_pos] - s2[s2_pos];
s1_pos++;
s2_pos++;
}
if (c_isdigit (s1[s1_pos]))
return 1;
if (c_isdigit (s2[s2_pos]))
return -1;
if (first_diff)
return first_diff;
}
return 0;
}
/* Compare version strings S1 and S2.
See filevercmp.h for function description. */
int
filevercmp (const char *s1, const char *s2)
{
const char *s1_pos;
const char *s2_pos;
const char *s1_suffix, *s2_suffix;
size_t s1_len, s2_len;
int result;
/* easy comparison to see if strings are identical */
int simple_cmp = strcmp (s1, s2);
if (simple_cmp == 0)
return 0;
/* special handle for "", "." and ".." */
if (!*s1)
return -1;
if (!*s2)
return 1;
if (0 == strcmp (".", s1))
return -1;
if (0 == strcmp (".", s2))
return 1;
if (0 == strcmp ("..", s1))
return -1;
if (0 == strcmp ("..", s2))
return 1;
/* special handle for other hidden files */
if (*s1 == '.' && *s2 != '.')
return -1;
if (*s1 != '.' && *s2 == '.')
return 1;
if (*s1 == '.' && *s2 == '.')
{
s1++;
s2++;
}
/* "cut" file suffixes */
s1_pos = s1;
s2_pos = s2;
s1_suffix = match_suffix (&s1_pos);
s2_suffix = match_suffix (&s2_pos);
s1_len = (s1_suffix ? s1_suffix : s1_pos) - s1;
s2_len = (s2_suffix ? s2_suffix : s2_pos) - s2;
/* restore file suffixes if strings are identical after "cut" */
if ((s1_suffix || s2_suffix) && (s1_len == s2_len)
&& 0 == strncmp (s1, s2, s1_len))
{
s1_len = s1_pos - s1;
s2_len = s2_pos - s2;
}
result = verrevcmp (s1, s1_len, s2, s2_len);
return result == 0 ? simple_cmp : result;
}
supermin-4.1.6/lib/same-inode.h 0000664 0001750 0001750 00000002202 12177155607 013256 0000000 0000000 /* Determine whether two stat buffers refer to the same file.
Copyright (C) 2006, 2009-2013 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 . */
#ifndef SAME_INODE_H
# define SAME_INODE_H 1
# ifdef __VMS
# define SAME_INODE(a, b) \
((a).st_ino[0] == (b).st_ino[0] \
&& (a).st_ino[1] == (b).st_ino[1] \
&& (a).st_ino[2] == (b).st_ino[2] \
&& (a).st_dev == (b).st_dev)
# else
# define SAME_INODE(a, b) \
((a).st_ino == (b).st_ino \
&& (a).st_dev == (b).st_dev)
# endif
#endif
supermin-4.1.6/lib/xstrtol-error.c 0000664 0001750 0001750 00000005370 12177155610 014101 0000000 0000000 /* A more useful interface to strtol.
Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2013 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 . */
#include
#include "xstrtol.h"
#include
#include "error.h"
#include "exitfail.h"
#include "gettext.h"
#define N_(msgid) msgid
/* Report an error for an invalid integer in an option argument.
ERR is the error code returned by one of the xstrto* functions.
Use OPT_IDX to decide whether to print the short option string "C"
or "-C" or a long option string derived from LONG_OPTION. OPT_IDX
is -2 if the short option "C" was used, without any leading "-"; it
is -1 if the short option "-C" was used; otherwise it is an index
into LONG_OPTIONS, which should have a name preceded by two '-'
characters.
ARG is the option-argument containing the integer.
After reporting an error, exit with status EXIT_STATUS if it is
nonzero. */
static void
xstrtol_error (enum strtol_error err,
int opt_idx, char c, struct option const *long_options,
char const *arg,
int exit_status)
{
char const *hyphens = "--";
char const *msgid;
char const *option;
char option_buffer[2];
switch (err)
{
default:
abort ();
case LONGINT_INVALID:
msgid = N_("invalid %s%s argument '%s'");
break;
case LONGINT_INVALID_SUFFIX_CHAR:
case LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW:
msgid = N_("invalid suffix in %s%s argument '%s'");
break;
case LONGINT_OVERFLOW:
msgid = N_("%s%s argument '%s' too large");
break;
}
if (opt_idx < 0)
{
hyphens -= opt_idx;
option_buffer[0] = c;
option_buffer[1] = '\0';
option = option_buffer;
}
else
option = long_options[opt_idx].name;
error (exit_status, 0, gettext (msgid), hyphens, option, arg);
}
/* Like xstrtol_error, except exit with a failure status. */
void
xstrtol_fatal (enum strtol_error err,
int opt_idx, char c, struct option const *long_options,
char const *arg)
{
xstrtol_error (err, opt_idx, c, long_options, arg, exit_failure);
abort ();
}
supermin-4.1.6/lib/intprops.h 0000664 0001750 0001750 00000035006 12177155607 013123 0000000 0000000 /* intprops.h -- properties of integer types
Copyright (C) 2001-2005, 2009-2013 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 . */
/* Written by Paul Eggert. */
#ifndef _GL_INTPROPS_H
#define _GL_INTPROPS_H
#include
/* Return an integer value, converted to the same type as the integer
expression E after integer type promotion. V is the unconverted value. */
#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
. */
#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
/* The extra casts in the following macros work around compiler bugs,
e.g., in Cray C 5.0.3.0. */
/* True if the arithmetic type T is an integer type. bool counts as
an integer. */
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
/* True if negative values of the signed integer type T use two's
complement, ones' complement, or signed magnitude representation,
respectively. Much GNU code assumes two's complement, but some
people like to be portable to all possible C hosts. */
#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
/* True if the signed integer expression E uses two's complement. */
#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1)
/* True if the arithmetic type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* Return 1 if the integer expression E, after integer promotion, has
a signed type. */
#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
/* Minimum and maximum values for integer types and expressions. These
macros have undefined behavior if T is signed and has padding bits.
If this is a problem for you, please let us know how to fix it for
your host. */
/* The maximum and minimum values for the integer type T. */
#define TYPE_MINIMUM(t) \
((t) (! TYPE_SIGNED (t) \
? (t) 0 \
: TYPE_SIGNED_MAGNITUDE (t) \
? ~ (t) 0 \
: ~ TYPE_MAXIMUM (t)))
#define TYPE_MAXIMUM(t) \
((t) (! TYPE_SIGNED (t) \
? (t) -1 \
: ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
/* The maximum and minimum values for the type of the expression E,
after integer promotion. E should not have side effects. */
#define _GL_INT_MINIMUM(e) \
(_GL_INT_SIGNED (e) \
? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_CONVERT (e, 0))
#define _GL_INT_MAXIMUM(e) \
(_GL_INT_SIGNED (e) \
? _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_NEGATE_CONVERT (e, 1))
#define _GL_SIGNED_INT_MAXIMUM(e) \
(((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1)
/* Return 1 if the __typeof__ keyword works. This could be done by
'configure', but for now it's easier to do it by hand. */
#if 2 <= __GNUC__ || 0x5110 <= __SUNPRO_C
# define _GL_HAVE___TYPEOF__ 1
#else
# define _GL_HAVE___TYPEOF__ 0
#endif
/* Return 1 if the integer type or expression T might be signed. Return 0
if it is definitely unsigned. This macro does not evaluate its argument,
and expands to an integer constant expression. */
#if _GL_HAVE___TYPEOF__
# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
#else
# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
#endif
/* Bound on length of the string representing an unsigned integer
value representable in B bits. log10 (2.0) < 146/485. The
smallest value of B where this bound is not tight is 2621. */
#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
/* Bound on length of the string representing an integer type or expression T.
Subtract 1 for the sign bit if T is signed, and then add 1 more for
a minus sign if needed.
Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is
signed, this macro may overestimate the true bound by one byte when
applied to unsigned types of size 2, 4, 16, ... bytes. */
#define INT_STRLEN_BOUND(t) \
(INT_BITS_STRLEN_BOUND (sizeof (t) * CHAR_BIT \
- _GL_SIGNED_TYPE_OR_EXPR (t)) \
+ _GL_SIGNED_TYPE_OR_EXPR (t))
/* Bound on buffer size needed to represent an integer type or expression T,
including the terminating null. */
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
/* Range overflow checks.
The INT__RANGE_OVERFLOW macros return 1 if the corresponding C
operators might not yield numerically correct answers due to
arithmetic overflow. They do not rely on undefined or
implementation-defined behavior. Their implementations are simple
and straightforward, but they are a bit harder to use than the
INT__OVERFLOW macros described below.
Example usage:
long int i = ...;
long int j = ...;
if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX))
printf ("multiply would overflow");
else
printf ("product is %ld", i * j);
Restrictions on *_RANGE_OVERFLOW macros:
These macros do not check for all possible numerical problems or
undefined or unspecified behavior: they do not check for division
by zero, for bad shift counts, or for shifting negative numbers.
These macros may evaluate their arguments zero or multiple times,
so the arguments should not have side effects. The arithmetic
arguments (including the MIN and MAX arguments) must be of the same
integer type after the usual arithmetic conversions, and the type
must have minimum value MIN and maximum MAX. Unsigned types should
use a zero MIN of the proper type.
These macros are tuned for constant MIN and MAX. For commutative
operations such as A + B, they are also tuned for constant B. */
/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? (a) < (min) - (b) \
: (max) - (b) < (a))
/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? (max) + (b) < (a) \
: (a) < (min) + (b))
/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
((min) < 0 \
? (a) < - (max) \
: 0 < (a))
/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Avoid && and || as they tickle
bugs in Sun C 5.11 2010/08/13 and other compilers; see
. */
#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? ((a) < 0 \
? (a) < (max) / (b) \
: (b) == -1 \
? 0 \
: (min) / (b) < (a)) \
: (b) == 0 \
? 0 \
: ((a) < 0 \
? (a) < (min) / (b) \
: (max) / (b) < (a)))
/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Do not check for division by zero. */
#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \
((min) < 0 && (b) == -1 && (a) < - (max))
/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Do not check for division by zero.
Mathematically, % should never overflow, but on x86-like hosts
INT_MIN % -1 traps, and the C standard permits this, so treat this
as an overflow too. */
#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \
INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max)
/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Here, MIN and MAX are for A only, and B need
not be of the same type as the other arguments. The C standard says that
behavior is undefined for shifts unless 0 <= B < wordwidth, and that when
A is negative then A << B has undefined behavior and A >> B has
implementation-defined behavior, but do not check these other
restrictions. */
#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \
((a) < 0 \
? (a) < (min) >> (b) \
: (max) >> (b) < (a))
/* The _GL*_OVERFLOW macros have the same restrictions as the
*_RANGE_OVERFLOW macros, except that they do not assume that operands
(e.g., A and B) have the same type as MIN and MAX. Instead, they assume
that the result (e.g., A + B) has that type. */
#define _GL_ADD_OVERFLOW(a, b, min, max) \
((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \
: (a) < 0 ? (b) <= (a) + (b) \
: (b) < 0 ? (a) <= (a) + (b) \
: (a) + (b) < (b))
#define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \
: (a) < 0 ? 1 \
: (b) < 0 ? (a) - (b) <= (a) \
: (a) < (b))
#define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
(((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \
|| INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \
((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
: (a) < 0 ? (b) <= (a) + (b) - 1 \
: (b) < 0 && (a) + (b) <= (a))
#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \
((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
: (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \
: (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max))
/* Return a nonzero value if A is a mathematical multiple of B, where
A is unsigned, B is negative, and MAX is the maximum value of A's
type. A's type must be the same as (A % B)'s type. Normally (A %
-B == 0) suffices, but things get tricky if -B would overflow. */
#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \
(((b) < -_GL_SIGNED_INT_MAXIMUM (b) \
? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \
? (a) \
: (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \
: (a) % - (b)) \
== 0)
/* Integer overflow checks.
The INT__OVERFLOW macros return 1 if the corresponding C operators
might not yield numerically correct answers due to arithmetic overflow.
They work correctly on all known practical hosts, and do not rely
on undefined behavior due to signed arithmetic overflow.
Example usage:
long int i = ...;
long int j = ...;
if (INT_MULTIPLY_OVERFLOW (i, j))
printf ("multiply would overflow");
else
printf ("product is %ld", i * j);
These macros do not check for all possible numerical problems or
undefined or unspecified behavior: they do not check for division
by zero, for bad shift counts, or for shifting negative numbers.
These macros may evaluate their arguments zero or multiple times, so the
arguments should not have side effects.
These macros are tuned for their last argument being a constant.
Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
A % B, and A << B would overflow, respectively. */
#define INT_ADD_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
#define INT_SUBTRACT_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
#define INT_NEGATE_OVERFLOW(a) \
INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
#define INT_MULTIPLY_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
#define INT_DIVIDE_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
#define INT_REMAINDER_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW)
#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
_GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
/* Return 1 if the expression A B would overflow,
where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
assuming MIN and MAX are the minimum and maximum for the result type.
Arguments should be free of side effects. */
#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \
op_result_overflow (a, b, \
_GL_INT_MINIMUM (0 * (b) + (a)), \
_GL_INT_MAXIMUM (0 * (b) + (a)))
#endif /* _GL_INTPROPS_H */
supermin-4.1.6/lib/cycle-check.c 0000664 0001750 0001750 00000005200 12177155607 013403 0000000 0000000 /* help detect directory cycles efficiently
Copyright (C) 2003-2006, 2009-2013 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 . */
/* Written by Jim Meyering */
#include
#include
#include
#include
#include
#include
#include
#include "cycle-check.h"
#define CC_MAGIC 9827862
/* Return true if I is a power of 2, or is zero. */
static bool
is_zero_or_power_of_two (uintmax_t i)
{
return (i & (i - 1)) == 0;
}
void
cycle_check_init (struct cycle_check_state *state)
{
state->chdir_counter = 0;
state->magic = CC_MAGIC;
}
/* In traversing a directory hierarchy, call this function once for each
descending chdir call, with SB corresponding to the chdir operand.
If SB corresponds to a directory that has already been seen,
return true to indicate that there is a directory cycle.
Note that this is done "lazily", which means that some of
the directories in the cycle may be processed twice before
the cycle is detected. */
bool
cycle_check (struct cycle_check_state *state, struct stat const *sb)
{
assert (state->magic == CC_MAGIC);
/* If the current directory ever happens to be the same
as the one we last recorded for the cycle detection,
then it's obviously part of a cycle. */
if (state->chdir_counter && SAME_INODE (*sb, state->dev_ino))
return true;
/* If the number of "descending" chdir calls is a power of two,
record the dev/ino of the current directory. */
if (is_zero_or_power_of_two (++(state->chdir_counter)))
{
/* On all architectures that we know about, if the counter
overflows then there is a directory cycle here somewhere,
even if we haven't detected it yet. Typically this happens
only after the counter is incremented 2**64 times, so it's a
fairly theoretical point. */
if (state->chdir_counter == 0)
return true;
state->dev_ino.st_dev = sb->st_dev;
state->dev_ino.st_ino = sb->st_ino;
}
return false;
}
supermin-4.1.6/lib/fcntl--.h 0000664 0001750 0001750 00000001752 12177155607 012506 0000000 0000000 /* Like fcntl.h, but redefine some names to avoid glitches.
Copyright (C) 2005, 2009-2013 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 . */
/* Written by Paul Eggert. */
#include
#include "fcntl-safer.h"
#undef open
#define open open_safer
#undef creat
#define creat creat_safer
#if GNULIB_OPENAT_SAFER
# undef openat
# define openat openat_safer
#endif
supermin-4.1.6/lib/xsize.h 0000664 0001750 0001750 00000006736 12177155610 012411 0000000 0000000 /* xsize.h -- Checked size_t computations.
Copyright (C) 2003, 2008-2013 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 . */
#ifndef _XSIZE_H
#define _XSIZE_H
/* Get size_t. */
#include
/* Get SIZE_MAX. */
#include
#if HAVE_STDINT_H
# include
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef XSIZE_INLINE
# define XSIZE_INLINE _GL_INLINE
#endif
/* The size of memory objects is often computed through expressions of
type size_t. Example:
void* p = malloc (header_size + n * element_size).
These computations can lead to overflow. When this happens, malloc()
returns a piece of memory that is way too small, and the program then
crashes while attempting to fill the memory.
To avoid this, the functions and macros in this file check for overflow.
The convention is that SIZE_MAX represents overflow.
malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
implementation that uses mmap --, it's recommended to use size_overflow_p()
or size_in_bounds_p() before invoking malloc().
The example thus becomes:
size_t size = xsum (header_size, xtimes (n, element_size));
void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
*/
/* Convert an arbitrary value >= 0 to type size_t. */
#define xcast_size_t(N) \
((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
/* Sum of two sizes, with overflow check. */
XSIZE_INLINE size_t
#if __GNUC__ >= 3
__attribute__ ((__pure__))
#endif
xsum (size_t size1, size_t size2)
{
size_t sum = size1 + size2;
return (sum >= size1 ? sum : SIZE_MAX);
}
/* Sum of three sizes, with overflow check. */
XSIZE_INLINE size_t
#if __GNUC__ >= 3
__attribute__ ((__pure__))
#endif
xsum3 (size_t size1, size_t size2, size_t size3)
{
return xsum (xsum (size1, size2), size3);
}
/* Sum of four sizes, with overflow check. */
XSIZE_INLINE size_t
#if __GNUC__ >= 3
__attribute__ ((__pure__))
#endif
xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
{
return xsum (xsum (xsum (size1, size2), size3), size4);
}
/* Maximum of two sizes, with overflow check. */
XSIZE_INLINE size_t
#if __GNUC__ >= 3
__attribute__ ((__pure__))
#endif
xmax (size_t size1, size_t size2)
{
/* No explicit check is needed here, because for any n:
max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */
return (size1 >= size2 ? size1 : size2);
}
/* Multiplication of a count with an element size, with overflow check.
The count must be >= 0 and the element size must be > 0.
This is a macro, not a function, so that it works correctly even
when N is of a wider type and N > SIZE_MAX. */
#define xtimes(N, ELSIZE) \
((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
/* Check for overflow. */
#define size_overflow_p(SIZE) \
((SIZE) == SIZE_MAX)
/* Check against overflow. */
#define size_in_bounds_p(SIZE) \
((SIZE) != SIZE_MAX)
_GL_INLINE_HEADER_END
#endif /* _XSIZE_H */
supermin-4.1.6/lib/msvc-nothrow.h 0000664 0001750 0001750 00000003010 12177155607 013701 0000000 0000000 /* Wrappers that don't throw invalid parameter notifications
with MSVC runtime libraries.
Copyright (C) 2011-2013 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 . */
#ifndef _MSVC_NOTHROW_H
#define _MSVC_NOTHROW_H
/* With MSVC runtime libraries with the "invalid parameter handler" concept,
functions like fprintf(), dup2(), or close() crash when the caller passes
an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF)
instead.
This file defines wrappers that turn such an invalid parameter notification
into an error code. */
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get original declaration of _get_osfhandle. */
# include
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
/* Override _get_osfhandle. */
extern intptr_t _gl_nothrow_get_osfhandle (int fd);
# define _get_osfhandle _gl_nothrow_get_osfhandle
# endif
#endif
#endif /* _MSVC_NOTHROW_H */
supermin-4.1.6/lib/xmalloc.c 0000664 0001750 0001750 00000006467 12177155610 012702 0000000 0000000 /* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990-2000, 2002-2006, 2008-2013 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 . */
#include
#define XALLOC_INLINE _GL_EXTERN_INLINE
#include "xalloc.h"
#include
#include
/* 1 if calloc is known to be compatible with GNU calloc. This
matters if we are not also using the calloc module, which defines
HAVE_CALLOC_GNU and supports the GNU API even on non-GNU platforms. */
#if defined HAVE_CALLOC_GNU || (defined __GLIBC__ && !defined __UCLIBC__)
enum { HAVE_GNU_CALLOC = 1 };
#else
enum { HAVE_GNU_CALLOC = 0 };
#endif
/* Allocate N bytes of memory dynamically, with error checking. */
void *
xmalloc (size_t n)
{
void *p = malloc (n);
if (!p && n != 0)
xalloc_die ();
return p;
}
/* Change the size of an allocated block of memory P to N bytes,
with error checking. */
void *
xrealloc (void *p, size_t n)
{
if (!n && p)
{
/* The GNU and C99 realloc behaviors disagree here. Act like
GNU, even if the underlying realloc is C99. */
free (p);
return NULL;
}
p = realloc (p, n);
if (!p && n)
xalloc_die ();
return p;
}
/* If P is null, allocate a block of at least *PN bytes; otherwise,
reallocate P so that it contains more than *PN bytes. *PN must be
nonzero unless P is null. Set *PN to the new block's size, and
return the pointer to the new block. *PN is never set to zero, and
the returned pointer is never null. */
void *
x2realloc (void *p, size_t *pn)
{
return x2nrealloc (p, pn, 1);
}
/* Allocate S bytes of zeroed memory dynamically, with error checking.
There's no need for xnzalloc (N, S), since it would be equivalent
to xcalloc (N, S). */
void *
xzalloc (size_t s)
{
return memset (xmalloc (s), 0, s);
}
/* Allocate zeroed memory for N elements of S bytes, with error
checking. S must be nonzero. */
void *
xcalloc (size_t n, size_t s)
{
void *p;
/* Test for overflow, since some calloc implementations don't have
proper overflow checks. But omit overflow and size-zero tests if
HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
returns NULL if successful. */
if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
|| (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
xalloc_die ();
return p;
}
/* Clone an object P of size S, with error checking. There's no need
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
need for an arithmetic overflow check. */
void *
xmemdup (void const *p, size_t s)
{
return memcpy (xmalloc (s), p, s);
}
/* Clone STRING. */
char *
xstrdup (char const *string)
{
return xmemdup (string, strlen (string) + 1);
}
supermin-4.1.6/lib/float+.h 0000664 0001750 0001750 00000012745 12177155607 012432 0000000 0000000 /* Supplemental information about the floating-point formats.
Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc.
Written by Bruno Haible , 2007.
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 . */
#ifndef _FLOATPLUS_H
#define _FLOATPLUS_H
#include
#include
/* Number of bits in the mantissa of a floating-point number, including the
"hidden bit". */
#if FLT_RADIX == 2
# define FLT_MANT_BIT FLT_MANT_DIG
# define DBL_MANT_BIT DBL_MANT_DIG
# define LDBL_MANT_BIT LDBL_MANT_DIG
#elif FLT_RADIX == 4
# define FLT_MANT_BIT (FLT_MANT_DIG * 2)
# define DBL_MANT_BIT (DBL_MANT_DIG * 2)
# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2)
#elif FLT_RADIX == 16
# define FLT_MANT_BIT (FLT_MANT_DIG * 4)
# define DBL_MANT_BIT (DBL_MANT_DIG * 4)
# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4)
#endif
/* Bit mask that can be used to mask the exponent, as an unsigned number. */
#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7)
#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7)
/* Number of bits used for the exponent of a floating-point number, including
the exponent's sign. */
#define FLT_EXP_BIT \
(FLT_EXP_MASK < 0x100 ? 8 : \
FLT_EXP_MASK < 0x200 ? 9 : \
FLT_EXP_MASK < 0x400 ? 10 : \
FLT_EXP_MASK < 0x800 ? 11 : \
FLT_EXP_MASK < 0x1000 ? 12 : \
FLT_EXP_MASK < 0x2000 ? 13 : \
FLT_EXP_MASK < 0x4000 ? 14 : \
FLT_EXP_MASK < 0x8000 ? 15 : \
FLT_EXP_MASK < 0x10000 ? 16 : \
FLT_EXP_MASK < 0x20000 ? 17 : \
FLT_EXP_MASK < 0x40000 ? 18 : \
FLT_EXP_MASK < 0x80000 ? 19 : \
FLT_EXP_MASK < 0x100000 ? 20 : \
FLT_EXP_MASK < 0x200000 ? 21 : \
FLT_EXP_MASK < 0x400000 ? 22 : \
FLT_EXP_MASK < 0x800000 ? 23 : \
FLT_EXP_MASK < 0x1000000 ? 24 : \
FLT_EXP_MASK < 0x2000000 ? 25 : \
FLT_EXP_MASK < 0x4000000 ? 26 : \
FLT_EXP_MASK < 0x8000000 ? 27 : \
FLT_EXP_MASK < 0x10000000 ? 28 : \
FLT_EXP_MASK < 0x20000000 ? 29 : \
FLT_EXP_MASK < 0x40000000 ? 30 : \
FLT_EXP_MASK <= 0x7fffffff ? 31 : \
32)
#define DBL_EXP_BIT \
(DBL_EXP_MASK < 0x100 ? 8 : \
DBL_EXP_MASK < 0x200 ? 9 : \
DBL_EXP_MASK < 0x400 ? 10 : \
DBL_EXP_MASK < 0x800 ? 11 : \
DBL_EXP_MASK < 0x1000 ? 12 : \
DBL_EXP_MASK < 0x2000 ? 13 : \
DBL_EXP_MASK < 0x4000 ? 14 : \
DBL_EXP_MASK < 0x8000 ? 15 : \
DBL_EXP_MASK < 0x10000 ? 16 : \
DBL_EXP_MASK < 0x20000 ? 17 : \
DBL_EXP_MASK < 0x40000 ? 18 : \
DBL_EXP_MASK < 0x80000 ? 19 : \
DBL_EXP_MASK < 0x100000 ? 20 : \
DBL_EXP_MASK < 0x200000 ? 21 : \
DBL_EXP_MASK < 0x400000 ? 22 : \
DBL_EXP_MASK < 0x800000 ? 23 : \
DBL_EXP_MASK < 0x1000000 ? 24 : \
DBL_EXP_MASK < 0x2000000 ? 25 : \
DBL_EXP_MASK < 0x4000000 ? 26 : \
DBL_EXP_MASK < 0x8000000 ? 27 : \
DBL_EXP_MASK < 0x10000000 ? 28 : \
DBL_EXP_MASK < 0x20000000 ? 29 : \
DBL_EXP_MASK < 0x40000000 ? 30 : \
DBL_EXP_MASK <= 0x7fffffff ? 31 : \
32)
#define LDBL_EXP_BIT \
(LDBL_EXP_MASK < 0x100 ? 8 : \
LDBL_EXP_MASK < 0x200 ? 9 : \
LDBL_EXP_MASK < 0x400 ? 10 : \
LDBL_EXP_MASK < 0x800 ? 11 : \
LDBL_EXP_MASK < 0x1000 ? 12 : \
LDBL_EXP_MASK < 0x2000 ? 13 : \
LDBL_EXP_MASK < 0x4000 ? 14 : \
LDBL_EXP_MASK < 0x8000 ? 15 : \
LDBL_EXP_MASK < 0x10000 ? 16 : \
LDBL_EXP_MASK < 0x20000 ? 17 : \
LDBL_EXP_MASK < 0x40000 ? 18 : \
LDBL_EXP_MASK < 0x80000 ? 19 : \
LDBL_EXP_MASK < 0x100000 ? 20 : \
LDBL_EXP_MASK < 0x200000 ? 21 : \
LDBL_EXP_MASK < 0x400000 ? 22 : \
LDBL_EXP_MASK < 0x800000 ? 23 : \
LDBL_EXP_MASK < 0x1000000 ? 24 : \
LDBL_EXP_MASK < 0x2000000 ? 25 : \
LDBL_EXP_MASK < 0x4000000 ? 26 : \
LDBL_EXP_MASK < 0x8000000 ? 27 : \
LDBL_EXP_MASK < 0x10000000 ? 28 : \
LDBL_EXP_MASK < 0x20000000 ? 29 : \
LDBL_EXP_MASK < 0x40000000 ? 30 : \
LDBL_EXP_MASK <= 0x7fffffff ? 31 : \
32)
/* Number of bits used for a floating-point number: the mantissa (not
counting the "hidden bit", since it may or may not be explicit), the
exponent, and the sign. */
#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1)
#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1)
#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1)
/* Number of bytes used for a floating-point number.
This can be smaller than the 'sizeof'. For example, on i386 systems,
'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence
LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but
sizeof (long double) = 12 or = 16. */
#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
/* Verify that SIZEOF_FLT <= sizeof (float) etc. */
typedef int verify_sizeof_flt[SIZEOF_FLT <= sizeof (float) ? 1 : -1];
typedef int verify_sizeof_dbl[SIZEOF_DBL <= sizeof (double) ? 1 : - 1];
typedef int verify_sizeof_ldbl[SIZEOF_LDBL <= sizeof (long double) ? 1 : - 1];
#endif /* _FLOATPLUS_H */
supermin-4.1.6/lib/fts_.h 0000664 0001750 0001750 00000031624 12177155607 012202 0000000 0000000 /* Traverse a file hierarchy.
Copyright (C) 2004-2013 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 . */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fts.h 8.3 (Berkeley) 8/14/94
*/
#ifndef _FTS_H
# define _FTS_H 1
# ifdef _LIBC
# include
# else
# undef __THROW
# define __THROW
# undef __BEGIN_DECLS
# undef __END_DECLS
# ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
# else
# define __BEGIN_DECLS
# define __END_DECLS
# endif
# endif
# include
# include
# include
# include
# include "i-ring.h"
typedef struct {
struct _ftsent *fts_cur; /* current node */
struct _ftsent *fts_child; /* linked list of children */
struct _ftsent **fts_array; /* sort array */
dev_t fts_dev; /* starting device # */
char *fts_path; /* file name for this descent */
int fts_rfd; /* fd for root */
int fts_cwd_fd; /* the file descriptor on which the
virtual cwd is open, or AT_FDCWD */
size_t fts_pathlen; /* sizeof(path) */
size_t fts_nitems; /* elements in the sort array */
int (*fts_compar) (struct _ftsent const **, struct _ftsent const **);
/* compare fn */
# define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */
# define FTS_LOGICAL 0x0002 /* logical walk */
# define FTS_NOCHDIR 0x0004 /* don't change directories */
# define FTS_NOSTAT 0x0008 /* don't get stat info */
# define FTS_PHYSICAL 0x0010 /* physical walk */
# define FTS_SEEDOT 0x0020 /* return dot and dot-dot */
# define FTS_XDEV 0x0040 /* don't cross devices */
# define FTS_WHITEOUT 0x0080 /* return whiteout information */
/* There are two ways to detect cycles.
The lazy way (which works only with FTS_PHYSICAL),
with which one may process a directory that is a
part of the cycle several times before detecting the cycle.
The "tight" way, whereby fts uses more memory (proportional
to number of "active" directories, aka distance from root
of current tree to current directory -- see active_dir_ht)
to detect any cycle right away. For example, du must use
this option to avoid counting disk space in a cycle multiple
times, but chown -R need not.
The default is to use the constant-memory lazy way, when possible
(see below).
However, with FTS_LOGICAL (when following symlinks, e.g., chown -L)
using lazy cycle detection is inadequate. For example, traversing
a directory containing a symbolic link to a peer directory, it is
possible to encounter the same directory twice even though there
is no cycle:
dir
...
slink -> dir
So, when FTS_LOGICAL is selected, we have to use a different
mode of cycle detection: FTS_TIGHT_CYCLE_CHECK. */
# define FTS_TIGHT_CYCLE_CHECK 0x0100
/* Use this flag to enable semantics with which the parent
application may be made both more efficient and more robust.
Whereas the default is to visit each directory in a recursive
traversal (via chdir), using this flag makes it so the initial
working directory is never changed. Instead, these functions
perform the traversal via a virtual working directory, maintained
through the file descriptor member, fts_cwd_fd. */
# define FTS_CWDFD 0x0200
/* Historically, for each directory that fts initially encounters, it would
open it, read all entries, and stat each entry, storing the results, and
then it would process the first entry. But that behavior is bad for
locality of reference, and also causes trouble with inode-simulating
file systems like FAT, CIFS, FUSE-based ones, etc., when entries from
their name/inode cache are flushed too early.
Use this flag to make fts_open and fts_read defer the stat/lstat/fststat
of each entry until it is actually processed. However, note that if you
use this option and also specify a comparison function, that function may
not examine any data via fts_statp. However, when fts_statp->st_mode is
nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data.
Of course, that happens only on file systems that provide useful
dirent.d_type data. */
# define FTS_DEFER_STAT 0x0400
# define FTS_NOATIME 0x0800 /* use O_NOATIME during traversal */
/* Use this flag to disable stripping of trailing slashes
from input path names during fts_open initialization. */
# define FTS_VERBATIM 0x1000
# define FTS_OPTIONMASK 0x1fff /* valid user option mask */
# define FTS_NAMEONLY 0x2000 /* (private) child names only */
# define FTS_STOP 0x4000 /* (private) unrecoverable error */
int fts_options; /* fts_open options, global flags */
/* Map a directory's device number to a boolean. The boolean is
true if for that file system (type determined by a single fstatfs
call per FS) st_nlink can be used to calculate the number of
sub-directory entries in a directory.
Using this table is an optimization that permits us to look up
file system type on a per-inode basis at the minimal cost of
calling fstatfs only once per traversed device. */
struct hash_table *fts_leaf_optimization_works_ht;
union {
/* This data structure is used if FTS_TIGHT_CYCLE_CHECK is
specified. It records the directories between a starting
point and the current directory. I.e., a directory is
recorded here IFF we have visited it once, but we have not
yet completed processing of all its entries. Every time we
visit a new directory, we add that directory to this set.
When we finish with a directory (usually by visiting it a
second time), we remove it from this set. Each entry in
this data structure is a device/inode pair. This data
structure is used to detect directory cycles efficiently and
promptly even when the depth of a hierarchy is in the tens
of thousands. */
struct hash_table *ht;
/* FIXME: rename these two members to have the fts_ prefix */
/* This data structure uses a lazy cycle-detection algorithm,
as done by rm via cycle-check.c. It's the default,
but it's not appropriate for programs like du. */
struct cycle_check_state *state;
} fts_cycle;
/* A stack of the file descriptors corresponding to the
most-recently traversed parent directories.
Currently used only in FTS_CWDFD mode. */
I_ring fts_fd_ring;
} FTS;
typedef struct _ftsent {
struct _ftsent *fts_cycle; /* cycle node */
struct _ftsent *fts_parent; /* parent directory */
struct _ftsent *fts_link; /* next file in directory */
DIR *fts_dirp; /* Dir pointer for any directory
containing more entries than we
read at one time. */
long fts_number; /* local numeric value */
void *fts_pointer; /* local address value */
char *fts_accpath; /* access file name */
char *fts_path; /* root name; == fts_fts->fts_path */
int fts_errno; /* errno for this node */
int fts_symfd; /* fd for symlink */
size_t fts_pathlen; /* strlen(fts_path) */
FTS *fts_fts; /* the file hierarchy itself */
# define FTS_ROOTPARENTLEVEL (-1)
# define FTS_ROOTLEVEL 0
ptrdiff_t fts_level; /* depth (-1 to N) */
size_t fts_namelen; /* strlen(fts_name) */
nlink_t fts_n_dirs_remaining; /* count down from st_nlink */
# define FTS_D 1 /* preorder directory */
# define FTS_DC 2 /* directory that causes cycles */
# define FTS_DEFAULT 3 /* none of the above */
# define FTS_DNR 4 /* unreadable directory */
# define FTS_DOT 5 /* dot or dot-dot */
# define FTS_DP 6 /* postorder directory */
# define FTS_ERR 7 /* error; errno is set */
# define FTS_F 8 /* regular file */
# define FTS_INIT 9 /* initialized only */
# define FTS_NS 10 /* stat(2) failed */
# define FTS_NSOK 11 /* no stat(2) requested */
# define FTS_SL 12 /* symbolic link */
# define FTS_SLNONE 13 /* symbolic link without target */
# define FTS_W 14 /* whiteout object */
unsigned short int fts_info; /* user flags for FTSENT structure */
# define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
# define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */
unsigned short int fts_flags; /* private flags for FTSENT structure */
# define FTS_AGAIN 1 /* read node again */
# define FTS_FOLLOW 2 /* follow symbolic link */
# define FTS_NOINSTR 3 /* no instructions */
# define FTS_SKIP 4 /* discard node */
unsigned short int fts_instr; /* fts_set() instructions */
struct stat fts_statp[1]; /* stat(2) information */
char fts_name[1]; /* file name */
} FTSENT;
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
#if __GNUC_PREREQ (3,4)
# undef __attribute_warn_unused_result__
# define __attribute_warn_unused_result__ \
__attribute__ ((__warn_unused_result__))
#else
# define __attribute_warn_unused_result__ /* empty */
#endif
__BEGIN_DECLS
FTSENT *fts_children (FTS *, int) __THROW __attribute_warn_unused_result__;
int fts_close (FTS *) __THROW __attribute_warn_unused_result__;
FTS *fts_open (char * const *, int,
int (*)(const FTSENT **, const FTSENT **))
__THROW __attribute_warn_unused_result__;
FTSENT *fts_read (FTS *) __THROW __attribute_warn_unused_result__;
int fts_set (FTS *, FTSENT *, int) __THROW;
__END_DECLS
#endif /* fts.h */
supermin-4.1.6/lib/dirfd.c 0000664 0001750 0001750 00000001735 12177155607 012332 0000000 0000000 /* dirfd.c -- return the file descriptor associated with an open DIR*
Copyright (C) 2001, 2006, 2008-2013 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 . */
/* Written by Jim Meyering. */
#include
#include
#include
int
dirfd (DIR *dir_p)
{
int fd = DIR_TO_FD (dir_p);
if (fd == -1)
errno = ENOTSUP;
return fd;
}
supermin-4.1.6/lib/stdint.in.h 0000664 0001750 0001750 00000044610 12177155607 013160 0000000 0000000 /* Copyright (C) 2001-2002, 2004-2013 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
This file is part of gnulib.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see . */
/*
* ISO C 99 for platforms that lack it.
*
*/
#ifndef _@GUARD_PREFIX@_STDINT_H
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
/* When including a system file that in turn includes ,
use the system , not our substitute. This avoids
problems with (for example) VMS, whose includes
. */
#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
/* On Android (Bionic libc), includes this file before
having defined 'time_t'. Therefore in this case avoid including
other system header files; just include the system's .
Ideally we should test __BIONIC__ here, but it is only defined after
has been included; hence test __ANDROID__ instead. */
#if defined __ANDROID__ \
&& defined _SYS_TYPES_H_ && !defined __need_size_t
# @INCLUDE_NEXT@ @NEXT_STDINT_H@
#else
/* Get those types that are already defined in other system include
files, so that we can "#define int8_t signed char" below without
worrying about a later system include file containing a "typedef
signed char int8_t;" that will get messed up by our macro. Our
macros should all be consistent with the system versions, except
for the "fast" types and macros, which we recommend against using
in public interfaces due to compiler differences. */
#if @HAVE_STDINT_H@
# if defined __sgi && ! defined __c99
/* Bypass IRIX's if in C89 mode, since it merely annoys users
with "This header file is to be used only for c99 mode compilations"
diagnostics. */
# define __STDINT_H__
# endif
/* Some pre-C++11 implementations need this. */
# ifdef __cplusplus
# ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS 1
# endif
# ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS 1
# endif
# endif
/* Other systems may have an incomplete or buggy .
Include it before , since any "#include "
in would reinclude us, skipping our contents because
_@GUARD_PREFIX@_STDINT_H is defined.
The include_next requires a split double-inclusion guard. */
# @INCLUDE_NEXT@ @NEXT_STDINT_H@
#endif
#if ! defined _@GUARD_PREFIX@_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H
#define _@GUARD_PREFIX@_STDINT_H
/* defines some of the stdint.h types as well, on glibc,
IRIX 6.5, and OpenBSD 3.8 (via ).
AIX 5.2 isn't needed and causes troubles.
Mac OS X 10.4.6 includes (which is us), but
relies on the system definitions, so include
after @NEXT_STDINT_H@. */
#if @HAVE_SYS_TYPES_H@ && ! defined _AIX
# include
#endif
/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX,
LONG_MIN, LONG_MAX, ULONG_MAX. */
#include
#if @HAVE_INTTYPES_H@
/* In OpenBSD 3.8, includes , which defines
int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__.
also defines intptr_t and uintptr_t. */
# include
#elif @HAVE_SYS_INTTYPES_H@
/* Solaris 7 has the types except the *_fast*_t types, and
the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */
# include
#endif
#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__
/* Linux libc4 >= 4.6.7 and libc5 have a that defines
int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is
included by . */
# include
#endif
#undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
/* Minimum and maximum values for an integer type under the usual assumption.
Return an unspecified value if BITS == 0, adding a check to pacify
picky compilers. */
#define _STDINT_MIN(signed, bits, zero) \
((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero))
#define _STDINT_MAX(signed, bits, zero) \
((signed) \
? ~ _STDINT_MIN (signed, bits, zero) \
: /* The expression for the unsigned case. The subtraction of (signed) \
is a nop in the unsigned case and avoids "signed integer overflow" \
warnings in the signed case. */ \
((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1)
#if !GNULIB_defined_stdint_types
/* 7.18.1.1. Exact-width integer types */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits. */
#undef int8_t
#undef uint8_t
typedef signed char gl_int8_t;
typedef unsigned char gl_uint8_t;
#define int8_t gl_int8_t
#define uint8_t gl_uint8_t
#undef int16_t
#undef uint16_t
typedef short int gl_int16_t;
typedef unsigned short int gl_uint16_t;
#define int16_t gl_int16_t
#define uint16_t gl_uint16_t
#undef int32_t
#undef uint32_t
typedef int gl_int32_t;
typedef unsigned int gl_uint32_t;
#define int32_t gl_int32_t
#define uint32_t gl_uint32_t
/* If the system defines INT64_MAX, assume int64_t works. That way,
if the underlying platform defines int64_t to be a 64-bit long long
int, the code below won't mistakenly define it to be a 64-bit long
int, which would mess up C++ name mangling. We must use #ifdef
rather than #if, to avoid an error with HP-UX 10.20 cc. */
#ifdef INT64_MAX
# define GL_INT64_T
#else
/* Do not undefine int64_t if gnulib is not being used with 64-bit
types, since otherwise it breaks platforms like Tandem/NSK. */
# if LONG_MAX >> 31 >> 31 == 1
# undef int64_t
typedef long int gl_int64_t;
# define int64_t gl_int64_t
# define GL_INT64_T
# elif defined _MSC_VER
# undef int64_t
typedef __int64 gl_int64_t;
# define int64_t gl_int64_t
# define GL_INT64_T
# elif @HAVE_LONG_LONG_INT@
# undef int64_t
typedef long long int gl_int64_t;
# define int64_t gl_int64_t
# define GL_INT64_T
# endif
#endif
#ifdef UINT64_MAX
# define GL_UINT64_T
#else
# if ULONG_MAX >> 31 >> 31 >> 1 == 1
# undef uint64_t
typedef unsigned long int gl_uint64_t;
# define uint64_t gl_uint64_t
# define GL_UINT64_T
# elif defined _MSC_VER
# undef uint64_t
typedef unsigned __int64 gl_uint64_t;
# define uint64_t gl_uint64_t
# define GL_UINT64_T
# elif @HAVE_UNSIGNED_LONG_LONG_INT@
# undef uint64_t
typedef unsigned long long int gl_uint64_t;
# define uint64_t gl_uint64_t
# define GL_UINT64_T
# endif
#endif
/* Avoid collision with Solaris 2.5.1 etc. */
#define _UINT8_T
#define _UINT32_T
#define _UINT64_T
/* 7.18.1.2. Minimum-width integer types */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
are the same as the corresponding N_t types. */
#undef int_least8_t
#undef uint_least8_t
#undef int_least16_t
#undef uint_least16_t
#undef int_least32_t
#undef uint_least32_t
#undef int_least64_t
#undef uint_least64_t
#define int_least8_t int8_t
#define uint_least8_t uint8_t
#define int_least16_t int16_t
#define uint_least16_t uint16_t
#define int_least32_t int32_t
#define uint_least32_t uint32_t
#ifdef GL_INT64_T
# define int_least64_t int64_t
#endif
#ifdef GL_UINT64_T
# define uint_least64_t uint64_t
#endif
/* 7.18.1.3. Fastest minimum-width integer types */
/* Note: Other substitutes may define these types differently.
It is not recommended to use these types in public header files. */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
are taken from the same list of types. The following code normally
uses types consistent with glibc, as that lessens the chance of
incompatibility with older GNU hosts. */
#undef int_fast8_t
#undef uint_fast8_t
#undef int_fast16_t
#undef uint_fast16_t
#undef int_fast32_t
#undef uint_fast32_t
#undef int_fast64_t
#undef uint_fast64_t
typedef signed char gl_int_fast8_t;
typedef unsigned char gl_uint_fast8_t;
#ifdef __sun
/* Define types compatible with SunOS 5.10, so that code compiled under
earlier SunOS versions works with code compiled under SunOS 5.10. */
typedef int gl_int_fast32_t;
typedef unsigned int gl_uint_fast32_t;
#else
typedef long int gl_int_fast32_t;
typedef unsigned long int gl_uint_fast32_t;
#endif
typedef gl_int_fast32_t gl_int_fast16_t;
typedef gl_uint_fast32_t gl_uint_fast16_t;
#define int_fast8_t gl_int_fast8_t
#define uint_fast8_t gl_uint_fast8_t
#define int_fast16_t gl_int_fast16_t
#define uint_fast16_t gl_uint_fast16_t
#define int_fast32_t gl_int_fast32_t
#define uint_fast32_t gl_uint_fast32_t
#ifdef GL_INT64_T
# define int_fast64_t int64_t
#endif
#ifdef GL_UINT64_T
# define uint_fast64_t uint64_t
#endif
/* 7.18.1.4. Integer types capable of holding object pointers */
#undef intptr_t
#undef uintptr_t
typedef long int gl_intptr_t;
typedef unsigned long int gl_uintptr_t;
#define intptr_t gl_intptr_t
#define uintptr_t gl_uintptr_t
/* 7.18.1.5. Greatest-width integer types */
/* Note: These types are compiler dependent. It may be unwise to use them in
public header files. */
/* If the system defines INTMAX_MAX, assume that intmax_t works, and
similarly for UINTMAX_MAX and uintmax_t. This avoids problems with
assuming one type where another is used by the system. */
#ifndef INTMAX_MAX
# undef INTMAX_C
# undef intmax_t
# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
typedef long long int gl_intmax_t;
# define intmax_t gl_intmax_t
# elif defined GL_INT64_T
# define intmax_t int64_t
# else
typedef long int gl_intmax_t;
# define intmax_t gl_intmax_t
# endif
#endif
#ifndef UINTMAX_MAX
# undef UINTMAX_C
# undef uintmax_t
# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
typedef unsigned long long int gl_uintmax_t;
# define uintmax_t gl_uintmax_t
# elif defined GL_UINT64_T
# define uintmax_t uint64_t
# else
typedef unsigned long int gl_uintmax_t;
# define uintmax_t gl_uintmax_t
# endif
#endif
/* Verify that intmax_t and uintmax_t have the same size. Too much code
breaks if this is not the case. If this check fails, the reason is likely
to be found in the autoconf macros. */
typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
? 1 : -1];
#define GNULIB_defined_stdint_types 1
#endif /* !GNULIB_defined_stdint_types */
/* 7.18.2. Limits of specified-width integer types */
/* 7.18.2.1. Limits of exact-width integer types */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits. */
#undef INT8_MIN
#undef INT8_MAX
#undef UINT8_MAX
#define INT8_MIN (~ INT8_MAX)
#define INT8_MAX 127
#define UINT8_MAX 255
#undef INT16_MIN
#undef INT16_MAX
#undef UINT16_MAX
#define INT16_MIN (~ INT16_MAX)
#define INT16_MAX 32767
#define UINT16_MAX 65535
#undef INT32_MIN
#undef INT32_MAX
#undef UINT32_MAX
#define INT32_MIN (~ INT32_MAX)
#define INT32_MAX 2147483647
#define UINT32_MAX 4294967295U
#if defined GL_INT64_T && ! defined INT64_MAX
/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0
evaluates the latter incorrectly in preprocessor expressions. */
# define INT64_MIN (- INTMAX_C (1) << 63)
# define INT64_MAX INTMAX_C (9223372036854775807)
#endif
#if defined GL_UINT64_T && ! defined UINT64_MAX
# define UINT64_MAX UINTMAX_C (18446744073709551615)
#endif
/* 7.18.2.2. Limits of minimum-width integer types */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
are the same as the corresponding N_t types. */
#undef INT_LEAST8_MIN
#undef INT_LEAST8_MAX
#undef UINT_LEAST8_MAX
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#undef INT_LEAST16_MIN
#undef INT_LEAST16_MAX
#undef UINT_LEAST16_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#undef INT_LEAST32_MIN
#undef INT_LEAST32_MAX
#undef UINT_LEAST32_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#undef INT_LEAST64_MIN
#undef INT_LEAST64_MAX
#ifdef GL_INT64_T
# define INT_LEAST64_MIN INT64_MIN
# define INT_LEAST64_MAX INT64_MAX
#endif
#undef UINT_LEAST64_MAX
#ifdef GL_UINT64_T
# define UINT_LEAST64_MAX UINT64_MAX
#endif
/* 7.18.2.3. Limits of fastest minimum-width integer types */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
are taken from the same list of types. */
#undef INT_FAST8_MIN
#undef INT_FAST8_MAX
#undef UINT_FAST8_MAX
#define INT_FAST8_MIN SCHAR_MIN
#define INT_FAST8_MAX SCHAR_MAX
#define UINT_FAST8_MAX UCHAR_MAX
#undef INT_FAST16_MIN
#undef INT_FAST16_MAX
#undef UINT_FAST16_MAX
#define INT_FAST16_MIN INT_FAST32_MIN
#define INT_FAST16_MAX INT_FAST32_MAX
#define UINT_FAST16_MAX UINT_FAST32_MAX
#undef INT_FAST32_MIN
#undef INT_FAST32_MAX
#undef UINT_FAST32_MAX
#ifdef __sun
# define INT_FAST32_MIN INT_MIN
# define INT_FAST32_MAX INT_MAX
# define UINT_FAST32_MAX UINT_MAX
#else
# define INT_FAST32_MIN LONG_MIN
# define INT_FAST32_MAX LONG_MAX
# define UINT_FAST32_MAX ULONG_MAX
#endif
#undef INT_FAST64_MIN
#undef INT_FAST64_MAX
#ifdef GL_INT64_T
# define INT_FAST64_MIN INT64_MIN
# define INT_FAST64_MAX INT64_MAX
#endif
#undef UINT_FAST64_MAX
#ifdef GL_UINT64_T
# define UINT_FAST64_MAX UINT64_MAX
#endif
/* 7.18.2.4. Limits of integer types capable of holding object pointers */
#undef INTPTR_MIN
#undef INTPTR_MAX
#undef UINTPTR_MAX
#define INTPTR_MIN LONG_MIN
#define INTPTR_MAX LONG_MAX
#define UINTPTR_MAX ULONG_MAX
/* 7.18.2.5. Limits of greatest-width integer types */
#ifndef INTMAX_MAX
# undef INTMAX_MIN
# ifdef INT64_MAX
# define INTMAX_MIN INT64_MIN
# define INTMAX_MAX INT64_MAX
# else
# define INTMAX_MIN INT32_MIN
# define INTMAX_MAX INT32_MAX
# endif
#endif
#ifndef UINTMAX_MAX
# ifdef UINT64_MAX
# define UINTMAX_MAX UINT64_MAX
# else
# define UINTMAX_MAX UINT32_MAX
# endif
#endif
/* 7.18.3. Limits of other integer types */
/* ptrdiff_t limits */
#undef PTRDIFF_MIN
#undef PTRDIFF_MAX
#if @APPLE_UNIVERSAL_BUILD@
# ifdef _LP64
# define PTRDIFF_MIN _STDINT_MIN (1, 64, 0l)
# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l)
# else
# define PTRDIFF_MIN _STDINT_MIN (1, 32, 0)
# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0)
# endif
#else
# define PTRDIFF_MIN \
_STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@)
# define PTRDIFF_MAX \
_STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@)
#endif
/* sig_atomic_t limits */
#undef SIG_ATOMIC_MIN
#undef SIG_ATOMIC_MAX
#define SIG_ATOMIC_MIN \
_STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
0@SIG_ATOMIC_T_SUFFIX@)
#define SIG_ATOMIC_MAX \
_STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
0@SIG_ATOMIC_T_SUFFIX@)
/* size_t limit */
#undef SIZE_MAX
#if @APPLE_UNIVERSAL_BUILD@
# ifdef _LP64
# define SIZE_MAX _STDINT_MAX (0, 64, 0ul)
# else
# define SIZE_MAX _STDINT_MAX (0, 32, 0ul)
# endif
#else
# define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@)
#endif
/* wchar_t limits */
/* Get WCHAR_MIN, WCHAR_MAX.
This include is not on the top, above, because on OSF/1 4.0 we have a
sequence of nested includes
-> -> -> , and the latter includes
and assumes its types are already defined. */
#if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX)
/* BSD/OS 4.0.1 has a bug: , and must be
included before . */
# include
# include
# include
# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
# include
# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
#endif
#undef WCHAR_MIN
#undef WCHAR_MAX
#define WCHAR_MIN \
_STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
#define WCHAR_MAX \
_STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
/* wint_t limits */
#undef WINT_MIN
#undef WINT_MAX
#define WINT_MIN \
_STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
#define WINT_MAX \
_STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
/* 7.18.4. Macros for integer constants */
/* 7.18.4.1. Macros for minimum-width integer constants */
/* According to ISO C 99 Technical Corrigendum 1 */
/* Here we assume a standard architecture where the hardware integer
types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */
#undef INT8_C
#undef UINT8_C
#define INT8_C(x) x
#define UINT8_C(x) x
#undef INT16_C
#undef UINT16_C
#define INT16_C(x) x
#define UINT16_C(x) x
#undef INT32_C
#undef UINT32_C
#define INT32_C(x) x
#define UINT32_C(x) x ## U
#undef INT64_C
#undef UINT64_C
#if LONG_MAX >> 31 >> 31 == 1
# define INT64_C(x) x##L
#elif defined _MSC_VER
# define INT64_C(x) x##i64
#elif @HAVE_LONG_LONG_INT@
# define INT64_C(x) x##LL
#endif
#if ULONG_MAX >> 31 >> 31 >> 1 == 1
# define UINT64_C(x) x##UL
#elif defined _MSC_VER
# define UINT64_C(x) x##ui64
#elif @HAVE_UNSIGNED_LONG_LONG_INT@
# define UINT64_C(x) x##ULL
#endif
/* 7.18.4.2. Macros for greatest-width integer constants */
#ifndef INTMAX_C
# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
# define INTMAX_C(x) x##LL
# elif defined GL_INT64_T
# define INTMAX_C(x) INT64_C(x)
# else
# define INTMAX_C(x) x##L
# endif
#endif
#ifndef UINTMAX_C
# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
# define UINTMAX_C(x) x##ULL
# elif defined GL_UINT64_T
# define UINTMAX_C(x) UINT64_C(x)
# else
# define UINTMAX_C(x) x##UL
# endif
#endif
#endif /* _@GUARD_PREFIX@_STDINT_H */
#endif /* !(defined __ANDROID__ && ...) */
#endif /* !defined _@GUARD_PREFIX@_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */
supermin-4.1.6/lib/asprintf.c 0000664 0001750 0001750 00000002101 12177155607 013054 0000000 0000000 /* Formatted output to strings.
Copyright (C) 1999, 2002, 2006-2007, 2009-2013 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 . */
#include
/* Specification. */
#ifdef IN_LIBASPRINTF
# include "vasprintf.h"
#else
# include
#endif
#include
int
asprintf (char **resultp, const char *format, ...)
{
va_list args;
int result;
va_start (args, format);
result = vasprintf (resultp, format, args);
va_end (args);
return result;
}
supermin-4.1.6/lib/vasprintf.c 0000664 0001750 0001750 00000002472 12177155610 013247 0000000 0000000 /* Formatted output to strings.
Copyright (C) 1999, 2002, 2006-2013 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 . */
#include
/* Specification. */
#ifdef IN_LIBASPRINTF
# include "vasprintf.h"
#else
# include
#endif
#include
#include
#include
#include "vasnprintf.h"
int
vasprintf (char **resultp, const char *format, va_list args)
{
size_t length;
char *result = vasnprintf (NULL, &length, format, args);
if (result == NULL)
return -1;
if (length > INT_MAX)
{
free (result);
errno = EOVERFLOW;
return -1;
}
*resultp = result;
/* Return the number of resulting bytes, excluding the trailing NUL. */
return length;
}
supermin-4.1.6/lib/vasnprintf.c 0000664 0001750 0001750 00000664642 12177155610 013442 0000000 0000000 /* vsprintf with automatic memory allocation.
Copyright (C) 1999, 2002-2013 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 . */
/* This file can be parametrized with the following macros:
VASNPRINTF The name of the function being defined.
FCHAR_T The element type of the format string.
DCHAR_T The element type of the destination (result) string.
FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
in the format string are ASCII. MUST be set if
FCHAR_T and DCHAR_T are not the same type.
DIRECTIVE Structure denoting a format directive.
Depends on FCHAR_T.
DIRECTIVES Structure denoting the set of format directives of a
format string. Depends on FCHAR_T.
PRINTF_PARSE Function that parses a format string.
Depends on FCHAR_T.
DCHAR_CPY memcpy like function for DCHAR_T[] arrays.
DCHAR_SET memset like function for DCHAR_T[] arrays.
DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays.
SNPRINTF The system's snprintf (or similar) function.
This may be either snprintf or swprintf.
TCHAR_T The element type of the argument and result string
of the said SNPRINTF function. This may be either
char or wchar_t. The code exploits that
sizeof (TCHAR_T) | sizeof (DCHAR_T) and
alignof (TCHAR_T) <= alignof (DCHAR_T).
DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type.
DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t.
DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t.
DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */
/* Tell glibc's to provide a prototype for snprintf().
This must come before because may include
, and once has been included, it's too late. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
#ifndef VASNPRINTF
# include
#endif
#ifndef IN_LIBINTL
# include
#endif
/* Specification. */
#ifndef VASNPRINTF
# if WIDE_CHAR_VERSION
# include "vasnwprintf.h"
# else
# include "vasnprintf.h"
# endif
#endif
#include /* localeconv() */
#include /* snprintf(), sprintf() */
#include /* abort(), malloc(), realloc(), free() */
#include /* memcpy(), strlen() */
#include /* errno */
#include /* CHAR_BIT */
#include /* DBL_MAX_EXP, LDBL_MAX_EXP */
#if HAVE_NL_LANGINFO
# include
#endif
#ifndef VASNPRINTF
# if WIDE_CHAR_VERSION
# include "wprintf-parse.h"
# else
# include "printf-parse.h"
# endif
#endif
/* Checked size_t computations. */
#include "xsize.h"
#include "verify.h"
#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
# include
# include "float+.h"
#endif
#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
# include
# include "isnand-nolibm.h"
#endif
#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
# include
# include "isnanl-nolibm.h"
# include "fpucw.h"
#endif
#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
# include
# include "isnand-nolibm.h"
# include "printf-frexp.h"
#endif
#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
# include
# include "isnanl-nolibm.h"
# include "printf-frexpl.h"
# include "fpucw.h"
#endif
/* Default parameters. */
#ifndef VASNPRINTF
# if WIDE_CHAR_VERSION
# define VASNPRINTF vasnwprintf
# define FCHAR_T wchar_t
# define DCHAR_T wchar_t
# define TCHAR_T wchar_t
# define DCHAR_IS_TCHAR 1
# define DIRECTIVE wchar_t_directive
# define DIRECTIVES wchar_t_directives
# define PRINTF_PARSE wprintf_parse
# define DCHAR_CPY wmemcpy
# define DCHAR_SET wmemset
# else
# define VASNPRINTF vasnprintf
# define FCHAR_T char
# define DCHAR_T char
# define TCHAR_T char
# define DCHAR_IS_TCHAR 1
# define DIRECTIVE char_directive
# define DIRECTIVES char_directives
# define PRINTF_PARSE printf_parse
# define DCHAR_CPY memcpy
# define DCHAR_SET memset
# endif
#endif
#if WIDE_CHAR_VERSION
/* TCHAR_T is wchar_t. */
# define USE_SNPRINTF 1
# if HAVE_DECL__SNWPRINTF
/* On Windows, the function swprintf() has a different signature than
on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
instead. The mingw function snwprintf() has fewer bugs than the
MSVCRT function _snwprintf(), so prefer that. */
# if defined __MINGW32__
# define SNPRINTF snwprintf
# else
# define SNPRINTF _snwprintf
# endif
# else
/* Unix. */
# define SNPRINTF swprintf
# endif
#else
/* TCHAR_T is char. */
/* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
But don't use it on BeOS, since BeOS snprintf produces no output if the
size argument is >= 0x3000000.
Also don't use it on Linux libc5, since there snprintf with size = 1
writes any output without bounds, like sprintf. */
# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
# define USE_SNPRINTF 1
# else
# define USE_SNPRINTF 0
# endif
# if HAVE_DECL__SNPRINTF
/* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT
function _snprintf(), so prefer that. */
# if defined __MINGW32__
# define SNPRINTF snprintf
/* Here we need to call the native snprintf, not rpl_snprintf. */
# undef snprintf
# else
# define SNPRINTF _snprintf
# endif
# else
/* Unix. */
# define SNPRINTF snprintf
/* Here we need to call the native snprintf, not rpl_snprintf. */
# undef snprintf
# endif
#endif
/* Here we need to call the native sprintf, not rpl_sprintf. */
#undef sprintf
/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
warnings in this file. Use -Dlint to suppress them. */
#ifdef lint
# define IF_LINT(Code) Code
#else
# define IF_LINT(Code) /* empty */
#endif
/* Avoid some warnings from "gcc -Wshadow".
This file doesn't use the exp() and remainder() functions. */
#undef exp
#define exp expo
#undef remainder
#define remainder rem
#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
# if (HAVE_STRNLEN && !defined _AIX)
# define local_strnlen strnlen
# else
# ifndef local_strnlen_defined
# define local_strnlen_defined 1
static size_t
local_strnlen (const char *string, size_t maxlen)
{
const char *end = memchr (string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen;
}
# endif
# endif
#endif
#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
# if HAVE_WCSLEN
# define local_wcslen wcslen
# else
/* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
a dependency towards this library, here is a local substitute.
Define this substitute only once, even if this file is included
twice in the same compilation unit. */
# ifndef local_wcslen_defined
# define local_wcslen_defined 1
static size_t
local_wcslen (const wchar_t *s)
{
const wchar_t *ptr;
for (ptr = s; *ptr != (wchar_t) 0; ptr++)
;
return ptr - s;
}
# endif
# endif
#endif
#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
# if HAVE_WCSNLEN
# define local_wcsnlen wcsnlen
# else
# ifndef local_wcsnlen_defined
# define local_wcsnlen_defined 1
static size_t
local_wcsnlen (const wchar_t *s, size_t maxlen)
{
const wchar_t *ptr;
for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
;
return ptr - s;
}
# endif
# endif
#endif
#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
/* Determine the decimal-point character according to the current locale. */
# ifndef decimal_point_char_defined
# define decimal_point_char_defined 1
static char
decimal_point_char (void)
{
const char *point;
/* Determine it in a multithread-safe way. We know nl_langinfo is
multithread-safe on glibc systems and Mac OS X systems, but is not required
to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
localeconv() is rarely multithread-safe. */
# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
point = nl_langinfo (RADIXCHAR);
# elif 1
char pointbuf[5];
sprintf (pointbuf, "%#.0f", 1.0);
point = &pointbuf[1];
# else
point = localeconv () -> decimal_point;
# endif
/* The decimal point is always a single byte: either '.' or ','. */
return (point[0] != '\0' ? point[0] : '.');
}
# endif
#endif
#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
static int
is_infinite_or_zero (double x)
{
return isnand (x) || x + x == x;
}
#endif
#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
static int
is_infinite_or_zerol (long double x)
{
return isnanl (x) || x + x == x;
}
#endif
#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
/* Converting 'long double' to decimal without rare rounding bugs requires
real bignums. We use the naming conventions of GNU gmp, but vastly simpler
(and slower) algorithms. */
typedef unsigned int mp_limb_t;
# define GMP_LIMB_BITS 32
verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
typedef unsigned long long mp_twolimb_t;
# define GMP_TWOLIMB_BITS 64
verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS);
/* Representation of a bignum >= 0. */
typedef struct
{
size_t nlimbs;
mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
} mpn_t;
/* Compute the product of two bignums >= 0.
Return the allocated memory in case of success, NULL in case of memory
allocation failure. */
static void *
multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
{
const mp_limb_t *p1;
const mp_limb_t *p2;
size_t len1;
size_t len2;
if (src1.nlimbs <= src2.nlimbs)
{
len1 = src1.nlimbs;
p1 = src1.limbs;
len2 = src2.nlimbs;
p2 = src2.limbs;
}
else
{
len1 = src2.nlimbs;
p1 = src2.limbs;
len2 = src1.nlimbs;
p2 = src1.limbs;
}
/* Now 0 <= len1 <= len2. */
if (len1 == 0)
{
/* src1 or src2 is zero. */
dest->nlimbs = 0;
dest->limbs = (mp_limb_t *) malloc (1);
}
else
{
/* Here 1 <= len1 <= len2. */
size_t dlen;
mp_limb_t *dp;
size_t k, i, j;
dlen = len1 + len2;
dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
if (dp == NULL)
return NULL;
for (k = len2; k > 0; )
dp[--k] = 0;
for (i = 0; i < len1; i++)
{
mp_limb_t digit1 = p1[i];
mp_twolimb_t carry = 0;
for (j = 0; j < len2; j++)
{
mp_limb_t digit2 = p2[j];
carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
carry += dp[i + j];
dp[i + j] = (mp_limb_t) carry;
carry = carry >> GMP_LIMB_BITS;
}
dp[i + len2] = (mp_limb_t) carry;
}
/* Normalise. */
while (dlen > 0 && dp[dlen - 1] == 0)
dlen--;
dest->nlimbs = dlen;
dest->limbs = dp;
}
return dest->limbs;
}
/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
the remainder.
Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
q is incremented.
Return the allocated memory in case of success, NULL in case of memory
allocation failure. */
static void *
divide (mpn_t a, mpn_t b, mpn_t *q)
{
/* Algorithm:
First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
If m=n=1, perform a single-precision division:
r:=0, j:=m,
while j>0 do
{Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
= a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r=n>1, perform a multiple-precision division:
We have a/b < beta^(m-n+1).
s:=intDsize-1-(highest bit in b[n-1]), 0<=s=beta/2.
For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
Compute q* :
q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
In case of overflow (q* >= beta) set q* := beta-1.
Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
and c3 := b[n-2] * q*.
{We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
occurred. Furthermore 0 <= c3 < beta^2.
If there was overflow and
r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
the next test can be skipped.}
While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
If q* > 0:
Put r := r - b * q* * beta^j. In detail:
[r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
hence: u:=0, for i:=0 to n-1 do
u := u + q* * b[i],
r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
u:=u div beta (+ 1, if carry in subtraction)
r[n+j]:=r[n+j]-u.
{Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
< q* + 1 <= beta,
the carry u does not overflow.}
If a negative carry occurs, put q* := q* - 1
and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
Set q[j] := q*.
Normalise [q[m-n],..,q[0]]; this yields the quotient q.
Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
rest r.
The room for q[j] can be allocated at the memory location of r[n+j].
Finally, round-to-even:
Shift r left by 1 bit.
If r > b or if r = b and q[0] is odd, q := q+1.
*/
const mp_limb_t *a_ptr = a.limbs;
size_t a_len = a.nlimbs;
const mp_limb_t *b_ptr = b.limbs;
size_t b_len = b.nlimbs;
mp_limb_t *roomptr;
mp_limb_t *tmp_roomptr = NULL;
mp_limb_t *q_ptr;
size_t q_len;
mp_limb_t *r_ptr;
size_t r_len;
/* Allocate room for a_len+2 digits.
(Need a_len+1 digits for the real division and 1 more digit for the
final rounding of q.) */
roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
if (roomptr == NULL)
return NULL;
/* Normalise a. */
while (a_len > 0 && a_ptr[a_len - 1] == 0)
a_len--;
/* Normalise b. */
for (;;)
{
if (b_len == 0)
/* Division by zero. */
abort ();
if (b_ptr[b_len - 1] == 0)
b_len--;
else
break;
}
/* Here m = a_len >= 0 and n = b_len > 0. */
if (a_len < b_len)
{
/* m beta^(m-2) <= a/b < beta^m */
r_ptr = roomptr;
q_ptr = roomptr + 1;
{
mp_limb_t den = b_ptr[0];
mp_limb_t remainder = 0;
const mp_limb_t *sourceptr = a_ptr + a_len;
mp_limb_t *destptr = q_ptr + a_len;
size_t count;
for (count = a_len; count > 0; count--)
{
mp_twolimb_t num =
((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
*--destptr = num / den;
remainder = num % den;
}
/* Normalise and store r. */
if (remainder > 0)
{
r_ptr[0] = remainder;
r_len = 1;
}
else
r_len = 0;
/* Normalise q. */
q_len = a_len;
if (q_ptr[q_len - 1] == 0)
q_len--;
}
}
else
{
/* n>1: multiple precision division.
beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
beta^(m-n-1) <= a/b < beta^(m-n+1). */
/* Determine s. */
size_t s;
{
mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
/* Determine s = GMP_LIMB_BITS - integer_length (msd).
Code copied from gnulib's integer_length.c. */
# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
s = __builtin_clz (msd);
# else
# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
if (GMP_LIMB_BITS <= DBL_MANT_BIT)
{
/* Use 'double' operations.
Assumes an IEEE 754 'double' implementation. */
# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1)
# define NWORDS \
((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
union { double value; unsigned int word[NWORDS]; } m;
/* Use a single integer to floating-point conversion. */
m.value = msd;
s = GMP_LIMB_BITS
- (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK)
- DBL_EXP_BIAS);
}
else
# undef NWORDS
# endif
{
s = 31;
if (msd >= 0x10000)
{
msd = msd >> 16;
s -= 16;
}
if (msd >= 0x100)
{
msd = msd >> 8;
s -= 8;
}
if (msd >= 0x10)
{
msd = msd >> 4;
s -= 4;
}
if (msd >= 0x4)
{
msd = msd >> 2;
s -= 2;
}
if (msd >= 0x2)
{
msd = msd >> 1;
s -= 1;
}
}
# endif
}
/* 0 <= s < GMP_LIMB_BITS.
Copy b, shifting it left by s bits. */
if (s > 0)
{
tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
if (tmp_roomptr == NULL)
{
free (roomptr);
return NULL;
}
{
const mp_limb_t *sourceptr = b_ptr;
mp_limb_t *destptr = tmp_roomptr;
mp_twolimb_t accu = 0;
size_t count;
for (count = b_len; count > 0; count--)
{
accu += (mp_twolimb_t) *sourceptr++ << s;
*destptr++ = (mp_limb_t) accu;
accu = accu >> GMP_LIMB_BITS;
}
/* accu must be zero, since that was how s was determined. */
if (accu != 0)
abort ();
}
b_ptr = tmp_roomptr;
}
/* Copy a, shifting it left by s bits, yields r.
Memory layout:
At the beginning: r = roomptr[0..a_len],
at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
r_ptr = roomptr;
if (s == 0)
{
memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
r_ptr[a_len] = 0;
}
else
{
const mp_limb_t *sourceptr = a_ptr;
mp_limb_t *destptr = r_ptr;
mp_twolimb_t accu = 0;
size_t count;
for (count = a_len; count > 0; count--)
{
accu += (mp_twolimb_t) *sourceptr++ << s;
*destptr++ = (mp_limb_t) accu;
accu = accu >> GMP_LIMB_BITS;
}
*destptr++ = (mp_limb_t) accu;
}
q_ptr = roomptr + b_len;
q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
{
size_t j = a_len - b_len; /* m-n */
mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
/* Division loop, traversed m-n+1 times.
j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
for (;;)
{
mp_limb_t q_star;
mp_limb_t c1;
if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
{
/* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
mp_twolimb_t num =
((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
| r_ptr[j + b_len - 1];
q_star = num / b_msd;
c1 = num % b_msd;
}
else
{
/* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
/* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
<==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
<==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
{<= beta !}.
If yes, jump directly to the subtraction loop.
(Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
<==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
if (r_ptr[j + b_len] > b_msd
|| (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
/* r[j+n] >= b[n-1]+1 or
r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
carry. */
goto subtract;
}
/* q_star = q*,
c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, 0, decrease it by
b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
this can happen only twice. */
if (c3 > c2)
{
q_star = q_star - 1; /* q* := q* - 1 */
if (c3 - c2 > b_msdd)
q_star = q_star - 1; /* q* := q* - 1 */
}
}
if (q_star > 0)
subtract:
{
/* Subtract r := r - b * q* * beta^j. */
mp_limb_t cr;
{
const mp_limb_t *sourceptr = b_ptr;
mp_limb_t *destptr = r_ptr + j;
mp_twolimb_t carry = 0;
size_t count;
for (count = b_len; count > 0; count--)
{
/* Here 0 <= carry <= q*. */
carry =
carry
+ (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
+ (mp_limb_t) ~(*destptr);
/* Here 0 <= carry <= beta*q* + beta-1. */
*destptr++ = ~(mp_limb_t) carry;
carry = carry >> GMP_LIMB_BITS; /* <= q* */
}
cr = (mp_limb_t) carry;
}
/* Subtract cr from r_ptr[j + b_len], then forget about
r_ptr[j + b_len]. */
if (cr > r_ptr[j + b_len])
{
/* Subtraction gave a carry. */
q_star = q_star - 1; /* q* := q* - 1 */
/* Add b back. */
{
const mp_limb_t *sourceptr = b_ptr;
mp_limb_t *destptr = r_ptr + j;
mp_limb_t carry = 0;
size_t count;
for (count = b_len; count > 0; count--)
{
mp_limb_t source1 = *sourceptr++;
mp_limb_t source2 = *destptr;
*destptr++ = source1 + source2 + carry;
carry =
(carry
? source1 >= (mp_limb_t) ~source2
: source1 > (mp_limb_t) ~source2);
}
}
/* Forget about the carry and about r[j+n]. */
}
}
/* q* is determined. Store it as q[j]. */
q_ptr[j] = q_star;
if (j == 0)
break;
j--;
}
}
r_len = b_len;
/* Normalise q. */
if (q_ptr[q_len - 1] == 0)
q_len--;
# if 0 /* Not needed here, since we need r only to compare it with b/2, and
b is shifted left by s bits. */
/* Shift r right by s bits. */
if (s > 0)
{
mp_limb_t ptr = r_ptr + r_len;
mp_twolimb_t accu = 0;
size_t count;
for (count = r_len; count > 0; count--)
{
accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
*ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
}
}
# endif
/* Normalise r. */
while (r_len > 0 && r_ptr[r_len - 1] == 0)
r_len--;
}
/* Compare r << 1 with b. */
if (r_len > b_len)
goto increment_q;
{
size_t i;
for (i = b_len;;)
{
mp_limb_t r_i =
(i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
| (i < r_len ? r_ptr[i] << 1 : 0);
mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
if (r_i > b_i)
goto increment_q;
if (r_i < b_i)
goto keep_q;
if (i == 0)
break;
i--;
}
}
if (q_len > 0 && ((q_ptr[0] & 1) != 0))
/* q is odd. */
increment_q:
{
size_t i;
for (i = 0; i < q_len; i++)
if (++(q_ptr[i]) != 0)
goto keep_q;
q_ptr[q_len++] = 1;
}
keep_q:
if (tmp_roomptr != NULL)
free (tmp_roomptr);
q->limbs = q_ptr;
q->nlimbs = q_len;
return roomptr;
}
/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
representation.
Destroys the contents of a.
Return the allocated memory - containing the decimal digits in low-to-high
order, terminated with a NUL character - in case of success, NULL in case
of memory allocation failure. */
static char *
convert_to_decimal (mpn_t a, size_t extra_zeroes)
{
mp_limb_t *a_ptr = a.limbs;
size_t a_len = a.nlimbs;
/* 0.03345 is slightly larger than log(2)/(9*log(10)). */
size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
if (c_ptr != NULL)
{
char *d_ptr = c_ptr;
for (; extra_zeroes > 0; extra_zeroes--)
*d_ptr++ = '0';
while (a_len > 0)
{
/* Divide a by 10^9, in-place. */
mp_limb_t remainder = 0;
mp_limb_t *ptr = a_ptr + a_len;
size_t count;
for (count = a_len; count > 0; count--)
{
mp_twolimb_t num =
((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
*ptr = num / 1000000000;
remainder = num % 1000000000;
}
/* Store the remainder as 9 decimal digits. */
for (count = 9; count > 0; count--)
{
*d_ptr++ = '0' + (remainder % 10);
remainder = remainder / 10;
}
/* Normalize a. */
if (a_ptr[a_len - 1] == 0)
a_len--;
}
/* Remove leading zeroes. */
while (d_ptr > c_ptr && d_ptr[-1] == '0')
d_ptr--;
/* But keep at least one zero. */
if (d_ptr == c_ptr)
*d_ptr++ = '0';
/* Terminate the string. */
*d_ptr = '\0';
}
return c_ptr;
}
# if NEED_PRINTF_LONG_DOUBLE
/* Assuming x is finite and >= 0:
write x as x = 2^e * m, where m is a bignum.
Return the allocated memory in case of success, NULL in case of memory
allocation failure. */
static void *
decode_long_double (long double x, int *ep, mpn_t *mp)
{
mpn_t m;
int exp;
long double y;
size_t i;
/* Allocate memory for result. */
m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
if (m.limbs == NULL)
return NULL;
/* Split into exponential part and mantissa. */
y = frexpl (x, &exp);
if (!(y >= 0.0L && y < 1.0L))
abort ();
/* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
latter is an integer. */
/* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs.
I'm not sure whether it's safe to cast a 'long double' value between
2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
doesn't matter). */
# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
{
mp_limb_t hi, lo;
y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
hi = (int) y;
y -= hi;
if (!(y >= 0.0L && y < 1.0L))
abort ();
y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
lo = (int) y;
y -= lo;
if (!(y >= 0.0L && y < 1.0L))
abort ();
m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
}
# else
{
mp_limb_t d;
y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
d = (int) y;
y -= d;
if (!(y >= 0.0L && y < 1.0L))
abort ();
m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
}
# endif
# endif
for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
{
mp_limb_t hi, lo;
y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
hi = (int) y;
y -= hi;
if (!(y >= 0.0L && y < 1.0L))
abort ();
y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
lo = (int) y;
y -= lo;
if (!(y >= 0.0L && y < 1.0L))
abort ();
m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
}
# if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
precision. */
if (!(y == 0.0L))
abort ();
# endif
/* Normalise. */
while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
m.nlimbs--;
*mp = m;
*ep = exp - LDBL_MANT_BIT;
return m.limbs;
}
# endif
# if NEED_PRINTF_DOUBLE
/* Assuming x is finite and >= 0:
write x as x = 2^e * m, where m is a bignum.
Return the allocated memory in case of success, NULL in case of memory
allocation failure. */
static void *
decode_double (double x, int *ep, mpn_t *mp)
{
mpn_t m;
int exp;
double y;
size_t i;
/* Allocate memory for result. */
m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
if (m.limbs == NULL)
return NULL;
/* Split into exponential part and mantissa. */
y = frexp (x, &exp);
if (!(y >= 0.0 && y < 1.0))
abort ();
/* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the
latter is an integer. */
/* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs.
I'm not sure whether it's safe to cast a 'double' value between
2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
doesn't matter). */
# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
{
mp_limb_t hi, lo;
y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
hi = (int) y;
y -= hi;
if (!(y >= 0.0 && y < 1.0))
abort ();
y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
lo = (int) y;
y -= lo;
if (!(y >= 0.0 && y < 1.0))
abort ();
m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
}
# else
{
mp_limb_t d;
y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
d = (int) y;
y -= d;
if (!(y >= 0.0 && y < 1.0))
abort ();
m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
}
# endif
# endif
for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
{
mp_limb_t hi, lo;
y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
hi = (int) y;
y -= hi;
if (!(y >= 0.0 && y < 1.0))
abort ();
y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
lo = (int) y;
y -= lo;
if (!(y >= 0.0 && y < 1.0))
abort ();
m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
}
if (!(y == 0.0))
abort ();
/* Normalise. */
while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
m.nlimbs--;
*mp = m;
*ep = exp - DBL_MANT_BIT;
return m.limbs;
}
# endif
/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
Returns the decimal representation of round (x * 10^n).
Return the allocated memory - containing the decimal digits in low-to-high
order, terminated with a NUL character - in case of success, NULL in case
of memory allocation failure. */
static char *
scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
{
int s;
size_t extra_zeroes;
unsigned int abs_n;
unsigned int abs_s;
mp_limb_t *pow5_ptr;
size_t pow5_len;
unsigned int s_limbs;
unsigned int s_bits;
mpn_t pow5;
mpn_t z;
void *z_memory;
char *digits;
if (memory == NULL)
return NULL;
/* x = 2^e * m, hence
y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
= round (2^s * 5^n * m). */
s = e + n;
extra_zeroes = 0;
/* Factor out a common power of 10 if possible. */
if (s > 0 && n > 0)
{
extra_zeroes = (s < n ? s : n);
s -= extra_zeroes;
n -= extra_zeroes;
}
/* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
Before converting to decimal, we need to compute
z = round (2^s * 5^n * m). */
/* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
sign. 2.322 is slightly larger than log(5)/log(2). */
abs_n = (n >= 0 ? n : -n);
abs_s = (s >= 0 ? s : -s);
pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
+ abs_s / GMP_LIMB_BITS + 1)
* sizeof (mp_limb_t));
if (pow5_ptr == NULL)
{
free (memory);
return NULL;
}
/* Initialize with 1. */
pow5_ptr[0] = 1;
pow5_len = 1;
/* Multiply with 5^|n|. */
if (abs_n > 0)
{
static mp_limb_t const small_pow5[13 + 1] =
{
1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
48828125, 244140625, 1220703125
};
unsigned int n13;
for (n13 = 0; n13 <= abs_n; n13 += 13)
{
mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
size_t j;
mp_twolimb_t carry = 0;
for (j = 0; j < pow5_len; j++)
{
mp_limb_t digit2 = pow5_ptr[j];
carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
pow5_ptr[j] = (mp_limb_t) carry;
carry = carry >> GMP_LIMB_BITS;
}
if (carry > 0)
pow5_ptr[pow5_len++] = (mp_limb_t) carry;
}
}
s_limbs = abs_s / GMP_LIMB_BITS;
s_bits = abs_s % GMP_LIMB_BITS;
if (n >= 0 ? s >= 0 : s <= 0)
{
/* Multiply with 2^|s|. */
if (s_bits > 0)
{
mp_limb_t *ptr = pow5_ptr;
mp_twolimb_t accu = 0;
size_t count;
for (count = pow5_len; count > 0; count--)
{
accu += (mp_twolimb_t) *ptr << s_bits;
*ptr++ = (mp_limb_t) accu;
accu = accu >> GMP_LIMB_BITS;
}
if (accu > 0)
{
*ptr = (mp_limb_t) accu;
pow5_len++;
}
}
if (s_limbs > 0)
{
size_t count;
for (count = pow5_len; count > 0;)
{
count--;
pow5_ptr[s_limbs + count] = pow5_ptr[count];
}
for (count = s_limbs; count > 0;)
{
count--;
pow5_ptr[count] = 0;
}
pow5_len += s_limbs;
}
pow5.limbs = pow5_ptr;
pow5.nlimbs = pow5_len;
if (n >= 0)
{
/* Multiply m with pow5. No division needed. */
z_memory = multiply (m, pow5, &z);
}
else
{
/* Divide m by pow5 and round. */
z_memory = divide (m, pow5, &z);
}
}
else
{
pow5.limbs = pow5_ptr;
pow5.nlimbs = pow5_len;
if (n >= 0)
{
/* n >= 0, s < 0.
Multiply m with pow5, then divide by 2^|s|. */
mpn_t numerator;
mpn_t denominator;
void *tmp_memory;
tmp_memory = multiply (m, pow5, &numerator);
if (tmp_memory == NULL)
{
free (pow5_ptr);
free (memory);
return NULL;
}
/* Construct 2^|s|. */
{
mp_limb_t *ptr = pow5_ptr + pow5_len;
size_t i;
for (i = 0; i < s_limbs; i++)
ptr[i] = 0;
ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
denominator.limbs = ptr;
denominator.nlimbs = s_limbs + 1;
}
z_memory = divide (numerator, denominator, &z);
free (tmp_memory);
}
else
{
/* n < 0, s > 0.
Multiply m with 2^s, then divide by pow5. */
mpn_t numerator;
mp_limb_t *num_ptr;
num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
* sizeof (mp_limb_t));
if (num_ptr == NULL)
{
free (pow5_ptr);
free (memory);
return NULL;
}
{
mp_limb_t *destptr = num_ptr;
{
size_t i;
for (i = 0; i < s_limbs; i++)
*destptr++ = 0;
}
if (s_bits > 0)
{
const mp_limb_t *sourceptr = m.limbs;
mp_twolimb_t accu = 0;
size_t count;
for (count = m.nlimbs; count > 0; count--)
{
accu += (mp_twolimb_t) *sourceptr++ << s_bits;
*destptr++ = (mp_limb_t) accu;
accu = accu >> GMP_LIMB_BITS;
}
if (accu > 0)
*destptr++ = (mp_limb_t) accu;
}
else
{
const mp_limb_t *sourceptr = m.limbs;
size_t count;
for (count = m.nlimbs; count > 0; count--)
*destptr++ = *sourceptr++;
}
numerator.limbs = num_ptr;
numerator.nlimbs = destptr - num_ptr;
}
z_memory = divide (numerator, pow5, &z);
free (num_ptr);
}
}
free (pow5_ptr);
free (memory);
/* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
if (z_memory == NULL)
return NULL;
digits = convert_to_decimal (z, extra_zeroes);
free (z_memory);
return digits;
}
# if NEED_PRINTF_LONG_DOUBLE
/* Assuming x is finite and >= 0, and n is an integer:
Returns the decimal representation of round (x * 10^n).
Return the allocated memory - containing the decimal digits in low-to-high
order, terminated with a NUL character - in case of success, NULL in case
of memory allocation failure. */
static char *
scale10_round_decimal_long_double (long double x, int n)
{
int e IF_LINT(= 0);
mpn_t m;
void *memory = decode_long_double (x, &e, &m);
return scale10_round_decimal_decoded (e, m, memory, n);
}
# endif
# if NEED_PRINTF_DOUBLE
/* Assuming x is finite and >= 0, and n is an integer:
Returns the decimal representation of round (x * 10^n).
Return the allocated memory - containing the decimal digits in low-to-high
order, terminated with a NUL character - in case of success, NULL in case
of memory allocation failure. */
static char *
scale10_round_decimal_double (double x, int n)
{
int e IF_LINT(= 0);
mpn_t m;
void *memory = decode_double (x, &e, &m);
return scale10_round_decimal_decoded (e, m, memory, n);
}
# endif
# if NEED_PRINTF_LONG_DOUBLE
/* Assuming x is finite and > 0:
Return an approximation for n with 10^n <= x < 10^(n+1).
The approximation is usually the right n, but may be off by 1 sometimes. */
static int
floorlog10l (long double x)
{
int exp;
long double y;
double z;
double l;
/* Split into exponential part and mantissa. */
y = frexpl (x, &exp);
if (!(y >= 0.0L && y < 1.0L))
abort ();
if (y == 0.0L)
return INT_MIN;
if (y < 0.5L)
{
while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
{
y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
exp -= GMP_LIMB_BITS;
}
if (y < (1.0L / (1 << 16)))
{
y *= 1.0L * (1 << 16);
exp -= 16;
}
if (y < (1.0L / (1 << 8)))
{
y *= 1.0L * (1 << 8);
exp -= 8;
}
if (y < (1.0L / (1 << 4)))
{
y *= 1.0L * (1 << 4);
exp -= 4;
}
if (y < (1.0L / (1 << 2)))
{
y *= 1.0L * (1 << 2);
exp -= 2;
}
if (y < (1.0L / (1 << 1)))
{
y *= 1.0L * (1 << 1);
exp -= 1;
}
}
if (!(y >= 0.5L && y < 1.0L))
abort ();
/* Compute an approximation for l = log2(x) = exp + log2(y). */
l = exp;
z = y;
if (z < 0.70710678118654752444)
{
z *= 1.4142135623730950488;
l -= 0.5;
}
if (z < 0.8408964152537145431)
{
z *= 1.1892071150027210667;
l -= 0.25;
}
if (z < 0.91700404320467123175)
{
z *= 1.0905077326652576592;
l -= 0.125;
}
if (z < 0.9576032806985736469)
{
z *= 1.0442737824274138403;
l -= 0.0625;
}
/* Now 0.95 <= z <= 1.01. */
z = 1 - z;
/* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
Four terms are enough to get an approximation with error < 10^-7. */
l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
/* Finally multiply with log(2)/log(10), yields an approximation for
log10(x). */
l *= 0.30102999566398119523;
/* Round down to the next integer. */
return (int) l + (l < 0 ? -1 : 0);
}
# endif
# if NEED_PRINTF_DOUBLE
/* Assuming x is finite and > 0:
Return an approximation for n with 10^n <= x < 10^(n+1).
The approximation is usually the right n, but may be off by 1 sometimes. */
static int
floorlog10 (double x)
{
int exp;
double y;
double z;
double l;
/* Split into exponential part and mantissa. */
y = frexp (x, &exp);
if (!(y >= 0.0 && y < 1.0))
abort ();
if (y == 0.0)
return INT_MIN;
if (y < 0.5)
{
while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
{
y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
exp -= GMP_LIMB_BITS;
}
if (y < (1.0 / (1 << 16)))
{
y *= 1.0 * (1 << 16);
exp -= 16;
}
if (y < (1.0 / (1 << 8)))
{
y *= 1.0 * (1 << 8);
exp -= 8;
}
if (y < (1.0 / (1 << 4)))
{
y *= 1.0 * (1 << 4);
exp -= 4;
}
if (y < (1.0 / (1 << 2)))
{
y *= 1.0 * (1 << 2);
exp -= 2;
}
if (y < (1.0 / (1 << 1)))
{
y *= 1.0 * (1 << 1);
exp -= 1;
}
}
if (!(y >= 0.5 && y < 1.0))
abort ();
/* Compute an approximation for l = log2(x) = exp + log2(y). */
l = exp;
z = y;
if (z < 0.70710678118654752444)
{
z *= 1.4142135623730950488;
l -= 0.5;
}
if (z < 0.8408964152537145431)
{
z *= 1.1892071150027210667;
l -= 0.25;
}
if (z < 0.91700404320467123175)
{
z *= 1.0905077326652576592;
l -= 0.125;
}
if (z < 0.9576032806985736469)
{
z *= 1.0442737824274138403;
l -= 0.0625;
}
/* Now 0.95 <= z <= 1.01. */
z = 1 - z;
/* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
Four terms are enough to get an approximation with error < 10^-7. */
l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
/* Finally multiply with log(2)/log(10), yields an approximation for
log10(x). */
l *= 0.30102999566398119523;
/* Round down to the next integer. */
return (int) l + (l < 0 ? -1 : 0);
}
# endif
/* Tests whether a string of digits consists of exactly PRECISION zeroes and
a single '1' digit. */
static int
is_borderline (const char *digits, size_t precision)
{
for (; precision > 0; precision--, digits++)
if (*digits != '0')
return 0;
if (*digits != '1')
return 0;
digits++;
return *digits == '\0';
}
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
/* Use a different function name, to make it possible that the 'wchar_t'
parametrization and the 'char' parametrization get compiled in the same
translation unit. */
# if WIDE_CHAR_VERSION
# define MAX_ROOM_NEEDED wmax_room_needed
# else
# define MAX_ROOM_NEEDED max_room_needed
# endif
/* Returns the number of TCHAR_T units needed as temporary space for the result
of sprintf or SNPRINTF of a single conversion directive. */
static size_t
MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
arg_type type, int flags, size_t width, int has_precision,
size_t precision, int pad_ourselves)
{
size_t tmp_length;
switch (conversion)
{
case 'd': case 'i': case 'u':
# if HAVE_LONG_LONG_INT
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
* 0.30103 /* binary -> decimal */
)
+ 1; /* turn floor into ceil */
else
# endif
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long) * CHAR_BIT
* 0.30103 /* binary -> decimal */
)
+ 1; /* turn floor into ceil */
else
tmp_length =
(unsigned int) (sizeof (unsigned int) * CHAR_BIT
* 0.30103 /* binary -> decimal */
)
+ 1; /* turn floor into ceil */
if (tmp_length < precision)
tmp_length = precision;
/* Multiply by 2, as an estimate for FLAG_GROUP. */
tmp_length = xsum (tmp_length, tmp_length);
/* Add 1, to account for a leading sign. */
tmp_length = xsum (tmp_length, 1);
break;
case 'o':
# if HAVE_LONG_LONG_INT
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
* 0.333334 /* binary -> octal */
)
+ 1; /* turn floor into ceil */
else
# endif
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long) * CHAR_BIT
* 0.333334 /* binary -> octal */
)
+ 1; /* turn floor into ceil */
else
tmp_length =
(unsigned int) (sizeof (unsigned int) * CHAR_BIT
* 0.333334 /* binary -> octal */
)
+ 1; /* turn floor into ceil */
if (tmp_length < precision)
tmp_length = precision;
/* Add 1, to account for a leading sign. */
tmp_length = xsum (tmp_length, 1);
break;
case 'x': case 'X':
# if HAVE_LONG_LONG_INT
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
* 0.25 /* binary -> hexadecimal */
)
+ 1; /* turn floor into ceil */
else
# endif
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long) * CHAR_BIT
* 0.25 /* binary -> hexadecimal */
)
+ 1; /* turn floor into ceil */
else
tmp_length =
(unsigned int) (sizeof (unsigned int) * CHAR_BIT
* 0.25 /* binary -> hexadecimal */
)
+ 1; /* turn floor into ceil */
if (tmp_length < precision)
tmp_length = precision;
/* Add 2, to account for a leading sign or alternate form. */
tmp_length = xsum (tmp_length, 2);
break;
case 'f': case 'F':
if (type == TYPE_LONGDOUBLE)
tmp_length =
(unsigned int) (LDBL_MAX_EXP
* 0.30103 /* binary -> decimal */
* 2 /* estimate for FLAG_GROUP */
)
+ 1 /* turn floor into ceil */
+ 10; /* sign, decimal point etc. */
else
tmp_length =
(unsigned int) (DBL_MAX_EXP
* 0.30103 /* binary -> decimal */
* 2 /* estimate for FLAG_GROUP */
)
+ 1 /* turn floor into ceil */
+ 10; /* sign, decimal point etc. */
tmp_length = xsum (tmp_length, precision);
break;
case 'e': case 'E': case 'g': case 'G':
tmp_length =
12; /* sign, decimal point, exponent etc. */
tmp_length = xsum (tmp_length, precision);
break;
case 'a': case 'A':
if (type == TYPE_LONGDOUBLE)
tmp_length =
(unsigned int) (LDBL_DIG
* 0.831 /* decimal -> hexadecimal */
)
+ 1; /* turn floor into ceil */
else
tmp_length =
(unsigned int) (DBL_DIG
* 0.831 /* decimal -> hexadecimal */
)
+ 1; /* turn floor into ceil */
if (tmp_length < precision)
tmp_length = precision;
/* Account for sign, decimal point etc. */
tmp_length = xsum (tmp_length, 12);
break;
case 'c':
# if HAVE_WINT_T && !WIDE_CHAR_VERSION
if (type == TYPE_WIDE_CHAR)
tmp_length = MB_CUR_MAX;
else
# endif
tmp_length = 1;
break;
case 's':
# if HAVE_WCHAR_T
if (type == TYPE_WIDE_STRING)
{
# if WIDE_CHAR_VERSION
/* ISO C says about %ls in fwprintf:
"If the precision is not specified or is greater than the size
of the array, the array shall contain a null wide character."
So if there is a precision, we must not use wcslen. */
const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
if (has_precision)
tmp_length = local_wcsnlen (arg, precision);
else
tmp_length = local_wcslen (arg);
# else
/* ISO C says about %ls in fprintf:
"If a precision is specified, no more than that many bytes are
written (including shift sequences, if any), and the array
shall contain a null wide character if, to equal the multibyte
character sequence length given by the precision, the function
would need to access a wide character one past the end of the
array."
So if there is a precision, we must not use wcslen. */
/* This case has already been handled separately in VASNPRINTF. */
abort ();
# endif
}
else
# endif
{
# if WIDE_CHAR_VERSION
/* ISO C says about %s in fwprintf:
"If the precision is not specified or is greater than the size
of the converted array, the converted array shall contain a
null wide character."
So if there is a precision, we must not use strlen. */
/* This case has already been handled separately in VASNPRINTF. */
abort ();
# else
/* ISO C says about %s in fprintf:
"If the precision is not specified or greater than the size of
the array, the array shall contain a null character."
So if there is a precision, we must not use strlen. */
const char *arg = ap->arg[arg_index].a.a_string;
if (has_precision)
tmp_length = local_strnlen (arg, precision);
else
tmp_length = strlen (arg);
# endif
}
break;
case 'p':
tmp_length =
(unsigned int) (sizeof (void *) * CHAR_BIT
* 0.25 /* binary -> hexadecimal */
)
+ 1 /* turn floor into ceil */
+ 2; /* account for leading 0x */
break;
default:
abort ();
}
if (!pad_ourselves)
{
# if ENABLE_UNISTDIO
/* Padding considers the number of characters, therefore the number of
elements after padding may be
> max (tmp_length, width)
but is certainly
<= tmp_length + width. */
tmp_length = xsum (tmp_length, width);
# else
/* Padding considers the number of elements, says POSIX. */
if (tmp_length < width)
tmp_length = width;
# endif
}
tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
return tmp_length;
}
#endif
DCHAR_T *
VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
const FCHAR_T *format, va_list args)
{
DIRECTIVES d;
arguments a;
if (PRINTF_PARSE (format, &d, &a) < 0)
/* errno is already set. */
return NULL;
#define CLEANUP() \
if (d.dir != d.direct_alloc_dir) \
free (d.dir); \
if (a.arg != a.direct_alloc_arg) \
free (a.arg);
if (PRINTF_FETCHARGS (args, &a) < 0)
{
CLEANUP ();
errno = EINVAL;
return NULL;
}
{
size_t buf_neededlength;
TCHAR_T *buf;
TCHAR_T *buf_malloced;
const FCHAR_T *cp;
size_t i;
DIRECTIVE *dp;
/* Output string accumulator. */
DCHAR_T *result;
size_t allocated;
size_t length;
/* Allocate a small buffer that will hold a directive passed to
sprintf or snprintf. */
buf_neededlength =
xsum4 (7, d.max_width_length, d.max_precision_length, 6);
#if HAVE_ALLOCA
if (buf_neededlength < 4000 / sizeof (TCHAR_T))
{
buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
buf_malloced = NULL;
}
else
#endif
{
size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
if (size_overflow_p (buf_memsize))
goto out_of_memory_1;
buf = (TCHAR_T *) malloc (buf_memsize);
if (buf == NULL)
goto out_of_memory_1;
buf_malloced = buf;
}
if (resultbuf != NULL)
{
result = resultbuf;
allocated = *lengthp;
}
else
{
result = NULL;
allocated = 0;
}
length = 0;
/* Invariants:
result is either == resultbuf or == NULL or malloc-allocated.
If length > 0, then result != NULL. */
/* Ensures that allocated >= needed. Aborts through a jump to
out_of_memory if needed is SIZE_MAX or otherwise too big. */
#define ENSURE_ALLOCATION(needed) \
if ((needed) > allocated) \
{ \
size_t memory_size; \
DCHAR_T *memory; \
\
allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
if ((needed) > allocated) \
allocated = (needed); \
memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
if (size_overflow_p (memory_size)) \
goto out_of_memory; \
if (result == resultbuf || result == NULL) \
memory = (DCHAR_T *) malloc (memory_size); \
else \
memory = (DCHAR_T *) realloc (result, memory_size); \
if (memory == NULL) \
goto out_of_memory; \
if (result == resultbuf && length > 0) \
DCHAR_CPY (memory, result, length); \
result = memory; \
}
for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
{
if (cp != dp->dir_start)
{
size_t n = dp->dir_start - cp;
size_t augmented_length = xsum (length, n);
ENSURE_ALLOCATION (augmented_length);
/* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we
need that the format string contains only ASCII characters
if FCHAR_T and DCHAR_T are not the same type. */
if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
{
DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
length = augmented_length;
}
else
{
do
result[length++] = (unsigned char) *cp++;
while (--n > 0);
}
}
if (i == d.count)
break;
/* Execute a single directive. */
if (dp->conversion == '%')
{
size_t augmented_length;
if (!(dp->arg_index == ARG_NONE))
abort ();
augmented_length = xsum (length, 1);
ENSURE_ALLOCATION (augmented_length);
result[length] = '%';
length = augmented_length;
}
else
{
if (!(dp->arg_index != ARG_NONE))
abort ();
if (dp->conversion == 'n')
{
switch (a.arg[dp->arg_index].type)
{
case TYPE_COUNT_SCHAR_POINTER:
*a.arg[dp->arg_index].a.a_count_schar_pointer = length;
break;
case TYPE_COUNT_SHORT_POINTER:
*a.arg[dp->arg_index].a.a_count_short_pointer = length;
break;
case TYPE_COUNT_INT_POINTER:
*a.arg[dp->arg_index].a.a_count_int_pointer = length;
break;
case TYPE_COUNT_LONGINT_POINTER:
*a.arg[dp->arg_index].a.a_count_longint_pointer = length;
break;
#if HAVE_LONG_LONG_INT
case TYPE_COUNT_LONGLONGINT_POINTER:
*a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
break;
#endif
default:
abort ();
}
}
#if ENABLE_UNISTDIO
/* The unistdio extensions. */
else if (dp->conversion == 'U')
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
int has_width;
size_t width;
int has_precision;
size_t precision;
has_width = 0;
width = 0;
if (dp->width_start != dp->width_end)
{
if (dp->width_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = (unsigned int) (-arg);
}
else
width = arg;
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
has_width = 1;
}
has_precision = 0;
precision = 0;
if (dp->precision_start != dp->precision_end)
{
if (dp->precision_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->precision_arg_index].a.a_int;
/* "A negative precision is taken as if the precision
were omitted." */
if (arg >= 0)
{
precision = arg;
has_precision = 1;
}
}
else
{
const FCHAR_T *digitp = dp->precision_start + 1;
precision = 0;
while (digitp != dp->precision_end)
precision = xsum (xtimes (precision, 10), *digitp++ - '0');
has_precision = 1;
}
}
switch (type)
{
case TYPE_U8_STRING:
{
const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
const uint8_t *arg_end;
size_t characters;
if (has_precision)
{
/* Use only PRECISION characters, from the left. */
arg_end = arg;
characters = 0;
for (; precision > 0; precision--)
{
int count = u8_strmblen (arg_end);
if (count == 0)
break;
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else if (has_width)
{
/* Use the entire string, and count the number of
characters. */
arg_end = arg;
characters = 0;
for (;;)
{
int count = u8_strmblen (arg_end);
if (count == 0)
break;
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else
{
/* Use the entire string. */
arg_end = arg + u8_strlen (arg);
/* The number of characters doesn't matter. */
characters = 0;
}
if (has_width && width > characters
&& !(dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
# if DCHAR_IS_UINT8_T
{
size_t n = arg_end - arg;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_CPY (result + length, arg, n);
length += n;
}
# else
{ /* Convert. */
DCHAR_T *converted = result + length;
size_t converted_len = allocated - length;
# if DCHAR_IS_TCHAR
/* Convert from UTF-8 to locale encoding. */
converted =
u8_conv_to_encoding (locale_charset (),
iconveh_question_mark,
arg, arg_end - arg, NULL,
converted, &converted_len);
# else
/* Convert from UTF-8 to UTF-16/UTF-32. */
converted =
U8_TO_DCHAR (arg, arg_end - arg,
converted, &converted_len);
# endif
if (converted == NULL)
{
int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = saved_errno;
return NULL;
}
if (converted != result + length)
{
ENSURE_ALLOCATION (xsum (length, converted_len));
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
length += converted_len;
}
# endif
if (has_width && width > characters
&& (dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
break;
case TYPE_U16_STRING:
{
const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
const uint16_t *arg_end;
size_t characters;
if (has_precision)
{
/* Use only PRECISION characters, from the left. */
arg_end = arg;
characters = 0;
for (; precision > 0; precision--)
{
int count = u16_strmblen (arg_end);
if (count == 0)
break;
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else if (has_width)
{
/* Use the entire string, and count the number of
characters. */
arg_end = arg;
characters = 0;
for (;;)
{
int count = u16_strmblen (arg_end);
if (count == 0)
break;
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else
{
/* Use the entire string. */
arg_end = arg + u16_strlen (arg);
/* The number of characters doesn't matter. */
characters = 0;
}
if (has_width && width > characters
&& !(dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
# if DCHAR_IS_UINT16_T
{
size_t n = arg_end - arg;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_CPY (result + length, arg, n);
length += n;
}
# else
{ /* Convert. */
DCHAR_T *converted = result + length;
size_t converted_len = allocated - length;
# if DCHAR_IS_TCHAR
/* Convert from UTF-16 to locale encoding. */
converted =
u16_conv_to_encoding (locale_charset (),
iconveh_question_mark,
arg, arg_end - arg, NULL,
converted, &converted_len);
# else
/* Convert from UTF-16 to UTF-8/UTF-32. */
converted =
U16_TO_DCHAR (arg, arg_end - arg,
converted, &converted_len);
# endif
if (converted == NULL)
{
int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = saved_errno;
return NULL;
}
if (converted != result + length)
{
ENSURE_ALLOCATION (xsum (length, converted_len));
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
length += converted_len;
}
# endif
if (has_width && width > characters
&& (dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
break;
case TYPE_U32_STRING:
{
const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
const uint32_t *arg_end;
size_t characters;
if (has_precision)
{
/* Use only PRECISION characters, from the left. */
arg_end = arg;
characters = 0;
for (; precision > 0; precision--)
{
int count = u32_strmblen (arg_end);
if (count == 0)
break;
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else if (has_width)
{
/* Use the entire string, and count the number of
characters. */
arg_end = arg;
characters = 0;
for (;;)
{
int count = u32_strmblen (arg_end);
if (count == 0)
break;
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else
{
/* Use the entire string. */
arg_end = arg + u32_strlen (arg);
/* The number of characters doesn't matter. */
characters = 0;
}
if (has_width && width > characters
&& !(dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
# if DCHAR_IS_UINT32_T
{
size_t n = arg_end - arg;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_CPY (result + length, arg, n);
length += n;
}
# else
{ /* Convert. */
DCHAR_T *converted = result + length;
size_t converted_len = allocated - length;
# if DCHAR_IS_TCHAR
/* Convert from UTF-32 to locale encoding. */
converted =
u32_conv_to_encoding (locale_charset (),
iconveh_question_mark,
arg, arg_end - arg, NULL,
converted, &converted_len);
# else
/* Convert from UTF-32 to UTF-8/UTF-16. */
converted =
U32_TO_DCHAR (arg, arg_end - arg,
converted, &converted_len);
# endif
if (converted == NULL)
{
int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = saved_errno;
return NULL;
}
if (converted != result + length)
{
ENSURE_ALLOCATION (xsum (length, converted_len));
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
length += converted_len;
}
# endif
if (has_width && width > characters
&& (dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
break;
default:
abort ();
}
}
#endif
#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
else if (dp->conversion == 's'
# if WIDE_CHAR_VERSION
&& a.arg[dp->arg_index].type != TYPE_WIDE_STRING
# else
&& a.arg[dp->arg_index].type == TYPE_WIDE_STRING
# endif
)
{
/* The normal handling of the 's' directive below requires
allocating a temporary buffer. The determination of its
length (tmp_length), in the case when a precision is
specified, below requires a conversion between a char[]
string and a wchar_t[] wide string. It could be done, but
we have no guarantee that the implementation of sprintf will
use the exactly same algorithm. Without this guarantee, it
is possible to have buffer overrun bugs. In order to avoid
such bugs, we implement the entire processing of the 's'
directive ourselves. */
int flags = dp->flags;
int has_width;
size_t width;
int has_precision;
size_t precision;
has_width = 0;
width = 0;
if (dp->width_start != dp->width_end)
{
if (dp->width_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = (unsigned int) (-arg);
}
else
width = arg;
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
has_width = 1;
}
has_precision = 0;
precision = 6;
if (dp->precision_start != dp->precision_end)
{
if (dp->precision_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->precision_arg_index].a.a_int;
/* "A negative precision is taken as if the precision
were omitted." */
if (arg >= 0)
{
precision = arg;
has_precision = 1;
}
}
else
{
const FCHAR_T *digitp = dp->precision_start + 1;
precision = 0;
while (digitp != dp->precision_end)
precision = xsum (xtimes (precision, 10), *digitp++ - '0');
has_precision = 1;
}
}
# if WIDE_CHAR_VERSION
/* %s in vasnwprintf. See the specification of fwprintf. */
{
const char *arg = a.arg[dp->arg_index].a.a_string;
const char *arg_end;
size_t characters;
if (has_precision)
{
/* Use only as many bytes as needed to produce PRECISION
wide characters, from the left. */
# if HAVE_MBRTOWC
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
arg_end = arg;
characters = 0;
for (; precision > 0; precision--)
{
int count;
# if HAVE_MBRTOWC
count = mbrlen (arg_end, MB_CUR_MAX, &state);
# else
count = mblen (arg_end, MB_CUR_MAX);
# endif
if (count == 0)
/* Found the terminating NUL. */
break;
if (count < 0)
{
/* Invalid or incomplete multibyte character. */
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else if (has_width)
{
/* Use the entire string, and count the number of wide
characters. */
# if HAVE_MBRTOWC
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
arg_end = arg;
characters = 0;
for (;;)
{
int count;
# if HAVE_MBRTOWC
count = mbrlen (arg_end, MB_CUR_MAX, &state);
# else
count = mblen (arg_end, MB_CUR_MAX);
# endif
if (count == 0)
/* Found the terminating NUL. */
break;
if (count < 0)
{
/* Invalid or incomplete multibyte character. */
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end += count;
characters++;
}
}
else
{
/* Use the entire string. */
arg_end = arg + strlen (arg);
/* The number of characters doesn't matter. */
characters = 0;
}
if (has_width && width > characters
&& !(dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
if (has_precision || has_width)
{
/* We know the number of wide characters in advance. */
size_t remaining;
# if HAVE_MBRTOWC
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
ENSURE_ALLOCATION (xsum (length, characters));
for (remaining = characters; remaining > 0; remaining--)
{
wchar_t wc;
int count;
# if HAVE_MBRTOWC
count = mbrtowc (&wc, arg, arg_end - arg, &state);
# else
count = mbtowc (&wc, arg, arg_end - arg);
# endif
if (count <= 0)
/* mbrtowc not consistent with mbrlen, or mbtowc
not consistent with mblen. */
abort ();
result[length++] = wc;
arg += count;
}
if (!(arg == arg_end))
abort ();
}
else
{
# if HAVE_MBRTOWC
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
while (arg < arg_end)
{
wchar_t wc;
int count;
# if HAVE_MBRTOWC
count = mbrtowc (&wc, arg, arg_end - arg, &state);
# else
count = mbtowc (&wc, arg, arg_end - arg);
# endif
if (count <= 0)
/* mbrtowc not consistent with mbrlen, or mbtowc
not consistent with mblen. */
abort ();
ENSURE_ALLOCATION (xsum (length, 1));
result[length++] = wc;
arg += count;
}
}
if (has_width && width > characters
&& (dp->flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
# else
/* %ls in vasnprintf. See the specification of fprintf. */
{
const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
const wchar_t *arg_end;
size_t characters;
# if !DCHAR_IS_TCHAR
/* This code assumes that TCHAR_T is 'char'. */
verify (sizeof (TCHAR_T) == 1);
TCHAR_T *tmpsrc;
DCHAR_T *tmpdst;
size_t tmpdst_len;
# endif
size_t w;
if (has_precision)
{
/* Use only as many wide characters as needed to produce
at most PRECISION bytes, from the left. */
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
arg_end = arg;
characters = 0;
while (precision > 0)
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
if (*arg_end == 0)
/* Found the terminating null wide character. */
break;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
count = wcrtomb (cbuf, *arg_end, &state);
# else
count = wctomb (cbuf, *arg_end);
# endif
if (count < 0)
{
/* Cannot convert. */
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
if (precision < count)
break;
arg_end++;
characters += count;
precision -= count;
}
}
# if DCHAR_IS_TCHAR
else if (has_width)
# else
else
# endif
{
/* Use the entire string, and count the number of
bytes. */
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
arg_end = arg;
characters = 0;
for (;;)
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
if (*arg_end == 0)
/* Found the terminating null wide character. */
break;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
count = wcrtomb (cbuf, *arg_end, &state);
# else
count = wctomb (cbuf, *arg_end);
# endif
if (count < 0)
{
/* Cannot convert. */
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
arg_end++;
characters += count;
}
}
# if DCHAR_IS_TCHAR
else
{
/* Use the entire string. */
arg_end = arg + local_wcslen (arg);
/* The number of bytes doesn't matter. */
characters = 0;
}
# endif
# if !DCHAR_IS_TCHAR
/* Convert the string into a piece of temporary memory. */
tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
if (tmpsrc == NULL)
goto out_of_memory;
{
TCHAR_T *tmpptr = tmpsrc;
size_t remaining;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
for (remaining = characters; remaining > 0; )
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
if (*arg == 0)
abort ();
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
count = wcrtomb (cbuf, *arg, &state);
# else
count = wctomb (cbuf, *arg);
# endif
if (count <= 0)
/* Inconsistency. */
abort ();
memcpy (tmpptr, cbuf, count);
tmpptr += count;
arg++;
remaining -= count;
}
if (!(arg == arg_end))
abort ();
}
/* Convert from TCHAR_T[] to DCHAR_T[]. */
tmpdst =
DCHAR_CONV_FROM_ENCODING (locale_charset (),
iconveh_question_mark,
tmpsrc, characters,
NULL,
NULL, &tmpdst_len);
if (tmpdst == NULL)
{
int saved_errno = errno;
free (tmpsrc);
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = saved_errno;
return NULL;
}
free (tmpsrc);
# endif
if (has_width)
{
# if ENABLE_UNISTDIO
/* Outside POSIX, it's preferable to compare the width
against the number of _characters_ of the converted
value. */
w = DCHAR_MBSNLEN (result + length, characters);
# else
/* The width is compared against the number of _bytes_
of the converted value, says POSIX. */
w = characters;
# endif
}
else
/* w doesn't matter. */
w = 0;
if (has_width && width > w
&& !(dp->flags & FLAG_LEFT))
{
size_t n = width - w;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
# if DCHAR_IS_TCHAR
if (has_precision || has_width)
{
/* We know the number of bytes in advance. */
size_t remaining;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
ENSURE_ALLOCATION (xsum (length, characters));
for (remaining = characters; remaining > 0; )
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
if (*arg == 0)
abort ();
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
count = wcrtomb (cbuf, *arg, &state);
# else
count = wctomb (cbuf, *arg);
# endif
if (count <= 0)
/* Inconsistency. */
abort ();
memcpy (result + length, cbuf, count);
length += count;
arg++;
remaining -= count;
}
if (!(arg == arg_end))
abort ();
}
else
{
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
while (arg < arg_end)
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
if (*arg == 0)
abort ();
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
count = wcrtomb (cbuf, *arg, &state);
# else
count = wctomb (cbuf, *arg);
# endif
if (count <= 0)
{
/* Cannot convert. */
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EILSEQ;
return NULL;
}
ENSURE_ALLOCATION (xsum (length, count));
memcpy (result + length, cbuf, count);
length += count;
arg++;
}
}
# else
ENSURE_ALLOCATION (xsum (length, tmpdst_len));
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
length += tmpdst_len;
# endif
if (has_width && width > w
&& (dp->flags & FLAG_LEFT))
{
size_t n = width - w;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
# endif
}
#endif
#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
else if ((dp->conversion == 'a' || dp->conversion == 'A')
# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
&& (0
# if NEED_PRINTF_DOUBLE
|| a.arg[dp->arg_index].type == TYPE_DOUBLE
# endif
# if NEED_PRINTF_LONG_DOUBLE
|| a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
# endif
)
# endif
)
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
int has_width;
size_t width;
int has_precision;
size_t precision;
size_t tmp_length;
DCHAR_T tmpbuf[700];
DCHAR_T *tmp;
DCHAR_T *pad_ptr;
DCHAR_T *p;
has_width = 0;
width = 0;
if (dp->width_start != dp->width_end)
{
if (dp->width_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = (unsigned int) (-arg);
}
else
width = arg;
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
has_width = 1;
}
has_precision = 0;
precision = 0;
if (dp->precision_start != dp->precision_end)
{
if (dp->precision_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->precision_arg_index].a.a_int;
/* "A negative precision is taken as if the precision
were omitted." */
if (arg >= 0)
{
precision = arg;
has_precision = 1;
}
}
else
{
const FCHAR_T *digitp = dp->precision_start + 1;
precision = 0;
while (digitp != dp->precision_end)
precision = xsum (xtimes (precision, 10), *digitp++ - '0');
has_precision = 1;
}
}
/* Allocate a temporary buffer of sufficient size. */
if (type == TYPE_LONGDOUBLE)
tmp_length =
(unsigned int) ((LDBL_DIG + 1)
* 0.831 /* decimal -> hexadecimal */
)
+ 1; /* turn floor into ceil */
else
tmp_length =
(unsigned int) ((DBL_DIG + 1)
* 0.831 /* decimal -> hexadecimal */
)
+ 1; /* turn floor into ceil */
if (tmp_length < precision)
tmp_length = precision;
/* Account for sign, decimal point etc. */
tmp_length = xsum (tmp_length, 12);
if (tmp_length < width)
tmp_length = width;
tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
tmp = tmpbuf;
else
{
size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
if (size_overflow_p (tmp_memsize))
/* Overflow, would lead to out of memory. */
goto out_of_memory;
tmp = (DCHAR_T *) malloc (tmp_memsize);
if (tmp == NULL)
/* Out of memory. */
goto out_of_memory;
}
pad_ptr = NULL;
p = tmp;
if (type == TYPE_LONGDOUBLE)
{
# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
long double arg = a.arg[dp->arg_index].a.a_longdouble;
if (isnanl (arg))
{
if (dp->conversion == 'A')
{
*p++ = 'N'; *p++ = 'A'; *p++ = 'N';
}
else
{
*p++ = 'n'; *p++ = 'a'; *p++ = 'n';
}
}
else
{
int sign = 0;
DECL_LONG_DOUBLE_ROUNDING
BEGIN_LONG_DOUBLE_ROUNDING ();
if (signbit (arg)) /* arg < 0.0L or negative zero */
{
sign = -1;
arg = -arg;
}
if (sign < 0)
*p++ = '-';
else if (flags & FLAG_SHOWSIGN)
*p++ = '+';
else if (flags & FLAG_SPACE)
*p++ = ' ';
if (arg > 0.0L && arg + arg == arg)
{
if (dp->conversion == 'A')
{
*p++ = 'I'; *p++ = 'N'; *p++ = 'F';
}
else
{
*p++ = 'i'; *p++ = 'n'; *p++ = 'f';
}
}
else
{
int exponent;
long double mantissa;
if (arg > 0.0L)
mantissa = printf_frexpl (arg, &exponent);
else
{
exponent = 0;
mantissa = 0.0L;
}
if (has_precision
&& precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
{
/* Round the mantissa. */
long double tail = mantissa;
size_t q;
for (q = precision; ; q--)
{
int digit = (int) tail;
tail -= digit;
if (q == 0)
{
if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
tail = 1 - tail;
else
tail = - tail;
break;
}
tail *= 16.0L;
}
if (tail != 0.0L)
for (q = precision; q > 0; q--)
tail *= 0.0625L;
mantissa += tail;
}
*p++ = '0';
*p++ = dp->conversion - 'A' + 'X';
pad_ptr = p;
{
int digit;
digit = (int) mantissa;
mantissa -= digit;
*p++ = '0' + digit;
if ((flags & FLAG_ALT)
|| mantissa > 0.0L || precision > 0)
{
*p++ = decimal_point_char ();
/* This loop terminates because we assume
that FLT_RADIX is a power of 2. */
while (mantissa > 0.0L)
{
mantissa *= 16.0L;
digit = (int) mantissa;
mantissa -= digit;
*p++ = digit
+ (digit < 10
? '0'
: dp->conversion - 10);
if (precision > 0)
precision--;
}
while (precision > 0)
{
*p++ = '0';
precision--;
}
}
}
*p++ = dp->conversion - 'A' + 'P';
# if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', 'd', '\0' };
SNPRINTF (p, 6 + 1, decimal_format, exponent);
}
while (*p != '\0')
p++;
# else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+d", exponent);
while (*p != '\0')
p++;
}
else
{
char expbuf[6 + 1];
const char *ep;
sprintf (expbuf, "%+d", exponent);
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
# endif
}
END_LONG_DOUBLE_ROUNDING ();
}
# else
abort ();
# endif
}
else
{
# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
double arg = a.arg[dp->arg_index].a.a_double;
if (isnand (arg))
{
if (dp->conversion == 'A')
{
*p++ = 'N'; *p++ = 'A'; *p++ = 'N';
}
else
{
*p++ = 'n'; *p++ = 'a'; *p++ = 'n';
}
}
else
{
int sign = 0;
if (signbit (arg)) /* arg < 0.0 or negative zero */
{
sign = -1;
arg = -arg;
}
if (sign < 0)
*p++ = '-';
else if (flags & FLAG_SHOWSIGN)
*p++ = '+';
else if (flags & FLAG_SPACE)
*p++ = ' ';
if (arg > 0.0 && arg + arg == arg)
{
if (dp->conversion == 'A')
{
*p++ = 'I'; *p++ = 'N'; *p++ = 'F';
}
else
{
*p++ = 'i'; *p++ = 'n'; *p++ = 'f';
}
}
else
{
int exponent;
double mantissa;
if (arg > 0.0)
mantissa = printf_frexp (arg, &exponent);
else
{
exponent = 0;
mantissa = 0.0;
}
if (has_precision
&& precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
{
/* Round the mantissa. */
double tail = mantissa;
size_t q;
for (q = precision; ; q--)
{
int digit = (int) tail;
tail -= digit;
if (q == 0)
{
if (digit & 1 ? tail >= 0.5 : tail > 0.5)
tail = 1 - tail;
else
tail = - tail;
break;
}
tail *= 16.0;
}
if (tail != 0.0)
for (q = precision; q > 0; q--)
tail *= 0.0625;
mantissa += tail;
}
*p++ = '0';
*p++ = dp->conversion - 'A' + 'X';
pad_ptr = p;
{
int digit;
digit = (int) mantissa;
mantissa -= digit;
*p++ = '0' + digit;
if ((flags & FLAG_ALT)
|| mantissa > 0.0 || precision > 0)
{
*p++ = decimal_point_char ();
/* This loop terminates because we assume
that FLT_RADIX is a power of 2. */
while (mantissa > 0.0)
{
mantissa *= 16.0;
digit = (int) mantissa;
mantissa -= digit;
*p++ = digit
+ (digit < 10
? '0'
: dp->conversion - 10);
if (precision > 0)
precision--;
}
while (precision > 0)
{
*p++ = '0';
precision--;
}
}
}
*p++ = dp->conversion - 'A' + 'P';
# if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', 'd', '\0' };
SNPRINTF (p, 6 + 1, decimal_format, exponent);
}
while (*p != '\0')
p++;
# else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+d", exponent);
while (*p != '\0')
p++;
}
else
{
char expbuf[6 + 1];
const char *ep;
sprintf (expbuf, "%+d", exponent);
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
# endif
}
}
# else
abort ();
# endif
}
/* The generated string now extends from tmp to p, with the
zero padding insertion point being at pad_ptr. */
if (has_width && p - tmp < width)
{
size_t pad = width - (p - tmp);
DCHAR_T *end = p + pad;
if (flags & FLAG_LEFT)
{
/* Pad with spaces on the right. */
for (; pad > 0; pad--)
*p++ = ' ';
}
else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
{
/* Pad with zeroes. */
DCHAR_T *q = end;
while (p > pad_ptr)
*--q = *--p;
for (; pad > 0; pad--)
*p++ = '0';
}
else
{
/* Pad with spaces on the left. */
DCHAR_T *q = end;
while (p > tmp)
*--q = *--p;
for (; pad > 0; pad--)
*p++ = ' ';
}
p = end;
}
{
size_t count = p - tmp;
if (count >= tmp_length)
/* tmp_length was incorrectly calculated - fix the
code above! */
abort ();
/* Make room for the result. */
if (count >= allocated - length)
{
size_t n = xsum (length, count);
ENSURE_ALLOCATION (n);
}
/* Append the result. */
memcpy (result + length, tmp, count * sizeof (DCHAR_T));
if (tmp != tmpbuf)
free (tmp);
length += count;
}
}
#endif
#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
else if ((dp->conversion == 'f' || dp->conversion == 'F'
|| dp->conversion == 'e' || dp->conversion == 'E'
|| dp->conversion == 'g' || dp->conversion == 'G'
|| dp->conversion == 'a' || dp->conversion == 'A')
&& (0
# if NEED_PRINTF_DOUBLE
|| a.arg[dp->arg_index].type == TYPE_DOUBLE
# elif NEED_PRINTF_INFINITE_DOUBLE
|| (a.arg[dp->arg_index].type == TYPE_DOUBLE
/* The systems (mingw) which produce wrong output
for Inf, -Inf, and NaN also do so for -0.0.
Therefore we treat this case here as well. */
&& is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
# endif
# if NEED_PRINTF_LONG_DOUBLE
|| a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
|| (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
/* Some systems produce wrong output for Inf,
-Inf, and NaN. Some systems in this category
(IRIX 5.3) also do so for -0.0. Therefore we
treat this case here as well. */
&& is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
# endif
))
{
# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
arg_type type = a.arg[dp->arg_index].type;
# endif
int flags = dp->flags;
int has_width;
size_t width;
int has_precision;
size_t precision;
size_t tmp_length;
DCHAR_T tmpbuf[700];
DCHAR_T *tmp;
DCHAR_T *pad_ptr;
DCHAR_T *p;
has_width = 0;
width = 0;
if (dp->width_start != dp->width_end)
{
if (dp->width_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = (unsigned int) (-arg);
}
else
width = arg;
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
has_width = 1;
}
has_precision = 0;
precision = 0;
if (dp->precision_start != dp->precision_end)
{
if (dp->precision_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->precision_arg_index].a.a_int;
/* "A negative precision is taken as if the precision
were omitted." */
if (arg >= 0)
{
precision = arg;
has_precision = 1;
}
}
else
{
const FCHAR_T *digitp = dp->precision_start + 1;
precision = 0;
while (digitp != dp->precision_end)
precision = xsum (xtimes (precision, 10), *digitp++ - '0');
has_precision = 1;
}
}
/* POSIX specifies the default precision to be 6 for %f, %F,
%e, %E, but not for %g, %G. Implementations appear to use
the same default precision also for %g, %G. But for %a, %A,
the default precision is 0. */
if (!has_precision)
if (!(dp->conversion == 'a' || dp->conversion == 'A'))
precision = 6;
/* Allocate a temporary buffer of sufficient size. */
# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
# elif NEED_PRINTF_LONG_DOUBLE
tmp_length = LDBL_DIG + 1;
# elif NEED_PRINTF_DOUBLE
tmp_length = DBL_DIG + 1;
# else
tmp_length = 0;
# endif
if (tmp_length < precision)
tmp_length = precision;
# if NEED_PRINTF_LONG_DOUBLE
# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
if (type == TYPE_LONGDOUBLE)
# endif
if (dp->conversion == 'f' || dp->conversion == 'F')
{
long double arg = a.arg[dp->arg_index].a.a_longdouble;
if (!(isnanl (arg) || arg + arg == arg))
{
/* arg is finite and nonzero. */
int exponent = floorlog10l (arg < 0 ? -arg : arg);
if (exponent >= 0 && tmp_length < exponent + precision)
tmp_length = exponent + precision;
}
}
# endif
# if NEED_PRINTF_DOUBLE
# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
if (type == TYPE_DOUBLE)
# endif
if (dp->conversion == 'f' || dp->conversion == 'F')
{
double arg = a.arg[dp->arg_index].a.a_double;
if (!(isnand (arg) || arg + arg == arg))
{
/* arg is finite and nonzero. */
int exponent = floorlog10 (arg < 0 ? -arg : arg);
if (exponent >= 0 && tmp_length < exponent + precision)
tmp_length = exponent + precision;
}
}
# endif
/* Account for sign, decimal point etc. */
tmp_length = xsum (tmp_length, 12);
if (tmp_length < width)
tmp_length = width;
tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
tmp = tmpbuf;
else
{
size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
if (size_overflow_p (tmp_memsize))
/* Overflow, would lead to out of memory. */
goto out_of_memory;
tmp = (DCHAR_T *) malloc (tmp_memsize);
if (tmp == NULL)
/* Out of memory. */
goto out_of_memory;
}
pad_ptr = NULL;
p = tmp;
# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
if (type == TYPE_LONGDOUBLE)
# endif
{
long double arg = a.arg[dp->arg_index].a.a_longdouble;
if (isnanl (arg))
{
if (dp->conversion >= 'A' && dp->conversion <= 'Z')
{
*p++ = 'N'; *p++ = 'A'; *p++ = 'N';
}
else
{
*p++ = 'n'; *p++ = 'a'; *p++ = 'n';
}
}
else
{
int sign = 0;
DECL_LONG_DOUBLE_ROUNDING
BEGIN_LONG_DOUBLE_ROUNDING ();
if (signbit (arg)) /* arg < 0.0L or negative zero */
{
sign = -1;
arg = -arg;
}
if (sign < 0)
*p++ = '-';
else if (flags & FLAG_SHOWSIGN)
*p++ = '+';
else if (flags & FLAG_SPACE)
*p++ = ' ';
if (arg > 0.0L && arg + arg == arg)
{
if (dp->conversion >= 'A' && dp->conversion <= 'Z')
{
*p++ = 'I'; *p++ = 'N'; *p++ = 'F';
}
else
{
*p++ = 'i'; *p++ = 'n'; *p++ = 'f';
}
}
else
{
# if NEED_PRINTF_LONG_DOUBLE
pad_ptr = p;
if (dp->conversion == 'f' || dp->conversion == 'F')
{
char *digits;
size_t ndigits;
digits =
scale10_round_decimal_long_double (arg, precision);
if (digits == NULL)
{
END_LONG_DOUBLE_ROUNDING ();
goto out_of_memory;
}
ndigits = strlen (digits);
if (ndigits > precision)
do
{
--ndigits;
*p++ = digits[ndigits];
}
while (ndigits > precision);
else
*p++ = '0';
/* Here ndigits <= precision. */
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > ndigits; precision--)
*p++ = '0';
while (ndigits > 0)
{
--ndigits;
*p++ = digits[ndigits];
}
}
free (digits);
}
else if (dp->conversion == 'e' || dp->conversion == 'E')
{
int exponent;
if (arg == 0.0L)
{
exponent = 0;
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
}
else
{
/* arg > 0.0L. */
int adjusted;
char *digits;
size_t ndigits;
exponent = floorlog10l (arg);
adjusted = 0;
for (;;)
{
digits =
scale10_round_decimal_long_double (arg,
(int)precision - exponent);
if (digits == NULL)
{
END_LONG_DOUBLE_ROUNDING ();
goto out_of_memory;
}
ndigits = strlen (digits);
if (ndigits == precision + 1)
break;
if (ndigits < precision
|| ndigits > precision + 2)
/* The exponent was not guessed
precisely enough. */
abort ();
if (adjusted)
/* None of two values of exponent is
the right one. Prevent an endless
loop. */
abort ();
free (digits);
if (ndigits == precision)
exponent -= 1;
else
exponent += 1;
adjusted = 1;
}
/* Here ndigits = precision+1. */
if (is_borderline (digits, precision))
{
/* Maybe the exponent guess was too high
and a smaller exponent can be reached
by turning a 10...0 into 9...9x. */
char *digits2 =
scale10_round_decimal_long_double (arg,
(int)precision - exponent + 1);
if (digits2 == NULL)
{
free (digits);
END_LONG_DOUBLE_ROUNDING ();
goto out_of_memory;
}
if (strlen (digits2) == precision + 1)
{
free (digits);
digits = digits2;
exponent -= 1;
}
else
free (digits2);
}
/* Here ndigits = precision+1. */
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
while (ndigits > 0)
{
--ndigits;
*p++ = digits[ndigits];
}
}
free (digits);
}
*p++ = dp->conversion; /* 'e' or 'E' */
# if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', '.', '2', 'd', '\0' };
SNPRINTF (p, 6 + 1, decimal_format, exponent);
}
while (*p != '\0')
p++;
# else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+.2d", exponent);
while (*p != '\0')
p++;
}
else
{
char expbuf[6 + 1];
const char *ep;
sprintf (expbuf, "%+.2d", exponent);
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
# endif
}
else if (dp->conversion == 'g' || dp->conversion == 'G')
{
if (precision == 0)
precision = 1;
/* precision >= 1. */
if (arg == 0.0L)
/* The exponent is 0, >= -4, < precision.
Use fixed-point notation. */
{
size_t ndigits = precision;
/* Number of trailing zeroes that have to be
dropped. */
size_t nzeroes =
(flags & FLAG_ALT ? 0 : precision - 1);
--ndigits;
*p++ = '0';
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = '0';
}
}
}
else
{
/* arg > 0.0L. */
int exponent;
int adjusted;
char *digits;
size_t ndigits;
size_t nzeroes;
exponent = floorlog10l (arg);
adjusted = 0;
for (;;)
{
digits =
scale10_round_decimal_long_double (arg,
(int)(precision - 1) - exponent);
if (digits == NULL)
{
END_LONG_DOUBLE_ROUNDING ();
goto out_of_memory;
}
ndigits = strlen (digits);
if (ndigits == precision)
break;
if (ndigits < precision - 1
|| ndigits > precision + 1)
/* The exponent was not guessed
precisely enough. */
abort ();
if (adjusted)
/* None of two values of exponent is
the right one. Prevent an endless
loop. */
abort ();
free (digits);
if (ndigits < precision)
exponent -= 1;
else
exponent += 1;
adjusted = 1;
}
/* Here ndigits = precision. */
if (is_borderline (digits, precision - 1))
{
/* Maybe the exponent guess was too high
and a smaller exponent can be reached
by turning a 10...0 into 9...9x. */
char *digits2 =
scale10_round_decimal_long_double (arg,
(int)(precision - 1) - exponent + 1);
if (digits2 == NULL)
{
free (digits);
END_LONG_DOUBLE_ROUNDING ();
goto out_of_memory;
}
if (strlen (digits2) == precision)
{
free (digits);
digits = digits2;
exponent -= 1;
}
else
free (digits2);
}
/* Here ndigits = precision. */
/* Determine the number of trailing zeroes
that have to be dropped. */
nzeroes = 0;
if ((flags & FLAG_ALT) == 0)
while (nzeroes < ndigits
&& digits[nzeroes] == '0')
nzeroes++;
/* The exponent is now determined. */
if (exponent >= -4
&& exponent < (long)precision)
{
/* Fixed-point notation:
max(exponent,0)+1 digits, then the
decimal point, then the remaining
digits without trailing zeroes. */
if (exponent >= 0)
{
size_t count = exponent + 1;
/* Note: count <= precision = ndigits. */
for (; count > 0; count--)
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
}
else
{
size_t count = -exponent - 1;
*p++ = '0';
*p++ = decimal_point_char ();
for (; count > 0; count--)
*p++ = '0';
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
}
else
{
/* Exponential notation. */
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
*p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
# if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', '.', '2', 'd', '\0' };
SNPRINTF (p, 6 + 1, decimal_format, exponent);
}
while (*p != '\0')
p++;
# else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+.2d", exponent);
while (*p != '\0')
p++;
}
else
{
char expbuf[6 + 1];
const char *ep;
sprintf (expbuf, "%+.2d", exponent);
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
# endif
}
free (digits);
}
}
else
abort ();
# else
/* arg is finite. */
if (!(arg == 0.0L))
abort ();
pad_ptr = p;
if (dp->conversion == 'f' || dp->conversion == 'F')
{
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
}
else if (dp->conversion == 'e' || dp->conversion == 'E')
{
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
*p++ = dp->conversion; /* 'e' or 'E' */
*p++ = '+';
*p++ = '0';
*p++ = '0';
}
else if (dp->conversion == 'g' || dp->conversion == 'G')
{
*p++ = '0';
if (flags & FLAG_ALT)
{
size_t ndigits =
(precision > 0 ? precision - 1 : 0);
*p++ = decimal_point_char ();
for (; ndigits > 0; --ndigits)
*p++ = '0';
}
}
else if (dp->conversion == 'a' || dp->conversion == 'A')
{
*p++ = '0';
*p++ = dp->conversion - 'A' + 'X';
pad_ptr = p;
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
*p++ = dp->conversion - 'A' + 'P';
*p++ = '+';
*p++ = '0';
}
else
abort ();
# endif
}
END_LONG_DOUBLE_ROUNDING ();
}
}
# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
else
# endif
# endif
# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
{
double arg = a.arg[dp->arg_index].a.a_double;
if (isnand (arg))
{
if (dp->conversion >= 'A' && dp->conversion <= 'Z')
{
*p++ = 'N'; *p++ = 'A'; *p++ = 'N';
}
else
{
*p++ = 'n'; *p++ = 'a'; *p++ = 'n';
}
}
else
{
int sign = 0;
if (signbit (arg)) /* arg < 0.0 or negative zero */
{
sign = -1;
arg = -arg;
}
if (sign < 0)
*p++ = '-';
else if (flags & FLAG_SHOWSIGN)
*p++ = '+';
else if (flags & FLAG_SPACE)
*p++ = ' ';
if (arg > 0.0 && arg + arg == arg)
{
if (dp->conversion >= 'A' && dp->conversion <= 'Z')
{
*p++ = 'I'; *p++ = 'N'; *p++ = 'F';
}
else
{
*p++ = 'i'; *p++ = 'n'; *p++ = 'f';
}
}
else
{
# if NEED_PRINTF_DOUBLE
pad_ptr = p;
if (dp->conversion == 'f' || dp->conversion == 'F')
{
char *digits;
size_t ndigits;
digits =
scale10_round_decimal_double (arg, precision);
if (digits == NULL)
goto out_of_memory;
ndigits = strlen (digits);
if (ndigits > precision)
do
{
--ndigits;
*p++ = digits[ndigits];
}
while (ndigits > precision);
else
*p++ = '0';
/* Here ndigits <= precision. */
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > ndigits; precision--)
*p++ = '0';
while (ndigits > 0)
{
--ndigits;
*p++ = digits[ndigits];
}
}
free (digits);
}
else if (dp->conversion == 'e' || dp->conversion == 'E')
{
int exponent;
if (arg == 0.0)
{
exponent = 0;
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
}
else
{
/* arg > 0.0. */
int adjusted;
char *digits;
size_t ndigits;
exponent = floorlog10 (arg);
adjusted = 0;
for (;;)
{
digits =
scale10_round_decimal_double (arg,
(int)precision - exponent);
if (digits == NULL)
goto out_of_memory;
ndigits = strlen (digits);
if (ndigits == precision + 1)
break;
if (ndigits < precision
|| ndigits > precision + 2)
/* The exponent was not guessed
precisely enough. */
abort ();
if (adjusted)
/* None of two values of exponent is
the right one. Prevent an endless
loop. */
abort ();
free (digits);
if (ndigits == precision)
exponent -= 1;
else
exponent += 1;
adjusted = 1;
}
/* Here ndigits = precision+1. */
if (is_borderline (digits, precision))
{
/* Maybe the exponent guess was too high
and a smaller exponent can be reached
by turning a 10...0 into 9...9x. */
char *digits2 =
scale10_round_decimal_double (arg,
(int)precision - exponent + 1);
if (digits2 == NULL)
{
free (digits);
goto out_of_memory;
}
if (strlen (digits2) == precision + 1)
{
free (digits);
digits = digits2;
exponent -= 1;
}
else
free (digits2);
}
/* Here ndigits = precision+1. */
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
while (ndigits > 0)
{
--ndigits;
*p++ = digits[ndigits];
}
}
free (digits);
}
*p++ = dp->conversion; /* 'e' or 'E' */
# if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
{ '%', '+', '.', '3', 'd', '\0' };
# else
{ '%', '+', '.', '2', 'd', '\0' };
# endif
SNPRINTF (p, 6 + 1, decimal_format, exponent);
}
while (*p != '\0')
p++;
# else
{
static const char decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
"%+.3d";
# else
"%+.2d";
# endif
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, decimal_format, exponent);
while (*p != '\0')
p++;
}
else
{
char expbuf[6 + 1];
const char *ep;
sprintf (expbuf, decimal_format, exponent);
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
}
# endif
}
else if (dp->conversion == 'g' || dp->conversion == 'G')
{
if (precision == 0)
precision = 1;
/* precision >= 1. */
if (arg == 0.0)
/* The exponent is 0, >= -4, < precision.
Use fixed-point notation. */
{
size_t ndigits = precision;
/* Number of trailing zeroes that have to be
dropped. */
size_t nzeroes =
(flags & FLAG_ALT ? 0 : precision - 1);
--ndigits;
*p++ = '0';
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = '0';
}
}
}
else
{
/* arg > 0.0. */
int exponent;
int adjusted;
char *digits;
size_t ndigits;
size_t nzeroes;
exponent = floorlog10 (arg);
adjusted = 0;
for (;;)
{
digits =
scale10_round_decimal_double (arg,
(int)(precision - 1) - exponent);
if (digits == NULL)
goto out_of_memory;
ndigits = strlen (digits);
if (ndigits == precision)
break;
if (ndigits < precision - 1
|| ndigits > precision + 1)
/* The exponent was not guessed
precisely enough. */
abort ();
if (adjusted)
/* None of two values of exponent is
the right one. Prevent an endless
loop. */
abort ();
free (digits);
if (ndigits < precision)
exponent -= 1;
else
exponent += 1;
adjusted = 1;
}
/* Here ndigits = precision. */
if (is_borderline (digits, precision - 1))
{
/* Maybe the exponent guess was too high
and a smaller exponent can be reached
by turning a 10...0 into 9...9x. */
char *digits2 =
scale10_round_decimal_double (arg,
(int)(precision - 1) - exponent + 1);
if (digits2 == NULL)
{
free (digits);
goto out_of_memory;
}
if (strlen (digits2) == precision)
{
free (digits);
digits = digits2;
exponent -= 1;
}
else
free (digits2);
}
/* Here ndigits = precision. */
/* Determine the number of trailing zeroes
that have to be dropped. */
nzeroes = 0;
if ((flags & FLAG_ALT) == 0)
while (nzeroes < ndigits
&& digits[nzeroes] == '0')
nzeroes++;
/* The exponent is now determined. */
if (exponent >= -4
&& exponent < (long)precision)
{
/* Fixed-point notation:
max(exponent,0)+1 digits, then the
decimal point, then the remaining
digits without trailing zeroes. */
if (exponent >= 0)
{
size_t count = exponent + 1;
/* Note: count <= precision = ndigits. */
for (; count > 0; count--)
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
}
else
{
size_t count = -exponent - 1;
*p++ = '0';
*p++ = decimal_point_char ();
for (; count > 0; count--)
*p++ = '0';
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
}
else
{
/* Exponential notation. */
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
*p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
# if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
{ '%', '+', '.', '3', 'd', '\0' };
# else
{ '%', '+', '.', '2', 'd', '\0' };
# endif
SNPRINTF (p, 6 + 1, decimal_format, exponent);
}
while (*p != '\0')
p++;
# else
{
static const char decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
"%+.3d";
# else
"%+.2d";
# endif
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, decimal_format, exponent);
while (*p != '\0')
p++;
}
else
{
char expbuf[6 + 1];
const char *ep;
sprintf (expbuf, decimal_format, exponent);
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
}
# endif
}
free (digits);
}
}
else
abort ();
# else
/* arg is finite. */
if (!(arg == 0.0))
abort ();
pad_ptr = p;
if (dp->conversion == 'f' || dp->conversion == 'F')
{
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
}
else if (dp->conversion == 'e' || dp->conversion == 'E')
{
*p++ = '0';
if ((flags & FLAG_ALT) || precision > 0)
{
*p++ = decimal_point_char ();
for (; precision > 0; precision--)
*p++ = '0';
}
*p++ = dp->conversion; /* 'e' or 'E' */
*p++ = '+';
/* Produce the same number of exponent digits as
the native printf implementation. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
*p++ = '0';
# endif
*p++ = '0';
*p++ = '0';
}
else if (dp->conversion == 'g' || dp->conversion == 'G')
{
*p++ = '0';
if (flags & FLAG_ALT)
{
size_t ndigits =
(precision > 0 ? precision - 1 : 0);
*p++ = decimal_point_char ();
for (; ndigits > 0; --ndigits)
*p++ = '0';
}
}
else
abort ();
# endif
}
}
}
# endif
/* The generated string now extends from tmp to p, with the
zero padding insertion point being at pad_ptr. */
if (has_width && p - tmp < width)
{
size_t pad = width - (p - tmp);
DCHAR_T *end = p + pad;
if (flags & FLAG_LEFT)
{
/* Pad with spaces on the right. */
for (; pad > 0; pad--)
*p++ = ' ';
}
else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
{
/* Pad with zeroes. */
DCHAR_T *q = end;
while (p > pad_ptr)
*--q = *--p;
for (; pad > 0; pad--)
*p++ = '0';
}
else
{
/* Pad with spaces on the left. */
DCHAR_T *q = end;
while (p > tmp)
*--q = *--p;
for (; pad > 0; pad--)
*p++ = ' ';
}
p = end;
}
{
size_t count = p - tmp;
if (count >= tmp_length)
/* tmp_length was incorrectly calculated - fix the
code above! */
abort ();
/* Make room for the result. */
if (count >= allocated - length)
{
size_t n = xsum (length, count);
ENSURE_ALLOCATION (n);
}
/* Append the result. */
memcpy (result + length, tmp, count * sizeof (DCHAR_T));
if (tmp != tmpbuf)
free (tmp);
length += count;
}
}
#endif
else
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int has_width;
size_t width;
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
int has_precision;
size_t precision;
#endif
#if NEED_PRINTF_UNBOUNDED_PRECISION
int prec_ourselves;
#else
# define prec_ourselves 0
#endif
#if NEED_PRINTF_FLAG_LEFTADJUST
# define pad_ourselves 1
#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int pad_ourselves;
#else
# define pad_ourselves 0
#endif
TCHAR_T *fbp;
unsigned int prefix_count;
int prefixes[2] IF_LINT (= { 0 });
int orig_errno;
#if !USE_SNPRINTF
size_t tmp_length;
TCHAR_T tmpbuf[700];
TCHAR_T *tmp;
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 0;
width = 0;
if (dp->width_start != dp->width_end)
{
if (dp->width_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = (unsigned int) (-arg);
}
else
width = arg;
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
has_width = 1;
}
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
has_precision = 0;
precision = 6;
if (dp->precision_start != dp->precision_end)
{
if (dp->precision_arg_index != ARG_NONE)
{
int arg;
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->precision_arg_index].a.a_int;
/* "A negative precision is taken as if the precision
were omitted." */
if (arg >= 0)
{
precision = arg;
has_precision = 1;
}
}
else
{
const FCHAR_T *digitp = dp->precision_start + 1;
precision = 0;
while (digitp != dp->precision_end)
precision = xsum (xtimes (precision, 10), *digitp++ - '0');
has_precision = 1;
}
}
#endif
/* Decide whether to handle the precision ourselves. */
#if NEED_PRINTF_UNBOUNDED_PRECISION
switch (dp->conversion)
{
case 'd': case 'i': case 'u':
case 'o':
case 'x': case 'X': case 'p':
prec_ourselves = has_precision && (precision > 0);
break;
default:
prec_ourselves = 0;
break;
}
#endif
/* Decide whether to perform the padding ourselves. */
#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
switch (dp->conversion)
{
# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
/* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
to perform the padding after this conversion. Functions
with unistdio extensions perform the padding based on
character count rather than element count. */
case 'c': case 's':
# endif
# if NEED_PRINTF_FLAG_ZERO
case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
# endif
pad_ourselves = 1;
break;
default:
pad_ourselves = prec_ourselves;
break;
}
#endif
#if !USE_SNPRINTF
/* Allocate a temporary buffer of sufficient size for calling
sprintf. */
tmp_length =
MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
flags, width, has_precision, precision,
pad_ourselves);
if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
tmp = tmpbuf;
else
{
size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
if (size_overflow_p (tmp_memsize))
/* Overflow, would lead to out of memory. */
goto out_of_memory;
tmp = (TCHAR_T *) malloc (tmp_memsize);
if (tmp == NULL)
/* Out of memory. */
goto out_of_memory;
}
#endif
/* Construct the format string for calling snprintf or
sprintf. */
fbp = buf;
*fbp++ = '%';
#if NEED_PRINTF_FLAG_GROUPING
/* The underlying implementation doesn't support the ' flag.
Produce no grouping characters in this case; this is
acceptable because the grouping is locale dependent. */
#else
if (flags & FLAG_GROUP)
*fbp++ = '\'';
#endif
if (flags & FLAG_LEFT)
*fbp++ = '-';
if (flags & FLAG_SHOWSIGN)
*fbp++ = '+';
if (flags & FLAG_SPACE)
*fbp++ = ' ';
if (flags & FLAG_ALT)
*fbp++ = '#';
#if __GLIBC__ >= 2 && !defined __UCLIBC__
if (flags & FLAG_LOCALIZED)
*fbp++ = 'I';
#endif
if (!pad_ourselves)
{
if (flags & FLAG_ZERO)
*fbp++ = '0';
if (dp->width_start != dp->width_end)
{
size_t n = dp->width_end - dp->width_start;
/* The width specification is known to consist only
of standard ASCII characters. */
if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
{
memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
fbp += n;
}
else
{
const FCHAR_T *mp = dp->width_start;
do
*fbp++ = (unsigned char) *mp++;
while (--n > 0);
}
}
}
if (!prec_ourselves)
{
if (dp->precision_start != dp->precision_end)
{
size_t n = dp->precision_end - dp->precision_start;
/* The precision specification is known to consist only
of standard ASCII characters. */
if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
{
memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
fbp += n;
}
else
{
const FCHAR_T *mp = dp->precision_start;
do
*fbp++ = (unsigned char) *mp++;
while (--n > 0);
}
}
}
switch (type)
{
#if HAVE_LONG_LONG_INT
case TYPE_LONGLONGINT:
case TYPE_ULONGLONGINT:
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
*fbp++ = 'I';
*fbp++ = '6';
*fbp++ = '4';
break;
# else
*fbp++ = 'l';
/*FALLTHROUGH*/
# endif
#endif
case TYPE_LONGINT:
case TYPE_ULONGINT:
#if HAVE_WINT_T
case TYPE_WIDE_CHAR:
#endif
#if HAVE_WCHAR_T
case TYPE_WIDE_STRING:
#endif
*fbp++ = 'l';
break;
case TYPE_LONGDOUBLE:
*fbp++ = 'L';
break;
default:
break;
}
#if NEED_PRINTF_DIRECTIVE_F
if (dp->conversion == 'F')
*fbp = 'f';
else
#endif
*fbp = dp->conversion;
#if USE_SNPRINTF
# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
fbp[1] = '%';
fbp[2] = 'n';
fbp[3] = '\0';
# else
/* On glibc2 systems from glibc >= 2.3 - probably also older
ones - we know that snprintf's return value conforms to
ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
gl_SNPRINTF_TRUNCATION_C99 pass.
Therefore we can avoid using %n in this situation.
On glibc2 systems from 2004-10-18 or newer, the use of %n
in format strings in writable memory may crash the program
(if compiled with _FORTIFY_SOURCE=2), so we should avoid it
in this situation. */
/* On native Windows systems (such as mingw), we can avoid using
%n because:
- Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
snprintf does not write more than the specified number
of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
'4', '5', '6' into buf, not '4', '5', '\0'.)
- Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
allows us to recognize the case of an insufficient
buffer size: it returns -1 in this case.
On native Windows systems (such as mingw) where the OS is
Windows Vista, the use of %n in format strings by default
crashes the program. See
and
So we should avoid %n in this situation. */
fbp[1] = '\0';
# endif
#else
fbp[1] = '\0';
#endif
/* Construct the arguments for calling snprintf or sprintf. */
prefix_count = 0;
if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
{
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
}
if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
{
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
}
#if USE_SNPRINTF
/* The SNPRINTF result is appended after result[0..length].
The latter is an array of DCHAR_T; SNPRINTF appends an
array of TCHAR_T to it. This is possible because
sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
alignof (TCHAR_T) <= alignof (DCHAR_T). */
# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
/* Ensure that maxlen below will be >= 2. Needed on BeOS,
where an snprintf() with maxlen==1 acts like sprintf(). */
ENSURE_ALLOCATION (xsum (length,
(2 + TCHARS_PER_DCHAR - 1)
/ TCHARS_PER_DCHAR));
/* Prepare checking whether snprintf returns the count
via %n. */
*(TCHAR_T *) (result + length) = '\0';
#endif
orig_errno = errno;
for (;;)
{
int count = -1;
#if USE_SNPRINTF
int retcount = 0;
size_t maxlen = allocated - length;
/* SNPRINTF can fail if its second argument is
> INT_MAX. */
if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
maxlen = INT_MAX / TCHARS_PER_DCHAR;
maxlen = maxlen * TCHARS_PER_DCHAR;
# define SNPRINTF_BUF(arg) \
switch (prefix_count) \
{ \
case 0: \
retcount = SNPRINTF ((TCHAR_T *) (result + length), \
maxlen, buf, \
arg, &count); \
break; \
case 1: \
retcount = SNPRINTF ((TCHAR_T *) (result + length), \
maxlen, buf, \
prefixes[0], arg, &count); \
break; \
case 2: \
retcount = SNPRINTF ((TCHAR_T *) (result + length), \
maxlen, buf, \
prefixes[0], prefixes[1], arg, \
&count); \
break; \
default: \
abort (); \
}
#else
# define SNPRINTF_BUF(arg) \
switch (prefix_count) \
{ \
case 0: \
count = sprintf (tmp, buf, arg); \
break; \
case 1: \
count = sprintf (tmp, buf, prefixes[0], arg); \
break; \
case 2: \
count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
arg); \
break; \
default: \
abort (); \
}
#endif
errno = 0;
switch (type)
{
case TYPE_SCHAR:
{
int arg = a.arg[dp->arg_index].a.a_schar;
SNPRINTF_BUF (arg);
}
break;
case TYPE_UCHAR:
{
unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
SNPRINTF_BUF (arg);
}
break;
case TYPE_SHORT:
{
int arg = a.arg[dp->arg_index].a.a_short;
SNPRINTF_BUF (arg);
}
break;
case TYPE_USHORT:
{
unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
SNPRINTF_BUF (arg);
}
break;
case TYPE_INT:
{
int arg = a.arg[dp->arg_index].a.a_int;
SNPRINTF_BUF (arg);
}
break;
case TYPE_UINT:
{
unsigned int arg = a.arg[dp->arg_index].a.a_uint;
SNPRINTF_BUF (arg);
}
break;
case TYPE_LONGINT:
{
long int arg = a.arg[dp->arg_index].a.a_longint;
SNPRINTF_BUF (arg);
}
break;
case TYPE_ULONGINT:
{
unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
SNPRINTF_BUF (arg);
}
break;
#if HAVE_LONG_LONG_INT
case TYPE_LONGLONGINT:
{
long long int arg = a.arg[dp->arg_index].a.a_longlongint;
SNPRINTF_BUF (arg);
}
break;
case TYPE_ULONGLONGINT:
{
unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_DOUBLE:
{
double arg = a.arg[dp->arg_index].a.a_double;
SNPRINTF_BUF (arg);
}
break;
case TYPE_LONGDOUBLE:
{
long double arg = a.arg[dp->arg_index].a.a_longdouble;
SNPRINTF_BUF (arg);
}
break;
case TYPE_CHAR:
{
int arg = a.arg[dp->arg_index].a.a_char;
SNPRINTF_BUF (arg);
}
break;
#if HAVE_WINT_T
case TYPE_WIDE_CHAR:
{
wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_STRING:
{
const char *arg = a.arg[dp->arg_index].a.a_string;
SNPRINTF_BUF (arg);
}
break;
#if HAVE_WCHAR_T
case TYPE_WIDE_STRING:
{
const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_POINTER:
{
void *arg = a.arg[dp->arg_index].a.a_pointer;
SNPRINTF_BUF (arg);
}
break;
default:
abort ();
}
#if USE_SNPRINTF
/* Portability: Not all implementations of snprintf()
are ISO C 99 compliant. Determine the number of
bytes that snprintf() has produced or would have
produced. */
if (count >= 0)
{
/* Verify that snprintf() has NUL-terminated its
result. */
if (count < maxlen
&& ((TCHAR_T *) (result + length)) [count] != '\0')
abort ();
/* Portability hack. */
if (retcount > count)
count = retcount;
}
else
{
/* snprintf() doesn't understand the '%n'
directive. */
if (fbp[1] != '\0')
{
/* Don't use the '%n' directive; instead, look
at the snprintf() return value. */
fbp[1] = '\0';
continue;
}
else
{
/* Look at the snprintf() return value. */
if (retcount < 0)
{
# if !HAVE_SNPRINTF_RETVAL_C99
/* HP-UX 10.20 snprintf() is doubly deficient:
It doesn't understand the '%n' directive,
*and* it returns -1 (rather than the length
that would have been required) when the
buffer is too small.
But a failure at this point can also come
from other reasons than a too small buffer,
such as an invalid wide string argument to
the %ls directive, or possibly an invalid
floating-point argument. */
size_t tmp_length =
MAX_ROOM_NEEDED (&a, dp->arg_index,
dp->conversion, type, flags,
width, has_precision,
precision, pad_ourselves);
if (maxlen < tmp_length)
{
/* Make more room. But try to do through
this reallocation only once. */
size_t bigger_need =
xsum (length,
xsum (tmp_length,
TCHARS_PER_DCHAR - 1)
/ TCHARS_PER_DCHAR);
/* And always grow proportionally.
(There may be several arguments, each
needing a little more room than the
previous one.) */
size_t bigger_need2 =
xsum (xtimes (allocated, 2), 12);
if (bigger_need < bigger_need2)
bigger_need = bigger_need2;
ENSURE_ALLOCATION (bigger_need);
continue;
}
# endif
}
else
count = retcount;
}
}
#endif
/* Attempt to handle failure. */
if (count < 0)
{
/* SNPRINTF or sprintf failed. Save and use the errno
that it has set, if any. */
int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno =
(saved_errno != 0
? saved_errno
: (dp->conversion == 'c' || dp->conversion == 's'
? EILSEQ
: EINVAL));
return NULL;
}
#if USE_SNPRINTF
/* Handle overflow of the allocated buffer.
If such an overflow occurs, a C99 compliant snprintf()
returns a count >= maxlen. However, a non-compliant
snprintf() function returns only count = maxlen - 1. To
cover both cases, test whether count >= maxlen - 1. */
if ((unsigned int) count + 1 >= maxlen)
{
/* If maxlen already has attained its allowed maximum,
allocating more memory will not increase maxlen.
Instead of looping, bail out. */
if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
goto overflow;
else
{
/* Need at least (count + 1) * sizeof (TCHAR_T)
bytes. (The +1 is for the trailing NUL.)
But ask for (count + 2) * sizeof (TCHAR_T)
bytes, so that in the next round, we likely get
maxlen > (unsigned int) count + 1
and so we don't get here again.
And allocate proportionally, to avoid looping
eternally if snprintf() reports a too small
count. */
size_t n =
xmax (xsum (length,
((unsigned int) count + 2
+ TCHARS_PER_DCHAR - 1)
/ TCHARS_PER_DCHAR),
xtimes (allocated, 2));
ENSURE_ALLOCATION (n);
continue;
}
}
#endif
#if NEED_PRINTF_UNBOUNDED_PRECISION
if (prec_ourselves)
{
/* Handle the precision. */
TCHAR_T *prec_ptr =
# if USE_SNPRINTF
(TCHAR_T *) (result + length);
# else
tmp;
# endif
size_t prefix_count;
size_t move;
prefix_count = 0;
/* Put the additional zeroes after the sign. */
if (count >= 1
&& (*prec_ptr == '-' || *prec_ptr == '+'
|| *prec_ptr == ' '))
prefix_count = 1;
/* Put the additional zeroes after the 0x prefix if
(flags & FLAG_ALT) || (dp->conversion == 'p'). */
else if (count >= 2
&& prec_ptr[0] == '0'
&& (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
prefix_count = 2;
move = count - prefix_count;
if (precision > move)
{
/* Insert zeroes. */
size_t insert = precision - move;
TCHAR_T *prec_end;
# if USE_SNPRINTF
size_t n =
xsum (length,
(count + insert + TCHARS_PER_DCHAR - 1)
/ TCHARS_PER_DCHAR);
length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
ENSURE_ALLOCATION (n);
length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
prec_ptr = (TCHAR_T *) (result + length);
# endif
prec_end = prec_ptr + count;
prec_ptr += prefix_count;
while (prec_end > prec_ptr)
{
prec_end--;
prec_end[insert] = prec_end[0];
}
prec_end += insert;
do
*--prec_end = '0';
while (prec_end > prec_ptr);
count += insert;
}
}
#endif
#if !USE_SNPRINTF
if (count >= tmp_length)
/* tmp_length was incorrectly calculated - fix the
code above! */
abort ();
#endif
#if !DCHAR_IS_TCHAR
/* Convert from TCHAR_T[] to DCHAR_T[]. */
if (dp->conversion == 'c' || dp->conversion == 's')
{
/* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
TYPE_WIDE_STRING.
The result string is not certainly ASCII. */
const TCHAR_T *tmpsrc;
DCHAR_T *tmpdst;
size_t tmpdst_len;
/* This code assumes that TCHAR_T is 'char'. */
verify (sizeof (TCHAR_T) == 1);
# if USE_SNPRINTF
tmpsrc = (TCHAR_T *) (result + length);
# else
tmpsrc = tmp;
# endif
tmpdst =
DCHAR_CONV_FROM_ENCODING (locale_charset (),
iconveh_question_mark,
tmpsrc, count,
NULL,
NULL, &tmpdst_len);
if (tmpdst == NULL)
{
int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = saved_errno;
return NULL;
}
ENSURE_ALLOCATION (xsum (length, tmpdst_len));
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
count = tmpdst_len;
}
else
{
/* The result string is ASCII.
Simple 1:1 conversion. */
# if USE_SNPRINTF
/* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
no-op conversion, in-place on the array starting
at (result + length). */
if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
# endif
{
const TCHAR_T *tmpsrc;
DCHAR_T *tmpdst;
size_t n;
# if USE_SNPRINTF
if (result == resultbuf)
{
tmpsrc = (TCHAR_T *) (result + length);
/* ENSURE_ALLOCATION will not move tmpsrc
(because it's part of resultbuf). */
ENSURE_ALLOCATION (xsum (length, count));
}
else
{
/* ENSURE_ALLOCATION will move the array
(because it uses realloc(). */
ENSURE_ALLOCATION (xsum (length, count));
tmpsrc = (TCHAR_T *) (result + length);
}
# else
tmpsrc = tmp;
ENSURE_ALLOCATION (xsum (length, count));
# endif
tmpdst = result + length;
/* Copy backwards, because of overlapping. */
tmpsrc += count;
tmpdst += count;
for (n = count; n > 0; n--)
*--tmpdst = (unsigned char) *--tmpsrc;
}
}
#endif
#if DCHAR_IS_TCHAR && !USE_SNPRINTF
/* Make room for the result. */
if (count > allocated - length)
{
/* Need at least count elements. But allocate
proportionally. */
size_t n =
xmax (xsum (length, count), xtimes (allocated, 2));
ENSURE_ALLOCATION (n);
}
#endif
/* Here count <= allocated - length. */
/* Perform padding. */
#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
if (pad_ourselves && has_width)
{
size_t w;
# if ENABLE_UNISTDIO
/* Outside POSIX, it's preferable to compare the width
against the number of _characters_ of the converted
value. */
w = DCHAR_MBSNLEN (result + length, count);
# else
/* The width is compared against the number of _bytes_
of the converted value, says POSIX. */
w = count;
# endif
if (w < width)
{
size_t pad = width - w;
/* Make room for the result. */
if (xsum (count, pad) > allocated - length)
{
/* Need at least count + pad elements. But
allocate proportionally. */
size_t n =
xmax (xsum3 (length, count, pad),
xtimes (allocated, 2));
# if USE_SNPRINTF
length += count;
ENSURE_ALLOCATION (n);
length -= count;
# else
ENSURE_ALLOCATION (n);
# endif
}
/* Here count + pad <= allocated - length. */
{
# if !DCHAR_IS_TCHAR || USE_SNPRINTF
DCHAR_T * const rp = result + length;
# else
DCHAR_T * const rp = tmp;
# endif
DCHAR_T *p = rp + count;
DCHAR_T *end = p + pad;
DCHAR_T *pad_ptr;
# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
if (dp->conversion == 'c'
|| dp->conversion == 's')
/* No zero-padding for string directives. */
pad_ptr = NULL;
else
# endif
{
pad_ptr = (*rp == '-' ? rp + 1 : rp);
/* No zero-padding of "inf" and "nan". */
if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
|| (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
pad_ptr = NULL;
}
/* The generated string now extends from rp to p,
with the zero padding insertion point being at
pad_ptr. */
count = count + pad; /* = end - rp */
if (flags & FLAG_LEFT)
{
/* Pad with spaces on the right. */
for (; pad > 0; pad--)
*p++ = ' ';
}
else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
{
/* Pad with zeroes. */
DCHAR_T *q = end;
while (p > pad_ptr)
*--q = *--p;
for (; pad > 0; pad--)
*p++ = '0';
}
else
{
/* Pad with spaces on the left. */
DCHAR_T *q = end;
while (p > rp)
*--q = *--p;
for (; pad > 0; pad--)
*p++ = ' ';
}
}
}
}
#endif
/* Here still count <= allocated - length. */
#if !DCHAR_IS_TCHAR || USE_SNPRINTF
/* The snprintf() result did fit. */
#else
/* Append the sprintf() result. */
memcpy (result + length, tmp, count * sizeof (DCHAR_T));
#endif
#if !USE_SNPRINTF
if (tmp != tmpbuf)
free (tmp);
#endif
#if NEED_PRINTF_DIRECTIVE_F
if (dp->conversion == 'F')
{
/* Convert the %f result to upper case for %F. */
DCHAR_T *rp = result + length;
size_t rc;
for (rc = count; rc > 0; rc--, rp++)
if (*rp >= 'a' && *rp <= 'z')
*rp = *rp - 'a' + 'A';
}
#endif
length += count;
break;
}
errno = orig_errno;
#undef pad_ourselves
#undef prec_ourselves
}
}
}
/* Add the final NUL. */
ENSURE_ALLOCATION (xsum (length, 1));
result[length] = '\0';
if (result != resultbuf && length + 1 < allocated)
{
/* Shrink the allocated memory if possible. */
DCHAR_T *memory;
memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
if (memory != NULL)
result = memory;
}
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
*lengthp = length;
/* Note that we can produce a big string of a length > INT_MAX. POSIX
says that snprintf() fails with errno = EOVERFLOW in this case, but
that's only because snprintf() returns an 'int'. This function does
not have this limitation. */
return result;
#if USE_SNPRINTF
overflow:
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EOVERFLOW;
return NULL;
#endif
out_of_memory:
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
out_of_memory_1:
CLEANUP ();
errno = ENOMEM;
return NULL;
}
}
#undef MAX_ROOM_NEEDED
#undef TCHARS_PER_DCHAR
#undef SNPRINTF
#undef USE_SNPRINTF
#undef DCHAR_SET
#undef DCHAR_CPY
#undef PRINTF_PARSE
#undef DIRECTIVES
#undef DIRECTIVE
#undef DCHAR_IS_TCHAR
#undef TCHAR_T
#undef DCHAR_T
#undef FCHAR_T
#undef VASNPRINTF
supermin-4.1.6/lib/inttypes.in.h 0000664 0001750 0001750 00000063752 12177155607 013542 0000000 0000000 /* Copyright (C) 2006-2013 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Derek Price.
This file is part of gnulib.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 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 . */
/*
* ISO C 99 for platforms that lack it.
*
*/
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
/* Include the original if it exists, and if this file
has not been included yet or if this file includes gnulib stdint.h
which in turn includes this file.
The include_next requires a split double-inclusion guard. */
#if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
# if @HAVE_INTTYPES_H@
/* Some pre-C++11 implementations need this. */
# if defined __cplusplus && ! defined __STDC_FORMAT_MACROS
# define __STDC_FORMAT_MACROS 1
# endif
# @INCLUDE_NEXT@ @NEXT_INTTYPES_H@
# endif
#endif
#if ! defined INTTYPES_H && ! defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
#define INTTYPES_H
/* Include or the gnulib replacement.
But avoid namespace pollution on glibc systems. */
#ifndef __GLIBC__
# include
#endif
/* Get CHAR_BIT. */
#include
#if !(INT_MIN == INT32_MIN && INT_MAX == INT32_MAX)
# error "This file assumes that 'int' has exactly 32 bits. Please report your platform and compiler to ."
#endif
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
/* The definition of _GL_WARN_ON_USE is copied here. */
/* 7.8.1 Macros for format specifiers */
#if defined _TNS_R_TARGET
/* Tandem NonStop R series and compatible platforms released before
July 2005 support %Ld but not %lld. */
# define _LONG_LONG_FORMAT_PREFIX "L"
#else
# define _LONG_LONG_FORMAT_PREFIX "ll"
#endif
#if !defined PRId8 || @PRI_MACROS_BROKEN@
# undef PRId8
# ifdef INT8_MAX
# define PRId8 "d"
# endif
#endif
#if !defined PRIi8 || @PRI_MACROS_BROKEN@
# undef PRIi8
# ifdef INT8_MAX
# define PRIi8 "i"
# endif
#endif
#if !defined PRIo8 || @PRI_MACROS_BROKEN@
# undef PRIo8
# ifdef UINT8_MAX
# define PRIo8 "o"
# endif
#endif
#if !defined PRIu8 || @PRI_MACROS_BROKEN@
# undef PRIu8
# ifdef UINT8_MAX
# define PRIu8 "u"
# endif
#endif
#if !defined PRIx8 || @PRI_MACROS_BROKEN@
# undef PRIx8
# ifdef UINT8_MAX
# define PRIx8 "x"
# endif
#endif
#if !defined PRIX8 || @PRI_MACROS_BROKEN@
# undef PRIX8
# ifdef UINT8_MAX
# define PRIX8 "X"
# endif
#endif
#if !defined PRId16 || @PRI_MACROS_BROKEN@
# undef PRId16
# ifdef INT16_MAX
# define PRId16 "d"
# endif
#endif
#if !defined PRIi16 || @PRI_MACROS_BROKEN@
# undef PRIi16
# ifdef INT16_MAX
# define PRIi16 "i"
# endif
#endif
#if !defined PRIo16 || @PRI_MACROS_BROKEN@
# undef PRIo16
# ifdef UINT16_MAX
# define PRIo16 "o"
# endif
#endif
#if !defined PRIu16 || @PRI_MACROS_BROKEN@
# undef PRIu16
# ifdef UINT16_MAX
# define PRIu16 "u"
# endif
#endif
#if !defined PRIx16 || @PRI_MACROS_BROKEN@
# undef PRIx16
# ifdef UINT16_MAX
# define PRIx16 "x"
# endif
#endif
#if !defined PRIX16 || @PRI_MACROS_BROKEN@
# undef PRIX16
# ifdef UINT16_MAX
# define PRIX16 "X"
# endif
#endif
#if !defined PRId32 || @PRI_MACROS_BROKEN@
# undef PRId32
# ifdef INT32_MAX
# define PRId32 "d"
# endif
#endif
#if !defined PRIi32 || @PRI_MACROS_BROKEN@
# undef PRIi32
# ifdef INT32_MAX
# define PRIi32 "i"
# endif
#endif
#if !defined PRIo32 || @PRI_MACROS_BROKEN@
# undef PRIo32
# ifdef UINT32_MAX
# define PRIo32 "o"
# endif
#endif
#if !defined PRIu32 || @PRI_MACROS_BROKEN@
# undef PRIu32
# ifdef UINT32_MAX
# define PRIu32 "u"
# endif
#endif
#if !defined PRIx32 || @PRI_MACROS_BROKEN@
# undef PRIx32
# ifdef UINT32_MAX
# define PRIx32 "x"
# endif
#endif
#if !defined PRIX32 || @PRI_MACROS_BROKEN@
# undef PRIX32
# ifdef UINT32_MAX
# define PRIX32 "X"
# endif
#endif
#ifdef INT64_MAX
# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@)
# define _PRI64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _PRI64_PREFIX "I64"
# elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined PRId64 || @PRI_MACROS_BROKEN@
# undef PRId64
# define PRId64 _PRI64_PREFIX "d"
# endif
# if !defined PRIi64 || @PRI_MACROS_BROKEN@
# undef PRIi64
# define PRIi64 _PRI64_PREFIX "i"
# endif
#endif
#ifdef UINT64_MAX
# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@)
# define _PRIu64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _PRIu64_PREFIX "I64"
# elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined PRIo64 || @PRI_MACROS_BROKEN@
# undef PRIo64
# define PRIo64 _PRIu64_PREFIX "o"
# endif
# if !defined PRIu64 || @PRI_MACROS_BROKEN@
# undef PRIu64
# define PRIu64 _PRIu64_PREFIX "u"
# endif
# if !defined PRIx64 || @PRI_MACROS_BROKEN@
# undef PRIx64
# define PRIx64 _PRIu64_PREFIX "x"
# endif
# if !defined PRIX64 || @PRI_MACROS_BROKEN@
# undef PRIX64
# define PRIX64 _PRIu64_PREFIX "X"
# endif
#endif
#if !defined PRIdLEAST8 || @PRI_MACROS_BROKEN@
# undef PRIdLEAST8
# define PRIdLEAST8 "d"
#endif
#if !defined PRIiLEAST8 || @PRI_MACROS_BROKEN@
# undef PRIiLEAST8
# define PRIiLEAST8 "i"
#endif
#if !defined PRIoLEAST8 || @PRI_MACROS_BROKEN@
# undef PRIoLEAST8
# define PRIoLEAST8 "o"
#endif
#if !defined PRIuLEAST8 || @PRI_MACROS_BROKEN@
# undef PRIuLEAST8
# define PRIuLEAST8 "u"
#endif
#if !defined PRIxLEAST8 || @PRI_MACROS_BROKEN@
# undef PRIxLEAST8
# define PRIxLEAST8 "x"
#endif
#if !defined PRIXLEAST8 || @PRI_MACROS_BROKEN@
# undef PRIXLEAST8
# define PRIXLEAST8 "X"
#endif
#if !defined PRIdLEAST16 || @PRI_MACROS_BROKEN@
# undef PRIdLEAST16
# define PRIdLEAST16 "d"
#endif
#if !defined PRIiLEAST16 || @PRI_MACROS_BROKEN@
# undef PRIiLEAST16
# define PRIiLEAST16 "i"
#endif
#if !defined PRIoLEAST16 || @PRI_MACROS_BROKEN@
# undef PRIoLEAST16
# define PRIoLEAST16 "o"
#endif
#if !defined PRIuLEAST16 || @PRI_MACROS_BROKEN@
# undef PRIuLEAST16
# define PRIuLEAST16 "u"
#endif
#if !defined PRIxLEAST16 || @PRI_MACROS_BROKEN@
# undef PRIxLEAST16
# define PRIxLEAST16 "x"
#endif
#if !defined PRIXLEAST16 || @PRI_MACROS_BROKEN@
# undef PRIXLEAST16
# define PRIXLEAST16 "X"
#endif
#if !defined PRIdLEAST32 || @PRI_MACROS_BROKEN@
# undef PRIdLEAST32
# define PRIdLEAST32 "d"
#endif
#if !defined PRIiLEAST32 || @PRI_MACROS_BROKEN@
# undef PRIiLEAST32
# define PRIiLEAST32 "i"
#endif
#if !defined PRIoLEAST32 || @PRI_MACROS_BROKEN@
# undef PRIoLEAST32
# define PRIoLEAST32 "o"
#endif
#if !defined PRIuLEAST32 || @PRI_MACROS_BROKEN@
# undef PRIuLEAST32
# define PRIuLEAST32 "u"
#endif
#if !defined PRIxLEAST32 || @PRI_MACROS_BROKEN@
# undef PRIxLEAST32
# define PRIxLEAST32 "x"
#endif
#if !defined PRIXLEAST32 || @PRI_MACROS_BROKEN@
# undef PRIXLEAST32
# define PRIXLEAST32 "X"
#endif
#ifdef INT64_MAX
# if !defined PRIdLEAST64 || @PRI_MACROS_BROKEN@
# undef PRIdLEAST64
# define PRIdLEAST64 PRId64
# endif
# if !defined PRIiLEAST64 || @PRI_MACROS_BROKEN@
# undef PRIiLEAST64
# define PRIiLEAST64 PRIi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined PRIoLEAST64 || @PRI_MACROS_BROKEN@
# undef PRIoLEAST64
# define PRIoLEAST64 PRIo64
# endif
# if !defined PRIuLEAST64 || @PRI_MACROS_BROKEN@
# undef PRIuLEAST64
# define PRIuLEAST64 PRIu64
# endif
# if !defined PRIxLEAST64 || @PRI_MACROS_BROKEN@
# undef PRIxLEAST64
# define PRIxLEAST64 PRIx64
# endif
# if !defined PRIXLEAST64 || @PRI_MACROS_BROKEN@
# undef PRIXLEAST64
# define PRIXLEAST64 PRIX64
# endif
#endif
#if !defined PRIdFAST8 || @PRI_MACROS_BROKEN@
# undef PRIdFAST8
# if INT_FAST8_MAX > INT32_MAX
# define PRIdFAST8 PRId64
# else
# define PRIdFAST8 "d"
# endif
#endif
#if !defined PRIiFAST8 || @PRI_MACROS_BROKEN@
# undef PRIiFAST8
# if INT_FAST8_MAX > INT32_MAX
# define PRIiFAST8 PRIi64
# else
# define PRIiFAST8 "i"
# endif
#endif
#if !defined PRIoFAST8 || @PRI_MACROS_BROKEN@
# undef PRIoFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIoFAST8 PRIo64
# else
# define PRIoFAST8 "o"
# endif
#endif
#if !defined PRIuFAST8 || @PRI_MACROS_BROKEN@
# undef PRIuFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIuFAST8 PRIu64
# else
# define PRIuFAST8 "u"
# endif
#endif
#if !defined PRIxFAST8 || @PRI_MACROS_BROKEN@
# undef PRIxFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIxFAST8 PRIx64
# else
# define PRIxFAST8 "x"
# endif
#endif
#if !defined PRIXFAST8 || @PRI_MACROS_BROKEN@
# undef PRIXFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIXFAST8 PRIX64
# else
# define PRIXFAST8 "X"
# endif
#endif
#if !defined PRIdFAST16 || @PRI_MACROS_BROKEN@
# undef PRIdFAST16
# if INT_FAST16_MAX > INT32_MAX
# define PRIdFAST16 PRId64
# else
# define PRIdFAST16 "d"
# endif
#endif
#if !defined PRIiFAST16 || @PRI_MACROS_BROKEN@
# undef PRIiFAST16
# if INT_FAST16_MAX > INT32_MAX
# define PRIiFAST16 PRIi64
# else
# define PRIiFAST16 "i"
# endif
#endif
#if !defined PRIoFAST16 || @PRI_MACROS_BROKEN@
# undef PRIoFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIoFAST16 PRIo64
# else
# define PRIoFAST16 "o"
# endif
#endif
#if !defined PRIuFAST16 || @PRI_MACROS_BROKEN@
# undef PRIuFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIuFAST16 PRIu64
# else
# define PRIuFAST16 "u"
# endif
#endif
#if !defined PRIxFAST16 || @PRI_MACROS_BROKEN@
# undef PRIxFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIxFAST16 PRIx64
# else
# define PRIxFAST16 "x"
# endif
#endif
#if !defined PRIXFAST16 || @PRI_MACROS_BROKEN@
# undef PRIXFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIXFAST16 PRIX64
# else
# define PRIXFAST16 "X"
# endif
#endif
#if !defined PRIdFAST32 || @PRI_MACROS_BROKEN@
# undef PRIdFAST32
# if INT_FAST32_MAX > INT32_MAX
# define PRIdFAST32 PRId64
# else
# define PRIdFAST32 "d"
# endif
#endif
#if !defined PRIiFAST32 || @PRI_MACROS_BROKEN@
# undef PRIiFAST32
# if INT_FAST32_MAX > INT32_MAX
# define PRIiFAST32 PRIi64
# else
# define PRIiFAST32 "i"
# endif
#endif
#if !defined PRIoFAST32 || @PRI_MACROS_BROKEN@
# undef PRIoFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIoFAST32 PRIo64
# else
# define PRIoFAST32 "o"
# endif
#endif
#if !defined PRIuFAST32 || @PRI_MACROS_BROKEN@
# undef PRIuFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIuFAST32 PRIu64
# else
# define PRIuFAST32 "u"
# endif
#endif
#if !defined PRIxFAST32 || @PRI_MACROS_BROKEN@
# undef PRIxFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIxFAST32 PRIx64
# else
# define PRIxFAST32 "x"
# endif
#endif
#if !defined PRIXFAST32 || @PRI_MACROS_BROKEN@
# undef PRIXFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIXFAST32 PRIX64
# else
# define PRIXFAST32 "X"
# endif
#endif
#ifdef INT64_MAX
# if !defined PRIdFAST64 || @PRI_MACROS_BROKEN@
# undef PRIdFAST64
# define PRIdFAST64 PRId64
# endif
# if !defined PRIiFAST64 || @PRI_MACROS_BROKEN@
# undef PRIiFAST64
# define PRIiFAST64 PRIi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined PRIoFAST64 || @PRI_MACROS_BROKEN@
# undef PRIoFAST64
# define PRIoFAST64 PRIo64
# endif
# if !defined PRIuFAST64 || @PRI_MACROS_BROKEN@
# undef PRIuFAST64
# define PRIuFAST64 PRIu64
# endif
# if !defined PRIxFAST64 || @PRI_MACROS_BROKEN@
# undef PRIxFAST64
# define PRIxFAST64 PRIx64
# endif
# if !defined PRIXFAST64 || @PRI_MACROS_BROKEN@
# undef PRIXFAST64
# define PRIXFAST64 PRIX64
# endif
#endif
#if !defined PRIdMAX || @PRI_MACROS_BROKEN@
# undef PRIdMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define PRIdMAX PRId64
# else
# define PRIdMAX "ld"
# endif
#endif
#if !defined PRIiMAX || @PRI_MACROS_BROKEN@
# undef PRIiMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define PRIiMAX PRIi64
# else
# define PRIiMAX "li"
# endif
#endif
#if !defined PRIoMAX || @PRI_MACROS_BROKEN@
# undef PRIoMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIoMAX PRIo64
# else
# define PRIoMAX "lo"
# endif
#endif
#if !defined PRIuMAX || @PRI_MACROS_BROKEN@
# undef PRIuMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIuMAX PRIu64
# else
# define PRIuMAX "lu"
# endif
#endif
#if !defined PRIxMAX || @PRI_MACROS_BROKEN@
# undef PRIxMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIxMAX PRIx64
# else
# define PRIxMAX "lx"
# endif
#endif
#if !defined PRIXMAX || @PRI_MACROS_BROKEN@
# undef PRIXMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIXMAX PRIX64
# else
# define PRIXMAX "lX"
# endif
#endif
#if !defined PRIdPTR || @PRI_MACROS_BROKEN@
# undef PRIdPTR
# ifdef INTPTR_MAX
# define PRIdPTR @PRIPTR_PREFIX@ "d"
# endif
#endif
#if !defined PRIiPTR || @PRI_MACROS_BROKEN@
# undef PRIiPTR
# ifdef INTPTR_MAX
# define PRIiPTR @PRIPTR_PREFIX@ "i"
# endif
#endif
#if !defined PRIoPTR || @PRI_MACROS_BROKEN@
# undef PRIoPTR
# ifdef UINTPTR_MAX
# define PRIoPTR @PRIPTR_PREFIX@ "o"
# endif
#endif
#if !defined PRIuPTR || @PRI_MACROS_BROKEN@
# undef PRIuPTR
# ifdef UINTPTR_MAX
# define PRIuPTR @PRIPTR_PREFIX@ "u"
# endif
#endif
#if !defined PRIxPTR || @PRI_MACROS_BROKEN@
# undef PRIxPTR
# ifdef UINTPTR_MAX
# define PRIxPTR @PRIPTR_PREFIX@ "x"
# endif
#endif
#if !defined PRIXPTR || @PRI_MACROS_BROKEN@
# undef PRIXPTR
# ifdef UINTPTR_MAX
# define PRIXPTR @PRIPTR_PREFIX@ "X"
# endif
#endif
#if !defined SCNd8 || @PRI_MACROS_BROKEN@
# undef SCNd8
# ifdef INT8_MAX
# define SCNd8 "hhd"
# endif
#endif
#if !defined SCNi8 || @PRI_MACROS_BROKEN@
# undef SCNi8
# ifdef INT8_MAX
# define SCNi8 "hhi"
# endif
#endif
#if !defined SCNo8 || @PRI_MACROS_BROKEN@
# undef SCNo8
# ifdef UINT8_MAX
# define SCNo8 "hho"
# endif
#endif
#if !defined SCNu8 || @PRI_MACROS_BROKEN@
# undef SCNu8
# ifdef UINT8_MAX
# define SCNu8 "hhu"
# endif
#endif
#if !defined SCNx8 || @PRI_MACROS_BROKEN@
# undef SCNx8
# ifdef UINT8_MAX
# define SCNx8 "hhx"
# endif
#endif
#if !defined SCNd16 || @PRI_MACROS_BROKEN@
# undef SCNd16
# ifdef INT16_MAX
# define SCNd16 "hd"
# endif
#endif
#if !defined SCNi16 || @PRI_MACROS_BROKEN@
# undef SCNi16
# ifdef INT16_MAX
# define SCNi16 "hi"
# endif
#endif
#if !defined SCNo16 || @PRI_MACROS_BROKEN@
# undef SCNo16
# ifdef UINT16_MAX
# define SCNo16 "ho"
# endif
#endif
#if !defined SCNu16 || @PRI_MACROS_BROKEN@
# undef SCNu16
# ifdef UINT16_MAX
# define SCNu16 "hu"
# endif
#endif
#if !defined SCNx16 || @PRI_MACROS_BROKEN@
# undef SCNx16
# ifdef UINT16_MAX
# define SCNx16 "hx"
# endif
#endif
#if !defined SCNd32 || @PRI_MACROS_BROKEN@
# undef SCNd32
# ifdef INT32_MAX
# define SCNd32 "d"
# endif
#endif
#if !defined SCNi32 || @PRI_MACROS_BROKEN@
# undef SCNi32
# ifdef INT32_MAX
# define SCNi32 "i"
# endif
#endif
#if !defined SCNo32 || @PRI_MACROS_BROKEN@
# undef SCNo32
# ifdef UINT32_MAX
# define SCNo32 "o"
# endif
#endif
#if !defined SCNu32 || @PRI_MACROS_BROKEN@
# undef SCNu32
# ifdef UINT32_MAX
# define SCNu32 "u"
# endif
#endif
#if !defined SCNx32 || @PRI_MACROS_BROKEN@
# undef SCNx32
# ifdef UINT32_MAX
# define SCNx32 "x"
# endif
#endif
#ifdef INT64_MAX
# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@)
# define _SCN64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _SCN64_PREFIX "I64"
# elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined SCNd64 || @PRI_MACROS_BROKEN@
# undef SCNd64
# define SCNd64 _SCN64_PREFIX "d"
# endif
# if !defined SCNi64 || @PRI_MACROS_BROKEN@
# undef SCNi64
# define SCNi64 _SCN64_PREFIX "i"
# endif
#endif
#ifdef UINT64_MAX
# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@)
# define _SCNu64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _SCNu64_PREFIX "I64"
# elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined SCNo64 || @PRI_MACROS_BROKEN@
# undef SCNo64
# define SCNo64 _SCNu64_PREFIX "o"
# endif
# if !defined SCNu64 || @PRI_MACROS_BROKEN@
# undef SCNu64
# define SCNu64 _SCNu64_PREFIX "u"
# endif
# if !defined SCNx64 || @PRI_MACROS_BROKEN@
# undef SCNx64
# define SCNx64 _SCNu64_PREFIX "x"
# endif
#endif
#if !defined SCNdLEAST8 || @PRI_MACROS_BROKEN@
# undef SCNdLEAST8
# define SCNdLEAST8 "hhd"
#endif
#if !defined SCNiLEAST8 || @PRI_MACROS_BROKEN@
# undef SCNiLEAST8
# define SCNiLEAST8 "hhi"
#endif
#if !defined SCNoLEAST8 || @PRI_MACROS_BROKEN@
# undef SCNoLEAST8
# define SCNoLEAST8 "hho"
#endif
#if !defined SCNuLEAST8 || @PRI_MACROS_BROKEN@
# undef SCNuLEAST8
# define SCNuLEAST8 "hhu"
#endif
#if !defined SCNxLEAST8 || @PRI_MACROS_BROKEN@
# undef SCNxLEAST8
# define SCNxLEAST8 "hhx"
#endif
#if !defined SCNdLEAST16 || @PRI_MACROS_BROKEN@
# undef SCNdLEAST16
# define SCNdLEAST16 "hd"
#endif
#if !defined SCNiLEAST16 || @PRI_MACROS_BROKEN@
# undef SCNiLEAST16
# define SCNiLEAST16 "hi"
#endif
#if !defined SCNoLEAST16 || @PRI_MACROS_BROKEN@
# undef SCNoLEAST16
# define SCNoLEAST16 "ho"
#endif
#if !defined SCNuLEAST16 || @PRI_MACROS_BROKEN@
# undef SCNuLEAST16
# define SCNuLEAST16 "hu"
#endif
#if !defined SCNxLEAST16 || @PRI_MACROS_BROKEN@
# undef SCNxLEAST16
# define SCNxLEAST16 "hx"
#endif
#if !defined SCNdLEAST32 || @PRI_MACROS_BROKEN@
# undef SCNdLEAST32
# define SCNdLEAST32 "d"
#endif
#if !defined SCNiLEAST32 || @PRI_MACROS_BROKEN@
# undef SCNiLEAST32
# define SCNiLEAST32 "i"
#endif
#if !defined SCNoLEAST32 || @PRI_MACROS_BROKEN@
# undef SCNoLEAST32
# define SCNoLEAST32 "o"
#endif
#if !defined SCNuLEAST32 || @PRI_MACROS_BROKEN@
# undef SCNuLEAST32
# define SCNuLEAST32 "u"
#endif
#if !defined SCNxLEAST32 || @PRI_MACROS_BROKEN@
# undef SCNxLEAST32
# define SCNxLEAST32 "x"
#endif
#ifdef INT64_MAX
# if !defined SCNdLEAST64 || @PRI_MACROS_BROKEN@
# undef SCNdLEAST64
# define SCNdLEAST64 SCNd64
# endif
# if !defined SCNiLEAST64 || @PRI_MACROS_BROKEN@
# undef SCNiLEAST64
# define SCNiLEAST64 SCNi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined SCNoLEAST64 || @PRI_MACROS_BROKEN@
# undef SCNoLEAST64
# define SCNoLEAST64 SCNo64
# endif
# if !defined SCNuLEAST64 || @PRI_MACROS_BROKEN@
# undef SCNuLEAST64
# define SCNuLEAST64 SCNu64
# endif
# if !defined SCNxLEAST64 || @PRI_MACROS_BROKEN@
# undef SCNxLEAST64
# define SCNxLEAST64 SCNx64
# endif
#endif
#if !defined SCNdFAST8 || @PRI_MACROS_BROKEN@
# undef SCNdFAST8
# if INT_FAST8_MAX > INT32_MAX
# define SCNdFAST8 SCNd64
# elif INT_FAST8_MAX == 0x7fff
# define SCNdFAST8 "hd"
# elif INT_FAST8_MAX == 0x7f
# define SCNdFAST8 "hhd"
# else
# define SCNdFAST8 "d"
# endif
#endif
#if !defined SCNiFAST8 || @PRI_MACROS_BROKEN@
# undef SCNiFAST8
# if INT_FAST8_MAX > INT32_MAX
# define SCNiFAST8 SCNi64
# elif INT_FAST8_MAX == 0x7fff
# define SCNiFAST8 "hi"
# elif INT_FAST8_MAX == 0x7f
# define SCNiFAST8 "hhi"
# else
# define SCNiFAST8 "i"
# endif
#endif
#if !defined SCNoFAST8 || @PRI_MACROS_BROKEN@
# undef SCNoFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define SCNoFAST8 SCNo64
# elif UINT_FAST8_MAX == 0xffff
# define SCNoFAST8 "ho"
# elif UINT_FAST8_MAX == 0xff
# define SCNoFAST8 "hho"
# else
# define SCNoFAST8 "o"
# endif
#endif
#if !defined SCNuFAST8 || @PRI_MACROS_BROKEN@
# undef SCNuFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define SCNuFAST8 SCNu64
# elif UINT_FAST8_MAX == 0xffff
# define SCNuFAST8 "hu"
# elif UINT_FAST8_MAX == 0xff
# define SCNuFAST8 "hhu"
# else
# define SCNuFAST8 "u"
# endif
#endif
#if !defined SCNxFAST8 || @PRI_MACROS_BROKEN@
# undef SCNxFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define SCNxFAST8 SCNx64
# elif UINT_FAST8_MAX == 0xffff
# define SCNxFAST8 "hx"
# elif UINT_FAST8_MAX == 0xff
# define SCNxFAST8 "hhx"
# else
# define SCNxFAST8 "x"
# endif
#endif
#if !defined SCNdFAST16 || @PRI_MACROS_BROKEN@
# undef SCNdFAST16
# if INT_FAST16_MAX > INT32_MAX
# define SCNdFAST16 SCNd64
# elif INT_FAST16_MAX == 0x7fff
# define SCNdFAST16 "hd"
# else
# define SCNdFAST16 "d"
# endif
#endif
#if !defined SCNiFAST16 || @PRI_MACROS_BROKEN@
# undef SCNiFAST16
# if INT_FAST16_MAX > INT32_MAX
# define SCNiFAST16 SCNi64
# elif INT_FAST16_MAX == 0x7fff
# define SCNiFAST16 "hi"
# else
# define SCNiFAST16 "i"
# endif
#endif
#if !defined SCNoFAST16 || @PRI_MACROS_BROKEN@
# undef SCNoFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define SCNoFAST16 SCNo64
# elif UINT_FAST16_MAX == 0xffff
# define SCNoFAST16 "ho"
# else
# define SCNoFAST16 "o"
# endif
#endif
#if !defined SCNuFAST16 || @PRI_MACROS_BROKEN@
# undef SCNuFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define SCNuFAST16 SCNu64
# elif UINT_FAST16_MAX == 0xffff
# define SCNuFAST16 "hu"
# else
# define SCNuFAST16 "u"
# endif
#endif
#if !defined SCNxFAST16 || @PRI_MACROS_BROKEN@
# undef SCNxFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define SCNxFAST16 SCNx64
# elif UINT_FAST16_MAX == 0xffff
# define SCNxFAST16 "hx"
# else
# define SCNxFAST16 "x"
# endif
#endif
#if !defined SCNdFAST32 || @PRI_MACROS_BROKEN@
# undef SCNdFAST32
# if INT_FAST32_MAX > INT32_MAX
# define SCNdFAST32 SCNd64
# else
# define SCNdFAST32 "d"
# endif
#endif
#if !defined SCNiFAST32 || @PRI_MACROS_BROKEN@
# undef SCNiFAST32
# if INT_FAST32_MAX > INT32_MAX
# define SCNiFAST32 SCNi64
# else
# define SCNiFAST32 "i"
# endif
#endif
#if !defined SCNoFAST32 || @PRI_MACROS_BROKEN@
# undef SCNoFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNoFAST32 SCNo64
# else
# define SCNoFAST32 "o"
# endif
#endif
#if !defined SCNuFAST32 || @PRI_MACROS_BROKEN@
# undef SCNuFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNuFAST32 SCNu64
# else
# define SCNuFAST32 "u"
# endif
#endif
#if !defined SCNxFAST32 || @PRI_MACROS_BROKEN@
# undef SCNxFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNxFAST32 SCNx64
# else
# define SCNxFAST32 "x"
# endif
#endif
#ifdef INT64_MAX
# if !defined SCNdFAST64 || @PRI_MACROS_BROKEN@
# undef SCNdFAST64
# define SCNdFAST64 SCNd64
# endif
# if !defined SCNiFAST64 || @PRI_MACROS_BROKEN@
# undef SCNiFAST64
# define SCNiFAST64 SCNi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined SCNoFAST64 || @PRI_MACROS_BROKEN@
# undef SCNoFAST64
# define SCNoFAST64 SCNo64
# endif
# if !defined SCNuFAST64 || @PRI_MACROS_BROKEN@
# undef SCNuFAST64
# define SCNuFAST64 SCNu64
# endif
# if !defined SCNxFAST64 || @PRI_MACROS_BROKEN@
# undef SCNxFAST64
# define SCNxFAST64 SCNx64
# endif
#endif
#if !defined SCNdMAX || @PRI_MACROS_BROKEN@
# undef SCNdMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define SCNdMAX SCNd64
# else
# define SCNdMAX "ld"
# endif
#endif
#if !defined SCNiMAX || @PRI_MACROS_BROKEN@
# undef SCNiMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define SCNiMAX SCNi64
# else
# define SCNiMAX "li"
# endif
#endif
#if !defined SCNoMAX || @PRI_MACROS_BROKEN@
# undef SCNoMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNoMAX SCNo64
# else
# define SCNoMAX "lo"
# endif
#endif
#if !defined SCNuMAX || @PRI_MACROS_BROKEN@
# undef SCNuMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNuMAX SCNu64
# else
# define SCNuMAX "lu"
# endif
#endif
#if !defined SCNxMAX || @PRI_MACROS_BROKEN@
# undef SCNxMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNxMAX SCNx64
# else
# define SCNxMAX "lx"
# endif
#endif
#if !defined SCNdPTR || @PRI_MACROS_BROKEN@
# undef SCNdPTR
# ifdef INTPTR_MAX
# define SCNdPTR @PRIPTR_PREFIX@ "d"
# endif
#endif
#if !defined SCNiPTR || @PRI_MACROS_BROKEN@
# undef SCNiPTR
# ifdef INTPTR_MAX
# define SCNiPTR @PRIPTR_PREFIX@ "i"
# endif
#endif
#if !defined SCNoPTR || @PRI_MACROS_BROKEN@
# undef SCNoPTR
# ifdef UINTPTR_MAX
# define SCNoPTR @PRIPTR_PREFIX@ "o"
# endif
#endif
#if !defined SCNuPTR || @PRI_MACROS_BROKEN@
# undef SCNuPTR
# ifdef UINTPTR_MAX
# define SCNuPTR @PRIPTR_PREFIX@ "u"
# endif
#endif
#if !defined SCNxPTR || @PRI_MACROS_BROKEN@
# undef SCNxPTR
# ifdef UINTPTR_MAX
# define SCNxPTR @PRIPTR_PREFIX@ "x"
# endif
#endif
/* 7.8.2 Functions for greatest-width integer types */
#ifdef __cplusplus
extern "C" {
#endif
#if @GNULIB_IMAXABS@
# if !@HAVE_DECL_IMAXABS@
extern intmax_t imaxabs (intmax_t);
# endif
#elif defined GNULIB_POSIXCHECK
# undef imaxabs
# if HAVE_RAW_DECL_IMAXABS
_GL_WARN_ON_USE (imaxabs, "imaxabs is unportable - "
"use gnulib module imaxabs for portability");
# endif
#endif
#if @GNULIB_IMAXDIV@
# if !@HAVE_DECL_IMAXDIV@
# if !GNULIB_defined_imaxdiv_t
typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t;
# define GNULIB_defined_imaxdiv_t 1
# endif
extern imaxdiv_t imaxdiv (intmax_t, intmax_t);
# endif
#elif defined GNULIB_POSIXCHECK
# undef imaxdiv
# if HAVE_RAW_DECL_IMAXDIV
_GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - "
"use gnulib module imaxdiv for portability");
# endif
#endif
#if @GNULIB_STRTOIMAX@
# if @REPLACE_STRTOIMAX@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef strtoimax
# define strtoimax rpl_strtoimax
# endif
_GL_FUNCDECL_RPL (strtoimax, intmax_t,
(const char *, char **, int) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (strtoimax, intmax_t, (const char *, char **, int));
# else
# if !@HAVE_DECL_STRTOIMAX@
# undef strtoimax
_GL_FUNCDECL_SYS (strtoimax, intmax_t,
(const char *, char **, int) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (strtoimax, intmax_t, (const char *, char **, int));
# endif
_GL_CXXALIASWARN (strtoimax);
#elif defined GNULIB_POSIXCHECK
# undef strtoimax
# if HAVE_RAW_DECL_STRTOIMAX
_GL_WARN_ON_USE (strtoimax, "strtoimax is unportable - "
"use gnulib module strtoimax for portability");
# endif
#endif
#if @GNULIB_STRTOUMAX@
# if !@HAVE_DECL_STRTOUMAX@
# undef strtoumax
_GL_FUNCDECL_SYS (strtoumax, uintmax_t,
(const char *, char **, int) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (strtoumax, uintmax_t, (const char *, char **, int));
_GL_CXXALIASWARN (strtoumax);
#elif defined GNULIB_POSIXCHECK
# undef strtoumax
# if HAVE_RAW_DECL_STRTOUMAX
_GL_WARN_ON_USE (strtoumax, "strtoumax is unportable - "
"use gnulib module strtoumax for portability");
# endif
#endif
/* Don't bother defining or declaring wcstoimax and wcstoumax, since
wide-character functions like this are hardly ever useful. */
#ifdef __cplusplus
}
#endif
#endif /* !defined INTTYPES_H && !defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H */
supermin-4.1.6/lib/safe-write.h 0000664 0001750 0001750 00000003334 12177155607 013312 0000000 0000000 /* An interface to write() that retries after interrupts.
Copyright (C) 2002, 2009-2013 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 . */
/* Some system calls may be interrupted and fail with errno = EINTR in the
following situations:
- The process is stopped and restarted (signal SIGSTOP and SIGCONT, user
types Ctrl-Z) on some platforms: Mac OS X.
- The process receives a signal for which a signal handler was installed
with sigaction() with an sa_flags field that does not contain
SA_RESTART.
- The process receives a signal for which a signal handler was installed
with signal() and for which no call to siginterrupt(sig,0) was done,
on some platforms: AIX, HP-UX, IRIX, OSF/1, Solaris.
This module provides a wrapper around write() that handles EINTR. */
#include
#define SAFE_WRITE_ERROR ((size_t) -1)
/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR
upon error. */
extern size_t safe_write (int fd, const void *buf, size_t count);
supermin-4.1.6/lib/itold.c 0000664 0001750 0001750 00000002010 12177155607 012340 0000000 0000000 /* Replacement for 'int' to 'long double' conversion routine.
Copyright (C) 2011-2013 Free Software Foundation, Inc.
Written by Bruno Haible , 2011.
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 . */
#include
/* Specification. */
#include
void
_Qp_itoq (long double *result, int a)
{
/* Convert from 'int' to 'double', then from 'double' to 'long double'. */
*result = (double) a;
}
supermin-4.1.6/lib/fstat.c 0000664 0001750 0001750 00000004605 12177155607 012362 0000000 0000000 /* fstat() replacement.
Copyright (C) 2011-2013 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