recode-3.7.14/ 0000755 0001750 0001750 00000000000 14366053657 010067 5 0000000 0000000 recode-3.7.14/NEWS 0000644 0001750 0001750 00000042545 14366047242 010511 0000000 0000000 ==================================
Recode NEWS - User visible changes
==================================
.. contents::
.. sectnum::
:Copyright: © 1993-2023 Free Software Foundation, Inc.
Version 3.7.14
==============
:Author: Reuben Thomas, 2023-01.
+ No user-visible changes; minor clean-ups as part of the Debian
packaging process.
Version 3.7.13
==============
:Author: Reuben Thomas, 2023-01.
+ Fix request diagnostics with --verbose: avoid output of confusing and
possibly incorrect diagnostics.
+ Fix a file descriptor leak.
Version 3.7.12
==============
:Author: Reuben Thomas, 2022-02.
+ Simplify support for ignoring invalid input with iconv, integrated with
the --strict and --force mechanisms.
+ Various documentation improvements.
Version 3.7.11
==============
:Author: Reuben Thomas, 2022-01.
+ Re-add support for transliteration with iconv (removed in 3.7).
+ Add support for ignoring invalid input with iconv.
+ Fix a bug introduced in 3.7.10 that prevented building the code.
Version 3.7.10
==============
:Author: Reuben Thomas, 2022-01.
+ In recode program, only use iconv if needed; add --prefer-iconv option to
allow its use in all cases.
+ Remove support for pre-3.5 request syntax (colon as charset separator).
+ PO files have been updated from the Translation Project.
+ Build system fixes and improvements.
+ Update gnulib to fix a problem building on Android.
+ Fix confusingly wrong NEWS entry for 3.7.4.
Version 3.7.9
=============
:Author: Reuben Thomas, 2021-06.
+ A fix to the CP1252 encoding: U+017E LATIN SMALL LETTER Z WITH CARON is at
byte 0x9e, not byte 0x8f.
+ Minor documentation fixes.
Version 3.7.8
=============
:Author: Reuben Thomas, 2020-09.
+ Improvements to the build system.
+ Fix man page generation, and document that help2man must be built with
gettext.
+ Updates to nl, pt, sv translations (thanks, translators!).
Version 3.7.7
=============
:Author: Reuben Thomas, 2020-07.
+ Improvements to the build system.
+ Updates to nl, pt, sv translations (thanks, translators!).
Version 3.7.6
=============
:Author: Reuben Thomas, 2019-09.
+ Improvements to the build system.
Version 3.7.5
=============
:Author: Reuben Thomas, 2019-09.
+ Port tests to Python 3.
Version 3.7.4
=============
:Author: Reuben Thomas, 2019-09.
+ Fixes to file handling in recode program.
+ Fix tests on Windows.
Version 3.7.3
=============
:Author: Reuben Thomas, 2019-08.
+ No code changes to recode itself; this release features a properly
versioned shared library.
Version 3.7.2
=============
:Author: Reuben Thomas, 2019-08.
+ No code changes to recode itself; this release includes updates to license
headers to guide users to the GPL online, corrects the version of
COPYING-LIB shipped with the sources, and updates the message files for
various languages.
Version 3.7.1
=============
:Author: Reuben Thomas, 2018-09.
+ No code changes to recode itself; this release just updates the version of
gnulib to fix a bug in glibc 2.28: (GitHub issue #11
https://github.com/rrthomas/recode/issues/11
Version 3.7
===========
:Author: François Pinard, 2008-03; Reuben Thomas, 2018-01.
+ Converters for BibTeX (from Vincent Danjean) and the ANSEL and ISO 5426
character sets (from Wolfram Schneider) have been added.
+ The conversion strategies (whether to use pipes, memory or files) are
no longer available. Now it is reasonable to assume virtual memory, so
files and memory have similar performance characteristics (in
particular, the memory method is not limited by physical memory.)
Further, tests showed that even for runs on little data, the pipes
method has minimal performance impact (none was measured). This is
not a surprise, as for one-step recodings, the commonest case, no
forking is needed. The command-line options -i, -p and
--sequence=STRATEGY are ignored for backwards compatibility.
+ Recode does not include libiconv anymore, but uses an external iconv
library if one was available at installation time. The -x: option
to the program, or a new flag to the library recode_new_outer
function, inhibits the initialisation and usage of iconv.
+ The experimental ``tree`` surface is removed. Structured data
needs a proper parser, and that doesn't fit the framework of Recode.
+ Many bug fixes.
+ Long ago, I renamed GNU recode to Free recode: the permission for
using the GNU prefix mandated a level of obedience to the FSF that
once went overboard, in my opinion. After that change, I realized
that some people read Free as a four letter word! To be peaceful,
this version changes the name again, to merely Recode. recode
(no capital) still names the executable program specifically, or
the distribution archive itself.
+ make check accepts a LIMIT= option, for limiting tests to one or a
few cases. See tests/Makefile.am.
+ PO files have been updated from the Translation Project.
+ The test system has been overhauled. Tests now run much faster, and
require Python and Cython.
+ Overhauled build system, now using gnulib for portability. This reduces
the amount of code in the Recode tree considerably.
Version 3.6
===========
:Author: François Pinard, Bruno Haible, 2001-01.
General changes
---------------
+ The recode manual is now indexed, by charset, by concept, etc.
+ Program messages are also available in Greek, Gallicean and Italian.
+ Bruno Haible's nice portable iconv library has been integrated.
+ RFC 1345 tables and French character names have been updated.
+ The Texinfo charset has been refreshed, and made reversible.
New charsets
------------
(most from libiconv)
+ Japanese
+ EUC-JP (csEUCPkdFmtJapanese, EUC_JP,
Extended_UNIX_Code_Packed_Format_for_Japanese);
+ ISO-2022-JP (csISO2022JP); ISO-2022-JP-1; ISO-2022-JP-2 (csISO2022JP2);
+ JIS_C6220-1969-ro (csISO14JISC6220ro, ISO646-JP, iso-ir-14, jp);
+ JIS_X0201 (csHalfWidthKatakana, JIS0201, JISX0201-1976, JISX0201.1976-0,
X0201);
+ JIS_X0208 (csISO87JISX0208, ISO-IR-87, JIS0208, JIS_X0208.1983-0,
JIS_X0208.1983-1, JIS_X0208-1990-0, JIS_X0208.1983-1, X0208);
+ JIS_X0212 (csISO159JISX02121990, ISO-IR-159, JIS0212, JIS_X0212.1990-0,
JIS_X0212-1990, X0212);
+ SJIS (csShiftJIS, MS_KANJI, SHIFT-JIS).
+ Chinese
+ BIG5 (BIG-5, BIG-FIVE, BIGFIVE, CN-BIG5 csBig5); BIG5HKSCS;
+ EUC-CN (CN-GB, csGB2312, EUC_CN, GB2312); EUC-TW (csEUCTW, EUC_TW);
+ GB18030; HZ (HZ-GB-2312); ISO-2022-CN (csISO2022CN); ISO-2022-CN-EXT;
+ GB_1988-80 (cn, csISO57GB1988, ISO646-CN, iso-ir-57);
+ GB_2312-80 (CHINESE, csISO58GB231280, GB2312.1980-0, ISO-IR-58);
+ ISO-IR-165 (CN-GB-ISOIR165).
+ Korean
+ JOHAB (CP1361); EUC-KR (csEUCKR, EUC_KR); GBK (CP936);
+ ISO-2022-KR (csISO2022KR);
+ KSC_5601 (CP949, csKSC56011987, ISO-IR-149, KOREAN, KSC5601.1987-0,
KS_C_5601-1987, KS_C_5601-1989, KSX1001:1992).
+ Vietnamese (independently of libiconv)
+ TCVN; VIQR; VISCII; VNI; VPS.
+ Other languages
+ ARMSCII-8; Georgian-Academy; Georgian-PS; WINDOWS-874 (CP874);
+ MuleLao-1; CP1133 (IBM-CP1133); CP1258 (WINDOWS-1258);
+ TIS-620 (ISO-IR-166, TIS620, TIS620.2529-1, TIS620-0, TIS620.2533-0,
TIS620.2533-1).
+ Apple specifics
+ MacArabic; MacCentralEurope; MacCroatian; MacCyrillic; MacGreek;
+ MacHebrew; MacIceland; MacRomania; MacThai; MacTurkish; MacUkraine
+ Unicode
+ JAVA; UCS-2-INTERNAL; UCS-2LE (UnicodeLITTLE); UCS-2-SWAPPED; UCS-4BE;
+ UCS-4-INTERNAL; UCS-4LE; UCS-4-SWAPPED; UTF-16BE; UTF-16LE.
+ Others
+ CP932; CP949 (UHC); CP950; CP866 (866, csIBM866, IBM866).
+ ISO-8859-16 (ISO-IR-226, ISO_8859-16:2000).
+ Recode internal
+ :libiconv: (:) [so option -x: avoids going through libiconv]
New aliases
-----------
(from libiconv) [list to be revised]
+ csASCII (for ANSI_X3.4-1968); csHPRoman8 (for hp-roman8);
+ csISOLatin1 (for ISO-8859-1); csISOLatin2 (for ISO-8859-2);
+ csISOLatin3 (for ISO-8859-3); csISOLatin4 (for ISO-8859-4);
+ csISOLatin5 (for ISO-8859-9);
+ csISOLatin6 and ISO_8859-10:1992 (for ISO-8859-10);
+ csISOLatinArabic (for ISO-8859-6); csISOLatinCyrillic (for ISO-8859-5);
+ csISOLatinGreek (for ISO-8859-7); csISOLatinHebrew (for ISO-8859-8);
+ csKOI8R (for KOI8-R); csPC850Multilingual (for IBM850);
+ csUCS4 (for ISO-10646-UCS-4);
+ csUnicode, csUnicode11, UCS-2BE, UnicodeBIG (for ISO-10646-UCS-2);
+ csUnicode11UTF7 (for UNICODE-1-1-UTF-7);
+ csVISCII and VISCII1.1-1 (for VISCII);
+ ISO-IR-179 (for ISO-8859-13); csMacintosh and MacRoman (for macintosh);
+ TCVN5712-1, TCVN5712-1:1993 and TCVN-5712 (for TCVN).
New surfaces
------------
+ tree (experimental).
Version 3.5
===========
:Author: François Pinard, 1999-05.
Incompatible changes
--------------------
+ A double dot ``..`` should now be used instead of a colon ``:``.
+ Option --force (-f) is needed to pursue recoding despite errors.
+ There is no more quoting for special characters within charsets names.
+ Auto check (``-a``) and popen (``-o``) options have been withdrawn.
+ Some charsets and aliases were deleted, see `Charsets & aliases`_ below.
Extended features
-----------------
+ Program messages are available in localised form for many languages.
+ Long character names are available in French, if LANGUAGE is set to ``fr``.
+ A new request syntax allows for recode chaining, and for surfaces.
+ Option --header-file (-h) accepts a language parameter, and Perl is new.
+ Full charset listings now show the UCS-2 value for characters.
+ Option --known=PAIRS (-k) also accepts octal and hexadecimal numbers.
+ Option --list (-l) better sorts charsets and aliases, also fully written.
+ Charset ``RFC1345`` implements mnemonic+ascii+38, and is now reversible.
+ HTML is not limited anymore to Latin-1, HTML 4.0 entities are supported.
New features
------------
+ Euro support.
+ Updated RFC 1345 set of tables, from Keld Simonsen.
+ Some African charsets and transliterated forms.
+ Conversions for ISO 10646 and Unicode.
+ Combining or explosion of UCS-2 diacriticized characters and ligatures.
+ Implementation of surfaces, see `Surfaces & aliases`_ below.
+ Mixed mode for recoding only comments and strings in C sources or PO files.
+ A stand-alone recoding library gets installed, often as a shared library.
+ Option --find-subsets (-T) lists charsets which are subsets of another.
+ The library may generate testing data, and study character frequencies.
Charsets & aliases
------------------
+ New ISO 10646 and Unicode charsets
+ combined-UCS-2: pseudo-charset.
+ count-characters: pseudo-charset.
+ dump-with-names: pseudo-charset.
+ ISO-10646-UCS-2 (UNICODE-1-1, BMP, rune, u2).
+ ISO-10646-UCS-4 (10646, ISO-10646, UCS-4, u4).
+ UNICODE-1-1-UTF-7 (TF-7, u7).
+ UTF-8 (UTF-2, UTF-FSS, FSS_UTF, TF-8, u8).
+ UTF-16 (Unicode, TF-16, u6).
+ RFC 1345.bis matters
+ Deleted charsets
+ dk-us, us-dk (because of &duplicate which Recode does not handle yet).
+ New charsets
+ baltic (alias is iso-ir-179); CP1250 (1250, ms-ee, windows-1250);
+ CP1251 (1251, ms-cyrl, windows-1251);
+ CP1252 (1252, ms-ansi, windows-1252);
+ CP1253 (1253, ms-greek, windows-1253);
+ CP1254 (1254, ms-turk, windows-1254);
+ CP1255 (1255, ms-hebr, windows-1255);
+ CP1256 (1256, ms-arab, windows-1256);
+ CP1257 (1257, WinBaltRim, windows-1257);
+ CWI (CWI-2, cp-hu); EBCDIC-IS-FRISS (friss);
+ GOST_19768-87 with aliases of previous GOST_19768-74;
+ IBM256 (256, CP256, EBCDIC-INT1); IBM875 (875, CP875, EBCDIC-Greek);
+ IBM1004 (1004, CP1004, os2latin1); IBM1047 (1047, CP1047);
+ ISO-8859-13 (ISO_8859-13:1998, iso-baltic, iso-ir-179a, l7, latin7);
+ ISO-8859-14 (ISO_8859-14:1998, iso-celtic, iso-ir-199, l8, latin8);
+ ISO-8859-15 (ISO_8859-15:1998, iso-ir-203, l9, latin9);
+ KOI-7; KOI-8 (GOST_19768-74); KOI8-R; KOI8-RU; KOI8-U;
+ macintosh_ce (macce); mac-is;
+ NeXTSTEP (next) yet previous Recode had it outside RFC 1345.
+ Alias promoted to charset (with previous charset becoming alias)
+ ISO-646.basic (with ISO-646.basic:1983); ISO-646.irv (ISO-646.irv:1983);
+ ISO_5427-ext (ISO_5427:1981); ISO_5428 (ISO_5428:1980);
+ ISO-8859-1 (ISO_8859-1:1987); ISO-8859-2 (ISO_8859-2:1987);
+ ISO-8859-3 (ISO_8859-3:1988); ISO-8859-4 (ISO_8859-4:1988);
+ ISO-8859-5 (ISO_8859-5:1988); ISO-8859-6 (ISO_8859-6:1987);
+ ISO-8859-7 (ISO_8859-7:1987); ISO-8859-8 (ISO_8859-8:1988);
+ ISO-8859-9 (ISO_8859-9:1989); ISO-8859-10 (latin6);
+ NC_NC00-10 (NC_NC00-10:81); sami (latin-lap).
+ New aliases
+ 037 (for charset IBM037); 038 (IBM038); 273 (IBM273); 274 (IBM274);
+ 275 (IBM275); 278 (IBM278); 280 (IBM280); 281 (IBM281); 284 (IBM284);
+ 285 (IBM285); 290 (IBM290); 297 (IBM297); 367 (ANSI_X3.4-1968);
+ 420 (IBM420); 423 (IBM423); 424 (IBM424); 500, 500V1 (IBM500);
+ 819 (ISO-8859-1); 864 (IBM864); 868 (IBM868); 870 (IBM870);
+ 871 (IBM871); 880 (IBM880); 891 (IBM891); 903 (IBM903); 905 (IBM905);
+ 912, CP912, IBM912 (ISO-8859-2); 918 (IBM918); 1026 (IBM1026);
+ ECMA-113, ECMA-113:1986 (ECMA-Cyrillic); GOST_19768-74 (KOI8);
+ ISO_8859-N (ISO-8859-N) for N = 1 through 10 and 13 through 15;
+ ISO_8859-10:1993 (ISO-8869-10); iso-ir-170 (INVARIANT);
+ KOI8_L2 (CSN_369103); pclatin2, pcl2 (IBM852); SS636127 (SEN_850200_B).
+ New African charsets
+ AFRL1-101-BPI_OCIL (t-francais, t-fra);
+ AFRFUL-102-BPI_OCIL (bambara, bra, ewondo, fulfulde);
+ AFRFUL-103-BPI_OCIL (t-bambara, t-bra, t-ewondo, t-fulfulde);
+ AFRLIN-104-BPI_OCIL (lingala, lin, sango, wolof);
+ AFRLIN-105-BPI_OCIL (t-lingala, t-lin, t-sango, t-wolof).
+ Extra miscellaneous charsets
+ KEYBCS2 (Kamenicky); CORK (T1); KOI-8_CS2.
+ New HTML pseudo-charsets
+ HTML_1.1 (h1); HTML_2.0 (RFC 1866, 1866, h2); HTML-i18n (RFC 2070);
+ HTML_3.2 (h3) reimplemented; HTML_4.0 (h4, HTML, h);
+ deleted aliases HTF, 8859, ISO 8859, Entities, SGML, WWW, w3.
Surfaces & aliases
------------------
+ Base64 (64, b64); Quoted-Printable (qp, Quote-Printable);
+ 21-Permutation (swabytes); 4321-Permutation; CR; CR-LF (cl);
+ Decimal-1 (d, d1); Decimal-2 (d2), Decimal-4 (d4);
+ Hexadecimal-1 (x, x1); Hexadecimal-2 (x2); Hexadecimal-4 (x4);
+ Octal-1 (o, o1); Octal-2 (o2); Octal-4 (o4).
+ data; test7; test8; test15; test16.
Version 3.4
===========
:Author: François Pinard, 1994-11.
+ Charset HTML is new, it handles ``&...;`` sequences for Latin-1.
+ Charset AtariST handling is more general, --list may be used with it.
+ Charset ASCII-BS overstriking has been extended, mainly for German.
+ Charset RFC1345 may be a goal, to debug or study RFC 1345 short names.
+ Charset names have been revised. Note that nextstep is now NeXT.
+ Option --force (-f) is accepted, but does not yet protect reversibility.
+ Option --quiet or --silent (-q) silences irreversible recoding messages.
+ Option --known=PAIRS (-k) helps searching through recodings.
+ Option --sequence=pipe (-p) does not fall back on -o anymore.
+ Option --auto-check may narrow its study around one particular charset.
+ An MSDOS port is available, check ftp.iro.umontreal.ca in pub/gnuish.
+ Compilation should now succeed on OS/2 EMX. Thanks to Kai Uwe Rommel.
+ Program initialization is almost three times faster on average.
+ Corrected reported bugs, added small improvements, some aesthetic.
Version 3.3
===========
:Author: François Pinard, 1993-12.
+ Charsets atarist, ebcdic-ccc, ebcdic-ibm and nextstep have been added.
+ Also, most RFC 1345 charsets and aliases are handled. That's a bunch!
+ Old ascii disappears because of RFC 1345's ascii, use ascii-bs instead.
+ Old maci disappears because of RFC 1345's macintosh, use applemac instead.
+ Charsets cccascii and cdcascii disappear, use ebcdic-ccc and ebcdic instead.
+ Recoding between latin1, ibmpc and applemac is (almost) reversible.
+ The texinfo documentation has been reorganized, this to be continued.
+ Long options are accepted, charset names may be abbreviated.
+ Option --list (-l) displays charsets, aliases and contents in many formats.
+ Option --strict (-s) asks for stricter, non-reversible recodings.
+ Option --graphics (-g) approximates ibmpc rulers with ASCII graphics.
+ Option --header (-h) produces C source for many recoding tables.
+ Option --auto-check (-a) reports about all possible recodings.
+ Option --ignore (-x) prevents a charset from being selected.
+ Execution has been sped up through step merging, hashing for charset names.
+ Many various buglets have been eradicated, portability increased.
+ Charsets may be edited out by modifying the Makefile only.
+ Configuration is made through the use of an external config.h file.
+ New -d ``diacritics_only`` option for LaTeX.
+ A few bugs have been corrected.
+ Documentation reorganization and improvements.
+ Increased portability, now uses Autoconf.
+ A few bugs solved.
Version 3.2
===========
:Author: François Pinard, 1991-10.
+ MSDOS port redone.
+ New check goal at installation time.
+ Add -v option for verbose processing, remove old -q.
+ Add -i, -o and -p for letting the user control the strategy.
+ A few bugs corrected.
+ Embedded NULs should now be transmitted.
Version 3.1
===========
:Author: François Pinard, 1990-03.
+ Rename -V to -C for showing Copyright.
+ Calling sequence changed, said files now recoded on themselves.
+ Add -t option for touching files.
+ Better on-line help.
+ Add -q option for quiet processing.
+ Executable file now considerably smaller, also speedier.
+ A few bugs corrected.
Version 3.0
===========
:Author: François Pinard, 1989-10.
+ New Text to Latin1 processing, should be faster.
+ A few bugs corrected.
For prior history down to 1980, see at the end of the ChangeLog.
recode-3.7.14/AUTHORS 0000644 0001750 0001750 00000002122 13574515205 011044 0000000 0000000 Authors of Recode
The following contributions warranted legal paper exchanges with the
Free Software Foundation. Also see files ChangeLog and THANKS.
RECODE François Pinard CANADA, 1949
Assigns the program.
RECODE Odyssee Recherches Appliquees
Disclaims work by François Pinard
RECODE Ulrich Drepper Germany 1968 1996-03-25
Assigns all past and future changes.
drepper@gnu.ai.mit.edu
RECODE Bruno Haible Germany/France 1965 1999-09-08
Assigns past and future changes.
haible@clisp.cons.org
LIBUTF8 Bruno Haible Germany/France 1965 1999-12-08
Assigns program and future changes.
haible@clisp.cons.org
LIBICONV Bruno Haible Germany/France 1965 1999-12-08
Assigns program and future changes.
haible@clisp.cons.org
RECODE Linus Walleij Sweden 1972 2000-07-03
Assigns past and future changes (rtf.c).
triad@df.lth.se
RECODE Otfried Cheong Germany 1964 2000-10-19
Assigns past and future changes (utfmule.c, mkutf2mule.pl).
otfried@cs.uu.nl
RECODE Bruno Haible Germany/France 1965 2001-03-09
Assigns past and future changes.
haible@clisp.cons.org
recode-3.7.14/THANKS 0000644 0001750 0001750 00000035612 13574515205 010721 0000000 0000000 Recode has originally been written by François Pinard. Other people
contributed to Recode by reporting problems, suggesting various
improvements or submitting actual code. Here is a list of these
people. Help me keeping it complete and exempt of errors. See various
ChangeLogs for a detailed description of contributions. Santiago Vila
Doncel deserves a special mention for his dedication and patience!
======================= ======================================================
Akim Demaille | demaille at inf dot enst dot fr
Alain Labonté | alb at riq dot qc dot ca
Alain Magloire | alainm at macs dot ee dot mcgill dot ca
Alan J. Flavell | flavell at a5 dot ph dot gla dot ac dot uk
Alexander Kurz | akurz at blala dot de
Alexander L. Belikoff | abel at vallinor4 dot com
| http://www.vallinor4.com
Alexandre Duret-Lutz | duret_g at epita dot fr
Alexandre Oliva | oliva at dcc dot unicamp dot br
| http://www.dcc.unicamp.br/~oliva
Andreas Dietrich | quasi at mathematik dot uni-marburg dot de
Andreas Frick | afr at aifb dot uni-karlsruhe dot de
Andreas Kunert | akunert at main-rheiner dot de
Andreas Mueller | afm at othello dot ch
| http://www.othello.ch
Andreas Schwab | schwab at suse dot de
Andrew Green | andrew at article7 dot co dot uk
Andries Brouwer | Andries dot Brouwer at cwi dot nl
Arnaldo Mandel | am at ime dot usp dot br
Bastian Schlueter | buzz at gmx dot de
| http://home.pages.de/~buzz
Ben Sittler | bsittler at knownow dot com
Bennett Todd | bet at rahul dot net
| http://bent.latency.net/
Bernt Guldbrandtsen | bg at rs580 dot sh dot dk
Bert Schweitzer | b dot schweitzer at tu-bs dot de
Branimir Dolicki
Brendan O'Dea | bod at compusol dot com dot au
| http://www.ozemail.com.au/~bod/
Bruno Haible | haible at ilog dot fr
| http://clisp.cons.org/~haible/
Christian Limpach | Christian dot Limpach at nice dot ch
| http://www.nice.ch/~chris/
Christian Recktenwald | chris at citecs dot de
| http://www.citecs.de/
Christian Rolland
Christian Weisgerber | naddy at mips dot inka dot de
| http://home.pages.de/~naddy/
Claude Goutier | goutier at jsp dot umontreal dot ca
Colin Plumb
Dagobert Michelsen | dam at baltic-online dot de
| http://www.familie-michelsen.de
Dan Jacobson | jidanni at jidanni dot org
| http://jidanni.org/
Daniel Pfeiffer | occitan at esperanto dot org
| http://makepp.sourceforge.net
Daniel Quinlan | quinlan at best dot com
Daniel Taupin | taupin at lps dot u-psud dot fr
David E. A. Wilson | david_wilson at uow dot edu dot au
| http://www.uow.edu.au/~david
David Kastrup
David Lebel | lebel at lebel dot org
David Mentre
David Necas | yeti at monoceros dot physics dot muni dot cz
| http://physics.muni.cz/~yeti/
David van Leeuwen
Detlev Droege | droege at informatik dot uni-koblenz dot de
Dennis Veatch | dennisveatch at bellsouth dot net
Dominique Quatravaux | Dominique dot Quatravaux at quatramaran dot ens dot fr
| http://www.piren.epita.fr/~dom
Dominique Schmit | dschmit at tabarly dot saclay dot cea dot fr
Duane Ellis | duane at franklin dot com
| http://www.franklin.com
Eli Zaretskii | eliz at is dot elta dot co dot il
Enrik Berkhan | Enrik dot Berkhan at planb dot de
Eric Backus | eric_backus at hp dot com
| http://www.wolfenet.com/~ericjb
Éric Bischoff | eric at caldera dot de
Erick Branderhorst | Erick dot Branderhorst at asml dot nl
Erwan Mas | erwanmas at chez dot com
| http://www.chez.com/erwanmas/
Farzad Farid
Florian Oelmaier | 100265 dot 2501 at compuserve dot com
François Pinard | pinard at iro dot umontreal dot ca
| http://www.iro.umontreal.ca/~pinard
François Robitaille
François Yergeau | yergeau at alis dot com
| http://www.alis.com/~yergeau/
Francois-Xavier Bergot | bergotfx at com dot enst dot fr
Françoise Audebrand | audebran at ere dot umontreal dot ca
Frederic Albrecht
Frederic Gobry | frederic dot gobry at epfl dot ch
Frederik Fouvry | fouvry at CoLi dot Uni-SB dot DE
Frère Roy | roy at taize dot fr
| http://www.taize.fr
Gabriel P. Silva | gpsilva at geocities dot com
| http://www.nce.ufrj.br/~gabriel
Gaël Le Mignot | kilobug at freesurf dot fr
Ghislain Plamondon
Georg Haefele | haefele at atlas dot gis dot univie dot ac dot at
Greg McGary
Guillaume Rumeau | rumeau at isty-info dot uvsq dot fr
Guy Lapalme | lapalme at iro dot umontreal dot ca
| http://www.iro.umontreal.ca/~lapalme
Harald Falkenberg | harald dot falkenberg at desy dot de
Harald Koenig | koenig at tat dot physik dot uni-tuebingen dot de
Hermann Hueni | hueni at iam dot unibe dot ch
Hennus Bergman
Hilmar Schlegel | hs at semic dot ag-berlin dot mpg dot de
Holger Benl | benl at websphere dot de
Hrvoje Niksic | hniksic at srce dot hr
Jacques Madelaine | jacques at info dot unicaen dot fr
| http://www.info.unicaen.r/~jacques
Jacques Richer | Jacques dot Richer at CERCA dot UMontreal dot CA
| http://www.CERCA.UMontreal.CA/~richer
Jan Djarv | jan dot djarv at mbox200 dot swipnet dot se
Jean-Christophe
Guillain | jcg at adviseo dot fr
Jean-Claude Nadeau | nadeau at jsp dot umontreal dot ca
Jean-Michel Dault | jmdault at mandrakesoft dot com
Jens Quade | jens at ronja dot dinoco dot de
Jim Meyering | meyering at na-net dot ornl dot gov
Joelle Stemp
John Gorman | jgorman at webbysoft dot com
John van Krieken | John dot van dot Krieken at ATComputing dot nl
| http://www.ATComputing.nl/images/pasfotos/john.jpg
Jörg Höhle | Joerg dot Hoehle at gmd dot de
| http://fit.gmd.de/~hoehle/
Jose Joao Almeida | jj at di dot uminho dot pt
| http://www.di.uminho.pt/~jj
Juan Manuel Guerrero | juan dot guerrero at gmx dot de
Julio Sanchez | jsanchez at gmv dot es
Juliusz Chroboczek | jch at clipper dot ens dot fr
Juergen Zeller | zet at rupert dot franken dot de
Kai Uwe Rommel
Karl Berry | karl at cs dot umb dot edu
| http://www.cs.umb.edu/~karl/
Keld Jørn Simonsen | keld at dkuug dot dk
Kester Habermann | kester at unix-ag dot uni-kl dot de
| http://www.unix-ag.uni-kl.de/~kester/
Kevin Stuckless | kevins at stuck dot warped dot com
| http://stuck.warped.com/~kevins
Konstantin Osipov | rabid at spylog dot ru
Kristian Köhntopp | kk at netuse dot de
Laurent Bourbeau | bourbeau at progiciels-bpi dot ca
Larry W. Virden | lvirden at cas dot org
| http://purl.org/net/lvirden/
Liisa R{ih{ | lr at cs dot uta dot fi
Lionel Elie Mamane | lionel at mamane dot lu
Loic Dachary
Luc Maisonobe | Luc dot Maisonobe at free dot fr
| http://www.spaceroots.org/
Lukas Petrlik
Mac Pigman | gwp at dido dot caltech dot edu
Magnus Määttä | novell at kiruna dot nu
| http://novell.stoldgods.nu
Marc Gingold | gingold at spht dot saclay dot cea dot fr
| http:////www-spht.cea.fr/doc.html
Marc Shapiro | shapiro at prof dot inria dot fr
Marc Verreault
Marcin Owsiany | marcin at owsiany dot pl
| http://marcin.owsiany.pl/
Mario Gay | mgay at ti-edu dot ch
Markus Kuhn | Markus dot Kuhn at cl dot cam dot ac dot uk
| http://www.cl.cam.ac.uk/~mgk25/
Martin J. Dürst | duerst at w3 dot org
| http://www.w3.org/People/D%C3%BCrst
Martin Maechler | maechler at stat dot math dot ethz dot ch
Martin Michlmayr | tbm at cyrius dot com
| http://www.cyrius.com/
Martin Trautmann | traut at gmx dot de
Martin Mares | mj at ucw dot cz
| http://atrey.karlin.mff.cuni.cz/~mj/
Marty Leisner | martyleisner at yahoo dot com
Michael Gschwind | mike at vlsivie dot tuwien dot ac dot at
Michael L. Dowling | M dot Dowling at tu-bs dot de
| http://www.mathematik.tu-bs.de
Michael Schmidt | mschmidt at koblenz dot fh-rpl dot de
Michael Shields | shields at msrl dot com
| http://www.msrl.com/
Mikko Harjula | mikko dot harjula at gware dot com
Mikko Silvonen | silvonen at iki dot fi
| http://www.iki.fi/silvonen/
Nathanael Makarevitch
Nathaniel Borenstein | nsb at aa dot fv dot com
Neal McBurnett | http://bcn.boulder.co.us/~neal/
Nguyên-Ðai Quý | daiquy dot nguyen at ulg dot ac dot be
Nicolas Anquetil
Nicolas Thiery | Nicolas dot Thiery at jonas dot univ-lyon1 dot fr
| http://www.lmd.univ-lyon1.fr/home/nthiery/
Niels Kr. Bech Jensen | nkbj at image dot dk
| http://www.image.dk/~nkbj/
Noèl Köthe | noel at debian dot org
| http://www.koethe.net/
Olivier Lecarme | Olivier dot Lecarme at unice dot fr
Olivier Tharan | olive at laria dot u-picardie dot fr
| http://www.laria.u-picardie.fr/~olive/
Pascal Gourdel | gourdel at univ-paris1 dot fr
Patrick Andries | pandries at iti dot qc dot ca
Pavel Osipov | forsite at spamtest dot ru
| http://forsite.ibch.ru/
Pavel Pokorny | Pavel dot Pokorny at vscht dot cz
| http://www.vscht.cz/mat/Pavel.Pokorny
Pawel Krawczyk | kravietz at ceti dot pl
| http://ceti.pl/~kravietz/
Per Andersson | perand at stacken dot kth dot se
Per Starback | starback at ling dot uu dot se
| http://stp.ling.uu.se/~starback/me.html
Per Steinar Iversen
Peter Much | pmc at citylink dot dinoex dot sub dot org
Peter Poeml | poeml at cmdline dot net
| http://www.poeml.de/
Peter Turcan | peter dot turcan at minerva-is dot sk
Petr Pajas | pajas at ufal dot ms dot mff dot cuni dot cz
| http://pajas.matfyz.cz
Phyllis Frankl | phyllis at morph dot poly dot edu
| http://ebbets.poly.edu/~pfrankl
Pierre Gaumond | gaumondp at ere dot umontreal dot ca
Pierre Girard | pierreg at crt dot umontreal dot ca
Pierre Mathieu | mathieu at geod dot emr dot ca
Povl H. Pedersen | pope at netguide dot dk
Primož Peterlin | primoz dot peterlin at biofiz dot mf dot uni-lj dot si
| http://sizif.mf.uni-lj.si/~peterlin/
Régis Martin | contact at interloc dot ca
Réjean Payette | rejean dot payette at rtsq dot qc dot ca
Reuben Thomas | rrt at sc3d dot org
| http://rrt.sc3d.org/
Ricard Torres | torres at upf dot es
Richard Nault | rnfc at videotron dot ca
| www.RichardNault.com
Richard Plasun | plasun at iue dot tuwien dot ac dot at
Richard Stallman | rms at gnu dot org
Robert Joop | rj at rainbow dot in-berlin dot de
Roman Czyborra | roman at czyborra dot com
| http://czyborra.com/
Roman Suzi | rnd at onego dot ru
Ronald C.F. Antony | rcfa at cubiculum dot com
| http://www.cubiculum.com/~rcfa
Santiago Vila Doncel | sanvila at unex dot es
Saverio Pangoli | saverio at mystere dot sci dot sns dot it
Sebastian Huebner | cyco at baud dot de
| http://www.baud.de/cyco/
Sean McLaughlin | Seanster at Seanster dot com
Scott Schwartz | schwartz at bio dot cse dot psu dot edu
Simon Cozens | simon at cozens dot net
Slaven Rezic | eserte at cs dot tu-berlin dot de
| http://user.cs.tu-berlin.de/~eserte
Stefan Albertz | Stefan dot Albertz at rus dot uni-stuttgart dot de
Stefan Haubenthal | haubi at geocities dot com
| http://home.pages.de/~haubi
Stephen Boulet | stephen at theboulets dot net
Stephen Walkauskas | SWalkaus at endeca dot com
Steinar Bang | sb at metis dot no
Stephane Berube | berube at iro dot umontreal dot ca
Stephen Grecni | steve at steem dot com
| http://steem.com
Steve Langasek | vorlon at netexpress dot net
Sumit Bose | bose at physik dot tu-berlin dot de
Thomas Gebhardt | gebhardt at hrz dot uni-marburg dot de
| http://www.uni-marburg.de/hrz/mitarbeiter
/gebhardt.html
Thomas M. Ott
Thomas Seeling
Tom Hageman | tom at basil dot icce dot rug dot nl
Tom Tromey | tromey at cygnus dot com
| http://cafe.colorado.edu/~tromey/
Tomasz Kłoczko | kloczek at wun dot zie dot pg dot gda dot pl
Urban Mueller | mueller at iogram dot ch
Ulrich Drepper | drepper at gnu dot org
Ulrich Windl | Ulrich dot Windl at rz dot uni-regensburg dot de
| http://www.uni-regensburg.de/Einrichtungen
/Rechenzentrum/Orientierung/Mitarbeiter/windl.html
Vern Paxson | vern at ee dot lbl dot gov
Vitor Duarte | vad at di dot fct dot unl dot pt
Volker Wysk | post at volker-wysk dot de
Walter Müller | walt at pi4 dot informatik dot uni-mannheim dot de
Wiel Seuskens | wiel at xs4all dot nl
| http://www.xs4all.nl/~wiel/
Wilhelm Zadrapa | wfz at aon dot at
William Bader | wbader at scarecrow dot csee dot lehigh dot edu
Wolfgang Boerner | Wolfgang dot Boerner at rz dot uni-regensburg dot de
Wolfgang Wander | wwc at hermes dot desy dot de
Xabier Rodriguez Calvar | xrcalvar at igalia dot com
Yves Arrouye
======================= ======================================================
recode-3.7.14/configure.ac 0000644 0001750 0001750 00000007341 14366050422 012265 0000000 0000000 # Configure template for Recode.
# Copyright (C) 1994-2023 Free Software Foundation, Inc.
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.71])
AC_INIT([recode],[3.7.14],[rrt@sc3d.org])
AC_CONFIG_SRCDIR(src/recode.c)
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE
AC_CONFIG_MACRO_DIR(m4)
AC_CANONICAL_HOST
dnl Release number rules:
dnl This is derived from "Versioning" chapter of info libtool documentation.
dnl Format is MAJOR:MINOR:MICRO
dnl 4a) Increment major when removing or changing interfaces.
dnl 4a) 5) Increment minor when adding interfaces.
dnl 6) Set minor to zero when removing or changing interfaces.
dnl 3) Increment micro when interfaces not changed at all,
dnl only bug fixes or internal changes made.
dnl 4b) Set micro to zero when adding, removing or changing interfaces.
dnl First extract pieces from the version number string
RECODE_MAJOR_VERSION=`echo $VERSION | awk -F. '{print $1}'`
RECODE_MINOR_VERSION=`echo $VERSION | awk -F. '{print $2}'`
RECODE_MICRO_VERSION=`echo $VERSION | awk -F. '{print $3}'`
dnl Version info for libraries = CURRENT:REVISION:AGE
RECODE_SONUM=$RECODE_MAJOR_VERSION
AGE=$RECODE_MINOR_VERSION
REVISION=$RECODE_MICRO_VERSION
CURRENT=`expr $RECODE_SONUM + $AGE`
VERSION_INFO=$CURRENT:$REVISION:$AGE
AC_SUBST(VERSION_INFO)
AC_PROG_CC
gl_EARLY
LT_INIT
AC_PROG_LEX([noyywrap])
AM_PATH_PYTHON([3.5])
gl_INIT
dnl help2man
dnl Set a value even if not found, so that an invocation via build-aux/missing works
AC_PATH_PROG([HELP2MAN], [help2man], [help2man])
dnl Cython
AC_CHECK_PROGS([CYTHON], [cython3 cython])
AM_CONDITIONAL([HAVE_CYTHON], test -n "$ac_cv_prog_CYTHON")
AC_SUBST([objdir])
LT_SYS_MODULE_EXT
case $host_os in
*mingw* ) pyextext=.pyd;;
*cygwin*) pyextext=.dll;;
* ) pyextext=.so;;
esac
AC_SUBST([pyextext], [$pyextext])
dnl Extra warnings with GCC and compatible compilers
AC_ARG_ENABLE([gcc-warnings],
[AS_HELP_STRING([--disable-gcc-warnings],
[turn off lots of GCC warnings])],
[case $enableval in
yes|no) ;;
*) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;;
esac
gl_gcc_warnings=$enableval],
[gl_gcc_warnings=yes]
)
if test "$gl_gcc_warnings" = yes; then
dnl Set up the list of undesired warnings.
nw=
nw="$nw -Wsystem-headers" # Don’t let system headers trigger warnings
nw="$nw -Wundef" # All compiler preprocessors support #if UNDEF
nw="$nw -Wtraditional" # All compilers nowadays support ANSI C
nw="$nw -Wdeclaration-after-statement" # We require C99.
nw="$nw -Wstrict-overflow" # Use a lower level (see below).
nw="$nw -Wconversion" # These warnings usually don’t point to mistakes.
nw="$nw -Wsign-conversion" # Likewise.
gl_MANYWARN_ALL_GCC([warnings])
dnl Enable all GCC warnings not in this list.
gl_MANYWARN_COMPLEMENT([warnings], [$warnings], [$nw])
for w in $warnings; do
gl_WARN_ADD([$w])
done
dnl Add an extra warning
gl_WARN_ADD([-Wstrict-overflow=1])
dnl Remove a warning being promoted to error: we trigger this and can't turn it off with pragmas.
gl_WARN_ADD([-Wno-error=format-security])
# When compiling with GCC, prefer -isystem to -I when including system
# include files, to avoid generating useless diagnostics for the files.
ISYSTEM='-isystem '
else
ISYSTEM='-I'
fi
AC_SUBST([ISYSTEM])
# Extra settings for running tests, e.g. LD_PRELOAD for ASAN
AC_SUBST([TESTS_ENVIRONMENT_EXTRA])
AC_CONFIG_HEADERS([config.h])
AM_ICONV
LIBS="$LIBICONV $LIBS"
AM_GNU_GETTEXT_VERSION(0.19)
AM_GNU_GETTEXT(external)
AM_XGETTEXT_OPTION([--from-code=UTF-8])
AC_CONFIG_FILES([Makefile contrib/Makefile doc/Makefile lib/Makefile
po/Makefile.in src/Makefile tests/Makefile tests/setup.py])
AC_OUTPUT
recode-3.7.14/lib/ 0000755 0001750 0001750 00000000000 14366053656 010634 5 0000000 0000000 recode-3.7.14/lib/inttypes.in.h 0000644 0001750 0001750 00000051232 14366047013 013202 0000000 0000000 /* Copyright (C) 2006-2023 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Derek Price.
This file is part of gnulib.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/*
* 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@
# define _GL_FINISHED_INCLUDING_SYSTEM_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, INT_MAX, LONG_MAX, etc. */
#include
/* On mingw, __USE_MINGW_ANSI_STDIO only works if is also included */
#if defined _WIN32 && ! defined __CYGWIN__
# include
#endif
#if !(INT_MAX == 0x7fffffff && INT_MIN + INT_MAX == -1)
# error "This file assumes that 'int' is 32-bit two's complement. 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
# ifdef INT8_MAX
# define PRId8 "d"
# endif
#endif
#if !defined PRIi8
# ifdef INT8_MAX
# define PRIi8 "i"
# endif
#endif
#if !defined PRIo8
# ifdef UINT8_MAX
# define PRIo8 "o"
# endif
#endif
#if !defined PRIu8
# ifdef UINT8_MAX
# define PRIu8 "u"
# endif
#endif
#if !defined PRIx8
# ifdef UINT8_MAX
# define PRIx8 "x"
# endif
#endif
#if !defined PRIX8
# ifdef UINT8_MAX
# define PRIX8 "X"
# endif
#endif
#if !defined PRId16
# ifdef INT16_MAX
# define PRId16 "d"
# endif
#endif
#if !defined PRIi16
# ifdef INT16_MAX
# define PRIi16 "i"
# endif
#endif
#if !defined PRIo16
# ifdef UINT16_MAX
# define PRIo16 "o"
# endif
#endif
#if !defined PRIu16
# ifdef UINT16_MAX
# define PRIu16 "u"
# endif
#endif
#if !defined PRIx16
# ifdef UINT16_MAX
# define PRIx16 "x"
# endif
#endif
#if !defined PRIX16
# ifdef UINT16_MAX
# define PRIX16 "X"
# endif
#endif
#if !defined PRId32
# ifdef INT32_MAX
# define PRId32 "d"
# endif
#endif
#if !defined PRIi32
# ifdef INT32_MAX
# define PRIi32 "i"
# endif
#endif
#if !defined PRIo32
# ifdef UINT32_MAX
# define PRIo32 "o"
# endif
#endif
#if !defined PRIu32
# ifdef UINT32_MAX
# define PRIu32 "u"
# endif
#endif
#if !defined PRIx32
# ifdef UINT32_MAX
# define PRIx32 "x"
# endif
#endif
#if !defined 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 LONG_MAX >> 30 == 1
# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined PRId64
# define PRId64 _PRI64_PREFIX "d"
# endif
# if !defined 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 ULONG_MAX >> 31 == 1
# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined PRIo64
# define PRIo64 _PRIu64_PREFIX "o"
# endif
# if !defined PRIu64
# define PRIu64 _PRIu64_PREFIX "u"
# endif
# if !defined PRIx64
# define PRIx64 _PRIu64_PREFIX "x"
# endif
# if !defined PRIX64
# define PRIX64 _PRIu64_PREFIX "X"
# endif
#endif
#if !defined PRIdLEAST8
# define PRIdLEAST8 "d"
#endif
#if !defined PRIiLEAST8
# define PRIiLEAST8 "i"
#endif
#if !defined PRIoLEAST8
# define PRIoLEAST8 "o"
#endif
#if !defined PRIuLEAST8
# define PRIuLEAST8 "u"
#endif
#if !defined PRIxLEAST8
# define PRIxLEAST8 "x"
#endif
#if !defined PRIXLEAST8
# define PRIXLEAST8 "X"
#endif
#if !defined PRIdLEAST16
# define PRIdLEAST16 "d"
#endif
#if !defined PRIiLEAST16
# define PRIiLEAST16 "i"
#endif
#if !defined PRIoLEAST16
# define PRIoLEAST16 "o"
#endif
#if !defined PRIuLEAST16
# define PRIuLEAST16 "u"
#endif
#if !defined PRIxLEAST16
# define PRIxLEAST16 "x"
#endif
#if !defined PRIXLEAST16
# define PRIXLEAST16 "X"
#endif
#if !defined PRIdLEAST32
# define PRIdLEAST32 "d"
#endif
#if !defined PRIiLEAST32
# define PRIiLEAST32 "i"
#endif
#if !defined PRIoLEAST32
# define PRIoLEAST32 "o"
#endif
#if !defined PRIuLEAST32
# define PRIuLEAST32 "u"
#endif
#if !defined PRIxLEAST32
# define PRIxLEAST32 "x"
#endif
#if !defined PRIXLEAST32
# define PRIXLEAST32 "X"
#endif
#ifdef INT64_MAX
# if !defined PRIdLEAST64
# define PRIdLEAST64 PRId64
# endif
# if !defined PRIiLEAST64
# define PRIiLEAST64 PRIi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined PRIoLEAST64
# define PRIoLEAST64 PRIo64
# endif
# if !defined PRIuLEAST64
# define PRIuLEAST64 PRIu64
# endif
# if !defined PRIxLEAST64
# define PRIxLEAST64 PRIx64
# endif
# if !defined PRIXLEAST64
# define PRIXLEAST64 PRIX64
# endif
#endif
#if !defined PRIdFAST8
# if INT_FAST8_MAX > INT32_MAX
# define PRIdFAST8 PRId64
# else
# define PRIdFAST8 "d"
# endif
#endif
#if !defined PRIiFAST8
# if INT_FAST8_MAX > INT32_MAX
# define PRIiFAST8 PRIi64
# else
# define PRIiFAST8 "i"
# endif
#endif
#if !defined PRIoFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIoFAST8 PRIo64
# else
# define PRIoFAST8 "o"
# endif
#endif
#if !defined PRIuFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIuFAST8 PRIu64
# else
# define PRIuFAST8 "u"
# endif
#endif
#if !defined PRIxFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIxFAST8 PRIx64
# else
# define PRIxFAST8 "x"
# endif
#endif
#if !defined PRIXFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define PRIXFAST8 PRIX64
# else
# define PRIXFAST8 "X"
# endif
#endif
#if !defined PRIdFAST16
# if INT_FAST16_MAX > INT32_MAX
# define PRIdFAST16 PRId64
# else
# define PRIdFAST16 "d"
# endif
#endif
#if !defined PRIiFAST16
# if INT_FAST16_MAX > INT32_MAX
# define PRIiFAST16 PRIi64
# else
# define PRIiFAST16 "i"
# endif
#endif
#if !defined PRIoFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIoFAST16 PRIo64
# else
# define PRIoFAST16 "o"
# endif
#endif
#if !defined PRIuFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIuFAST16 PRIu64
# else
# define PRIuFAST16 "u"
# endif
#endif
#if !defined PRIxFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIxFAST16 PRIx64
# else
# define PRIxFAST16 "x"
# endif
#endif
#if !defined PRIXFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define PRIXFAST16 PRIX64
# else
# define PRIXFAST16 "X"
# endif
#endif
#if !defined PRIdFAST32
# if INT_FAST32_MAX > INT32_MAX
# define PRIdFAST32 PRId64
# else
# define PRIdFAST32 "d"
# endif
#endif
#if !defined PRIiFAST32
# if INT_FAST32_MAX > INT32_MAX
# define PRIiFAST32 PRIi64
# else
# define PRIiFAST32 "i"
# endif
#endif
#if !defined PRIoFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIoFAST32 PRIo64
# else
# define PRIoFAST32 "o"
# endif
#endif
#if !defined PRIuFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIuFAST32 PRIu64
# else
# define PRIuFAST32 "u"
# endif
#endif
#if !defined PRIxFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIxFAST32 PRIx64
# else
# define PRIxFAST32 "x"
# endif
#endif
#if !defined PRIXFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIXFAST32 PRIX64
# else
# define PRIXFAST32 "X"
# endif
#endif
#ifdef INT64_MAX
# if !defined PRIdFAST64
# define PRIdFAST64 PRId64
# endif
# if !defined PRIiFAST64
# define PRIiFAST64 PRIi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined PRIoFAST64
# define PRIoFAST64 PRIo64
# endif
# if !defined PRIuFAST64
# define PRIuFAST64 PRIu64
# endif
# if !defined PRIxFAST64
# define PRIxFAST64 PRIx64
# endif
# if !defined PRIXFAST64
# define PRIXFAST64 PRIX64
# endif
#endif
#if !defined PRIdMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define PRIdMAX PRId64
# else
# define PRIdMAX "ld"
# endif
#endif
#if !defined PRIiMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define PRIiMAX PRIi64
# else
# define PRIiMAX "li"
# endif
#endif
#if !defined PRIoMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIoMAX PRIo64
# else
# define PRIoMAX "lo"
# endif
#endif
#if !defined PRIuMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIuMAX PRIu64
# else
# define PRIuMAX "lu"
# endif
#endif
#if !defined PRIxMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIxMAX PRIx64
# else
# define PRIxMAX "lx"
# endif
#endif
#if !defined PRIXMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIXMAX PRIX64
# else
# define PRIXMAX "lX"
# endif
#endif
#if !defined PRIdPTR
# ifdef INTPTR_MAX
# define PRIdPTR @PRIPTR_PREFIX@ "d"
# endif
#endif
#if !defined PRIiPTR
# ifdef INTPTR_MAX
# define PRIiPTR @PRIPTR_PREFIX@ "i"
# endif
#endif
#if !defined PRIoPTR
# ifdef UINTPTR_MAX
# define PRIoPTR @PRIPTR_PREFIX@ "o"
# endif
#endif
#if !defined PRIuPTR
# ifdef UINTPTR_MAX
# define PRIuPTR @PRIPTR_PREFIX@ "u"
# endif
#endif
#if !defined PRIxPTR
# ifdef UINTPTR_MAX
# define PRIxPTR @PRIPTR_PREFIX@ "x"
# endif
#endif
#if !defined PRIXPTR
# ifdef UINTPTR_MAX
# define PRIXPTR @PRIPTR_PREFIX@ "X"
# endif
#endif
#if !defined SCNd8
# ifdef INT8_MAX
# define SCNd8 "hhd"
# endif
#endif
#if !defined SCNi8
# ifdef INT8_MAX
# define SCNi8 "hhi"
# endif
#endif
#if !defined SCNo8
# ifdef UINT8_MAX
# define SCNo8 "hho"
# endif
#endif
#if !defined SCNu8
# ifdef UINT8_MAX
# define SCNu8 "hhu"
# endif
#endif
#if !defined SCNx8
# ifdef UINT8_MAX
# define SCNx8 "hhx"
# endif
#endif
#if !defined SCNd16
# ifdef INT16_MAX
# define SCNd16 "hd"
# endif
#endif
#if !defined SCNi16
# ifdef INT16_MAX
# define SCNi16 "hi"
# endif
#endif
#if !defined SCNo16
# ifdef UINT16_MAX
# define SCNo16 "ho"
# endif
#endif
#if !defined SCNu16
# ifdef UINT16_MAX
# define SCNu16 "hu"
# endif
#endif
#if !defined SCNx16
# ifdef UINT16_MAX
# define SCNx16 "hx"
# endif
#endif
#if !defined SCNd32
# ifdef INT32_MAX
# define SCNd32 "d"
# endif
#endif
#if !defined SCNi32
# ifdef INT32_MAX
# define SCNi32 "i"
# endif
#endif
#if !defined SCNo32
# ifdef UINT32_MAX
# define SCNo32 "o"
# endif
#endif
#if !defined SCNu32
# ifdef UINT32_MAX
# define SCNu32 "u"
# endif
#endif
#if !defined 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 LONG_MAX >> 30 == 1
# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined SCNd64
# define SCNd64 _SCN64_PREFIX "d"
# endif
# if !defined 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 ULONG_MAX >> 31 == 1
# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
# if !defined SCNo64
# define SCNo64 _SCNu64_PREFIX "o"
# endif
# if !defined SCNu64
# define SCNu64 _SCNu64_PREFIX "u"
# endif
# if !defined SCNx64
# define SCNx64 _SCNu64_PREFIX "x"
# endif
#endif
#if !defined SCNdLEAST8
# define SCNdLEAST8 "hhd"
#endif
#if !defined SCNiLEAST8
# define SCNiLEAST8 "hhi"
#endif
#if !defined SCNoLEAST8
# define SCNoLEAST8 "hho"
#endif
#if !defined SCNuLEAST8
# define SCNuLEAST8 "hhu"
#endif
#if !defined SCNxLEAST8
# define SCNxLEAST8 "hhx"
#endif
#if !defined SCNdLEAST16
# define SCNdLEAST16 "hd"
#endif
#if !defined SCNiLEAST16
# define SCNiLEAST16 "hi"
#endif
#if !defined SCNoLEAST16
# define SCNoLEAST16 "ho"
#endif
#if !defined SCNuLEAST16
# define SCNuLEAST16 "hu"
#endif
#if !defined SCNxLEAST16
# define SCNxLEAST16 "hx"
#endif
#if !defined SCNdLEAST32
# define SCNdLEAST32 "d"
#endif
#if !defined SCNiLEAST32
# define SCNiLEAST32 "i"
#endif
#if !defined SCNoLEAST32
# define SCNoLEAST32 "o"
#endif
#if !defined SCNuLEAST32
# define SCNuLEAST32 "u"
#endif
#if !defined SCNxLEAST32
# define SCNxLEAST32 "x"
#endif
#ifdef INT64_MAX
# if !defined SCNdLEAST64
# define SCNdLEAST64 SCNd64
# endif
# if !defined SCNiLEAST64
# define SCNiLEAST64 SCNi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined SCNoLEAST64
# define SCNoLEAST64 SCNo64
# endif
# if !defined SCNuLEAST64
# define SCNuLEAST64 SCNu64
# endif
# if !defined SCNxLEAST64
# define SCNxLEAST64 SCNx64
# endif
#endif
#if !defined 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# if INT_FAST32_MAX > INT32_MAX
# define SCNdFAST32 SCNd64
# else
# define SCNdFAST32 "d"
# endif
#endif
#if !defined SCNiFAST32
# if INT_FAST32_MAX > INT32_MAX
# define SCNiFAST32 SCNi64
# else
# define SCNiFAST32 "i"
# endif
#endif
#if !defined SCNoFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNoFAST32 SCNo64
# else
# define SCNoFAST32 "o"
# endif
#endif
#if !defined SCNuFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNuFAST32 SCNu64
# else
# define SCNuFAST32 "u"
# endif
#endif
#if !defined SCNxFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNxFAST32 SCNx64
# else
# define SCNxFAST32 "x"
# endif
#endif
#ifdef INT64_MAX
# if !defined SCNdFAST64
# define SCNdFAST64 SCNd64
# endif
# if !defined SCNiFAST64
# define SCNiFAST64 SCNi64
# endif
#endif
#ifdef UINT64_MAX
# if !defined SCNoFAST64
# define SCNoFAST64 SCNo64
# endif
# if !defined SCNuFAST64
# define SCNuFAST64 SCNu64
# endif
# if !defined SCNxFAST64
# define SCNxFAST64 SCNx64
# endif
#endif
#if !defined SCNdMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define SCNdMAX SCNd64
# else
# define SCNdMAX "ld"
# endif
#endif
#if !defined SCNiMAX
# if @INT32_MAX_LT_INTMAX_MAX@
# define SCNiMAX SCNi64
# else
# define SCNiMAX "li"
# endif
#endif
#if !defined SCNoMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNoMAX SCNo64
# else
# define SCNoMAX "lo"
# endif
#endif
#if !defined SCNuMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNuMAX SCNu64
# else
# define SCNuMAX "lu"
# endif
#endif
#if !defined SCNxMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNxMAX SCNx64
# else
# define SCNxMAX "lx"
# endif
#endif
#if !defined SCNdPTR
# ifdef INTPTR_MAX
# define SCNdPTR @PRIPTR_PREFIX@ "d"
# endif
#endif
#if !defined SCNiPTR
# ifdef INTPTR_MAX
# define SCNiPTR @PRIPTR_PREFIX@ "i"
# endif
#endif
#if !defined SCNoPTR
# ifdef UINTPTR_MAX
# define SCNoPTR @PRIPTR_PREFIX@ "o"
# endif
#endif
#if !defined SCNuPTR
# ifdef UINTPTR_MAX
# define SCNuPTR @PRIPTR_PREFIX@ "u"
# endif
#endif
#if !defined 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_IMAXDIV_T@
# if !GNULIB_defined_imaxdiv_t
typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t;
# define GNULIB_defined_imaxdiv_t 1
# endif
# endif
# if !@HAVE_DECL_IMAXDIV@
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 *restrict, char **restrict, int)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (strtoimax, intmax_t,
(const char *restrict, char **restrict, int));
# else
# if !@HAVE_DECL_STRTOIMAX@
# undef strtoimax
_GL_FUNCDECL_SYS (strtoimax, intmax_t,
(const char *restrict, char **restrict, int)
_GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (strtoimax, intmax_t,
(const char *restrict, char **restrict, 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 @REPLACE_STRTOUMAX@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef strtoumax
# define strtoumax rpl_strtoumax
# endif
_GL_FUNCDECL_RPL (strtoumax, uintmax_t,
(const char *restrict, char **restrict, int)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (strtoumax, uintmax_t,
(const char *restrict, char **restrict, int));
# else
# if !@HAVE_DECL_STRTOUMAX@
# undef strtoumax
_GL_FUNCDECL_SYS (strtoumax, uintmax_t,
(const char *restrict, char **restrict, int)
_GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (strtoumax, uintmax_t,
(const char *restrict, char **restrict, int));
# endif
_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 */
recode-3.7.14/lib/itold.c 0000644 0001750 0001750 00000002032 14366047013 012016 0000000 0000000 /* Replacement for 'int' to 'long double' conversion routine.
Copyright (C) 2011-2023 Free Software Foundation, Inc.
Written by Bruno Haible , 2011.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#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;
}
recode-3.7.14/lib/getopt-ext.h 0000644 0001750 0001750 00000005753 14366047013 013025 0000000 0000000 /* Declarations for getopt (GNU extensions).
Copyright (C) 1989-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
. */
#ifndef _GETOPT_EXT_H
#define _GETOPT_EXT_H 1
/* This header should not be used directly; include getopt.h instead.
Unlike most bits headers, it does not have a protective #error,
because the guard macro for getopt.h in gnulib is not fixed. */
__BEGIN_DECLS
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of 'struct option' terminated by an element containing a name which is
zero.
The field 'has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field 'flag' is not NULL, it points to a variable that is set
to the value given in the field 'val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an 'int' to
a compiled-in constant, such as set a value from 'optarg', set the
option's 'flag' field to zero and its 'val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero 'flag' field, 'getopt'
returns the contents of the 'val' field. */
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the 'has_arg' field of 'struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW _GL_ARG_NONNULL ((2, 3));
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW _GL_ARG_NONNULL ((2, 3));
__END_DECLS
#endif /* _GETOPT_EXT_H */
recode-3.7.14/lib/xsize.c 0000644 0001750 0001750 00000001504 14366047013 012050 0000000 0000000 /* Checked size_t computations.
Copyright (C) 2012-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
#define XSIZE_INLINE _GL_EXTERN_INLINE
#include "xsize.h"
recode-3.7.14/lib/filename.h 0000644 0001750 0001750 00000011106 14171566624 012502 0000000 0000000 /* Basic filename support macros.
Copyright (C) 2001-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
. */
/* From Paul Eggert and Jim Meyering. */
#ifndef _FILENAME_H
#define _FILENAME_H
#include
#ifdef __cplusplus
extern "C" {
#endif
/* Filename support.
ISSLASH(C) tests whether C is a directory separator
character.
HAS_DEVICE(Filename) tests whether Filename contains a device
specification.
FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification
at the beginning of Filename,
index of the part consisting of
alternating components and slashes.
FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
1 when a non-empty device specification
can be followed by an empty or relative
part,
0 when a non-empty device specification
must be followed by a slash,
0 when device specification don't exist.
IS_ABSOLUTE_FILE_NAME(Filename)
tests whether Filename is independent of
any notion of "current directory".
IS_RELATIVE_FILE_NAME(Filename)
tests whether Filename may be concatenated
to a directory filename.
Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a
relative file name!
IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device
or directory specification.
*/
#if defined _WIN32 || defined __CYGWIN__ \
|| defined __EMX__ || defined __MSDOS__ || defined __DJGPP__
/* Native Windows, Cygwin, OS/2, DOS */
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
/* Internal macro: Tests whether a character is a drive letter. */
# define _IS_DRIVE_LETTER(C) \
(((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z'))
/* Help the compiler optimizing it. This assumes ASCII. */
# undef _IS_DRIVE_LETTER
# define _IS_DRIVE_LETTER(C) \
(((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a')
# define HAS_DEVICE(Filename) \
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':')
# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0)
# ifdef __CYGWIN__
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
# else
/* On native Windows, OS/2, DOS, the system has the notion of a
"current directory" on each drive. */
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
# endif
# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
# define IS_ABSOLUTE_FILE_NAME(Filename) \
ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)])
# else
# define IS_ABSOLUTE_FILE_NAME(Filename) \
(ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))
# endif
# define IS_RELATIVE_FILE_NAME(Filename) \
(! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)))
# define IS_FILE_NAME_WITH_DIR(Filename) \
(strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \
|| HAS_DEVICE (Filename))
#else
/* Unix */
# define ISSLASH(C) ((C) == '/')
# define HAS_DEVICE(Filename) ((void) (Filename), 0)
# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
#endif
/* Deprecated macros. For backward compatibility with old users of the
'filename' module. */
#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME
#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR
#ifdef __cplusplus
}
#endif
#endif /* _FILENAME_H */
recode-3.7.14/lib/strnlen.c 0000644 0001750 0001750 00000002226 14366047013 012375 0000000 0000000 /* Find the length of STRING, but scan at most MAXLEN characters.
Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
Written by Simon Josefsson.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
#include
/* Find the length of STRING, but scan at most MAXLEN characters.
If no '\0' terminator is found in that many characters, return MAXLEN. */
size_t
strnlen (const char *string, size_t maxlen)
{
const char *end = memchr (string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen;
}
recode-3.7.14/lib/open.c 0000644 0001750 0001750 00000015377 14366047013 011664 0000000 0000000 /* Open a descriptor to a file.
Copyright (C) 2007-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Bruno Haible , 2007. */
/* If the user's config.h happens to include , let it include only
the system's here, so that orig_open doesn't recurse to
rpl_open. */
#define __need_system_fcntl_h
#include
/* Get the original definition of open. It might be defined as a macro. */
#include
#include
#undef __need_system_fcntl_h
static int
orig_open (const char *filename, int flags, mode_t mode)
{
#if defined _WIN32 && !defined __CYGWIN__
return _open (filename, flags, mode);
#else
return open (filename, flags, mode);
#endif
}
/* Specification. */
/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates
this include because of the preliminary #include above. */
#include "fcntl.h"
#include "cloexec.h"
#include
#include
#include
#include
#include
#include
#ifndef REPLACE_OPEN_DIRECTORY
# define REPLACE_OPEN_DIRECTORY 0
#endif
int
open (const char *filename, int flags, ...)
{
/* 0 = unknown, 1 = yes, -1 = no. */
#if GNULIB_defined_O_CLOEXEC
int have_cloexec = -1;
#else
static int have_cloexec;
#endif
mode_t mode;
int fd;
mode = 0;
if (flags & O_CREAT)
{
va_list arg;
va_start (arg, flags);
/* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4
creates crashing code when 'mode_t' is smaller than 'int'. */
mode = va_arg (arg, PROMOTED_MODE_T);
va_end (arg);
}
#if GNULIB_defined_O_NONBLOCK
/* The only known platform that lacks O_NONBLOCK is mingw, but it
also lacks named pipes and Unix sockets, which are the only two
file types that require non-blocking handling in open().
Therefore, it is safe to ignore O_NONBLOCK here. It is handy
that mingw also lacks openat(), so that is also covered here. */
flags &= ~O_NONBLOCK;
#endif
#if defined _WIN32 && ! defined __CYGWIN__
if (strcmp (filename, "/dev/null") == 0)
filename = "NUL";
#endif
#if OPEN_TRAILING_SLASH_BUG
/* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename
ends in a slash, as POSIX says such a filename must name a directory
:
"A pathname that contains at least one non- character and that
ends with one or more trailing characters shall not be resolved
successfully unless the last pathname component before the trailing
characters names an existing directory"
If the named file already exists as a directory, then
- if O_CREAT is specified, open() must fail because of the semantics
of O_CREAT,
- if O_WRONLY or O_RDWR is specified, open() must fail because POSIX
says that it fails with errno = EISDIR in this case.
If the named file does not exist or does not name a directory, then
- if O_CREAT is specified, open() must fail since open() cannot create
directories,
- if O_WRONLY or O_RDWR is specified, open() must fail because the
file does not contain a '.' directory. */
if ((flags & O_CREAT)
|| (flags & O_ACCMODE) == O_RDWR
|| (flags & O_ACCMODE) == O_WRONLY)
{
size_t len = strlen (filename);
if (len > 0 && filename[len - 1] == '/')
{
errno = EISDIR;
return -1;
}
}
#endif
fd = orig_open (filename,
flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode);
if (flags & O_CLOEXEC)
{
if (! have_cloexec)
{
if (0 <= fd)
have_cloexec = 1;
else if (errno == EINVAL)
{
fd = orig_open (filename, flags & ~O_CLOEXEC, mode);
have_cloexec = -1;
}
}
if (have_cloexec < 0 && 0 <= fd)
set_cloexec_flag (fd, true);
}
#if REPLACE_FCHDIR
/* Implementing fchdir and fdopendir requires the ability to open a
directory file descriptor. If open doesn't support that (as on
mingw), we use a dummy file that behaves the same as directories
on Linux (ie. always reports EOF on attempts to read()), and
override fstat() in fchdir.c to hide the fact that we have a
dummy. */
if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES
&& ((flags & O_ACCMODE) == O_RDONLY
|| (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH)))
{
struct stat statbuf;
if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
{
/* Maximum recursion depth of 1. */
fd = open ("/dev/null", flags, mode);
if (0 <= fd)
fd = _gl_register_fd (fd, filename);
}
else
errno = EACCES;
}
#endif
#if OPEN_TRAILING_SLASH_BUG
/* If the filename ends in a slash and fd does not refer to a directory,
then fail.
Rationale: POSIX says such a filename must name a directory
:
"A pathname that contains at least one non- character and that
ends with one or more trailing characters shall not be resolved
successfully unless the last pathname component before the trailing
characters names an existing directory"
If the named file without the slash is not a directory, open() must fail
with ENOTDIR. */
if (fd >= 0)
{
/* We know len is positive, since open did not fail with ENOENT. */
size_t len = strlen (filename);
if (filename[len - 1] == '/')
{
struct stat statbuf;
if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode))
{
close (fd);
errno = ENOTDIR;
return -1;
}
}
}
#endif
#if REPLACE_FCHDIR
if (!REPLACE_OPEN_DIRECTORY && 0 <= fd)
fd = _gl_register_fd (fd, filename);
#endif
return fd;
}
recode-3.7.14/lib/basename-lgpl.c 0000644 0001750 0001750 00000003440 14366047013 013416 0000000 0000000 /* basename.c -- return the last element in a file name
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2023 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
/* Specification. */
#include "basename-lgpl.h"
#include
#include "filename.h"
char *
last_component (char const *name)
{
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p;
bool last_was_slash = false;
while (ISSLASH (*base))
base++;
for (p = base; *p; p++)
{
if (ISSLASH (*p))
last_was_slash = true;
else if (last_was_slash)
{
base = p;
last_was_slash = false;
}
}
return (char *) base;
}
size_t
base_len (char const *name)
{
size_t len;
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
return 2;
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
&& len == prefix_len && ISSLASH (name[prefix_len]))
return prefix_len + 1;
return len;
}
recode-3.7.14/lib/quotearg.h 0000644 0001750 0001750 00000042433 14366047013 012550 0000000 0000000 /* quotearg.h - quote arguments for output
Copyright (C) 1998-2002, 2004, 2006, 2008-2023 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This 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 QUOTEARG_H_
# define QUOTEARG_H_ 1
# include
/* Basic quoting styles. For each style, an example is given on the
input strings "simple", "\0 \t\n'\"\033?""?/\\", and "a:b", using
quotearg_buffer, quotearg_mem, and quotearg_colon_mem with that
style and the default flags and quoted characters. Note that the
examples are shown here as valid C strings rather than what
displays on a terminal (with "??/" as a trigraph for "\\"). */
enum quoting_style
{
/* Output names as-is (ls --quoting-style=literal). Can result in
embedded null bytes if QA_ELIDE_NULL_BYTES is not in
effect.
quotearg_buffer:
"simple", "\0 \t\n'\"\033??/\\", "a:b"
quotearg:
"simple", " \t\n'\"\033??/\\", "a:b"
quotearg_colon:
"simple", " \t\n'\"\033??/\\", "a:b"
*/
literal_quoting_style,
/* Quote names for the shell if they contain shell metacharacters
or would cause ambiguous output (ls --quoting-style=shell).
Can result in embedded null bytes if QA_ELIDE_NULL_BYTES is not
in effect.
quotearg_buffer:
"simple", "'\0 \t\n'\\''\"\033??/\\'", "a:b"
quotearg:
"simple", "' \t\n'\\''\"\033??/\\'", "a:b"
quotearg_colon:
"simple", "' \t\n'\\''\"\033??/\\'", "'a:b'"
*/
shell_quoting_style,
/* Quote names for the shell, even if they would normally not
require quoting (ls --quoting-style=shell-always). Can result
in embedded null bytes if QA_ELIDE_NULL_BYTES is not in effect.
Behaves like shell_quoting_style if QA_ELIDE_OUTER_QUOTES is in
effect.
quotearg_buffer:
"'simple'", "'\0 \t\n'\\''\"\033??/\\'", "'a:b'"
quotearg:
"'simple'", "' \t\n'\\''\"\033??/\\'", "'a:b'"
quotearg_colon:
"'simple'", "' \t\n'\\''\"\033??/\\'", "'a:b'"
*/
shell_always_quoting_style,
/* Quote names for the shell if they contain shell metacharacters
or other problematic characters (ls --quoting-style=shell-escape).
Non printable characters are quoted using the $'...' syntax,
which originated in ksh93 and is widely supported by most shells,
and proposed for inclusion in POSIX.
quotearg_buffer:
"simple", "''$'\\0'' '$'\\t\\n'\\''\"'$'\\033''??/\\'", "a:b"
quotearg:
"simple", "''$'\\0'' '$'\\t\\n'\\''\"'$'\\033''??/\\'", "a:b"
quotearg_colon:
"simple", "''$'\\0'' '$'\\t\\n'\\''\"'$'\\033''??/\\'", "'a:b'"
*/
shell_escape_quoting_style,
/* Quote names for the shell even if they would normally not
require quoting (ls --quoting-style=shell-escape).
Non printable characters are quoted using the $'...' syntax,
which originated in ksh93 and is widely supported by most shells,
and proposed for inclusion in POSIX. Behaves like
shell_escape_quoting_style if QA_ELIDE_OUTER_QUOTES is in effect.
quotearg_buffer:
"simple", "''$'\\0'' '$'\\t\\n'\\''\"'$'\\033''??/\'", "a:b"
quotearg:
"simple", "''$'\\0'' '$'\\t\\n'\\''\"'$'\\033''??/\'", "a:b"
quotearg_colon:
"simple", "''$'\\0'' '$'\\t\\n'\\''\"'$'\\033''??/\'", "'a:b'"
*/
shell_escape_always_quoting_style,
/* Quote names as for a C language string (ls --quoting-style=c).
Behaves like c_maybe_quoting_style if QA_ELIDE_OUTER_QUOTES is
in effect. Split into consecutive strings if
QA_SPLIT_TRIGRAPHS.
quotearg_buffer:
"\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\""
quotearg:
"\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\""
quotearg_colon:
"\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a\\:b\""
*/
c_quoting_style,
/* Like c_quoting_style except omit the surrounding double-quote
characters if no quoted characters are encountered.
quotearg_buffer:
"simple", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "a:b"
quotearg:
"simple", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "a:b"
quotearg_colon:
"simple", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\""
*/
c_maybe_quoting_style,
/* Like c_quoting_style except always omit the surrounding
double-quote characters and ignore QA_SPLIT_TRIGRAPHS
(ls --quoting-style=escape).
quotearg_buffer:
"simple", "\\0 \\t\\n'\"\\033??/\\\\", "a:b"
quotearg:
"simple", "\\0 \\t\\n'\"\\033??/\\\\", "a:b"
quotearg_colon:
"simple", "\\0 \\t\\n'\"\\033??/\\\\", "a\\:b"
*/
escape_quoting_style,
/* Like clocale_quoting_style, but use single quotes in the
default C locale or if the program does not use gettext
(ls --quoting-style=locale). For UTF-8 locales, quote
characters will use Unicode.
LC_MESSAGES=C
quotearg_buffer:
"`simple'", "`\\0 \\t\\n\\'\"\\033??/\\\\'", "`a:b'"
quotearg:
"`simple'", "`\\0 \\t\\n\\'\"\\033??/\\\\'", "`a:b'"
quotearg_colon:
"`simple'", "`\\0 \\t\\n\\'\"\\033??/\\\\'", "`a\\:b'"
LC_MESSAGES=pt_PT.utf8
quotearg_buffer:
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
quotearg:
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
quotearg_colon:
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273"
*/
locale_quoting_style,
/* Like c_quoting_style except use quotation marks appropriate for
the locale and ignore QA_SPLIT_TRIGRAPHS
(ls --quoting-style=clocale).
LC_MESSAGES=C
quotearg_buffer:
"\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\""
quotearg:
"\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\""
quotearg_colon:
"\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a\\:b\""
LC_MESSAGES=pt_PT.utf8
quotearg_buffer:
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
quotearg:
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
quotearg_colon:
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273"
*/
clocale_quoting_style,
/* Like clocale_quoting_style except use the custom quotation marks
set by set_custom_quoting. If custom quotation marks are not
set, the behavior is undefined.
left_quote = right_quote = "'"
quotearg_buffer:
"'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a:b'"
quotearg:
"'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a:b'"
quotearg_colon:
"'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a\\:b'"
left_quote = "(" and right_quote = ")"
quotearg_buffer:
"(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a:b)"
quotearg:
"(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a:b)"
quotearg_colon:
"(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a\\:b)"
left_quote = ":" and right_quote = " "
quotearg_buffer:
":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a:b "
quotearg:
":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a:b "
quotearg_colon:
":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a\\:b "
left_quote = "\"'" and right_quote = "'\""
Notice that this is treated as a single level of quotes or two
levels where the outer quote need not be escaped within the inner
quotes. For two levels where the outer quote must be escaped
within the inner quotes, you must use separate quotearg
invocations.
quotearg_buffer:
"\"'simple'\"", "\"'\\0 \\t\\n\\'\"\\033??/\\\\'\"", "\"'a:b'\""
quotearg:
"\"'simple'\"", "\"'\\0 \\t\\n\\'\"\\033??/\\\\'\"", "\"'a:b'\""
quotearg_colon:
"\"'simple'\"", "\"'\\0 \\t\\n\\'\"\\033??/\\\\'\"", "\"'a\\:b'\""
*/
custom_quoting_style
};
/* Flags for use in set_quoting_flags. */
enum quoting_flags
{
/* Always elide null bytes from styles that do not quote them,
even when the length of the result is available to the
caller. */
QA_ELIDE_NULL_BYTES = 0x01,
/* Omit the surrounding quote characters if no escaped characters
are encountered. Note that if no other character needs
escaping, then neither does the escape character. */
QA_ELIDE_OUTER_QUOTES = 0x02,
/* In the c_quoting_style and c_maybe_quoting_style, split ANSI
trigraph sequences into concatenated strings (for example,
"?""?/" rather than "??/", which could be confused with
"\\"). */
QA_SPLIT_TRIGRAPHS = 0x04
};
/* For now, --quoting-style=literal is the default, but this may change. */
# ifndef DEFAULT_QUOTING_STYLE
# define DEFAULT_QUOTING_STYLE literal_quoting_style
# endif
/* Names of quoting styles and their corresponding values. */
extern char const *const quoting_style_args[];
extern enum quoting_style const quoting_style_vals[];
struct quoting_options;
/* The functions listed below set and use a hidden variable
that contains the default quoting style options. */
/* Allocate a new set of quoting options, with contents initially identical
to O if O is not null, or to the default if O is null.
It is the caller's responsibility to free the result. */
struct quoting_options *clone_quoting_options (struct quoting_options *o)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_RETURNS_NONNULL;
/* Get the value of O's quoting style. If O is null, use the default. */
enum quoting_style get_quoting_style (struct quoting_options const *o);
/* In O (or in the default if O is null),
set the value of the quoting style to S. */
void set_quoting_style (struct quoting_options *o, enum quoting_style s);
/* In O (or in the default if O is null),
set the value of the quoting options for character C to I.
Return the old value. Currently, the only values defined for I are
0 (the default) and 1 (which means to quote the character even if
it would not otherwise be quoted). C must never be a digit or a
letter that has special meaning after a backslash (for example, "\t"
for tab). */
int set_char_quoting (struct quoting_options *o, char c, int i);
/* In O (or in the default if O is null),
set the value of the quoting options flag to I, which can be a
bitwise combination of enum quoting_flags, or 0 for default
behavior. Return the old value. */
int set_quoting_flags (struct quoting_options *o, int i);
/* In O (or in the default if O is null),
set the value of the quoting style to custom_quoting_style,
set the left quote to LEFT_QUOTE, and set the right quote to
RIGHT_QUOTE. Each of LEFT_QUOTE and RIGHT_QUOTE must be
null-terminated and can be the empty string. Because backslashes are
used for escaping, it does not make sense for RIGHT_QUOTE to contain
a backslash. RIGHT_QUOTE must not begin with a digit or a letter
that has special meaning after a backslash (for example, "\t" for
tab). */
void set_custom_quoting (struct quoting_options *o,
char const *left_quote,
char const *right_quote);
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
argument ARG (of size ARGSIZE), using O to control quoting.
If O is null, use the default.
Terminate the output with a null character, and return the written
size of the output, not counting the terminating null.
If BUFFERSIZE is too small to store the output string, return the
value that would have been returned had BUFFERSIZE been large enough.
If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
On output, BUFFER might contain embedded null bytes if ARGSIZE was
not -1, the style of O does not use backslash escapes, and the
flags of O do not request elision of null bytes.*/
size_t quotearg_buffer (char *restrict buffer, size_t buffersize,
char const *arg, size_t argsize,
struct quoting_options const *o);
/* Like quotearg_buffer, except return the result in a newly allocated
buffer. It is the caller's responsibility to free the result. The
result will not contain embedded null bytes. */
char *quotearg_alloc (char const *arg, size_t argsize,
struct quoting_options const *o)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_RETURNS_NONNULL;
/* Like quotearg_alloc, except that the length of the result,
excluding the terminating null byte, is stored into SIZE if it is
non-NULL. The result might contain embedded null bytes if ARGSIZE
was not -1, SIZE was not NULL, the style of O does not use
backslash escapes, and the flags of O do not request elision of
null bytes.*/
char *quotearg_alloc_mem (char const *arg, size_t argsize,
size_t *size, struct quoting_options const *o)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_RETURNS_NONNULL;
/* Use storage slot N to return a quoted version of the string ARG.
Use the default quoting options.
The returned value points to static storage that can be
reused by the next call to this function with the same value of N.
N must be nonnegative. The output of all functions in the
quotearg_n family are guaranteed to not contain embedded null
bytes.*/
char *quotearg_n (int n, char const *arg);
/* Equivalent to quotearg_n (0, ARG). */
char *quotearg (char const *arg);
/* Use storage slot N to return a quoted version of the argument ARG
of size ARGSIZE. This is like quotearg_n (N, ARG), except it can
quote null bytes. */
char *quotearg_n_mem (int n, char const *arg, size_t argsize);
/* Equivalent to quotearg_n_mem (0, ARG, ARGSIZE). */
char *quotearg_mem (char const *arg, size_t argsize);
/* Use style S and storage slot N to return a quoted version of the string ARG.
This is like quotearg_n (N, ARG), except that it uses S with no other
options to specify the quoting method. */
char *quotearg_n_style (int n, enum quoting_style s, char const *arg);
/* Use style S and storage slot N to return a quoted version of the
argument ARG of size ARGSIZE. This is like quotearg_n_style
(N, S, ARG), except it can quote null bytes. */
char *quotearg_n_style_mem (int n, enum quoting_style s,
char const *arg, size_t argsize);
/* Equivalent to quotearg_n_style (0, S, ARG). */
char *quotearg_style (enum quoting_style s, char const *arg);
/* Equivalent to quotearg_n_style_mem (0, S, ARG, ARGSIZE). */
char *quotearg_style_mem (enum quoting_style s,
char const *arg, size_t argsize);
/* Like quotearg (ARG), except also quote any instances of CH.
See set_char_quoting for a description of acceptable CH values. */
char *quotearg_char (char const *arg, char ch);
/* Like quotearg_char (ARG, CH), except it can quote null bytes. */
char *quotearg_char_mem (char const *arg, size_t argsize, char ch);
/* Equivalent to quotearg_char (ARG, ':'). */
char *quotearg_colon (char const *arg);
/* Like quotearg_colon (ARG), except it can quote null bytes. */
char *quotearg_colon_mem (char const *arg, size_t argsize);
/* Like quotearg_n_style, except with ':' quoting enabled. */
char *quotearg_n_style_colon (int n, enum quoting_style s, char const *arg);
/* Like quotearg_n_style (N, S, ARG) but with S as custom_quoting_style
with left quote as LEFT_QUOTE and right quote as RIGHT_QUOTE. See
set_custom_quoting for a description of acceptable LEFT_QUOTE and
RIGHT_QUOTE values. */
char *quotearg_n_custom (int n, char const *left_quote,
char const *right_quote, char const *arg);
/* Like quotearg_n_custom (N, LEFT_QUOTE, RIGHT_QUOTE, ARG) except it
can quote null bytes. */
char *quotearg_n_custom_mem (int n, char const *left_quote,
char const *right_quote,
char const *arg, size_t argsize);
/* Equivalent to quotearg_n_custom (0, LEFT_QUOTE, RIGHT_QUOTE, ARG). */
char *quotearg_custom (char const *left_quote, char const *right_quote,
char const *arg);
/* Equivalent to quotearg_n_custom_mem (0, LEFT_QUOTE, RIGHT_QUOTE, ARG,
ARGSIZE). */
char *quotearg_custom_mem (char const *left_quote,
char const *right_quote,
char const *arg, size_t argsize);
/* Free any dynamically allocated memory. */
void quotearg_free (void);
#endif /* !QUOTEARG_H_ */
recode-3.7.14/lib/mbrtowc-impl-utf8.h 0000644 0001750 0001750 00000012255 14366047013 014220 0000000 0000000 /* Convert multibyte character to wide character.
Copyright (C) 1999-2002, 2005-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Bruno Haible , 2008. */
/* This file contains the part of the body of the mbrtowc and mbrtoc32 functions
that handles the special case of the UTF-8 encoding. */
/* Cf. unistr/u8-mbtouc.c. */
unsigned char c = (unsigned char) p[0];
if (c < 0x80)
{
if (pwc != NULL)
*pwc = c;
res = (c == 0 ? 0 : 1);
goto success;
}
if (c >= 0xc2)
{
if (c < 0xe0)
{
if (m == 1)
goto incomplete;
else /* m >= 2 */
{
unsigned char c2 = (unsigned char) p[1];
if ((c2 ^ 0x80) < 0x40)
{
if (pwc != NULL)
*pwc = ((unsigned int) (c & 0x1f) << 6)
| (unsigned int) (c2 ^ 0x80);
res = 2;
goto success;
}
}
}
else if (c < 0xf0)
{
if (m == 1)
goto incomplete;
else
{
unsigned char c2 = (unsigned char) p[1];
if ((c2 ^ 0x80) < 0x40
&& (c >= 0xe1 || c2 >= 0xa0)
&& (c != 0xed || c2 < 0xa0))
{
if (m == 2)
goto incomplete;
else /* m >= 3 */
{
unsigned char c3 = (unsigned char) p[2];
if ((c3 ^ 0x80) < 0x40)
{
unsigned int wc =
(((unsigned int) (c & 0x0f) << 12)
| ((unsigned int) (c2 ^ 0x80) << 6)
| (unsigned int) (c3 ^ 0x80));
if (FITS_IN_CHAR_TYPE (wc))
{
if (pwc != NULL)
*pwc = wc;
res = 3;
goto success;
}
}
}
}
}
}
else if (c <= 0xf4)
{
if (m == 1)
goto incomplete;
else
{
unsigned char c2 = (unsigned char) p[1];
if ((c2 ^ 0x80) < 0x40
&& (c >= 0xf1 || c2 >= 0x90)
&& (c < 0xf4 || (/* c == 0xf4 && */ c2 < 0x90)))
{
if (m == 2)
goto incomplete;
else
{
unsigned char c3 = (unsigned char) p[2];
if ((c3 ^ 0x80) < 0x40)
{
if (m == 3)
goto incomplete;
else /* m >= 4 */
{
unsigned char c4 = (unsigned char) p[3];
if ((c4 ^ 0x80) < 0x40)
{
unsigned int wc =
(((unsigned int) (c & 0x07) << 18)
| ((unsigned int) (c2 ^ 0x80) << 12)
| ((unsigned int) (c3 ^ 0x80) << 6)
| (unsigned int) (c4 ^ 0x80));
if (FITS_IN_CHAR_TYPE (wc))
{
if (pwc != NULL)
*pwc = wc;
res = 4;
goto success;
}
}
}
}
}
}
}
}
}
goto invalid;
recode-3.7.14/lib/printf-args.h 0000644 0001750 0001750 00000007406 14366047013 013156 0000000 0000000 /* Decomposed printf argument list.
Copyright (C) 1999, 2002-2003, 2006-2007, 2011-2023 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _PRINTF_ARGS_H
#define _PRINTF_ARGS_H
/* This file can be parametrized with the following macros:
ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
PRINTF_FETCHARGS Name of the function to be declared.
STATIC Set to 'static' to declare the function static. */
/* Default parameters. */
#ifndef PRINTF_FETCHARGS
# define PRINTF_FETCHARGS printf_fetchargs
#endif
/* Get size_t. */
#include
/* Get wchar_t. */
#if HAVE_WCHAR_T
# include
#endif
/* Get wint_t. */
#if HAVE_WINT_T
# include
#endif
/* Get va_list. */
#include
/* Argument types */
typedef enum
{
TYPE_NONE,
TYPE_SCHAR,
TYPE_UCHAR,
TYPE_SHORT,
TYPE_USHORT,
TYPE_INT,
TYPE_UINT,
TYPE_LONGINT,
TYPE_ULONGINT,
TYPE_LONGLONGINT,
TYPE_ULONGLONGINT,
TYPE_DOUBLE,
TYPE_LONGDOUBLE,
TYPE_CHAR,
#if HAVE_WINT_T
TYPE_WIDE_CHAR,
#endif
TYPE_STRING,
#if HAVE_WCHAR_T
TYPE_WIDE_STRING,
#endif
TYPE_POINTER,
TYPE_COUNT_SCHAR_POINTER,
TYPE_COUNT_SHORT_POINTER,
TYPE_COUNT_INT_POINTER,
TYPE_COUNT_LONGINT_POINTER,
TYPE_COUNT_LONGLONGINT_POINTER
#if ENABLE_UNISTDIO
/* The unistdio extensions. */
, TYPE_U8_STRING
, TYPE_U16_STRING
, TYPE_U32_STRING
#endif
} arg_type;
/* Polymorphic argument */
typedef struct
{
arg_type type;
union
{
signed char a_schar;
unsigned char a_uchar;
short a_short;
unsigned short a_ushort;
int a_int;
unsigned int a_uint;
long int a_longint;
unsigned long int a_ulongint;
long long int a_longlongint;
unsigned long long int a_ulonglongint;
float a_float;
double a_double;
long double a_longdouble;
int a_char;
#if HAVE_WINT_T
wint_t a_wide_char;
#endif
const char* a_string;
#if HAVE_WCHAR_T
const wchar_t* a_wide_string;
#endif
void* a_pointer;
signed char * a_count_schar_pointer;
short * a_count_short_pointer;
int * a_count_int_pointer;
long int * a_count_longint_pointer;
long long int * a_count_longlongint_pointer;
#if ENABLE_UNISTDIO
/* The unistdio extensions. */
const uint8_t * a_u8_string;
const uint16_t * a_u16_string;
const uint32_t * a_u32_string;
#endif
}
a;
}
argument;
/* Number of directly allocated arguments (no malloc() needed). */
#define N_DIRECT_ALLOC_ARGUMENTS 7
typedef struct
{
size_t count;
argument *arg;
argument direct_alloc_arg[N_DIRECT_ALLOC_ARGUMENTS];
}
arguments;
/* Fetch the arguments, putting them into a. */
#ifdef STATIC
STATIC
#else
extern
#endif
int PRINTF_FETCHARGS (va_list args, arguments *a);
#endif /* _PRINTF_ARGS_H */
recode-3.7.14/lib/wchar.in.h 0000644 0001750 0001750 00000130522 14366047013 012427 0000000 0000000 /* A substitute for ISO C99 , for platforms that have issues.
Copyright (C) 2007-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Eric Blake. */
/*
* ISO C 99 for platforms that have issues.
*
*
* For now, this just ensures proper prerequisite inclusion order and
* the declaration of wcwidth().
*/
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
#if (((defined __need_mbstate_t || defined __need_wint_t) \
&& !defined __MINGW32__) \
|| (defined __hpux \
&& ((defined _INTTYPES_INCLUDED \
&& !defined _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H) \
|| defined _GL_JUST_INCLUDE_SYSTEM_WCHAR_H)) \
|| (defined __MINGW32__ && defined __STRING_H_SOURCED__) \
|| defined _GL_ALREADY_INCLUDING_WCHAR_H)
/* Special invocation convention:
- Inside glibc and uClibc header files, but not MinGW.
- On HP-UX 11.00 we have a sequence of nested includes
-> -> , and the latter includes ,
once indirectly -> -> ->
and once directly. In both situations 'wint_t' is not yet defined,
therefore we cannot provide the function overrides; instead include only
the system's .
- With MinGW 3.22, when includes , only some part of
is actually processed, and that doesn't include 'mbstate_t'.
- On IRIX 6.5, similarly, we have an include -> , and
the latter includes . But here, we have no way to detect whether
is completely included or is still being included. */
#@INCLUDE_NEXT@ @NEXT_WCHAR_H@
#else
/* Normal invocation convention. */
#ifndef _@GUARD_PREFIX@_WCHAR_H
#define _GL_ALREADY_INCLUDING_WCHAR_H
#if @HAVE_FEATURES_H@
# include /* for __GLIBC__ */
#endif
/* In some builds of uClibc, is nonexistent and wchar_t is defined
by .
But avoid namespace pollution on glibc systems. */
#if !(defined __GLIBC__ && !defined __UCLIBC__)
# include
#endif
/* Include the original if it exists.
Some builds of uClibc lack it. */
/* The include_next requires a split double-inclusion guard. */
#if @HAVE_WCHAR_H@
# @INCLUDE_NEXT@ @NEXT_WCHAR_H@
#endif
#undef _GL_ALREADY_INCLUDING_WCHAR_H
#ifndef _@GUARD_PREFIX@_WCHAR_H
#define _@GUARD_PREFIX@_WCHAR_H
/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
that can be freed by passing them as the Ith argument to the
function F. */
#ifndef _GL_ATTRIBUTE_DEALLOC
# if __GNUC__ >= 11
# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
# else
# define _GL_ATTRIBUTE_DEALLOC(f, i)
# endif
#endif
/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
can be freed via 'free'; it can be used only after declaring 'free'. */
/* Applies to: functions. Cannot be used on inline functions. */
#ifndef _GL_ATTRIBUTE_DEALLOC_FREE
# if defined __cplusplus && defined __GNUC__ && !defined __clang__
/* Work around GCC bug */
# define _GL_ATTRIBUTE_DEALLOC_FREE \
_GL_ATTRIBUTE_DEALLOC ((void (*) (void *)) free, 1)
# else
# define _GL_ATTRIBUTE_DEALLOC_FREE \
_GL_ATTRIBUTE_DEALLOC (free, 1)
# endif
#endif
/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
allocated memory. */
/* Applies to: functions. */
#ifndef _GL_ATTRIBUTE_MALLOC
# if __GNUC__ >= 3 || defined __clang__
# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# else
# define _GL_ATTRIBUTE_MALLOC
# endif
#endif
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The attribute __pure__ was added in gcc 2.96. */
#ifndef _GL_ATTRIBUTE_PURE
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__
# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
# define _GL_ATTRIBUTE_PURE /* empty */
# endif
#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. */
/* Define wint_t and WEOF. (Also done in wctype.in.h.) */
#if !@HAVE_WINT_T@ && !defined wint_t
# define wint_t int
# ifndef WEOF
# define WEOF -1
# endif
#else
/* mingw and MSVC define wint_t as 'unsigned short' in or
. This is too small: ISO C 99 section 7.24.1.(2) says that
wint_t must be "unchanged by default argument promotions". Override it. */
# if @GNULIBHEADERS_OVERRIDE_WINT_T@
# if !GNULIB_defined_wint_t
# if @HAVE_CRTDEFS_H@
# include
# else
# include
# endif
typedef unsigned int rpl_wint_t;
# undef wint_t
# define wint_t rpl_wint_t
# define GNULIB_defined_wint_t 1
# endif
# endif
# ifndef WEOF
# define WEOF ((wint_t) -1)
# endif
#endif
/* Override mbstate_t if it is too small.
On IRIX 6.5, sizeof (mbstate_t) == 1, which is not sufficient for
implementing mbrtowc for encodings like UTF-8.
On AIX and MSVC, mbrtowc needs to be overridden, but mbstate_t exists and is
large enough and overriding it would cause problems in C++ mode. */
#if !(((defined _WIN32 && !defined __CYGWIN__) || @HAVE_MBSINIT@) && @HAVE_MBRTOWC@) || @REPLACE_MBSTATE_T@
# if !GNULIB_defined_mbstate_t
# if !(defined _AIX || defined _MSC_VER)
typedef int rpl_mbstate_t;
# undef mbstate_t
# define mbstate_t rpl_mbstate_t
# endif
# define GNULIB_defined_mbstate_t 1
# endif
#endif
/* Make _GL_ATTRIBUTE_DEALLOC_FREE work, even though may not have
been included yet. */
#if @GNULIB_FREE_POSIX@
# if (@REPLACE_FREE@ && !defined free \
&& !(defined __cplusplus && defined GNULIB_NAMESPACE))
/* We can't do '#define free rpl_free' here. */
_GL_EXTERN_C void rpl_free (void *);
# undef _GL_ATTRIBUTE_DEALLOC_FREE
# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1)
# else
# if defined _MSC_VER && !defined free
_GL_EXTERN_C
# if defined _DLL
__declspec (dllimport)
# endif
void __cdecl free (void *);
# else
# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
_GL_EXTERN_C void free (void *) throw ();
# else
_GL_EXTERN_C void free (void *);
# endif
# endif
# endif
#else
# if defined _MSC_VER && !defined free
_GL_EXTERN_C
# if defined _DLL
__declspec (dllimport)
# endif
void __cdecl free (void *);
# else
# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
_GL_EXTERN_C void free (void *) throw ();
# else
_GL_EXTERN_C void free (void *);
# endif
# endif
#endif
/* Convert a single-byte character to a wide character. */
#if @GNULIB_BTOWC@
# if @REPLACE_BTOWC@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef btowc
# define btowc rpl_btowc
# endif
_GL_FUNCDECL_RPL (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE);
_GL_CXXALIAS_RPL (btowc, wint_t, (int c));
# else
# if !@HAVE_BTOWC@
_GL_FUNCDECL_SYS (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE);
# endif
/* Need to cast, because on mingw, the return type is 'unsigned short'. */
_GL_CXXALIAS_SYS_CAST (btowc, wint_t, (int c));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (btowc);
# endif
#elif defined GNULIB_POSIXCHECK
# undef btowc
# if HAVE_RAW_DECL_BTOWC
_GL_WARN_ON_USE (btowc, "btowc is unportable - "
"use gnulib module btowc for portability");
# endif
#endif
/* Convert a wide character to a single-byte character. */
#if @GNULIB_WCTOB@
# if @REPLACE_WCTOB@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wctob
# define wctob rpl_wctob
# endif
_GL_FUNCDECL_RPL (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE);
_GL_CXXALIAS_RPL (wctob, int, (wint_t wc));
# else
# if !defined wctob && !@HAVE_DECL_WCTOB@
/* wctob is provided by gnulib, or wctob exists but is not declared. */
_GL_FUNCDECL_SYS (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wctob, int, (wint_t wc));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wctob);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wctob
# if HAVE_RAW_DECL_WCTOB
_GL_WARN_ON_USE (wctob, "wctob is unportable - "
"use gnulib module wctob for portability");
# endif
#endif
/* Test whether *PS is in the initial state. */
#if @GNULIB_MBSINIT@
# if @REPLACE_MBSINIT@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef mbsinit
# define mbsinit rpl_mbsinit
# endif
_GL_FUNCDECL_RPL (mbsinit, int, (const mbstate_t *ps));
_GL_CXXALIAS_RPL (mbsinit, int, (const mbstate_t *ps));
# else
# if !@HAVE_MBSINIT@
_GL_FUNCDECL_SYS (mbsinit, int, (const mbstate_t *ps));
# endif
_GL_CXXALIAS_SYS (mbsinit, int, (const mbstate_t *ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbsinit);
# endif
#elif defined GNULIB_POSIXCHECK
# undef mbsinit
# if HAVE_RAW_DECL_MBSINIT
_GL_WARN_ON_USE (mbsinit, "mbsinit is unportable - "
"use gnulib module mbsinit for portability");
# endif
#endif
/* Convert a multibyte character to a wide character. */
#if @GNULIB_MBRTOWC@
# if @REPLACE_MBRTOWC@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef mbrtowc
# define mbrtowc rpl_mbrtowc
# endif
_GL_FUNCDECL_RPL (mbrtowc, size_t,
(wchar_t *restrict pwc, const char *restrict s, size_t n,
mbstate_t *restrict ps));
_GL_CXXALIAS_RPL (mbrtowc, size_t,
(wchar_t *restrict pwc, const char *restrict s, size_t n,
mbstate_t *restrict ps));
# else
# if !@HAVE_MBRTOWC@
_GL_FUNCDECL_SYS (mbrtowc, size_t,
(wchar_t *restrict pwc, const char *restrict s, size_t n,
mbstate_t *restrict ps));
# endif
_GL_CXXALIAS_SYS (mbrtowc, size_t,
(wchar_t *restrict pwc, const char *restrict s, size_t n,
mbstate_t *restrict ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbrtowc);
# endif
#elif defined GNULIB_POSIXCHECK
# undef mbrtowc
# if HAVE_RAW_DECL_MBRTOWC
_GL_WARN_ON_USE (mbrtowc, "mbrtowc is unportable - "
"use gnulib module mbrtowc for portability");
# endif
#endif
/* Recognize a multibyte character. */
#if @GNULIB_MBRLEN@
# if @REPLACE_MBRLEN@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef mbrlen
# define mbrlen rpl_mbrlen
# endif
_GL_FUNCDECL_RPL (mbrlen, size_t,
(const char *restrict s, size_t n, mbstate_t *restrict ps));
_GL_CXXALIAS_RPL (mbrlen, size_t,
(const char *restrict s, size_t n, mbstate_t *restrict ps));
# else
# if !@HAVE_MBRLEN@
_GL_FUNCDECL_SYS (mbrlen, size_t,
(const char *restrict s, size_t n, mbstate_t *restrict ps));
# endif
_GL_CXXALIAS_SYS (mbrlen, size_t,
(const char *restrict s, size_t n, mbstate_t *restrict ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbrlen);
# endif
#elif defined GNULIB_POSIXCHECK
# undef mbrlen
# if HAVE_RAW_DECL_MBRLEN
_GL_WARN_ON_USE (mbrlen, "mbrlen is unportable - "
"use gnulib module mbrlen for portability");
# endif
#endif
/* Convert a string to a wide string. */
#if @GNULIB_MBSRTOWCS@
# if @REPLACE_MBSRTOWCS@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef mbsrtowcs
# define mbsrtowcs rpl_mbsrtowcs
# endif
_GL_FUNCDECL_RPL (mbsrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (mbsrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t len,
mbstate_t *restrict ps));
# else
# if !@HAVE_MBSRTOWCS@
_GL_FUNCDECL_SYS (mbsrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
# endif
_GL_CXXALIAS_SYS (mbsrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t len,
mbstate_t *restrict ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbsrtowcs);
# endif
#elif defined GNULIB_POSIXCHECK
# undef mbsrtowcs
# if HAVE_RAW_DECL_MBSRTOWCS
_GL_WARN_ON_USE (mbsrtowcs, "mbsrtowcs is unportable - "
"use gnulib module mbsrtowcs for portability");
# endif
#endif
/* Convert a string to a wide string. */
#if @GNULIB_MBSNRTOWCS@
# if @REPLACE_MBSNRTOWCS@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef mbsnrtowcs
# define mbsnrtowcs rpl_mbsnrtowcs
# endif
_GL_FUNCDECL_RPL (mbsnrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t srclen, size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (mbsnrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t srclen, size_t len,
mbstate_t *restrict ps));
# else
# if !@HAVE_MBSNRTOWCS@
_GL_FUNCDECL_SYS (mbsnrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t srclen, size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
# endif
_GL_CXXALIAS_SYS (mbsnrtowcs, size_t,
(wchar_t *restrict dest,
const char **restrict srcp, size_t srclen, size_t len,
mbstate_t *restrict ps));
# endif
_GL_CXXALIASWARN (mbsnrtowcs);
#elif defined GNULIB_POSIXCHECK
# undef mbsnrtowcs
# if HAVE_RAW_DECL_MBSNRTOWCS
_GL_WARN_ON_USE (mbsnrtowcs, "mbsnrtowcs is unportable - "
"use gnulib module mbsnrtowcs for portability");
# endif
#endif
/* Convert a wide character to a multibyte character. */
#if @GNULIB_WCRTOMB@
# if @REPLACE_WCRTOMB@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcrtomb
# define wcrtomb rpl_wcrtomb
# endif
_GL_FUNCDECL_RPL (wcrtomb, size_t,
(char *restrict s, wchar_t wc, mbstate_t *restrict ps));
_GL_CXXALIAS_RPL (wcrtomb, size_t,
(char *restrict s, wchar_t wc, mbstate_t *restrict ps));
# else
# if !@HAVE_WCRTOMB@
_GL_FUNCDECL_SYS (wcrtomb, size_t,
(char *restrict s, wchar_t wc, mbstate_t *restrict ps));
# endif
_GL_CXXALIAS_SYS (wcrtomb, size_t,
(char *restrict s, wchar_t wc, mbstate_t *restrict ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcrtomb);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcrtomb
# if HAVE_RAW_DECL_WCRTOMB
_GL_WARN_ON_USE (wcrtomb, "wcrtomb is unportable - "
"use gnulib module wcrtomb for portability");
# endif
#endif
/* Convert a wide string to a string. */
#if @GNULIB_WCSRTOMBS@
# if @REPLACE_WCSRTOMBS@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcsrtombs
# define wcsrtombs rpl_wcsrtombs
# endif
_GL_FUNCDECL_RPL (wcsrtombs, size_t,
(char *restrict dest, const wchar_t **restrict srcp,
size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (wcsrtombs, size_t,
(char *restrict dest, const wchar_t **restrict srcp,
size_t len,
mbstate_t *restrict ps));
# else
# if !@HAVE_WCSRTOMBS@
_GL_FUNCDECL_SYS (wcsrtombs, size_t,
(char *restrict dest, const wchar_t **restrict srcp,
size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
# endif
_GL_CXXALIAS_SYS (wcsrtombs, size_t,
(char *restrict dest, const wchar_t **restrict srcp,
size_t len,
mbstate_t *restrict ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsrtombs);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsrtombs
# if HAVE_RAW_DECL_WCSRTOMBS
_GL_WARN_ON_USE (wcsrtombs, "wcsrtombs is unportable - "
"use gnulib module wcsrtombs for portability");
# endif
#endif
/* Convert a wide string to a string. */
#if @GNULIB_WCSNRTOMBS@
# if @REPLACE_WCSNRTOMBS@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcsnrtombs
# define wcsnrtombs rpl_wcsnrtombs
# endif
_GL_FUNCDECL_RPL (wcsnrtombs, size_t,
(char *restrict dest,
const wchar_t **restrict srcp, size_t srclen,
size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (wcsnrtombs, size_t,
(char *restrict dest,
const wchar_t **restrict srcp, size_t srclen,
size_t len,
mbstate_t *restrict ps));
# else
# if !@HAVE_WCSNRTOMBS@ || (defined __cplusplus && defined __sun)
_GL_FUNCDECL_SYS (wcsnrtombs, size_t,
(char *restrict dest,
const wchar_t **restrict srcp, size_t srclen,
size_t len,
mbstate_t *restrict ps)
_GL_ARG_NONNULL ((2)));
# endif
_GL_CXXALIAS_SYS (wcsnrtombs, size_t,
(char *restrict dest,
const wchar_t **restrict srcp, size_t srclen,
size_t len,
mbstate_t *restrict ps));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsnrtombs);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsnrtombs
# if HAVE_RAW_DECL_WCSNRTOMBS
_GL_WARN_ON_USE (wcsnrtombs, "wcsnrtombs is unportable - "
"use gnulib module wcsnrtombs for portability");
# endif
#endif
/* Return the number of screen columns needed for WC. */
#if @GNULIB_WCWIDTH@
# if @REPLACE_WCWIDTH@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcwidth
# define wcwidth rpl_wcwidth
# endif
_GL_FUNCDECL_RPL (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE);
_GL_CXXALIAS_RPL (wcwidth, int, (wchar_t));
# else
# if !@HAVE_DECL_WCWIDTH@
/* wcwidth exists but is not declared. */
_GL_FUNCDECL_SYS (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcwidth, int, (wchar_t));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcwidth);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcwidth
# if HAVE_RAW_DECL_WCWIDTH
_GL_WARN_ON_USE (wcwidth, "wcwidth is unportable - "
"use gnulib module wcwidth for portability");
# endif
#endif
/* Search N wide characters of S for C. */
#if @GNULIB_WMEMCHR@
# if !@HAVE_WMEMCHR@
_GL_FUNCDECL_SYS (wmemchr, wchar_t *, (const wchar_t *s, wchar_t c, size_t n)
_GL_ATTRIBUTE_PURE);
# endif
/* On some systems, this function is defined as an overloaded function:
extern "C++" {
const wchar_t * std::wmemchr (const wchar_t *, wchar_t, size_t);
wchar_t * std::wmemchr (wchar_t *, wchar_t, size_t);
} */
_GL_CXXALIAS_SYS_CAST2 (wmemchr,
wchar_t *, (const wchar_t *, wchar_t, size_t),
const wchar_t *, (const wchar_t *, wchar_t, size_t));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wmemchr, wchar_t *, (wchar_t *s, wchar_t c, size_t n));
_GL_CXXALIASWARN1 (wmemchr, const wchar_t *,
(const wchar_t *s, wchar_t c, size_t n));
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemchr);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemchr
# if HAVE_RAW_DECL_WMEMCHR
_GL_WARN_ON_USE (wmemchr, "wmemchr is unportable - "
"use gnulib module wmemchr for portability");
# endif
#endif
/* Compare N wide characters of S1 and S2. */
#if @GNULIB_WMEMCMP@
# if !@HAVE_WMEMCMP@
_GL_FUNCDECL_SYS (wmemcmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wmemcmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemcmp);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemcmp
# if HAVE_RAW_DECL_WMEMCMP
_GL_WARN_ON_USE (wmemcmp, "wmemcmp is unportable - "
"use gnulib module wmemcmp for portability");
# endif
#endif
/* Copy N wide characters of SRC to DEST. */
#if @GNULIB_WMEMCPY@
# if !@HAVE_WMEMCPY@
_GL_FUNCDECL_SYS (wmemcpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# endif
_GL_CXXALIAS_SYS (wmemcpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemcpy);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemcpy
# if HAVE_RAW_DECL_WMEMCPY
_GL_WARN_ON_USE (wmemcpy, "wmemcpy is unportable - "
"use gnulib module wmemcpy for portability");
# endif
#endif
/* Copy N wide characters of SRC to DEST, guaranteeing correct behavior for
overlapping memory areas. */
#if @GNULIB_WMEMMOVE@
# if !@HAVE_WMEMMOVE@
_GL_FUNCDECL_SYS (wmemmove, wchar_t *,
(wchar_t *dest, const wchar_t *src, size_t n));
# endif
_GL_CXXALIAS_SYS (wmemmove, wchar_t *,
(wchar_t *dest, const wchar_t *src, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemmove);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemmove
# if HAVE_RAW_DECL_WMEMMOVE
_GL_WARN_ON_USE (wmemmove, "wmemmove is unportable - "
"use gnulib module wmemmove for portability");
# endif
#endif
/* Copy N wide characters of SRC to DEST.
Return pointer to wide characters after the last written wide character. */
#if @GNULIB_WMEMPCPY@
# if !@HAVE_WMEMPCPY@
_GL_FUNCDECL_SYS (wmempcpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# endif
_GL_CXXALIAS_SYS (wmempcpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmempcpy);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wmempcpy
# if HAVE_RAW_DECL_WMEMPCPY
_GL_WARN_ON_USE (wmempcpy, "wmempcpy is unportable - "
"use gnulib module wmempcpy for portability");
# endif
#endif
/* Set N wide characters of S to C. */
#if @GNULIB_WMEMSET@
# if !@HAVE_WMEMSET@
_GL_FUNCDECL_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n));
# endif
_GL_CXXALIAS_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemset);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemset
# if HAVE_RAW_DECL_WMEMSET
_GL_WARN_ON_USE (wmemset, "wmemset is unportable - "
"use gnulib module wmemset for portability");
# endif
#endif
/* Return the number of wide characters in S. */
#if @GNULIB_WCSLEN@
# if !@HAVE_WCSLEN@
_GL_FUNCDECL_SYS (wcslen, size_t, (const wchar_t *s) _GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcslen, size_t, (const wchar_t *s));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcslen);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcslen
# if HAVE_RAW_DECL_WCSLEN
_GL_WARN_ON_USE (wcslen, "wcslen is unportable - "
"use gnulib module wcslen for portability");
# endif
#endif
/* Return the number of wide characters in S, but at most MAXLEN. */
#if @GNULIB_WCSNLEN@
/* On Solaris 11.3, the header files declare the function in the std::
namespace, not in the global namespace. So, force a declaration in
the global namespace. */
# if !@HAVE_WCSNLEN@ || (defined __sun && defined __cplusplus)
_GL_FUNCDECL_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen));
_GL_CXXALIASWARN (wcsnlen);
#elif defined GNULIB_POSIXCHECK
# undef wcsnlen
# if HAVE_RAW_DECL_WCSNLEN
_GL_WARN_ON_USE (wcsnlen, "wcsnlen is unportable - "
"use gnulib module wcsnlen for portability");
# endif
#endif
/* Copy SRC to DEST. */
#if @GNULIB_WCSCPY@
# if !@HAVE_WCSCPY@
_GL_FUNCDECL_SYS (wcscpy, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src));
# endif
_GL_CXXALIAS_SYS (wcscpy, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscpy);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscpy
# if HAVE_RAW_DECL_WCSCPY
_GL_WARN_ON_USE (wcscpy, "wcscpy is unportable - "
"use gnulib module wcscpy for portability");
# endif
#endif
/* Copy SRC to DEST, returning the address of the terminating L'\0' in DEST. */
#if @GNULIB_WCPCPY@
/* On Solaris 11.3, the header files declare the function in the std::
namespace, not in the global namespace. So, force a declaration in
the global namespace. */
# if !@HAVE_WCPCPY@ || (defined __sun && defined __cplusplus)
_GL_FUNCDECL_SYS (wcpcpy, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src));
# endif
_GL_CXXALIAS_SYS (wcpcpy, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src));
_GL_CXXALIASWARN (wcpcpy);
#elif defined GNULIB_POSIXCHECK
# undef wcpcpy
# if HAVE_RAW_DECL_WCPCPY
_GL_WARN_ON_USE (wcpcpy, "wcpcpy is unportable - "
"use gnulib module wcpcpy for portability");
# endif
#endif
/* Copy no more than N wide characters of SRC to DEST. */
#if @GNULIB_WCSNCPY@
# if !@HAVE_WCSNCPY@
_GL_FUNCDECL_SYS (wcsncpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# endif
_GL_CXXALIAS_SYS (wcsncpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsncpy);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsncpy
# if HAVE_RAW_DECL_WCSNCPY
_GL_WARN_ON_USE (wcsncpy, "wcsncpy is unportable - "
"use gnulib module wcsncpy for portability");
# endif
#endif
/* Copy no more than N characters of SRC to DEST, returning the address of
the last character written into DEST. */
#if @GNULIB_WCPNCPY@
/* On Solaris 11.3, the header files declare the function in the std::
namespace, not in the global namespace. So, force a declaration in
the global namespace. */
# if !@HAVE_WCPNCPY@ || (defined __sun && defined __cplusplus)
_GL_FUNCDECL_SYS (wcpncpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
# endif
_GL_CXXALIAS_SYS (wcpncpy, wchar_t *,
(wchar_t *restrict dest,
const wchar_t *restrict src, size_t n));
_GL_CXXALIASWARN (wcpncpy);
#elif defined GNULIB_POSIXCHECK
# undef wcpncpy
# if HAVE_RAW_DECL_WCPNCPY
_GL_WARN_ON_USE (wcpncpy, "wcpncpy is unportable - "
"use gnulib module wcpncpy for portability");
# endif
#endif
/* Append SRC onto DEST. */
#if @GNULIB_WCSCAT@
# if !@HAVE_WCSCAT@
_GL_FUNCDECL_SYS (wcscat, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src));
# endif
_GL_CXXALIAS_SYS (wcscat, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscat);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscat
# if HAVE_RAW_DECL_WCSCAT
_GL_WARN_ON_USE (wcscat, "wcscat is unportable - "
"use gnulib module wcscat for portability");
# endif
#endif
/* Append no more than N wide characters of SRC onto DEST. */
#if @GNULIB_WCSNCAT@
# if !@HAVE_WCSNCAT@
_GL_FUNCDECL_SYS (wcsncat, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src,
size_t n));
# endif
_GL_CXXALIAS_SYS (wcsncat, wchar_t *,
(wchar_t *restrict dest, const wchar_t *restrict src,
size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsncat);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsncat
# if HAVE_RAW_DECL_WCSNCAT
_GL_WARN_ON_USE (wcsncat, "wcsncat is unportable - "
"use gnulib module wcsncat for portability");
# endif
#endif
/* Compare S1 and S2. */
#if @GNULIB_WCSCMP@
# if !@HAVE_WCSCMP@
_GL_FUNCDECL_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscmp);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscmp
# if HAVE_RAW_DECL_WCSCMP
_GL_WARN_ON_USE (wcscmp, "wcscmp is unportable - "
"use gnulib module wcscmp for portability");
# endif
#endif
/* Compare no more than N wide characters of S1 and S2. */
#if @GNULIB_WCSNCMP@
# if !@HAVE_WCSNCMP@
_GL_FUNCDECL_SYS (wcsncmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcsncmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsncmp);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsncmp
# if HAVE_RAW_DECL_WCSNCMP
_GL_WARN_ON_USE (wcsncmp, "wcsncmp is unportable - "
"use gnulib module wcsncmp for portability");
# endif
#endif
/* Compare S1 and S2, ignoring case. */
#if @GNULIB_WCSCASECMP@
/* On Solaris 11.3, the header files declare the function in the std::
namespace, not in the global namespace. So, force a declaration in
the global namespace. */
# if !@HAVE_WCSCASECMP@ || (defined __sun && defined __cplusplus)
_GL_FUNCDECL_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2));
_GL_CXXALIASWARN (wcscasecmp);
#elif defined GNULIB_POSIXCHECK
# undef wcscasecmp
# if HAVE_RAW_DECL_WCSCASECMP
_GL_WARN_ON_USE (wcscasecmp, "wcscasecmp is unportable - "
"use gnulib module wcscasecmp for portability");
# endif
#endif
/* Compare no more than N chars of S1 and S2, ignoring case. */
#if @GNULIB_WCSNCASECMP@
/* On Solaris 11.3, the header files declare the function in the std::
namespace, not in the global namespace. So, force a declaration in
the global namespace. */
# if !@HAVE_WCSNCASECMP@ || (defined __sun && defined __cplusplus)
_GL_FUNCDECL_SYS (wcsncasecmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcsncasecmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n));
_GL_CXXALIASWARN (wcsncasecmp);
#elif defined GNULIB_POSIXCHECK
# undef wcsncasecmp
# if HAVE_RAW_DECL_WCSNCASECMP
_GL_WARN_ON_USE (wcsncasecmp, "wcsncasecmp is unportable - "
"use gnulib module wcsncasecmp for portability");
# endif
#endif
/* Compare S1 and S2, both interpreted as appropriate to the LC_COLLATE
category of the current locale. */
#if @GNULIB_WCSCOLL@
# if !@HAVE_WCSCOLL@
_GL_FUNCDECL_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2));
# endif
_GL_CXXALIAS_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscoll);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscoll
# if HAVE_RAW_DECL_WCSCOLL
_GL_WARN_ON_USE (wcscoll, "wcscoll is unportable - "
"use gnulib module wcscoll for portability");
# endif
#endif
/* Transform S2 into array pointed to by S1 such that if wcscmp is applied
to two transformed strings the result is the as applying 'wcscoll' to the
original strings. */
#if @GNULIB_WCSXFRM@
# if !@HAVE_WCSXFRM@
_GL_FUNCDECL_SYS (wcsxfrm, size_t,
(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n));
# endif
_GL_CXXALIAS_SYS (wcsxfrm, size_t,
(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsxfrm);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsxfrm
# if HAVE_RAW_DECL_WCSXFRM
_GL_WARN_ON_USE (wcsxfrm, "wcsxfrm is unportable - "
"use gnulib module wcsxfrm for portability");
# endif
#endif
/* Duplicate S, returning an identical malloc'd string. */
#if @GNULIB_WCSDUP@
# if defined _WIN32 && !defined __CYGWIN__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcsdup
# define wcsdup _wcsdup
# endif
_GL_CXXALIAS_MDA (wcsdup, wchar_t *, (const wchar_t *s));
# else
/* On Solaris 11.3, the header files declare the function in the std::
namespace, not in the global namespace. So, force a declaration in
the global namespace. */
# if !@HAVE_WCSDUP@ || (defined __sun && defined __cplusplus) || __GNUC__ >= 11
_GL_FUNCDECL_SYS (wcsdup, wchar_t *,
(const wchar_t *s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# endif
_GL_CXXALIAS_SYS (wcsdup, wchar_t *, (const wchar_t *s));
# endif
_GL_CXXALIASWARN (wcsdup);
#else
# if __GNUC__ >= 11 && !defined wcsdup
/* For -Wmismatched-dealloc: Associate wcsdup with free or rpl_free. */
_GL_FUNCDECL_SYS (wcsdup, wchar_t *,
(const wchar_t *s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# endif
# if defined GNULIB_POSIXCHECK
# undef wcsdup
# if HAVE_RAW_DECL_WCSDUP
_GL_WARN_ON_USE (wcsdup, "wcsdup is unportable - "
"use gnulib module wcsdup for portability");
# endif
# elif @GNULIB_MDA_WCSDUP@
/* On native Windows, map 'wcsdup' to '_wcsdup', so that -loldnames is not
required. In C++ with GNULIB_NAMESPACE, avoid differences between
platforms by defining GNULIB_NAMESPACE::wcsdup always. */
# if defined _WIN32 && !defined __CYGWIN__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcsdup
# define wcsdup _wcsdup
# endif
_GL_CXXALIAS_MDA (wcsdup, wchar_t *, (const wchar_t *s));
# else
_GL_FUNCDECL_SYS (wcsdup, wchar_t *,
(const wchar_t *s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# if @HAVE_DECL_WCSDUP@
_GL_CXXALIAS_SYS (wcsdup, wchar_t *, (const wchar_t *s));
# endif
# endif
# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_WCSDUP@
_GL_CXXALIASWARN (wcsdup);
# endif
# endif
#endif
/* Find the first occurrence of WC in WCS. */
#if @GNULIB_WCSCHR@
# if !@HAVE_WCSCHR@
_GL_FUNCDECL_SYS (wcschr, wchar_t *, (const wchar_t *wcs, wchar_t wc)
_GL_ATTRIBUTE_PURE);
# endif
/* On some systems, this function is defined as an overloaded function:
extern "C++" {
const wchar_t * std::wcschr (const wchar_t *, wchar_t);
wchar_t * std::wcschr (wchar_t *, wchar_t);
} */
_GL_CXXALIAS_SYS_CAST2 (wcschr,
wchar_t *, (const wchar_t *, wchar_t),
const wchar_t *, (const wchar_t *, wchar_t));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wcschr, wchar_t *, (wchar_t *wcs, wchar_t wc));
_GL_CXXALIASWARN1 (wcschr, const wchar_t *, (const wchar_t *wcs, wchar_t wc));
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcschr);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcschr
# if HAVE_RAW_DECL_WCSCHR
_GL_WARN_ON_USE (wcschr, "wcschr is unportable - "
"use gnulib module wcschr for portability");
# endif
#endif
/* Find the last occurrence of WC in WCS. */
#if @GNULIB_WCSRCHR@
# if !@HAVE_WCSRCHR@
_GL_FUNCDECL_SYS (wcsrchr, wchar_t *, (const wchar_t *wcs, wchar_t wc)
_GL_ATTRIBUTE_PURE);
# endif
/* On some systems, this function is defined as an overloaded function:
extern "C++" {
const wchar_t * std::wcsrchr (const wchar_t *, wchar_t);
wchar_t * std::wcsrchr (wchar_t *, wchar_t);
} */
_GL_CXXALIAS_SYS_CAST2 (wcsrchr,
wchar_t *, (const wchar_t *, wchar_t),
const wchar_t *, (const wchar_t *, wchar_t));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wcsrchr, wchar_t *, (wchar_t *wcs, wchar_t wc));
_GL_CXXALIASWARN1 (wcsrchr, const wchar_t *, (const wchar_t *wcs, wchar_t wc));
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsrchr);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsrchr
# if HAVE_RAW_DECL_WCSRCHR
_GL_WARN_ON_USE (wcsrchr, "wcsrchr is unportable - "
"use gnulib module wcsrchr for portability");
# endif
#endif
/* Return the length of the initial segmet of WCS which consists entirely
of wide characters not in REJECT. */
#if @GNULIB_WCSCSPN@
# if !@HAVE_WCSCSPN@
_GL_FUNCDECL_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscspn);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscspn
# if HAVE_RAW_DECL_WCSCSPN
_GL_WARN_ON_USE (wcscspn, "wcscspn is unportable - "
"use gnulib module wcscspn for portability");
# endif
#endif
/* Return the length of the initial segmet of WCS which consists entirely
of wide characters in ACCEPT. */
#if @GNULIB_WCSSPN@
# if !@HAVE_WCSSPN@
_GL_FUNCDECL_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept));
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsspn);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsspn
# if HAVE_RAW_DECL_WCSSPN
_GL_WARN_ON_USE (wcsspn, "wcsspn is unportable - "
"use gnulib module wcsspn for portability");
# endif
#endif
/* Find the first occurrence in WCS of any character in ACCEPT. */
#if @GNULIB_WCSPBRK@
# if !@HAVE_WCSPBRK@
_GL_FUNCDECL_SYS (wcspbrk, wchar_t *,
(const wchar_t *wcs, const wchar_t *accept)
_GL_ATTRIBUTE_PURE);
# endif
/* On some systems, this function is defined as an overloaded function:
extern "C++" {
const wchar_t * std::wcspbrk (const wchar_t *, const wchar_t *);
wchar_t * std::wcspbrk (wchar_t *, const wchar_t *);
} */
_GL_CXXALIAS_SYS_CAST2 (wcspbrk,
wchar_t *, (const wchar_t *, const wchar_t *),
const wchar_t *, (const wchar_t *, const wchar_t *));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wcspbrk, wchar_t *,
(wchar_t *wcs, const wchar_t *accept));
_GL_CXXALIASWARN1 (wcspbrk, const wchar_t *,
(const wchar_t *wcs, const wchar_t *accept));
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcspbrk);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcspbrk
# if HAVE_RAW_DECL_WCSPBRK
_GL_WARN_ON_USE (wcspbrk, "wcspbrk is unportable - "
"use gnulib module wcspbrk for portability");
# endif
#endif
/* Find the first occurrence of NEEDLE in HAYSTACK. */
#if @GNULIB_WCSSTR@
# if !@HAVE_WCSSTR@
_GL_FUNCDECL_SYS (wcsstr, wchar_t *,
(const wchar_t *restrict haystack,
const wchar_t *restrict needle)
_GL_ATTRIBUTE_PURE);
# endif
/* On some systems, this function is defined as an overloaded function:
extern "C++" {
const wchar_t * std::wcsstr (const wchar_t *, const wchar_t *);
wchar_t * std::wcsstr (wchar_t *, const wchar_t *);
} */
_GL_CXXALIAS_SYS_CAST2 (wcsstr,
wchar_t *,
(const wchar_t *restrict, const wchar_t *restrict),
const wchar_t *,
(const wchar_t *restrict, const wchar_t *restrict));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wcsstr, wchar_t *,
(wchar_t *restrict haystack,
const wchar_t *restrict needle));
_GL_CXXALIASWARN1 (wcsstr, const wchar_t *,
(const wchar_t *restrict haystack,
const wchar_t *restrict needle));
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsstr);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsstr
# if HAVE_RAW_DECL_WCSSTR
_GL_WARN_ON_USE (wcsstr, "wcsstr is unportable - "
"use gnulib module wcsstr for portability");
# endif
#endif
/* Divide WCS into tokens separated by characters in DELIM. */
#if @GNULIB_WCSTOK@
# if @REPLACE_WCSTOK@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcstok
# define wcstok rpl_wcstok
# endif
_GL_FUNCDECL_RPL (wcstok, wchar_t *,
(wchar_t *restrict wcs, const wchar_t *restrict delim,
wchar_t **restrict ptr));
_GL_CXXALIAS_RPL (wcstok, wchar_t *,
(wchar_t *restrict wcs, const wchar_t *restrict delim,
wchar_t **restrict ptr));
# else
# if !@HAVE_WCSTOK@
_GL_FUNCDECL_SYS (wcstok, wchar_t *,
(wchar_t *restrict wcs, const wchar_t *restrict delim,
wchar_t **restrict ptr));
# endif
_GL_CXXALIAS_SYS (wcstok, wchar_t *,
(wchar_t *restrict wcs, const wchar_t *restrict delim,
wchar_t **restrict ptr));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcstok);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcstok
# if HAVE_RAW_DECL_WCSTOK
_GL_WARN_ON_USE (wcstok, "wcstok is unportable - "
"use gnulib module wcstok for portability");
# endif
#endif
/* Determine number of column positions required for first N wide
characters (or fewer if S ends before this) in S. */
#if @GNULIB_WCSWIDTH@
# if @REPLACE_WCSWIDTH@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcswidth
# define wcswidth rpl_wcswidth
# endif
_GL_FUNCDECL_RPL (wcswidth, int, (const wchar_t *s, size_t n)
_GL_ATTRIBUTE_PURE);
_GL_CXXALIAS_RPL (wcswidth, int, (const wchar_t *s, size_t n));
# else
# if !@HAVE_WCSWIDTH@
_GL_FUNCDECL_SYS (wcswidth, int, (const wchar_t *s, size_t n)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcswidth, int, (const wchar_t *s, size_t n));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcswidth);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcswidth
# if HAVE_RAW_DECL_WCSWIDTH
_GL_WARN_ON_USE (wcswidth, "wcswidth is unportable - "
"use gnulib module wcswidth for portability");
# endif
#endif
/* Convert *TP to a date and time wide string. See
. */
#if @GNULIB_WCSFTIME@
# if @REPLACE_WCSFTIME@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef wcsftime
# define wcsftime rpl_wcsftime
# endif
_GL_FUNCDECL_RPL (wcsftime, size_t,
(wchar_t *restrict __buf, size_t __bufsize,
const wchar_t *restrict __fmt,
const struct tm *restrict __tp)
_GL_ARG_NONNULL ((1, 3, 4)));
_GL_CXXALIAS_RPL (wcsftime, size_t,
(wchar_t *restrict __buf, size_t __bufsize,
const wchar_t *restrict __fmt,
const struct tm *restrict __tp));
# else
# if !@HAVE_WCSFTIME@
_GL_FUNCDECL_SYS (wcsftime, size_t,
(wchar_t *restrict __buf, size_t __bufsize,
const wchar_t *restrict __fmt,
const struct tm *restrict __tp)
_GL_ARG_NONNULL ((1, 3, 4)));
# endif
_GL_CXXALIAS_SYS (wcsftime, size_t,
(wchar_t *restrict __buf, size_t __bufsize,
const wchar_t *restrict __fmt,
const struct tm *restrict __tp));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsftime);
# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsftime
# if HAVE_RAW_DECL_WCSFTIME
_GL_WARN_ON_USE (wcsftime, "wcsftime is unportable - "
"use gnulib module wcsftime for portability");
# endif
#endif
#endif /* _@GUARD_PREFIX@_WCHAR_H */
#endif /* _@GUARD_PREFIX@_WCHAR_H */
#endif
recode-3.7.14/lib/canonicalize-lgpl.c 0000644 0001750 0001750 00000034415 14366047013 014310 0000000 0000000 /* Return the canonical absolute name of a given file.
Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
. */
#ifndef _LIBC
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the name == NULL test below. */
# define _GL_ARG_NONNULL(params)
# include
#endif
/* Specification. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef _LIBC
# include
# define GCC_LINT 1
# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
#else
# define __canonicalize_file_name canonicalize_file_name
# define __realpath realpath
# define __strdup strdup
# include "pathmax.h"
# define __faccessat faccessat
# if defined _WIN32 && !defined __CYGWIN__
# define __getcwd _getcwd
# elif HAVE_GETCWD
# if IN_RELOCWRAPPER
/* When building the relocatable program wrapper, use the system's getcwd
function, not the gnulib override, otherwise we would get a link error.
*/
# undef getcwd
# endif
# if defined VMS && !defined getcwd
/* We want the directory in Unix syntax, not in VMS syntax.
The gnulib override of 'getcwd' takes 2 arguments; the original VMS
'getcwd' takes 3 arguments. */
# define __getcwd(buf, max) getcwd (buf, max, 0)
# else
# define __getcwd getcwd
# endif
# else
# define __getcwd(buf, max) getwd (buf)
# endif
# define __mempcpy mempcpy
# define __pathconf pathconf
# define __rawmemchr rawmemchr
# define __readlink readlink
# if IN_RELOCWRAPPER
/* When building the relocatable program wrapper, use the system's memmove
function, not the gnulib override, otherwise we would get a link error.
*/
# undef memmove
# endif
#endif
/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
#if defined GCC_LINT || defined lint
# define IF_LINT(Code) Code
#else
# define IF_LINT(Code) /* empty */
#endif
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
#endif
#if defined _LIBC || !FUNC_REALPATH_WORKS
/* Return true if FILE's existence can be shown, false (setting errno)
otherwise. Follow symbolic links. */
static bool
file_accessible (char const *file)
{
# if defined _LIBC || HAVE_FACCESSAT
return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
# else
struct stat st;
return stat (file, &st) == 0 || errno == EOVERFLOW;
# endif
}
/* True if concatenating END as a suffix to a file name means that the
code needs to check that the file name is that of a searchable
directory, since the canonicalize_filename_mode_stk code won't
check this later anyway when it checks an ordinary file name
component within END. END must either be empty, or start with a
slash. */
static bool _GL_ATTRIBUTE_PURE
suffix_requires_dir_check (char const *end)
{
/* If END does not start with a slash, the suffix is OK. */
while (ISSLASH (*end))
{
/* Two or more slashes act like a single slash. */
do
end++;
while (ISSLASH (*end));
switch (*end++)
{
default: return false; /* An ordinary file name component is OK. */
case '\0': return true; /* Trailing "/" is trouble. */
case '.': break; /* Possibly "." or "..". */
}
/* Trailing "/.", or "/.." even if not trailing, is trouble. */
if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
return true;
}
return false;
}
/* Append this to a file name to test whether it is a searchable directory.
On POSIX platforms "/" suffices, but "/./" is sometimes needed on
macOS 10.13 , and should also work on
platforms like AIX 7.2 that need at least "/.". */
# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
static char const dir_suffix[] = "/";
# else
static char const dir_suffix[] = "/./";
# endif
/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
DIREND points to the NUL byte at the end of the DIR string.
Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
static bool
dir_check (char *dir, char *dirend)
{
strcpy (dirend, dir_suffix);
return file_accessible (dir);
}
static idx_t
get_path_max (void)
{
# ifdef PATH_MAX
long int path_max = PATH_MAX;
# else
/* The caller invoked realpath with a null RESOLVED, even though
PATH_MAX is not defined as a constant. The glibc manual says
programs should not do this, and POSIX says the behavior is undefined.
Historically, glibc here used the result of pathconf, or 1024 if that
failed; stay consistent with this (dubious) historical practice. */
int err = errno;
long int path_max = __pathconf ("/", _PC_PATH_MAX);
__set_errno (err);
# endif
return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
}
/* Scratch buffers used by realpath_stk and managed by __realpath. */
struct realpath_bufs
{
struct scratch_buffer rname;
struct scratch_buffer extra;
struct scratch_buffer link;
};
static char *
realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs)
{
char *dest;
char const *start;
char const *end;
int num_links = 0;
if (name == NULL)
{
/* As per Single Unix Specification V2 we must return an error if
either parameter is a null pointer. We extend this to allow
the RESOLVED parameter to be NULL in case the we are expected to
allocate the room for the return value. */
__set_errno (EINVAL);
return NULL;
}
if (name[0] == '\0')
{
/* As per Single Unix Specification V2 we must return an error if
the name argument points to an empty string. */
__set_errno (ENOENT);
return NULL;
}
char *rname = bufs->rname.data;
bool end_in_extra_buffer = false;
bool failed = true;
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
and MS-DOS X:/foo/bar file names. */
idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
if (!IS_ABSOLUTE_FILE_NAME (name))
{
while (!__getcwd (bufs->rname.data, bufs->rname.length))
{
if (errno != ERANGE)
{
dest = rname;
goto error;
}
if (!scratch_buffer_grow (&bufs->rname))
return NULL;
rname = bufs->rname.data;
}
dest = __rawmemchr (rname, '\0');
start = name;
prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
}
else
{
dest = __mempcpy (rname, name, prefix_len);
*dest++ = '/';
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
if (prefix_len == 0 /* implies ISSLASH (name[0]) */
&& ISSLASH (name[1]) && !ISSLASH (name[2]))
*dest++ = '/';
*dest = '\0';
}
start = name + prefix_len;
}
for ( ; *start; start = end)
{
/* Skip sequence of multiple file name separators. */
while (ISSLASH (*start))
++start;
/* Find end of component. */
for (end = start; *end && !ISSLASH (*end); ++end)
/* Nothing. */;
/* Length of this file name component; it can be zero if a file
name ends in '/'. */
idx_t startlen = end - start;
if (startlen == 0)
break;
else if (startlen == 1 && start[0] == '.')
/* nothing */;
else if (startlen == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rname + prefix_len + 1)
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
}
else
{
if (!ISSLASH (dest[-1]))
*dest++ = '/';
while (rname + bufs->rname.length - dest
< startlen + sizeof dir_suffix)
{
idx_t dest_offset = dest - rname;
if (!scratch_buffer_grow_preserve (&bufs->rname))
return NULL;
rname = bufs->rname.data;
dest = rname + dest_offset;
}
dest = __mempcpy (dest, start, startlen);
*dest = '\0';
char *buf;
ssize_t n;
while (true)
{
buf = bufs->link.data;
idx_t bufsize = bufs->link.length;
n = __readlink (rname, buf, bufsize - 1);
if (n < bufsize - 1)
break;
if (!scratch_buffer_grow (&bufs->link))
return NULL;
}
if (0 <= n)
{
if (++num_links > __eloop_threshold ())
{
__set_errno (ELOOP);
goto error;
}
buf[n] = '\0';
char *extra_buf = bufs->extra.data;
idx_t end_idx IF_LINT (= 0);
if (end_in_extra_buffer)
end_idx = end - extra_buf;
size_t len = strlen (end);
if (INT_ADD_OVERFLOW (len, n))
{
__set_errno (ENOMEM);
return NULL;
}
while (bufs->extra.length <= len + n)
{
if (!scratch_buffer_grow_preserve (&bufs->extra))
return NULL;
extra_buf = bufs->extra.data;
}
if (end_in_extra_buffer)
end = extra_buf + end_idx;
/* Careful here, end may be a pointer into extra_buf... */
memmove (&extra_buf[n], end, len + 1);
name = end = memcpy (extra_buf, buf, n);
end_in_extra_buffer = true;
if (IS_ABSOLUTE_FILE_NAME (buf))
{
idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
dest = __mempcpy (rname, buf, pfxlen);
*dest++ = '/'; /* It's an absolute symlink */
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
*dest++ = '/';
*dest = '\0';
}
/* Install the new prefix to be in effect hereafter. */
prefix_len = pfxlen;
}
else
{
/* Back up to previous component, ignore if at root
already: */
if (dest > rname + prefix_len + 1)
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
dest++;
}
}
else if (! (suffix_requires_dir_check (end)
? dir_check (rname, dest)
: errno == EINVAL))
goto error;
}
}
if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
--dest;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
failed = false;
error:
*dest++ = '\0';
if (resolved != NULL)
{
/* Copy the full result on success or partial result if failure was due
to the path not existing or not being accessible. */
if ((!failed || errno == ENOENT || errno == EACCES)
&& dest - rname <= get_path_max ())
{
strcpy (resolved, rname);
if (failed)
return NULL;
else
return resolved;
}
if (!failed)
__set_errno (ENAMETOOLONG);
return NULL;
}
else
{
if (failed)
return NULL;
else
return __strdup (bufs->rname.data);
}
}
/* Return the canonical absolute name of file NAME. A canonical name
does not contain any ".", ".." components nor any repeated file name
separators ('/') or symlinks. All file name components must exist. If
RESOLVED is null, the result is malloc'd; otherwise, if the
canonical name is PATH_MAX chars or more, returns null with 'errno'
set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
returns the name in RESOLVED. If the name cannot be resolved and
RESOLVED is non-NULL, it contains the name of the first component
that cannot be resolved. If the name can be resolved, RESOLVED
holds the same value as the value returned. */
char *
__realpath (const char *name, char *resolved)
{
struct realpath_bufs bufs;
scratch_buffer_init (&bufs.rname);
scratch_buffer_init (&bufs.extra);
scratch_buffer_init (&bufs.link);
char *result = realpath_stk (name, resolved, &bufs);
scratch_buffer_free (&bufs.link);
scratch_buffer_free (&bufs.extra);
scratch_buffer_free (&bufs.rname);
return result;
}
libc_hidden_def (__realpath)
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
char *
attribute_compat_text_section
__old_realpath (const char *name, char *resolved)
{
if (resolved == NULL)
{
__set_errno (EINVAL);
return NULL;
}
return __realpath (name, resolved);
}
compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
#endif
char *
__canonicalize_file_name (const char *name)
{
return __realpath (name, NULL);
}
weak_alias (__canonicalize_file_name, canonicalize_file_name)
recode-3.7.14/lib/cloexec.h 0000644 0001750 0001750 00000002727 14366047013 012345 0000000 0000000 /* cloexec.c - set or clear the close-on-exec descriptor flag
Copyright (C) 2004, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
or clear the flag if VALUE is false.
Return 0 on success, or -1 on error with 'errno' set.
Note that on MingW, this function does NOT protect DESC from being
inherited into spawned children. Instead, either use dup_cloexec
followed by closing the original DESC, or use interfaces such as
open or pipe2 that accept flags like O_CLOEXEC to create DESC
non-inheritable in the first place. */
int set_cloexec_flag (int desc, bool value);
/* Duplicates a file handle FD, while marking the copy to be closed
prior to exec or spawn. Returns -1 and sets errno if FD could not
be duplicated. */
int dup_cloexec (int fd);
recode-3.7.14/lib/utime.in.h 0000644 0001750 0001750 00000006617 14366047013 012455 0000000 0000000 /* Substitute for and wrapper around .
Copyright (C) 2017-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _@GUARD_PREFIX@_UTIME_H
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
/* The include_next requires a split double-inclusion guard. */
#if @HAVE_UTIME_H@
# @INCLUDE_NEXT@ @NEXT_UTIME_H@
#endif
#ifndef _@GUARD_PREFIX@_UTIME_H
#define _@GUARD_PREFIX@_UTIME_H
#if !@HAVE_UTIME_H@
# include
#endif
#if @GNULIB_UTIME@
/* Get struct timespec. */
# include
#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. */
#if defined _WIN32 && ! defined __CYGWIN__
/* Define 'struct utimbuf' as an alias of 'struct _utimbuf'
(or possibly, if present, 'struct __utimbuf64'). */
# define utimbuf _utimbuf
#endif
#if @GNULIB_UTIME@
# if @REPLACE_UTIME@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define utime rpl_utime
# endif
_GL_FUNCDECL_RPL (utime, int, (const char *filename, const struct utimbuf *ts)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (utime, int, (const char *filename, const struct utimbuf *ts));
# elif defined _WIN32 && !defined __CYGWIN__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef utime
# define utime _utime
# endif
_GL_CXXALIAS_MDA (utime, int, (const char *filename, const struct utimbuf *ts));
# else
# if !@HAVE_UTIME@
_GL_FUNCDECL_SYS (utime, int, (const char *filename, const struct utimbuf *ts)
_GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (utime, int, (const char *filename, const struct utimbuf *ts));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (utime);
# endif
#elif defined GNULIB_POSIXCHECK
# undef utime
# if HAVE_RAW_DECL_UTIME
_GL_WARN_ON_USE (utime,
"utime is unportable - "
"use gnulib module canonicalize-lgpl for portability");
# endif
#elif @GNULIB_MDA_UTIME@
/* On native Windows, map 'utime' to '_utime', so that -loldnames is not
required. In C++ with GNULIB_NAMESPACE, avoid differences between
platforms by defining GNULIB_NAMESPACE::utime always. */
# if defined _WIN32 && !defined __CYGWIN__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef utime
# define utime _utime
# endif
_GL_CXXALIAS_MDA (utime, int, (const char *filename, const struct utimbuf *ts));
# else
_GL_CXXALIAS_SYS (utime, int, (const char *filename, const struct utimbuf *ts));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (utime);
# endif
#endif
#if @GNULIB_UTIME@
extern int _gl_utimens_windows (const char *filename, struct timespec ts[2]);
#endif
#endif /* _@GUARD_PREFIX@_UTIME_H */
#endif /* _@GUARD_PREFIX@_UTIME_H */
recode-3.7.14/lib/pathmax.h 0000644 0001750 0001750 00000005630 14366047013 012361 0000000 0000000 /* Define PATH_MAX somehow. Requires sys/types.h.
Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2023 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _PATHMAX_H
# define _PATHMAX_H
/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename,
including the terminating NUL byte.
PATH_MAX is not defined on systems which have no limit on filename length,
such as GNU/Hurd.
This file does *not* define PATH_MAX always. Programs that use this file
can handle the GNU/Hurd case in several ways:
- Either with a package-wide handling, or with a per-file handling,
- Either through a
#ifdef PATH_MAX
or through a fallback like
#ifndef PATH_MAX
# define PATH_MAX 8192
#endif
or through a fallback like
#ifndef PATH_MAX
# define PATH_MAX pathconf ("/", _PC_PATH_MAX)
#endif
*/
# include
# include
# ifndef _POSIX_PATH_MAX
# define _POSIX_PATH_MAX 256
# endif
/* Don't include sys/param.h if it already has been. */
# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
# include
# endif
# if !defined PATH_MAX && defined MAXPATHLEN
# define PATH_MAX MAXPATHLEN
# endif
# ifdef __hpux
/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename,
*not* including the terminating NUL byte, and is set to 1023.
Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is
not defined at all any more. */
# undef PATH_MAX
# define PATH_MAX 1024
# endif
# if defined _WIN32 && ! defined __CYGWIN__
/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com,
section "Maximum Path Length Limitation",
explains that the maximum size of a filename, including the terminating
NUL byte, is 260 = 3 + 256 + 1.
This is the same value as
- FILENAME_MAX in ,
- _MAX_PATH in ,
- MAX_PATH in .
Undefine the original value, because mingw's gets it wrong. */
# undef PATH_MAX
# define PATH_MAX 260
# endif
#endif /* _PATHMAX_H */
recode-3.7.14/lib/stat-w32.h 0000644 0001750 0001750 00000003107 14366047013 012300 0000000 0000000 /* Core of implementation of fstat and stat for native Windows.
Copyright (C) 2017-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _STAT_W32_H
#define _STAT_W32_H 1
/* Converts a FILETIME to GMT time since 1970-01-01 00:00:00. */
#if _GL_WINDOWS_STAT_TIMESPEC
extern struct timespec _gl_convert_FILETIME_to_timespec (const FILETIME *ft);
#else
extern time_t _gl_convert_FILETIME_to_POSIX (const FILETIME *ft);
#endif
/* Fill *BUF with information about the file designated by H.
PATH is the file name, if known, otherwise NULL.
Return 0 if successful, or -1 with errno set upon failure. */
extern int _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf);
/* Bitmasks for st_mode. */
#define S_IREAD_UGO (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6))
#define S_IWRITE_UGO (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
#define S_IEXEC_UGO (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6))
#endif /* _STAT_W32_H */
recode-3.7.14/lib/vasnprintf.c 0000644 0001750 0001750 00000677000 14366047013 013112 0000000 0000000 /* vsprintf with automatic memory allocation.
Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* 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.
ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
ENABLE_WCHAR_FALLBACK Set to 1 to avoid EILSEQ during conversion of wide
characters (wchar_t) and wide character strings
(wchar_t[]) to multibyte sequences. The fallback is the
hexadecimal escape syntax (\unnnn or \Unnnnnnnn) or,
if wchar_t is not Unicode encoded, \wnnnn or \Wnnnnnnnn.
*/
/* 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
/* As of GCC 11.2.1, gcc -Wanalyzer-too-complex reports that main's
use of CHECK macros expands to code that is too complicated for gcc
-fanalyzer. Suppress the resulting bogus warnings. */
#if 10 <= __GNUC__
# pragma GCC diagnostic ignored "-Wanalyzer-null-argument"
#endif
#include
/* 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 "attribute.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
# define USE_MSVC__SNPRINTF 1
# 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
/* MSVC versions < 14 did not have snprintf, only _snprintf. */
# define SNPRINTF _snprintf
# define USE_MSVC__SNPRINTF 1
# 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. */
#if defined GCC_LINT || defined 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 || USE_MSVC__SNPRINTF) && !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 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (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 || USE_MSVC__SNPRINTF) && 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 (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || (ENABLE_WCHAR_FALLBACK && HAVE_WINT_T)) && !WIDE_CHAR_VERSION
# if ENABLE_WCHAR_FALLBACK
static size_t
wctomb_fallback (char *s, wchar_t wc)
{
static char hex[16] = "0123456789ABCDEF";
s[0] = '\\';
if (sizeof (wchar_t) > 2 && wc > 0xffff)
{
# if __STDC_ISO_10646__ || (__GLIBC__ >= 2) || (defined _WIN32 || defined __CYGWIN__)
s[1] = 'U';
# else
s[1] = 'W';
# endif
s[2] = hex[(wc & 0xf0000000U) >> 28];
s[3] = hex[(wc & 0xf000000U) >> 24];
s[4] = hex[(wc & 0xf00000U) >> 20];
s[5] = hex[(wc & 0xf0000U) >> 16];
s[6] = hex[(wc & 0xf000U) >> 12];
s[7] = hex[(wc & 0xf00U) >> 8];
s[8] = hex[(wc & 0xf0U) >> 4];
s[9] = hex[wc & 0xfU];
return 10;
}
else
{
# if __STDC_ISO_10646__ || (__GLIBC__ >= 2) || (defined _WIN32 || defined __CYGWIN__)
s[1] = 'u';
# else
s[1] = 'w';
# endif
s[2] = hex[(wc & 0xf000U) >> 12];
s[3] = hex[(wc & 0xf00U) >> 8];
s[4] = hex[(wc & 0xf0U) >> 4];
s[5] = hex[wc & 0xfU];
return 6;
}
}
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
static size_t
local_wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
{
size_t count = wcrtomb (s, wc, ps);
if (count == (size_t)(-1))
count = wctomb_fallback (s, wc);
return count;
}
# else
static int
local_wctomb (char *s, wchar_t wc)
{
int count = wctomb (s, wc);
if (count < 0)
count = wctomb_fallback (s, wc);
return count;
}
# define local_wcrtomb(S, WC, PS) local_wctomb ((S), (WC))
# endif
# else
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
# define local_wcrtomb(S, WC, PS) wcrtomb ((S), (WC), (PS))
# else
# define local_wcrtomb(S, WC, PS) wctomb ((S), (WC))
# 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
static_assert (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
typedef unsigned long long mp_twolimb_t;
# define GMP_TWOLIMB_BITS 64
static_assert (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) \
|| (__clang_major__ >= 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:
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);
/* We need extra_zeroes bytes for zeroes, followed by c_len bytes for the
digits of a, followed by 1 byte for the terminating NUL. */
char *c_ptr = (char *) malloc (xsum (xsum (extra_zeroes, c_len), 1));
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_MSVC__SNPRINTF
/* 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 (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 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 (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 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 (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 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;
# if ENABLE_WCHAR_FALLBACK
if (tmp_length < (sizeof (wchar_t) > 2 ? 10 : 6))
tmp_length = (sizeof (wchar_t) > 2 ? 10 : 6);
# endif
}
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;
/* Frees the memory allocated by this function. Preserves errno. */
#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)
goto fail_1_with_EINVAL;
{
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;
}
result = resultbuf;
allocated = (resultbuf != NULL ? *lengthp : 0);
length = 0;
/* Invariants:
result is either == resultbuf or malloc-allocated.
If result == NULL, resultbuf is == NULL as well.
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_ELSE(needed, oom_statement) \
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)) \
oom_statement \
if (result == resultbuf) \
memory = (DCHAR_T *) malloc (memory_size); \
else \
memory = (DCHAR_T *) realloc (result, memory_size); \
if (memory == NULL) \
oom_statement \
if (result == resultbuf && length > 0) \
DCHAR_CPY (memory, result, length); \
result = memory; \
}
#define ENSURE_ALLOCATION(needed) \
ENSURE_ALLOCATION_ELSE((needed), goto out_of_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++] = *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;
case TYPE_COUNT_LONGLONGINT_POINTER:
*a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
break;
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;
width = arg;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = -width;
}
}
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)
goto fail_with_EILSEQ;
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)
goto fail_with_EILSEQ;
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 (characters < width && !(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)
goto fail_with_errno;
if (converted != result + length)
{
ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
{ free (converted); goto out_of_memory; });
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
length += converted_len;
}
# endif
if (characters < width && (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)
goto fail_with_EILSEQ;
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)
goto fail_with_EILSEQ;
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 (characters < width && !(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)
goto fail_with_errno;
if (converted != result + length)
{
ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
{ free (converted); goto out_of_memory; });
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
length += converted_len;
}
# endif
if (characters < width && (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)
goto fail_with_EILSEQ;
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)
goto fail_with_EILSEQ;
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 (characters < width && !(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)
goto fail_with_errno;
if (converted != result + length)
{
ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
{ free (converted); goto out_of_memory; });
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
length += converted_len;
}
# endif
if (characters < width && (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 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && 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;
width = arg;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = -width;
}
}
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. */
goto fail_with_EILSEQ;
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. */
goto fail_with_EILSEQ;
arg_end += count;
characters++;
}
}
else
{
/* Use the entire string. */
arg_end = arg + strlen (arg);
/* The number of characters doesn't matter. */
characters = 0;
}
if (characters < width && !(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 (characters < width && (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'. */
static_assert (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;
count = local_wcrtomb (cbuf, *arg_end, &state);
if (count < 0)
/* Cannot convert. */
goto fail_with_EILSEQ;
if (precision < (unsigned int) 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;
count = local_wcrtomb (cbuf, *arg_end, &state);
if (count < 0)
/* Cannot convert. */
goto fail_with_EILSEQ;
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 ();
count = local_wcrtomb (cbuf, *arg, &state);
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)
{
free (tmpsrc);
goto fail_with_errno;
}
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 (w < width && !(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 ();
count = local_wcrtomb (cbuf, *arg, &state);
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 ();
count = local_wcrtomb (cbuf, *arg, &state);
if (count <= 0)
/* Cannot convert. */
goto fail_with_EILSEQ;
ENSURE_ALLOCATION (xsum (length, count));
memcpy (result + length, cbuf, count);
length += count;
arg++;
}
}
# else
ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
{ free (tmpdst); goto out_of_memory; });
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
length += tmpdst_len;
# endif
if (w < width && (dp->flags & FLAG_LEFT))
{
size_t n = width - w;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
# endif
}
#endif
#if ENABLE_WCHAR_FALLBACK && HAVE_WINT_T && !WIDE_CHAR_VERSION
else if (dp->conversion == 'c'
&& a.arg[dp->arg_index].type == TYPE_WIDE_CHAR)
{
/* Implement the 'lc' directive ourselves, in order to provide
the fallback that avoids EILSEQ. */
int flags = dp->flags;
int has_width;
size_t width;
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;
width = arg;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = -width;
}
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
has_width = 1;
}
/* %lc in vasnprintf. See the specification of fprintf. */
{
wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char;
size_t characters;
# if !DCHAR_IS_TCHAR
/* This code assumes that TCHAR_T is 'char'. */
static_assert (sizeof (TCHAR_T) == 1);
TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */
DCHAR_T *tmpdst;
size_t tmpdst_len;
# endif
size_t w;
# if DCHAR_IS_TCHAR
if (has_width)
# endif
{
/* Count the number of bytes. */
characters = 0;
if (arg != 0)
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
count = local_wcrtomb (cbuf, arg, &state);
if (count < 0)
/* Inconsistency. */
abort ();
characters = count;
}
}
# if DCHAR_IS_TCHAR
else
{
/* The number of bytes doesn't matter. */
characters = 0;
}
# endif
# if !DCHAR_IS_TCHAR
/* Convert the string into a piece of temporary memory. */
if (characters > 0) /* implies arg != 0 */
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
count = local_wcrtomb (cbuf, arg, &state);
if (count <= 0)
/* Inconsistency. */
abort ();
memcpy (tmpsrc, cbuf, count);
}
/* 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)
goto fail_with_errno;
# 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 (w < width && !(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_width)
{
/* We know the number of bytes in advance. */
ENSURE_ALLOCATION (xsum (length, characters));
if (characters > 0) /* implies arg != 0 */
{
int count;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
count = local_wcrtomb (result + length, arg, &state);
if (count <= 0)
/* Inconsistency. */
abort ();
length += count;
}
}
else
{
if (arg != 0)
{
char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
int count;
# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
mbstate_t state;
memset (&state, '\0', sizeof (mbstate_t));
# endif
count = local_wcrtomb (cbuf, arg, &state);
if (count <= 0)
/* Inconsistency. */
abort ();
ENSURE_ALLOCATION (xsum (length, count));
memcpy (result + length, cbuf, count);
length += count;
}
}
# else
ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
{ free (tmpdst); goto out_of_memory; });
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
length += tmpdst_len;
# endif
if (w < width && (dp->flags & FLAG_LEFT))
{
size_t n = width - w;
ENSURE_ALLOCATION (xsum (length, n));
DCHAR_SET (result + length, ' ', n);
length += n;
}
}
}
#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;
size_t width;
int has_precision;
size_t precision;
size_t tmp_length;
size_t count;
DCHAR_T tmpbuf[700];
DCHAR_T *tmp;
DCHAR_T *pad_ptr;
DCHAR_T *p;
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;
width = arg;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = -width;
}
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
}
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. */
count = p - tmp;
if (count < width)
{
size_t pad = width - count;
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;
}
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;
size_t width;
size_t count;
int has_precision;
size_t precision;
size_t tmp_length;
DCHAR_T tmpbuf[700];
DCHAR_T *tmp;
DCHAR_T *pad_ptr;
DCHAR_T *p;
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;
width = arg;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = -width;
}
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
}
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 ecount = exponent + 1;
/* Note: count <= precision = ndigits. */
for (; ecount > 0; ecount--)
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
}
else
{
size_t ecount = -exponent - 1;
*p++ = '0';
*p++ = decimal_point_char ();
for (; ecount > 0; ecount--)
*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 __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 __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 ecount = exponent + 1;
/* Note: ecount <= precision = ndigits. */
for (; ecount > 0; ecount--)
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
while (ndigits > nzeroes)
{
--ndigits;
*p++ = digits[ndigits];
}
}
}
else
{
size_t ecount = -exponent - 1;
*p++ = '0';
*p++ = decimal_point_char ();
for (; ecount > 0; ecount--)
*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 __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 __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 __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. */
count = p - tmp;
if (count < width)
{
size_t pad = width - count;
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;
}
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 !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int has_width;
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
size_t width;
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 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 !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 0;
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
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;
width = arg;
if (arg < 0)
{
/* "A negative field width is taken as a '-' flag
followed by a positive field width." */
flags |= FLAG_LEFT;
width = -width;
}
}
else
{
const FCHAR_T *digitp = dp->width_start;
do
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 1;
#endif
}
#endif
#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 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++ = *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++ = *mp++;
while (--n > 0);
}
}
}
switch (type)
{
case TYPE_LONGLONGINT:
case TYPE_ULONGLONGINT:
#if defined _WIN32 && ! defined __CYGWIN__
*fbp++ = 'I';
*fbp++ = '6';
*fbp++ = '4';
break;
#else
*fbp++ = 'l';
#endif
FALLTHROUGH;
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 ((HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99) \
|| ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \
&& !defined __UCLIBC__) \
|| (defined __APPLE__ && defined __MACH__) \
|| defined __ANDROID__ \
|| (defined _WIN32 && ! defined __CYGWIN__))
/* On systems where we know that snprintf's return value
conforms to ISO C 99 (HAVE_SNPRINTF_RETVAL_C99) and that
snprintf always produces NUL-terminated strings
(HAVE_SNPRINTF_TRUNCATION_C99), it is possible to avoid
using %n. And it is desirable to do so, because more and
more platforms no longer support %n, for "security reasons".
In particular, the following platforms:
- 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).
- On Mac OS X 10.13 or newer, the use of %n in format
strings in writable memory by default crashes the
program.
- On Android, starting on 2018-03-07, the use of %n in
format strings produces a fatal error (see
).
On these platforms, HAVE_SNPRINTF_RETVAL_C99 and
HAVE_SNPRINTF_TRUNCATION_C99 are 1. We have listed them
explicitly in the condition above, in case of cross-
compilation (just to be sure). */
/* 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';
# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */
fbp[1] = '%';
fbp[2] = 'n';
fbp[3] = '\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;
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;
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 ((unsigned int) 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 || USE_MSVC__SNPRINTF
/* 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. Use the errno that it
has set, if any. */
if (errno == 0)
{
if (dp->conversion == 'c' || dp->conversion == 's')
errno = EILSEQ;
else
errno = EINVAL;
}
goto fail_with_errno;
}
#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'. */
static_assert (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)
goto fail_with_errno;
ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
{ free (tmpdst); goto out_of_memory; });
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 = *--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:
errno = EOVERFLOW;
goto fail_with_errno;
#endif
out_of_memory:
errno = ENOMEM;
goto fail_with_errno;
#if ENABLE_UNISTDIO || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T)
fail_with_EILSEQ:
errno = EILSEQ;
goto fail_with_errno;
#endif
fail_with_errno:
if (result != resultbuf)
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
return NULL;
}
out_of_memory_1:
errno = ENOMEM;
goto fail_1_with_errno;
fail_1_with_EINVAL:
errno = EINVAL;
goto fail_1_with_errno;
fail_1_with_errno:
CLEANUP ();
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
recode-3.7.14/lib/streq.h 0000644 0001750 0001750 00000007703 14366047013 012060 0000000 0000000 /* Optimized string comparison.
Copyright (C) 2001-2002, 2007, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Bruno Haible . */
#ifndef _GL_STREQ_H
#define _GL_STREQ_H
#include
/* STREQ_OPT allows to optimize string comparison with a small literal string.
STREQ_OPT (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
is semantically equivalent to
strcmp (s, "EUC-KR") == 0
just faster. */
/* Help GCC to generate good code for string comparisons with
immediate strings. */
#if (defined __GNUC__ || defined __clang__) && defined __OPTIMIZE__
static inline int
streq9 (const char *s1, const char *s2)
{
return strcmp (s1 + 9, s2 + 9) == 0;
}
static inline int
streq8 (const char *s1, const char *s2, char s28)
{
if (s1[8] == s28)
{
if (s28 == 0)
return 1;
else
return streq9 (s1, s2);
}
else
return 0;
}
static inline int
streq7 (const char *s1, const char *s2, char s27, char s28)
{
if (s1[7] == s27)
{
if (s27 == 0)
return 1;
else
return streq8 (s1, s2, s28);
}
else
return 0;
}
static inline int
streq6 (const char *s1, const char *s2, char s26, char s27, char s28)
{
if (s1[6] == s26)
{
if (s26 == 0)
return 1;
else
return streq7 (s1, s2, s27, s28);
}
else
return 0;
}
static inline int
streq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
{
if (s1[5] == s25)
{
if (s25 == 0)
return 1;
else
return streq6 (s1, s2, s26, s27, s28);
}
else
return 0;
}
static inline int
streq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
{
if (s1[4] == s24)
{
if (s24 == 0)
return 1;
else
return streq5 (s1, s2, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
streq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (s1[3] == s23)
{
if (s23 == 0)
return 1;
else
return streq4 (s1, s2, s24, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
streq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (s1[2] == s22)
{
if (s22 == 0)
return 1;
else
return streq3 (s1, s2, s23, s24, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
streq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (s1[1] == s21)
{
if (s21 == 0)
return 1;
else
return streq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (s1[0] == s20)
{
if (s20 == 0)
return 1;
else
return streq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
}
else
return 0;
}
#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
streq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
#else
#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
(strcmp (s1, s2) == 0)
#endif
#endif /* _GL_STREQ_H */
recode-3.7.14/lib/msvc-nothrow.h 0000644 0001750 0001750 00000003023 14366047013 013357 0000000 0000000 /* Wrappers that don't throw invalid parameter notifications
with MSVC runtime libraries.
Copyright (C) 2011-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#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 __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 */
recode-3.7.14/lib/hash.c 0000644 0001750 0001750 00000100127 14366047013 011632 0000000 0000000 /* hash - hashing table processing.
Copyright (C) 1998-2004, 2006-2007, 2009-2023 Free Software Foundation, Inc.
Written by Jim Meyering, 1992.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* A generic hash table package. */
/* Define USE_OBSTACK to 1 if you want the allocator to use obstacks instead
of malloc. If you change USE_OBSTACK, you have to recompile! */
#include
#include "hash.h"
#include "bitrotate.h"
#include "xalloc-oversized.h"
#include
#include
#include
#if USE_OBSTACK
# include "obstack.h"
# ifndef obstack_chunk_alloc
# define obstack_chunk_alloc malloc
# endif
# ifndef obstack_chunk_free
# define obstack_chunk_free free
# endif
#endif
struct hash_entry
{
void *data;
struct hash_entry *next;
};
struct hash_table
{
/* The array of buckets starts at BUCKET and extends to BUCKET_LIMIT-1,
for a possibility of N_BUCKETS. Among those, N_BUCKETS_USED buckets
are not empty, there are N_ENTRIES active entries in the table. */
struct hash_entry *bucket;
struct hash_entry const *bucket_limit;
size_t n_buckets;
size_t n_buckets_used;
size_t n_entries;
/* Tuning arguments, kept in a physically separate structure. */
const Hash_tuning *tuning;
/* Three functions are given to 'hash_initialize', see the documentation
block for this function. In a word, HASHER randomizes a user entry
into a number up from 0 up to some maximum minus 1; COMPARATOR returns
true if two user entries compare equally; and DATA_FREER is the cleanup
function for a user entry. */
Hash_hasher hasher;
Hash_comparator comparator;
Hash_data_freer data_freer;
/* A linked list of freed struct hash_entry structs. */
struct hash_entry *free_entry_list;
#if USE_OBSTACK
/* Whenever obstacks are used, it is possible to allocate all overflowed
entries into a single stack, so they all can be freed in a single
operation. It is not clear if the speedup is worth the trouble. */
struct obstack entry_stack;
#endif
};
/* A hash table contains many internal entries, each holding a pointer to
some user-provided data (also called a user entry). An entry indistinctly
refers to both the internal entry and its associated user entry. A user
entry contents may be hashed by a randomization function (the hashing
function, or just "hasher" for short) into a number (or "slot") between 0
and the current table size. At each slot position in the hash table,
starts a linked chain of entries for which the user data all hash to this
slot. A bucket is the collection of all entries hashing to the same slot.
A good "hasher" function will distribute entries rather evenly in buckets.
In the ideal case, the length of each bucket is roughly the number of
entries divided by the table size. Finding the slot for a data is usually
done in constant time by the "hasher", and the later finding of a precise
entry is linear in time with the size of the bucket. Consequently, a
larger hash table size (that is, a larger number of buckets) is prone to
yielding shorter chains, *given* the "hasher" function behaves properly.
Long buckets slow down the lookup algorithm. One might use big hash table
sizes in hope to reduce the average length of buckets, but this might
become inordinate, as unused slots in the hash table take some space. The
best bet is to make sure you are using a good "hasher" function (beware
that those are not that easy to write! :-), and to use a table size
larger than the actual number of entries. */
/* If an insertion makes the ratio of nonempty buckets to table size larger
than the growth threshold (a number between 0.0 and 1.0), then increase
the table size by multiplying by the growth factor (a number greater than
1.0). The growth threshold defaults to 0.8, and the growth factor
defaults to 1.414, meaning that the table will have doubled its size
every second time 80% of the buckets get used. */
#define DEFAULT_GROWTH_THRESHOLD 0.8f
#define DEFAULT_GROWTH_FACTOR 1.414f
/* If a deletion empties a bucket and causes the ratio of used buckets to
table size to become smaller than the shrink threshold (a number between
0.0 and 1.0), then shrink the table by multiplying by the shrink factor (a
number greater than the shrink threshold but smaller than 1.0). The shrink
threshold and factor default to 0.0 and 1.0, meaning that the table never
shrinks. */
#define DEFAULT_SHRINK_THRESHOLD 0.0f
#define DEFAULT_SHRINK_FACTOR 1.0f
/* Use this to initialize or reset a TUNING structure to
some sensible values. */
static const Hash_tuning default_tuning =
{
DEFAULT_SHRINK_THRESHOLD,
DEFAULT_SHRINK_FACTOR,
DEFAULT_GROWTH_THRESHOLD,
DEFAULT_GROWTH_FACTOR,
false
};
/* Information and lookup. */
size_t
hash_get_n_buckets (const Hash_table *table)
{
return table->n_buckets;
}
size_t
hash_get_n_buckets_used (const Hash_table *table)
{
return table->n_buckets_used;
}
size_t
hash_get_n_entries (const Hash_table *table)
{
return table->n_entries;
}
size_t
hash_get_max_bucket_length (const Hash_table *table)
{
struct hash_entry const *bucket;
size_t max_bucket_length = 0;
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
if (bucket->data)
{
struct hash_entry const *cursor = bucket;
size_t bucket_length = 1;
while (cursor = cursor->next, cursor)
bucket_length++;
if (bucket_length > max_bucket_length)
max_bucket_length = bucket_length;
}
}
return max_bucket_length;
}
bool
hash_table_ok (const Hash_table *table)
{
struct hash_entry const *bucket;
size_t n_buckets_used = 0;
size_t n_entries = 0;
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
if (bucket->data)
{
struct hash_entry const *cursor = bucket;
/* Count bucket head. */
n_buckets_used++;
n_entries++;
/* Count bucket overflow. */
while (cursor = cursor->next, cursor)
n_entries++;
}
}
if (n_buckets_used == table->n_buckets_used && n_entries == table->n_entries)
return true;
return false;
}
void
hash_print_statistics (const Hash_table *table, FILE *stream)
{
size_t n_entries = hash_get_n_entries (table);
size_t n_buckets = hash_get_n_buckets (table);
size_t n_buckets_used = hash_get_n_buckets_used (table);
size_t max_bucket_length = hash_get_max_bucket_length (table);
fprintf (stream, "# entries: %lu\n", (unsigned long int) n_entries);
fprintf (stream, "# buckets: %lu\n", (unsigned long int) n_buckets);
fprintf (stream, "# buckets used: %lu (%.2f%%)\n",
(unsigned long int) n_buckets_used,
(100.0 * n_buckets_used) / n_buckets);
fprintf (stream, "max bucket length: %lu\n",
(unsigned long int) max_bucket_length);
}
/* Hash KEY and return a pointer to the selected bucket.
If TABLE->hasher misbehaves, abort. */
static struct hash_entry *
safe_hasher (const Hash_table *table, const void *key)
{
size_t n = table->hasher (key, table->n_buckets);
if (! (n < table->n_buckets))
abort ();
return table->bucket + n;
}
void *
hash_lookup (const Hash_table *table, const void *entry)
{
struct hash_entry const *bucket = safe_hasher (table, entry);
struct hash_entry const *cursor;
if (bucket->data == NULL)
return NULL;
for (cursor = bucket; cursor; cursor = cursor->next)
if (entry == cursor->data || table->comparator (entry, cursor->data))
return cursor->data;
return NULL;
}
/* Walking. */
void *
hash_get_first (const Hash_table *table)
{
struct hash_entry const *bucket;
if (table->n_entries == 0)
return NULL;
for (bucket = table->bucket; ; bucket++)
if (! (bucket < table->bucket_limit))
abort ();
else if (bucket->data)
return bucket->data;
}
void *
hash_get_next (const Hash_table *table, const void *entry)
{
struct hash_entry const *bucket = safe_hasher (table, entry);
struct hash_entry const *cursor;
/* Find next entry in the same bucket. */
cursor = bucket;
do
{
if (cursor->data == entry && cursor->next)
return cursor->next->data;
cursor = cursor->next;
}
while (cursor != NULL);
/* Find first entry in any subsequent bucket. */
while (++bucket < table->bucket_limit)
if (bucket->data)
return bucket->data;
/* None found. */
return NULL;
}
size_t
hash_get_entries (const Hash_table *table, void **buffer,
size_t buffer_size)
{
size_t counter = 0;
struct hash_entry const *bucket;
struct hash_entry const *cursor;
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
if (bucket->data)
{
for (cursor = bucket; cursor; cursor = cursor->next)
{
if (counter >= buffer_size)
return counter;
buffer[counter++] = cursor->data;
}
}
}
return counter;
}
size_t
hash_do_for_each (const Hash_table *table, Hash_processor processor,
void *processor_data)
{
size_t counter = 0;
struct hash_entry const *bucket;
struct hash_entry const *cursor;
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
if (bucket->data)
{
for (cursor = bucket; cursor; cursor = cursor->next)
{
if (! processor (cursor->data, processor_data))
return counter;
counter++;
}
}
}
return counter;
}
/* Allocation and clean-up. */
#if USE_DIFF_HASH
/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see
B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm,
Software--practice & experience 20, 2 (Feb 1990), 209-224. Good hash
algorithms tend to be domain-specific, so what's good for [diffutils'] io.c
may not be good for your application." */
size_t
hash_string (const char *string, size_t n_buckets)
{
# define HASH_ONE_CHAR(Value, Byte) \
((Byte) + rotl_sz (Value, 7))
size_t value = 0;
unsigned char ch;
for (; (ch = *string); string++)
value = HASH_ONE_CHAR (value, ch);
return value % n_buckets;
# undef HASH_ONE_CHAR
}
#else /* not USE_DIFF_HASH */
/* This one comes from 'recode', and performs a bit better than the above as
per a few experiments. It is inspired from a hashing routine found in the
very old Cyber 'snoop', itself written in typical Greg Mansfield style.
(By the way, what happened to this excellent man? Is he still alive?) */
size_t
hash_string (const char *string, size_t n_buckets)
{
size_t value = 0;
unsigned char ch;
for (; (ch = *string); string++)
value = (value * 31 + ch) % n_buckets;
return value;
}
#endif /* not USE_DIFF_HASH */
/* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd
number at least equal to 11. */
static bool _GL_ATTRIBUTE_CONST
is_prime (size_t candidate)
{
size_t divisor = 3;
size_t square = divisor * divisor;
while (square < candidate && (candidate % divisor))
{
divisor++;
square += 4 * divisor;
divisor++;
}
return (candidate % divisor ? true : false);
}
/* Round a given CANDIDATE number up to the nearest prime, and return that
prime. Primes lower than 10 are merely skipped. */
static size_t _GL_ATTRIBUTE_CONST
next_prime (size_t candidate)
{
/* Skip small primes. */
if (candidate < 10)
candidate = 10;
/* Make it definitely odd. */
candidate |= 1;
while (SIZE_MAX != candidate && !is_prime (candidate))
candidate += 2;
return candidate;
}
void
hash_reset_tuning (Hash_tuning *tuning)
{
*tuning = default_tuning;
}
/* If the user passes a NULL hasher, we hash the raw pointer. */
static size_t
raw_hasher (const void *data, size_t n)
{
/* When hashing unique pointers, it is often the case that they were
generated by malloc and thus have the property that the low-order
bits are 0. As this tends to give poorer performance with small
tables, we rotate the pointer value before performing division,
in an attempt to improve hash quality. */
size_t val = rotr_sz ((size_t) data, 3);
return val % n;
}
/* If the user passes a NULL comparator, we use pointer comparison. */
static bool
raw_comparator (const void *a, const void *b)
{
return a == b;
}
/* For the given hash TABLE, check the user supplied tuning structure for
reasonable values, and return true if there is no gross error with it.
Otherwise, definitively reset the TUNING field to some acceptable default
in the hash table (that is, the user loses the right of further modifying
tuning arguments), and return false. */
static bool
check_tuning (Hash_table *table)
{
const Hash_tuning *tuning = table->tuning;
float epsilon;
if (tuning == &default_tuning)
return true;
/* Be a bit stricter than mathematics would require, so that
rounding errors in size calculations do not cause allocations to
fail to grow or shrink as they should. The smallest allocation
is 11 (due to next_prime's algorithm), so an epsilon of 0.1
should be good enough. */
epsilon = 0.1f;
if (epsilon < tuning->growth_threshold
&& tuning->growth_threshold < 1 - epsilon
&& 1 + epsilon < tuning->growth_factor
&& 0 <= tuning->shrink_threshold
&& tuning->shrink_threshold + epsilon < tuning->shrink_factor
&& tuning->shrink_factor <= 1
&& tuning->shrink_threshold + epsilon < tuning->growth_threshold)
return true;
table->tuning = &default_tuning;
return false;
}
/* Compute the size of the bucket array for the given CANDIDATE and
TUNING, or return 0 if there is no possible way to allocate that
many entries. */
static size_t _GL_ATTRIBUTE_PURE
compute_bucket_size (size_t candidate, const Hash_tuning *tuning)
{
if (!tuning->is_n_buckets)
{
float new_candidate = candidate / tuning->growth_threshold;
if ((float) SIZE_MAX <= new_candidate)
return 0;
candidate = new_candidate;
}
candidate = next_prime (candidate);
if (xalloc_oversized (candidate, sizeof (struct hash_entry *)))
return 0;
return candidate;
}
Hash_table *
hash_initialize (size_t candidate, const Hash_tuning *tuning,
Hash_hasher hasher, Hash_comparator comparator,
Hash_data_freer data_freer)
{
Hash_table *table;
if (hasher == NULL)
hasher = raw_hasher;
if (comparator == NULL)
comparator = raw_comparator;
table = malloc (sizeof *table);
if (table == NULL)
return NULL;
if (!tuning)
tuning = &default_tuning;
table->tuning = tuning;
if (!check_tuning (table))
{
/* Fail if the tuning options are invalid. This is the only occasion
when the user gets some feedback about it. Once the table is created,
if the user provides invalid tuning options, we silently revert to
using the defaults, and ignore further request to change the tuning
options. */
goto fail;
}
table->n_buckets = compute_bucket_size (candidate, tuning);
if (!table->n_buckets)
goto fail;
table->bucket = calloc (table->n_buckets, sizeof *table->bucket);
if (table->bucket == NULL)
goto fail;
table->bucket_limit = table->bucket + table->n_buckets;
table->n_buckets_used = 0;
table->n_entries = 0;
table->hasher = hasher;
table->comparator = comparator;
table->data_freer = data_freer;
table->free_entry_list = NULL;
#if USE_OBSTACK
obstack_init (&table->entry_stack);
#endif
return table;
fail:
free (table);
return NULL;
}
void
hash_clear (Hash_table *table)
{
struct hash_entry *bucket;
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
if (bucket->data)
{
struct hash_entry *cursor;
struct hash_entry *next;
/* Free the bucket overflow. */
for (cursor = bucket->next; cursor; cursor = next)
{
if (table->data_freer)
table->data_freer (cursor->data);
cursor->data = NULL;
next = cursor->next;
/* Relinking is done one entry at a time, as it is to be expected
that overflows are either rare or short. */
cursor->next = table->free_entry_list;
table->free_entry_list = cursor;
}
/* Free the bucket head. */
if (table->data_freer)
table->data_freer (bucket->data);
bucket->data = NULL;
bucket->next = NULL;
}
}
table->n_buckets_used = 0;
table->n_entries = 0;
}
void
hash_free (Hash_table *table)
{
struct hash_entry *bucket;
struct hash_entry *cursor;
struct hash_entry *next;
/* Call the user data_freer function. */
if (table->data_freer && table->n_entries)
{
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
if (bucket->data)
{
for (cursor = bucket; cursor; cursor = cursor->next)
table->data_freer (cursor->data);
}
}
}
#if USE_OBSTACK
obstack_free (&table->entry_stack, NULL);
#else
/* Free all bucket overflowed entries. */
for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
{
for (cursor = bucket->next; cursor; cursor = next)
{
next = cursor->next;
free (cursor);
}
}
/* Also reclaim the internal list of previously freed entries. */
for (cursor = table->free_entry_list; cursor; cursor = next)
{
next = cursor->next;
free (cursor);
}
#endif
/* Free the remainder of the hash table structure. */
free (table->bucket);
free (table);
}
/* Insertion and deletion. */
/* Get a new hash entry for a bucket overflow, possibly by recycling a
previously freed one. If this is not possible, allocate a new one. */
static struct hash_entry *
allocate_entry (Hash_table *table)
{
struct hash_entry *new;
if (table->free_entry_list)
{
new = table->free_entry_list;
table->free_entry_list = new->next;
}
else
{
#if USE_OBSTACK
new = obstack_alloc (&table->entry_stack, sizeof *new);
#else
new = malloc (sizeof *new);
#endif
}
return new;
}
/* Free a hash entry which was part of some bucket overflow,
saving it for later recycling. */
static void
free_entry (Hash_table *table, struct hash_entry *entry)
{
entry->data = NULL;
entry->next = table->free_entry_list;
table->free_entry_list = entry;
}
/* This private function is used to help with insertion and deletion. When
ENTRY matches an entry in the table, return a pointer to the corresponding
user data and set *BUCKET_HEAD to the head of the selected bucket.
Otherwise, return NULL. When DELETE is true and ENTRY matches an entry in
the table, unlink the matching entry. */
static void *
hash_find_entry (Hash_table *table, const void *entry,
struct hash_entry **bucket_head, bool delete)
{
struct hash_entry *bucket = safe_hasher (table, entry);
struct hash_entry *cursor;
*bucket_head = bucket;
/* Test for empty bucket. */
if (bucket->data == NULL)
return NULL;
/* See if the entry is the first in the bucket. */
if (entry == bucket->data || table->comparator (entry, bucket->data))
{
void *data = bucket->data;
if (delete)
{
if (bucket->next)
{
struct hash_entry *next = bucket->next;
/* Bump the first overflow entry into the bucket head, then save
the previous first overflow entry for later recycling. */
*bucket = *next;
free_entry (table, next);
}
else
{
bucket->data = NULL;
}
}
return data;
}
/* Scan the bucket overflow. */
for (cursor = bucket; cursor->next; cursor = cursor->next)
{
if (entry == cursor->next->data
|| table->comparator (entry, cursor->next->data))
{
void *data = cursor->next->data;
if (delete)
{
struct hash_entry *next = cursor->next;
/* Unlink the entry to delete, then save the freed entry for later
recycling. */
cursor->next = next->next;
free_entry (table, next);
}
return data;
}
}
/* No entry found. */
return NULL;
}
/* Internal helper, to move entries from SRC to DST. Both tables must
share the same free entry list. If SAFE, only move overflow
entries, saving bucket heads for later, so that no allocations will
occur. Return false if the free entry list is exhausted and an
allocation fails. */
static bool
transfer_entries (Hash_table *dst, Hash_table *src, bool safe)
{
struct hash_entry *bucket;
struct hash_entry *cursor;
struct hash_entry *next;
for (bucket = src->bucket; bucket < src->bucket_limit; bucket++)
if (bucket->data)
{
void *data;
struct hash_entry *new_bucket;
/* Within each bucket, transfer overflow entries first and
then the bucket head, to minimize memory pressure. After
all, the only time we might allocate is when moving the
bucket head, but moving overflow entries first may create
free entries that can be recycled by the time we finally
get to the bucket head. */
for (cursor = bucket->next; cursor; cursor = next)
{
data = cursor->data;
new_bucket = safe_hasher (dst, data);
next = cursor->next;
if (new_bucket->data)
{
/* Merely relink an existing entry, when moving from a
bucket overflow into a bucket overflow. */
cursor->next = new_bucket->next;
new_bucket->next = cursor;
}
else
{
/* Free an existing entry, when moving from a bucket
overflow into a bucket header. */
new_bucket->data = data;
dst->n_buckets_used++;
free_entry (dst, cursor);
}
}
/* Now move the bucket head. Be sure that if we fail due to
allocation failure that the src table is in a consistent
state. */
data = bucket->data;
bucket->next = NULL;
if (safe)
continue;
new_bucket = safe_hasher (dst, data);
if (new_bucket->data)
{
/* Allocate or recycle an entry, when moving from a bucket
header into a bucket overflow. */
struct hash_entry *new_entry = allocate_entry (dst);
if (new_entry == NULL)
return false;
new_entry->data = data;
new_entry->next = new_bucket->next;
new_bucket->next = new_entry;
}
else
{
/* Move from one bucket header to another. */
new_bucket->data = data;
dst->n_buckets_used++;
}
bucket->data = NULL;
src->n_buckets_used--;
}
return true;
}
bool
hash_rehash (Hash_table *table, size_t candidate)
{
Hash_table storage;
Hash_table *new_table;
size_t new_size = compute_bucket_size (candidate, table->tuning);
if (!new_size)
return false;
if (new_size == table->n_buckets)
return true;
new_table = &storage;
new_table->bucket = calloc (new_size, sizeof *new_table->bucket);
if (new_table->bucket == NULL)
return false;
new_table->n_buckets = new_size;
new_table->bucket_limit = new_table->bucket + new_size;
new_table->n_buckets_used = 0;
new_table->n_entries = 0;
new_table->tuning = table->tuning;
new_table->hasher = table->hasher;
new_table->comparator = table->comparator;
new_table->data_freer = table->data_freer;
/* In order for the transfer to successfully complete, we need
additional overflow entries when distinct buckets in the old
table collide into a common bucket in the new table. The worst
case possible is a hasher that gives a good spread with the old
size, but returns a constant with the new size; if we were to
guarantee table->n_buckets_used-1 free entries in advance, then
the transfer would be guaranteed to not allocate memory.
However, for large tables, a guarantee of no further allocation
introduces a lot of extra memory pressure, all for an unlikely
corner case (most rehashes reduce, rather than increase, the
number of overflow entries needed). So, we instead ensure that
the transfer process can be reversed if we hit a memory
allocation failure mid-transfer. */
/* Merely reuse the extra old space into the new table. */
#if USE_OBSTACK
new_table->entry_stack = table->entry_stack;
#endif
new_table->free_entry_list = table->free_entry_list;
if (transfer_entries (new_table, table, false))
{
/* Entries transferred successfully; tie up the loose ends. */
free (table->bucket);
table->bucket = new_table->bucket;
table->bucket_limit = new_table->bucket_limit;
table->n_buckets = new_table->n_buckets;
table->n_buckets_used = new_table->n_buckets_used;
table->free_entry_list = new_table->free_entry_list;
/* table->n_entries and table->entry_stack already hold their value. */
return true;
}
/* We've allocated new_table->bucket (and possibly some entries),
exhausted the free list, and moved some but not all entries into
new_table. We must undo the partial move before returning
failure. The only way to get into this situation is if new_table
uses fewer buckets than the old table, so we will reclaim some
free entries as overflows in the new table are put back into
distinct buckets in the old table.
There are some pathological cases where a single pass through the
table requires more intermediate overflow entries than using two
passes. Two passes give worse cache performance and takes
longer, but at this point, we're already out of memory, so slow
and safe is better than failure. */
table->free_entry_list = new_table->free_entry_list;
if (! (transfer_entries (table, new_table, true)
&& transfer_entries (table, new_table, false)))
abort ();
/* table->n_entries already holds its value. */
free (new_table->bucket);
return false;
}
int
hash_insert_if_absent (Hash_table *table, void const *entry,
void const **matched_ent)
{
void *data;
struct hash_entry *bucket;
/* The caller cannot insert a NULL entry, since hash_lookup returns NULL
to indicate "not found", and hash_find_entry uses "bucket->data == NULL"
to indicate an empty bucket. */
if (! entry)
abort ();
/* If there's a matching entry already in the table, return that. */
if ((data = hash_find_entry (table, entry, &bucket, false)) != NULL)
{
if (matched_ent)
*matched_ent = data;
return 0;
}
/* If the growth threshold of the buckets in use has been reached, increase
the table size and rehash. There's no point in checking the number of
entries: if the hashing function is ill-conditioned, rehashing is not
likely to improve it. */
if (table->n_buckets_used
> table->tuning->growth_threshold * table->n_buckets)
{
/* Check more fully, before starting real work. If tuning arguments
became invalid, the second check will rely on proper defaults. */
check_tuning (table);
if (table->n_buckets_used
> table->tuning->growth_threshold * table->n_buckets)
{
const Hash_tuning *tuning = table->tuning;
float candidate =
(tuning->is_n_buckets
? (table->n_buckets * tuning->growth_factor)
: (table->n_buckets * tuning->growth_factor
* tuning->growth_threshold));
if ((float) SIZE_MAX <= candidate)
return -1;
/* If the rehash fails, arrange to return NULL. */
if (!hash_rehash (table, candidate))
return -1;
/* Update the bucket we are interested in. */
if (hash_find_entry (table, entry, &bucket, false) != NULL)
abort ();
}
}
/* ENTRY is not matched, it should be inserted. */
if (bucket->data)
{
struct hash_entry *new_entry = allocate_entry (table);
if (new_entry == NULL)
return -1;
/* Add ENTRY in the overflow of the bucket. */
new_entry->data = (void *) entry;
new_entry->next = bucket->next;
bucket->next = new_entry;
table->n_entries++;
return 1;
}
/* Add ENTRY right in the bucket head. */
bucket->data = (void *) entry;
table->n_entries++;
table->n_buckets_used++;
return 1;
}
void *
hash_insert (Hash_table *table, void const *entry)
{
void const *matched_ent;
int err = hash_insert_if_absent (table, entry, &matched_ent);
return (err == -1
? NULL
: (void *) (err == 0 ? matched_ent : entry));
}
void *
hash_remove (Hash_table *table, const void *entry)
{
void *data;
struct hash_entry *bucket;
data = hash_find_entry (table, entry, &bucket, true);
if (!data)
return NULL;
table->n_entries--;
if (!bucket->data)
{
table->n_buckets_used--;
/* If the shrink threshold of the buckets in use has been reached,
rehash into a smaller table. */
if (table->n_buckets_used
< table->tuning->shrink_threshold * table->n_buckets)
{
/* Check more fully, before starting real work. If tuning arguments
became invalid, the second check will rely on proper defaults. */
check_tuning (table);
if (table->n_buckets_used
< table->tuning->shrink_threshold * table->n_buckets)
{
const Hash_tuning *tuning = table->tuning;
size_t candidate =
(tuning->is_n_buckets
? table->n_buckets * tuning->shrink_factor
: (table->n_buckets * tuning->shrink_factor
* tuning->growth_threshold));
if (!hash_rehash (table, candidate))
{
/* Failure to allocate memory in an attempt to
shrink the table is not fatal. But since memory
is low, we can at least be kind and free any
spare entries, rather than keeping them tied up
in the free entry list. */
#if ! USE_OBSTACK
struct hash_entry *cursor = table->free_entry_list;
struct hash_entry *next;
while (cursor)
{
next = cursor->next;
free (cursor);
cursor = next;
}
table->free_entry_list = NULL;
#endif
}
}
}
}
return data;
}
void *
hash_delete (Hash_table *table, const void *entry)
{
return hash_remove (table, entry);
}
/* Testing. */
#if TESTING
void
hash_print (const Hash_table *table)
{
struct hash_entry *bucket = (struct hash_entry *) table->bucket;
for ( ; bucket < table->bucket_limit; bucket++)
{
struct hash_entry *cursor;
if (bucket)
printf ("%lu:\n", (unsigned long int) (bucket - table->bucket));
for (cursor = bucket; cursor; cursor = cursor->next)
{
char const *s = cursor->data;
/* FIXME */
if (s)
printf (" %s\n", s);
}
}
}
#endif /* TESTING */
recode-3.7.14/lib/isnanf.c 0000644 0001750 0001750 00000001541 14366047013 012165 0000000 0000000 /* Test for NaN that does not need libm.
Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Bruno Haible , 2007. */
#define USE_FLOAT
#include "isnan.c"
recode-3.7.14/lib/memchr.c 0000644 0001750 0001750 00000013455 14366047013 012171 0000000 0000000 /* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2023
Free Software Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
with help from Dan Sahlin (dan@sics.se) and
commentary by Jim Blandy (jimb@ai.mit.edu);
adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
and implemented by Roland McGrath (roland@ai.mit.edu).
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _LIBC
# include
#endif
#include
#include
#if defined _LIBC
# include
#else
# define reg_char char
#endif
#include
#if HAVE_BP_SYM_H || defined _LIBC
# include
#else
# define BP_SYM(sym) sym
#endif
#undef __memchr
#ifdef _LIBC
# undef memchr
#endif
#ifndef weak_alias
# define __memchr memchr
#endif
/* Search no more than N bytes of S for C. */
void *
__memchr (void const *s, int c_in, size_t n)
{
/* On 32-bit hardware, choosing longword to be a 32-bit unsigned
long instead of a 64-bit uintmax_t tends to give better
performance. On 64-bit hardware, unsigned long is generally 64
bits already. Change this typedef to experiment with
performance. */
typedef unsigned long int longword;
const unsigned char *char_ptr;
const longword *longword_ptr;
longword repeated_one;
longword repeated_c;
unsigned reg_char c;
c = (unsigned char) c_in;
/* Handle the first few bytes by reading one byte at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
for (char_ptr = (const unsigned char *) s;
n > 0 && (size_t) char_ptr % sizeof (longword) != 0;
--n, ++char_ptr)
if (*char_ptr == c)
return (void *) char_ptr;
longword_ptr = (const longword *) char_ptr;
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to any size longwords. */
/* Compute auxiliary longword values:
repeated_one is a value which has a 1 in every byte.
repeated_c has c in every byte. */
repeated_one = 0x01010101;
repeated_c = c | (c << 8);
repeated_c |= repeated_c << 16;
if (0xffffffffU < (longword) -1)
{
repeated_one |= repeated_one << 31 << 1;
repeated_c |= repeated_c << 31 << 1;
if (8 < sizeof (longword))
{
size_t i;
for (i = 64; i < sizeof (longword) * 8; i *= 2)
{
repeated_one |= repeated_one << i;
repeated_c |= repeated_c << i;
}
}
}
/* Instead of the traditional loop which tests each byte, we will test a
longword at a time. The tricky part is testing if *any of the four*
bytes in the longword in question are equal to c. We first use an xor
with repeated_c. This reduces the task to testing whether *any of the
four* bytes in longword1 is zero.
We compute tmp =
((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
That is, we perform the following operations:
1. Subtract repeated_one.
2. & ~longword1.
3. & a mask consisting of 0x80 in every byte.
Consider what happens in each byte:
- If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
and step 3 transforms it into 0x80. A carry can also be propagated
to more significant bytes.
- If a byte of longword1 is nonzero, let its lowest 1 bit be at
position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
the byte ends in a single bit of value 0 and k bits of value 1.
After step 2, the result is just k bits of value 1: 2^k - 1. After
step 3, the result is 0. And no carry is produced.
So, if longword1 has only non-zero bytes, tmp is zero.
Whereas if longword1 has a zero byte, call j the position of the least
significant zero byte. Then the result has a zero at positions 0, ...,
j-1 and a 0x80 at position j. We cannot predict the result at the more
significant bytes (positions j+1..3), but it does not matter since we
already have a non-zero bit at position 8*j+7.
So, the test whether any byte in longword1 is zero is equivalent to
testing whether tmp is nonzero. */
while (n >= sizeof (longword))
{
longword longword1 = *longword_ptr ^ repeated_c;
if ((((longword1 - repeated_one) & ~longword1)
& (repeated_one << 7)) != 0)
break;
longword_ptr++;
n -= sizeof (longword);
}
char_ptr = (const unsigned char *) longword_ptr;
/* At this point, we know that either n < sizeof (longword), or one of the
sizeof (longword) bytes starting at char_ptr is == c. On little-endian
machines, we could determine the first such byte without any further
memory accesses, just by looking at the tmp result from the last loop
iteration. But this does not work on big-endian machines. Choose code
that works in both cases. */
for (; n > 0; --n, ++char_ptr)
{
if (*char_ptr == c)
return (void *) char_ptr;
}
return NULL;
}
#ifdef weak_alias
weak_alias (__memchr, BP_SYM (memchr))
#endif
recode-3.7.14/lib/tempname.c 0000644 0001750 0001750 00000020776 14366047013 012530 0000000 0000000 /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
. */
#if !_LIBC
# include
# include "tempname.h"
#endif
#include
#include
#ifndef TMP_MAX
# define TMP_MAX 238328
#endif
#ifndef __GT_FILE
# define __GT_FILE 0
# define __GT_DIR 1
# define __GT_NOCREATE 2
#endif
#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \
|| GT_NOCREATE != __GT_NOCREATE)
# error report this to bug-gnulib@gnu.org
#endif
#include
#include
#include
#include
#include
#include
#include
#if _LIBC
# define struct_stat64 struct __stat64_t64
#else
# define struct_stat64 struct stat
# define __gen_tempname gen_tempname
# define __mkdir mkdir
# define __open open
# define __lstat64_time64(file, buf) lstat (file, buf)
# define __getrandom getrandom
# define __clock_gettime64 clock_gettime
# define __timespec64 timespec
#endif
/* Use getrandom if it works, falling back on a 64-bit linear
congruential generator that starts with Var's value
mixed in with a clock's low-order bits if available. */
typedef uint_fast64_t random_value;
#define RANDOM_VALUE_MAX UINT_FAST64_MAX
#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
/* Return the result of mixing the entropy from R and S.
Assume that R and S are not particularly random,
and that the result should look randomish to an untrained eye. */
static random_value
mix_random_values (random_value r, random_value s)
{
/* As this code is used only when high-quality randomness is neither
available nor necessary, there is no need for fancier polynomials
such as those in the Linux kernel's 'random' driver. */
return (2862933555777941757 * r + 3037000493) ^ s;
}
/* Set *R to a random value.
Return true if *R is set to high-quality value taken from getrandom.
Otherwise return false, falling back to a low-quality *R that might
depend on S.
This function returns false only when getrandom fails.
On GNU systems this should happen only early in the boot process,
when the fallback should be good enough for programs using tempname
because any attacker likely has root privileges already. */
static bool
random_bits (random_value *r, random_value s)
{
/* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */
if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r)
return true;
/* If getrandom did not work, use ersatz entropy based on low-order
clock bits. On GNU systems getrandom should fail only
early in booting, when ersatz should be good enough.
Do not use ASLR-based entropy, as that would leak ASLR info into
the resulting file name which is typically public.
Of course we are in a state of sin here. */
random_value v = s;
#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME)
struct __timespec64 tv;
__clock_gettime64 (CLOCK_REALTIME, &tv);
v = mix_random_values (v, tv.tv_sec);
v = mix_random_values (v, tv.tv_nsec);
#endif
*r = mix_random_values (v, clock ());
return false;
}
#if _LIBC
static int try_tempname_len (char *, int, void *, int (*) (char *, void *),
size_t);
#endif
static int
try_file (char *tmpl, void *flags)
{
int *openflags = flags;
return __open (tmpl,
(*openflags & ~O_ACCMODE)
| O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
}
static int
try_dir (char *tmpl, _GL_UNUSED void *flags)
{
return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
}
static int
try_nocreate (char *tmpl, _GL_UNUSED void *flags)
{
struct_stat64 st;
if (__lstat64_time64 (tmpl, &st) == 0 || errno == EOVERFLOW)
__set_errno (EEXIST);
return errno == ENOENT ? 0 : -1;
}
/* These are the characters used in temporary file names. */
static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
/* Generate a temporary file name based on TMPL. TMPL must match the
rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s,
possibly with a suffix).
The name constructed does not exist at the time of the call to
this function. TMPL is overwritten with the result.
KIND may be one of:
__GT_NOCREATE: simply verify that the name does not exist
at the time of the call.
__GT_FILE: create the file using open(O_CREAT|O_EXCL)
and return a read-write fd. The file is mode 0600.
__GT_DIR: create a directory, which will be mode 0700.
*/
#ifdef _LIBC
static
#endif
int
gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind,
size_t x_suffix_len)
{
static int (*const tryfunc[]) (char *, void *) =
{
[__GT_FILE] = try_file,
[__GT_DIR] = try_dir,
[__GT_NOCREATE] = try_nocreate
};
return try_tempname_len (tmpl, suffixlen, &flags, tryfunc[kind],
x_suffix_len);
}
#ifdef _LIBC
static
#endif
int
try_tempname_len (char *tmpl, int suffixlen, void *args,
int (*tryfunc) (char *, void *), size_t x_suffix_len)
{
size_t len;
char *XXXXXX;
unsigned int count;
int fd = -1;
int save_errno = errno;
/* A lower bound on the number of temporary files to attempt to
generate. The maximum total number of temporary file names that
can exist for a given template is 62**6. It should never be
necessary to try all of these combinations. Instead if a reasonable
number of names is tried (we define reasonable as 62**3) fail to
give the system administrator the chance to remove the problems.
This value requires that X_SUFFIX_LEN be at least 3. */
#define ATTEMPTS_MIN (62 * 62 * 62)
/* The number of times to attempt to generate a temporary file. To
conform to POSIX, this must be no smaller than TMP_MAX. */
#if ATTEMPTS_MIN < TMP_MAX
unsigned int attempts = TMP_MAX;
#else
unsigned int attempts = ATTEMPTS_MIN;
#endif
/* A random variable. */
random_value v = 0;
/* A value derived from the random variable, and how many random
base-62 digits can currently be extracted from VDIGBUF. */
random_value vdigbuf;
int vdigits = 0;
/* Least biased value for V. If V is less than this, V can generate
BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */
random_value const biased_min
= RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER;
len = strlen (tmpl);
if (len < x_suffix_len + suffixlen
|| strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len)
{
__set_errno (EINVAL);
return -1;
}
/* This is where the Xs start. */
XXXXXX = &tmpl[len - x_suffix_len - suffixlen];
for (count = 0; count < attempts; ++count)
{
for (size_t i = 0; i < x_suffix_len; i++)
{
if (vdigits == 0)
{
/* Worry about bias only if the bits are high quality. */
while (random_bits (&v, v) && biased_min <= v)
continue;
vdigbuf = v;
vdigits = BASE_62_DIGITS;
}
XXXXXX[i] = letters[vdigbuf % 62];
vdigbuf /= 62;
vdigits--;
}
fd = tryfunc (tmpl, args);
if (fd >= 0)
{
__set_errno (save_errno);
return fd;
}
else if (errno != EEXIST)
return -1;
}
/* We got out of the loop because we ran out of combinations to try. */
__set_errno (EEXIST);
return -1;
}
int
__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
{
return gen_tempname_len (tmpl, suffixlen, flags, kind, 6);
}
#if !_LIBC
int
try_tempname (char *tmpl, int suffixlen, void *args,
int (*tryfunc) (char *, void *))
{
return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6);
}
#endif
recode-3.7.14/lib/printf-frexp.h 0000644 0001750 0001750 00000002102 14366047013 013332 0000000 0000000 /* Split a double into fraction and mantissa, for hexadecimal printf.
Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Write a finite, positive number x as
x = mantissa * 2^exp
where exp >= DBL_MIN_EXP - 1,
mantissa < 2.0,
if x is not a denormalized number then mantissa >= 1.0.
Store exp in *EXPPTR and return mantissa. */
extern double printf_frexp (double x, int *expptr);
recode-3.7.14/lib/xmalloc.c 0000644 0001750 0001750 00000020272 14366047013 012350 0000000 0000000 /* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990-2000, 2002-2006, 2008-2023 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This 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 "ialloc.h"
#include "minmax.h"
#include
#include
#include
#include
static void * _GL_ATTRIBUTE_PURE
nonnull (void *p)
{
if (!p)
xalloc_die ();
return p;
}
/* Allocate S bytes of memory dynamically, with error checking. */
void *
xmalloc (size_t s)
{
return nonnull (malloc (s));
}
void *
ximalloc (idx_t s)
{
return nonnull (imalloc (s));
}
char *
xcharalloc (size_t n)
{
return XNMALLOC (n, char);
}
/* Change the size of an allocated block of memory P to S bytes,
with error checking. */
void *
xrealloc (void *p, size_t s)
{
void *r = realloc (p, s);
if (!r && (!p || s))
xalloc_die ();
return r;
}
void *
xirealloc (void *p, idx_t s)
{
return nonnull (irealloc (p, s));
}
/* Change the size of an allocated block of memory P to an array of N
objects each of S bytes, with error checking. */
void *
xreallocarray (void *p, size_t n, size_t s)
{
void *r = reallocarray (p, n, s);
if (!r && (!p || (n && s)))
xalloc_die ();
return r;
}
void *
xireallocarray (void *p, idx_t n, idx_t s)
{
return nonnull (ireallocarray (p, n, s));
}
/* Allocate an array of N objects, each with S bytes of memory,
dynamically, with error checking. S must be nonzero. */
void *
xnmalloc (size_t n, size_t s)
{
return xreallocarray (NULL, n, s);
}
void *
xinmalloc (idx_t n, idx_t s)
{
return xireallocarray (NULL, n, s);
}
/* If P is null, allocate a block of at least *PS bytes; otherwise,
reallocate P so that it contains more than *PS bytes. *PS must be
nonzero unless P is null. Set *PS to the new block's size, and
return the pointer to the new block. *PS is never set to zero, and
the returned pointer is never null. */
void *
x2realloc (void *p, size_t *ps)
{
return x2nrealloc (p, ps, 1);
}
/* If P is null, allocate a block of at least *PN such objects;
otherwise, reallocate P so that it contains more than *PN objects
each of S bytes. S must be nonzero. Set *PN to the new number of
objects, and return the pointer to the new block. *PN is never set
to zero, and the returned pointer is never null.
Repeated reallocations are guaranteed to make progress, either by
allocating an initial block with a nonzero size, or by allocating a
larger block.
In the following implementation, nonzero sizes are increased by a
factor of approximately 1.5 so that repeated reallocations have
O(N) overall cost rather than O(N**2) cost, but the
specification for this function does not guarantee that rate.
Here is an example of use:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
void
append_int (int value)
{
if (used == allocated)
p = x2nrealloc (p, &allocated, sizeof *p);
p[used++] = value;
}
This causes x2nrealloc to allocate a block of some nonzero size the
first time it is called.
To have finer-grained control over the initial size, set *PN to a
nonzero value before calling this function with P == NULL. For
example:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
size_t allocated1 = 1000;
void
append_int (int value)
{
if (used == allocated)
{
p = x2nrealloc (p, &allocated1, sizeof *p);
allocated = allocated1;
}
p[used++] = value;
}
*/
void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
size_t n = *pn;
if (! p)
{
if (! n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
zero. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
n = DEFAULT_MXFAST / s;
n += !n;
}
}
else
{
/* Set N = floor (1.5 * N) + 1 to make progress even if N == 0. */
if (ckd_add (&n, n, (n >> 1) + 1))
xalloc_die ();
}
p = xreallocarray (p, n, s);
*pn = n;
return p;
}
/* Grow PA, which points to an array of *PN items, and return the
location of the reallocated array, updating *PN to reflect its
new size. The new array will contain at least N_INCR_MIN more
items, but will not contain more than N_MAX items total.
S is the size of each item, in bytes.
S and N_INCR_MIN must be positive. *PN must be
nonnegative. If N_MAX is -1, it is treated as if it were
infinity.
If PA is null, then allocate a new array instead of reallocating
the old one.
Thus, to grow an array A without saving its old contents, do
{ free (A); A = xpalloc (NULL, &AITEMS, ...); }. */
void *
xpalloc (void *pa, idx_t *pn, idx_t n_incr_min, ptrdiff_t n_max, idx_t s)
{
idx_t n0 = *pn;
/* The approximate size to use for initial small allocation
requests. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
/* If the array is tiny, grow it to about (but no greater than)
DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%.
Adjust the growth according to three constraints: N_INCR_MIN,
N_MAX, and what the C language can represent safely. */
idx_t n;
if (ckd_add (&n, n0, n0 >> 1))
n = IDX_MAX;
if (0 <= n_max && n_max < n)
n = n_max;
/* NBYTES is of a type suitable for holding the count of bytes in an object.
This is typically idx_t, but it should be size_t on (theoretical?)
platforms where SIZE_MAX < IDX_MAX so xpalloc does not pass
values greater than SIZE_MAX to xrealloc. */
#if IDX_MAX <= SIZE_MAX
idx_t nbytes;
#else
size_t nbytes;
#endif
idx_t adjusted_nbytes
= (ckd_mul (&nbytes, n, s)
? MIN (IDX_MAX, SIZE_MAX)
: nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
if (adjusted_nbytes)
{
n = adjusted_nbytes / s;
nbytes = adjusted_nbytes - adjusted_nbytes % s;
}
if (! pa)
*pn = 0;
if (n - n0 < n_incr_min
&& (ckd_add (&n, n0, n_incr_min)
|| (0 <= n_max && n_max < n)
|| ckd_mul (&nbytes, n, s)))
xalloc_die ();
pa = xrealloc (pa, nbytes);
*pn = n;
return pa;
}
/* 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 xcalloc (s, 1);
}
void *
xizalloc (idx_t s)
{
return xicalloc (s, 1);
}
/* Allocate zeroed memory for N elements of S bytes, with error
checking. S must be nonzero. */
void *
xcalloc (size_t n, size_t s)
{
return nonnull (calloc (n, s));
}
void *
xicalloc (idx_t n, idx_t s)
{
return nonnull (icalloc (n, s));
}
/* 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);
}
void *
ximemdup (void const *p, idx_t s)
{
return memcpy (ximalloc (s), p, s);
}
/* Clone an object P of size S, with error checking. Append
a terminating NUL byte. */
char *
ximemdup0 (void const *p, idx_t s)
{
char *result = ximalloc (s + 1);
result[s] = 0;
return memcpy (result, p, s);
}
/* Clone STRING. */
char *
xstrdup (char const *string)
{
return xmemdup (string, strlen (string) + 1);
}
recode-3.7.14/lib/stat.c 0000644 0001750 0001750 00000032714 14366047013 011670 0000000 0000000 /* Work around platform bugs in stat.
Copyright (C) 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Eric Blake and Bruno Haible. */
/* 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 __CYGWIN__
# define WINDOWS_NATIVE
#endif
#if !defined WINDOWS_NATIVE
static int
orig_stat (const char *filename, struct stat *buf)
{
return stat (filename, buf);
}
#endif
/* Specification. */
#ifdef __osf__
/* 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"
#else
# include
#endif
#include "stat-time.h"
#include
#include
#include
#include "filename.h"
#include "malloca.h"
#ifdef WINDOWS_NATIVE
# define WIN32_LEAN_AND_MEAN
# include
# include "stat-w32.h"
/* Don't assume that UNICODE is not defined. */
# undef WIN32_FIND_DATA
# define WIN32_FIND_DATA WIN32_FIND_DATAA
# undef CreateFile
# define CreateFile CreateFileA
# undef FindFirstFile
# define FindFirstFile FindFirstFileA
#endif
#ifdef WINDOWS_NATIVE
/* Return TRUE if the given file name denotes an UNC root. */
static BOOL
is_unc_root (const char *rname)
{
/* Test whether it has the syntax '\\server\share'. */
if (ISSLASH (rname[0]) && ISSLASH (rname[1]))
{
/* It starts with two slashes. Find the next slash. */
const char *p = rname + 2;
const char *q = p;
while (*q != '\0' && !ISSLASH (*q))
q++;
if (q > p && *q != '\0')
{
/* Found the next slash at q. */
q++;
const char *r = q;
while (*r != '\0' && !ISSLASH (*r))
r++;
if (r > q && *r == '\0')
return TRUE;
}
}
return FALSE;
}
#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 *buf)
{
#ifdef WINDOWS_NATIVE
/* Fill the fields ourselves, because the original stat function returns
values for st_atime, st_mtime, st_ctime that depend on the current time
zone. See
*/
/* XXX Should we convert to wchar_t* and prepend '\\?\', in order to work
around length limitations
? */
/* POSIX
specifies: "More than two leading characters shall be treated as
a single character." */
if (ISSLASH (name[0]) && ISSLASH (name[1]) && ISSLASH (name[2]))
{
name += 2;
while (ISSLASH (name[1]))
name++;
}
size_t len = strlen (name);
size_t drive_prefix_len = (HAS_DEVICE (name) ? 2 : 0);
/* Remove trailing slashes (except the very first one, at position
drive_prefix_len), but remember their presence. */
size_t rlen;
bool check_dir = false;
rlen = len;
while (rlen > drive_prefix_len && ISSLASH (name[rlen-1]))
{
check_dir = true;
if (rlen == drive_prefix_len + 1)
break;
rlen--;
}
/* Handle '' and 'C:'. */
if (!check_dir && rlen == drive_prefix_len)
{
errno = ENOENT;
return -1;
}
/* Handle '\\'. */
if (rlen == 1 && ISSLASH (name[0]) && len >= 2)
{
errno = ENOENT;
return -1;
}
const char *rname;
char *malloca_rname;
if (rlen == len)
{
rname = name;
malloca_rname = NULL;
}
else
{
malloca_rname = malloca (rlen + 1);
if (malloca_rname == NULL)
{
errno = ENOMEM;
return -1;
}
memcpy (malloca_rname, name, rlen);
malloca_rname[rlen] = '\0';
rname = malloca_rname;
}
/* There are two ways to get at the requested information:
- by scanning the parent directory and examining the relevant
directory entry,
- by opening the file directly.
The first approach fails for root directories (e.g. 'C:\') and
UNC root directories (e.g. '\\server\share').
The second approach fails for some system files (e.g. 'C:\pagefile.sys'
and 'C:\hiberfil.sys'): ERROR_SHARING_VIOLATION.
The second approach gives more information (in particular, correct
st_dev, st_ino, st_nlink fields).
So we use the second approach and, as a fallback except for root and
UNC root directories, also the first approach. */
{
int ret;
{
/* Approach based on the file. */
/* Open a handle to the file.
CreateFile
*/
HANDLE h =
CreateFile (rname,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
/* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only
in case as different) makes sense only when applied to *all*
filesystem operations. */
FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */,
NULL);
if (h != INVALID_HANDLE_VALUE)
{
ret = _gl_fstat_by_handle (h, rname, buf);
CloseHandle (h);
goto done;
}
}
/* Test for root and UNC root directories. */
if ((rlen == drive_prefix_len + 1 && ISSLASH (rname[drive_prefix_len]))
|| is_unc_root (rname))
goto failed;
/* Fallback. */
{
/* Approach based on the directory entry. */
if (strchr (rname, '?') != NULL || strchr (rname, '*') != NULL)
{
/* Other Windows API functions would fail with error
ERROR_INVALID_NAME. */
if (malloca_rname != NULL)
freea (malloca_rname);
errno = ENOENT;
return -1;
}
/* Get the details about the directory entry. This can be done through
FindFirstFile
or through
FindFirstFileEx with argument FindExInfoBasic
*/
WIN32_FIND_DATA info;
HANDLE h = FindFirstFile (rname, &info);
if (h == INVALID_HANDLE_VALUE)
goto failed;
/* Test for error conditions before starting to fill *buf. */
if (sizeof (buf->st_size) <= 4 && info.nFileSizeHigh > 0)
{
FindClose (h);
if (malloca_rname != NULL)
freea (malloca_rname);
errno = EOVERFLOW;
return -1;
}
# if _GL_WINDOWS_STAT_INODES
buf->st_dev = 0;
# if _GL_WINDOWS_STAT_INODES == 2
buf->st_ino._gl_ino[0] = buf->st_ino._gl_ino[1] = 0;
# else /* _GL_WINDOWS_STAT_INODES == 1 */
buf->st_ino = 0;
# endif
# else
/* st_ino is not wide enough for identifying a file on a device.
Without st_ino, st_dev is pointless. */
buf->st_dev = 0;
buf->st_ino = 0;
# endif
/* st_mode. */
unsigned int mode =
/* XXX How to handle FILE_ATTRIBUTE_REPARSE_POINT ? */
((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR | S_IEXEC_UGO : _S_IFREG)
| S_IREAD_UGO
| ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE_UGO);
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
/* Determine whether the file is executable by looking at the file
name suffix. */
if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0)
{
const char *last_dot = NULL;
const char *p;
for (p = info.cFileName; *p != '\0'; p++)
if (*p == '.')
last_dot = p;
if (last_dot != NULL)
{
const char *suffix = last_dot + 1;
if (_stricmp (suffix, "exe") == 0
|| _stricmp (suffix, "bat") == 0
|| _stricmp (suffix, "cmd") == 0
|| _stricmp (suffix, "com") == 0)
mode |= S_IEXEC_UGO;
}
}
}
buf->st_mode = mode;
/* st_nlink. Ignore hard links here. */
buf->st_nlink = 1;
/* There's no easy way to map the Windows SID concept to an integer. */
buf->st_uid = 0;
buf->st_gid = 0;
/* st_rdev is irrelevant for normal files and directories. */
buf->st_rdev = 0;
/* st_size. */
if (sizeof (buf->st_size) <= 4)
/* Range check already done above. */
buf->st_size = info.nFileSizeLow;
else
buf->st_size = ((long long) info.nFileSizeHigh << 32) | (long long) info.nFileSizeLow;
/* st_atime, st_mtime, st_ctime. */
# if _GL_WINDOWS_STAT_TIMESPEC
buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime);
buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime);
buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime);
# else
buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime);
buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime);
buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime);
# endif
FindClose (h);
ret = 0;
}
done:
if (ret >= 0 && check_dir && !S_ISDIR (buf->st_mode))
{
errno = ENOTDIR;
ret = -1;
}
if (malloca_rname != NULL)
{
int saved_errno = errno;
freea (malloca_rname);
errno = saved_errno;
}
return ret;
}
failed:
{
DWORD error = GetLastError ();
#if 0
fprintf (stderr, "rpl_stat error 0x%x\n", (unsigned int) error);
#endif
if (malloca_rname != NULL)
freea (malloca_rname);
switch (error)
{
/* Some of these errors probably cannot happen with the specific flags
that we pass to CreateFile. But who knows... */
case ERROR_FILE_NOT_FOUND: /* The last component of rname does not exist. */
case ERROR_PATH_NOT_FOUND: /* Some directory component in rname does not exist. */
case ERROR_BAD_PATHNAME: /* rname is such as '\\server'. */
case ERROR_BAD_NET_NAME: /* rname is such as '\\server\nonexistentshare'. */
case ERROR_INVALID_NAME: /* rname contains wildcards, misplaced colon, etc. */
case ERROR_DIRECTORY:
errno = ENOENT;
break;
case ERROR_ACCESS_DENIED: /* rname is such as 'C:\System Volume Information\foo'. */
case ERROR_SHARING_VIOLATION: /* rname is such as 'C:\pagefile.sys' (second approach only). */
/* XXX map to EACCES or EPERM? */
errno = EACCES;
break;
case ERROR_OUTOFMEMORY:
errno = ENOMEM;
break;
case ERROR_WRITE_PROTECT:
errno = EROFS;
break;
case ERROR_WRITE_FAULT:
case ERROR_READ_FAULT:
case ERROR_GEN_FAILURE:
errno = EIO;
break;
case ERROR_BUFFER_OVERFLOW:
case ERROR_FILENAME_EXCED_RANGE:
errno = ENAMETOOLONG;
break;
case ERROR_DELETE_PENDING: /* XXX map to EACCES or EPERM? */
errno = EPERM;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
#else
int result = orig_stat (name, buf);
if (result == 0)
{
# if REPLACE_FUNC_STAT_FILE
/* Solaris 9 mistakenly succeeds when given a non-directory with a
trailing slash. */
if (!S_ISDIR (buf->st_mode))
{
size_t len = strlen (name);
if (ISSLASH (name[len - 1]))
{
errno = ENOTDIR;
return -1;
}
}
# endif /* REPLACE_FUNC_STAT_FILE */
result = stat_time_normalize (result, buf);
}
return result;
#endif
}
recode-3.7.14/lib/signbitd.c 0000644 0001750 0001750 00000004110 14366047013 012505 0000000 0000000 /* signbit() macro: Determine the sign bit of a floating-point number.
Copyright (C) 2007-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
/* Specification. */
#include
#include
#include "isnand-nolibm.h"
#include "float+.h"
#ifdef gl_signbitd_OPTIMIZED_MACRO
# undef gl_signbitd
#endif
int
gl_signbitd (double arg)
{
#if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
/* The use of a union to extract the bits of the representation of a
'long double' is safe in practice, despite of the "aliasing rules" of
C99, because the GCC docs say
"Even with '-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type."
and similarly for other compilers. */
# define NWORDS \
((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
union { double value; unsigned int word[NWORDS]; } m;
m.value = arg;
return (m.word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;
#elif HAVE_COPYSIGN_IN_LIBC
return copysign (1.0, arg) < 0;
#else
/* This does not do the right thing for NaN, but this is irrelevant for
most use cases. */
if (isnand (arg))
return 0;
if (arg < 0.0)
return 1;
else if (arg == 0.0)
{
/* Distinguish 0.0 and -0.0. */
static double plus_zero = 0.0;
double arg_mem = arg;
return (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0);
}
else
return 0;
#endif
}
recode-3.7.14/lib/float+.h 0000644 0001750 0001750 00000013007 14366047013 012074 0000000 0000000 /* Supplemental information about the floating-point formats.
Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
Written by Bruno Haible , 2007.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#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 */
recode-3.7.14/lib/getopt_int.h 0000644 0001750 0001750 00000010112 14366047013 013062 0000000 0000000 /* Internal declarations for getopt.
Copyright (C) 1989-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
#include
extern int _getopt_internal (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct);
/* Reentrant versions which can handle parsing multiple argument
vectors at the same time. */
/* Describe how to deal with options that follow non-option ARGV-elements.
REQUIRE_ORDER means don't recognize them as options; stop option
processing when the first non-option is seen. This is what POSIX
specifies should happen.
PERMUTE means permute the contents of ARGV as we scan, so that
eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written
to expect this.
RETURN_IN_ORDER is an option available to programs that were
written to expect options and other ARGV-elements in any order
and that care about the ordering of the two. We describe each
non-option ARGV-element as if it were the argument of an option
with character code 1.
The special argument '--' forces an end of option-scanning regardless
of the value of 'ordering'. In the case of RETURN_IN_ORDER, only
'--' can cause 'getopt' to return -1 with 'optind' != ARGC. */
enum __ord
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
};
/* Data type for reentrant functions. */
struct _getopt_data
{
/* These have exactly the same meaning as the corresponding global
variables, except that they are used for the reentrant
versions of getopt. */
int optind;
int opterr;
int optopt;
char *optarg;
/* Internal members. */
/* True if the internal members have been initialized. */
int __initialized;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
char *__nextchar;
/* See __ord above. */
enum __ord __ordering;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. 'first_nonopt' is the index in ARGV of the first
of them; 'last_nonopt' is the index after the last of them. */
int __first_nonopt;
int __last_nonopt;
};
/* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data,
int __posixly_correct);
extern int _getopt_long_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
extern int _getopt_long_only_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,
struct _getopt_data *__data);
#endif /* getopt_int.h */
recode-3.7.14/lib/getopt-core.h 0000644 0001750 0001750 00000007132 14366047013 013146 0000000 0000000 /* Declarations for getopt (basic, portable features only).
Copyright (C) 1989-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
. */
#ifndef _GETOPT_CORE_H
#define _GETOPT_CORE_H 1
/* This header should not be used directly; include getopt.h or
unistd.h instead. Unlike most bits headers, it does not have
a protective #error, because the guard macro for getopt.h in
gnulib is not fixed. */
__BEGIN_DECLS
/* For communication from 'getopt' to the caller.
When 'getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when 'ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to 'getopt'.
On entry to 'getopt', zero means this is the first call; initialize.
When 'getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, 'optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message 'getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, 'optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in 'optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU 'getopt'.
The argument '--' causes premature termination of argument
scanning, explicitly telling 'getopt' that there are no more
options.
If OPTS begins with '-', then non-option arguments are treated as
arguments to the option '\1'. This behavior is specific to the GNU
'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in
the environment, then do not permute arguments.
For standards compliance, the 'argv' argument has the type
char *const *, but this is inaccurate; if argument permutation is
enabled, the argv array (not the strings it points to) must be
writable. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW _GL_ARG_NONNULL ((2, 3));
__END_DECLS
#endif /* _GETOPT_CORE_H */
recode-3.7.14/lib/xalloc.h 0000644 0001750 0001750 00000015242 14366047013 012201 0000000 0000000 /* xalloc.h -- malloc with out-of-memory checking
Copyright (C) 1990-2000, 2003-2004, 2006-2023 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(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 XALLOC_H_
#define XALLOC_H_
#include
#include
#if GNULIB_XALLOC
# include "idx.h"
#endif
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef XALLOC_INLINE
# define XALLOC_INLINE _GL_INLINE
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if GNULIB_XALLOC_DIE
/* This function is always triggered when memory is exhausted.
It must be defined by the application, either explicitly
or by using gnulib's xalloc-die module. This is the
function to call when one wants the program to die because of a
memory allocation failure. */
/*extern*/ _Noreturn void xalloc_die (void);
#endif /* GNULIB_XALLOC_DIE */
#if GNULIB_XALLOC
void *xmalloc (size_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *ximalloc (idx_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xinmalloc (idx_t n, idx_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1, 2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xzalloc (size_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xizalloc (idx_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xcalloc (size_t n, size_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1, 2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xicalloc (idx_t n, idx_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1, 2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xrealloc (void *p, size_t s)
_GL_ATTRIBUTE_ALLOC_SIZE ((2));
void *xirealloc (void *p, idx_t s)
_GL_ATTRIBUTE_ALLOC_SIZE ((2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *xreallocarray (void *p, size_t n, size_t s)
_GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
void *xireallocarray (void *p, idx_t n, idx_t s)
_GL_ATTRIBUTE_ALLOC_SIZE ((2, 3)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *x2realloc (void *p, size_t *ps) /* superseded by xpalloc */
_GL_ATTRIBUTE_RETURNS_NONNULL;
void *x2nrealloc (void *p, size_t *pn, size_t s) /* superseded by xpalloc */
_GL_ATTRIBUTE_RETURNS_NONNULL;
void *xpalloc (void *pa, idx_t *pn, idx_t n_incr_min, ptrdiff_t n_max, idx_t s)
_GL_ATTRIBUTE_RETURNS_NONNULL;
void *xmemdup (void const *p, size_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
void *ximemdup (void const *p, idx_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
char *ximemdup0 (void const *p, idx_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_RETURNS_NONNULL;
char *xstrdup (char const *str)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_RETURNS_NONNULL;
/* In the following macros, T must be an elementary or structure/union or
typedef'ed type, or a pointer to such a type. To apply one of the
following macros to a function pointer or array type, you need to typedef
it first and use the typedef name. */
/* Allocate an object of type T dynamically, with error checking. */
/* extern t *XMALLOC (typename t); */
# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
/* Allocate memory for N elements of type T, with error checking. */
/* extern t *XNMALLOC (size_t n, typename t); */
# define XNMALLOC(n, t) \
((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
/* Allocate an object of type T dynamically, with error checking,
and zero it. */
/* extern t *XZALLOC (typename t); */
# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
/* Allocate memory for N elements of type T, with error checking,
and zero it. */
/* extern t *XCALLOC (size_t n, typename t); */
# define XCALLOC(n, t) \
((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
/* Allocate an array of N objects, each with S bytes of memory,
dynamically, with error checking. S must be nonzero. */
void *xnmalloc (size_t n, size_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1, 2)) _GL_ATTRIBUTE_RETURNS_NONNULL;
/* FIXME: Deprecate this in favor of xreallocarray? */
/* Change the size of an allocated block of memory P to an array of N
objects each of S bytes, with error checking. S must be nonzero. */
XALLOC_INLINE void *xnrealloc (void *p, size_t n, size_t s)
_GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
XALLOC_INLINE void *
xnrealloc (void *p, size_t n, size_t s)
{
return xreallocarray (p, n, s);
}
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
except it returns char *. */
char *xcharalloc (size_t n)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
_GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL;
#endif /* GNULIB_XALLOC */
#ifdef __cplusplus
}
#endif
#if GNULIB_XALLOC && defined __cplusplus
/* C++ does not allow conversions from void * to other pointer types
without a cast. Use templates to work around the problem when
possible. */
template inline T *
xrealloc (T *p, size_t s)
{
return (T *) xrealloc ((void *) p, s);
}
template inline T *
xreallocarray (T *p, size_t n, size_t s)
{
return (T *) xreallocarray ((void *) p, n, s);
}
/* FIXME: Deprecate this in favor of xreallocarray? */
template inline T *
xnrealloc (T *p, size_t n, size_t s)
{
return xreallocarray (p, n, s);
}
template inline T *
x2realloc (T *p, size_t *pn)
{
return (T *) x2realloc ((void *) p, pn);
}
template inline T *
x2nrealloc (T *p, size_t *pn, size_t s)
{
return (T *) x2nrealloc ((void *) p, pn, s);
}
template inline T *
xmemdup (T const *p, size_t s)
{
return (T *) xmemdup ((void const *) p, s);
}
#endif /* GNULIB_XALLOC && C++ */
_GL_INLINE_HEADER_END
#endif /* !XALLOC_H_ */
recode-3.7.14/lib/getopt-pfx-core.h 0000644 0001750 0001750 00000005024 14366047013 013737 0000000 0000000 /* getopt (basic, portable features) gnulib wrapper header.
Copyright (C) 1989-2023 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _GETOPT_PFX_CORE_H
#define _GETOPT_PFX_CORE_H 1
/* This header should not be used directly; include getopt.h or
unistd.h instead. It does not have a protective #error, because
the guard macro for getopt.h in gnulib is not fixed. */
/* Standalone applications should #define __GETOPT_PREFIX to an
identifier that prefixes the external functions and variables
defined in getopt-core.h and getopt-ext.h. Systematically
rename identifiers so that they do not collide with the system
functions and variables. Renaming avoids problems with some
compilers and linkers. */
#ifdef __GETOPT_PREFIX
# ifndef __GETOPT_ID
# define __GETOPT_CONCAT(x, y) x ## y
# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
# endif
# undef getopt
# undef optarg
# undef opterr
# undef optind
# undef optopt
# define getopt __GETOPT_ID (getopt)
# define optarg __GETOPT_ID (optarg)
# define opterr __GETOPT_ID (opterr)
# define optind __GETOPT_ID (optind)
# define optopt __GETOPT_ID (optopt)
/* Work around a a problem on macOS, which declares getopt with a
trailing __DARWIN_ALIAS(getopt) that would expand to something like
__asm("_" "rpl_getopt" "$UNIX2003") were it not for the following
hack to suppress the macOS declaration . */
# ifdef __APPLE__
# define _GETOPT
# endif
/* The system's getopt.h may have already included getopt-core.h to
declare the unprefixed identifiers. Undef _GETOPT_CORE_H so that
getopt-core.h declares them with prefixes. */
# undef _GETOPT_CORE_H
#endif
#include
#endif /* _GETOPT_PFX_CORE_H */
recode-3.7.14/lib/mbtowc-lock.c 0000644 0001750 0001750 00000010446 14366047013 013134 0000000 0000000 /* Return the internal lock used by mbrtowc and mbrtoc32.
Copyright (C) 2019-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Bruno Haible , 2019-2020. */
#include
/* When it is known that the gl_get_mbtowc_lock function is defined
by a dependency library, it should not be defined here. */
#if OMIT_MBTOWC_LOCK
/* This declaration is solely to ensure that after preprocessing
this file is never empty. */
typedef int dummy;
#else
/* This file defines the internal lock used by mbrtowc and mbrtoc32.
It is a separate compilation unit, so that only one copy of it is
present when linking statically. */
/* Prohibit renaming this symbol. */
# undef gl_get_mbtowc_lock
/* Macro for exporting a symbol (function, not variable) defined in this file,
when compiled into a shared library. */
# ifndef DLL_EXPORTED
# if HAVE_VISIBILITY
/* Override the effect of the compiler option '-fvisibility=hidden'. */
# define DLL_EXPORTED __attribute__((__visibility__("default")))
# elif defined _WIN32 || defined __CYGWIN__
# define DLL_EXPORTED __declspec(dllexport)
# else
# define DLL_EXPORTED
# endif
# endif
# if defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include
# include "windows-initguard.h"
/* The return type is a 'CRITICAL_SECTION *', not a 'glwthread_mutex_t *',
because the latter is not guaranteed to be a stable ABI in the future. */
/* Make sure the function gets exported from DLLs. */
DLL_EXPORTED CRITICAL_SECTION *gl_get_mbtowc_lock (void);
static glwthread_initguard_t guard = GLWTHREAD_INITGUARD_INIT;
static CRITICAL_SECTION lock;
/* Returns the internal lock used by mbrtowc and mbrtoc32. */
CRITICAL_SECTION *
gl_get_mbtowc_lock (void)
{
if (!guard.done)
{
if (InterlockedIncrement (&guard.started) == 0)
{
/* This thread is the first one to need the lock. Initialize it. */
InitializeCriticalSection (&lock);
guard.done = 1;
}
else
{
/* Don't let guard.started grow and wrap around. */
InterlockedDecrement (&guard.started);
/* Yield the CPU while waiting for another thread to finish
initializing this mutex. */
while (!guard.done)
Sleep (0);
}
}
return &lock;
}
# elif HAVE_PTHREAD_API
# include
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* Make sure the function gets exported from shared libraries. */
DLL_EXPORTED pthread_mutex_t *gl_get_mbtowc_lock (void);
/* Returns the internal lock used by mbrtowc and mbrtoc32. */
pthread_mutex_t *
gl_get_mbtowc_lock (void)
{
return &mutex;
}
# elif HAVE_THREADS_H
# include
# include
static int volatile init_needed = 1;
static once_flag init_once = ONCE_FLAG_INIT;
static mtx_t mutex;
static void
atomic_init (void)
{
if (mtx_init (&mutex, mtx_plain) != thrd_success)
abort ();
init_needed = 0;
}
/* Make sure the function gets exported from shared libraries. */
DLL_EXPORTED mtx_t *gl_get_mbtowc_lock (void);
/* Returns the internal lock used by mbrtowc and mbrtoc32. */
mtx_t *
gl_get_mbtowc_lock (void)
{
if (init_needed)
call_once (&init_once, atomic_init);
return &mutex;
}
# endif
# if (defined _WIN32 || defined __CYGWIN__) && !defined _MSC_VER
/* Make sure the '__declspec(dllimport)' in mbrtowc.c and mbrtoc32.c does not
cause a link failure when no DLLs are involved. */
# if defined _WIN64 || defined _LP64
# define IMP(x) __imp_##x
# else
# define IMP(x) _imp__##x
# endif
void * IMP(gl_get_mbtowc_lock) = &gl_get_mbtowc_lock;
# endif
#endif
recode-3.7.14/lib/mbrtowc-impl.h 0000644 0001750 0001750 00000016240 14366047013 013332 0000000 0000000 /* Convert multibyte character to wide character.
Copyright (C) 1999-2002, 2005-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Bruno Haible , 2008. */
/* This file contains the body of the mbrtowc and mbrtoc32 functions,
when GNULIB_defined_mbstate_t is defined. */
char *pstate = (char *)ps;
if (s == NULL)
{
pwc = NULL;
s = "";
n = 1;
}
if (n == 0)
return (size_t)(-2);
/* Here n > 0. */
if (pstate == NULL)
pstate = internal_state;
{
size_t nstate = pstate[0];
char buf[4];
const char *p;
size_t m;
enc_t enc;
int res;
switch (nstate)
{
case 0:
p = s;
m = n;
break;
case 3:
buf[2] = pstate[3];
FALLTHROUGH;
case 2:
buf[1] = pstate[2];
FALLTHROUGH;
case 1:
buf[0] = pstate[1];
p = buf;
m = nstate;
buf[m++] = s[0];
if (n >= 2 && m < 4)
{
buf[m++] = s[1];
if (n >= 3 && m < 4)
buf[m++] = s[2];
}
break;
default:
errno = EINVAL;
return (size_t)(-1);
}
/* Here m > 0. */
enc = locale_encoding_classification ();
if (enc == enc_utf8) /* UTF-8 */
{
/* Achieve
- multi-thread safety and
- the ability to produce wide character values > WCHAR_MAX
by not calling mbtowc() at all. */
#include "mbrtowc-impl-utf8.h"
}
else
{
/* The hidden internal state of mbtowc would make this function not
multi-thread safe. Achieve multi-thread safety through a lock. */
wchar_t wc;
res = mbtowc_with_lock (&wc, p, m);
if (res >= 0)
{
if ((wc == 0) != (res == 0))
abort ();
if (pwc != NULL)
*pwc = wc;
goto success;
}
/* mbtowc does not distinguish between invalid and incomplete multibyte
sequences. But mbrtowc needs to make this distinction.
There are two possible approaches:
- Use iconv() and its return value.
- Use built-in knowledge about the possible encodings.
Given the low quality of implementation of iconv() on the systems
that lack mbrtowc(), we use the second approach.
The possible encodings are:
- 8-bit encodings,
- EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
- UTF-8 (already handled above).
Use specialized code for each. */
if (m >= 4 || m >= MB_CUR_MAX)
goto invalid;
/* Here MB_CUR_MAX > 1 and 0 < m < 4. */
switch (enc)
{
/* As a reference for this code, you can use the GNU libiconv
implementation. Look for uses of the RET_TOOFEW macro. */
case enc_eucjp: /* EUC-JP */
{
if (m == 1)
{
unsigned char c = (unsigned char) p[0];
if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
goto incomplete;
}
if (m == 2)
{
unsigned char c = (unsigned char) p[0];
if (c == 0x8f)
{
unsigned char c2 = (unsigned char) p[1];
if (c2 >= 0xa1 && c2 < 0xff)
goto incomplete;
}
}
goto invalid;
}
case enc_94: /* EUC-KR, GB2312, BIG5 */
{
if (m == 1)
{
unsigned char c = (unsigned char) p[0];
if (c >= 0xa1 && c < 0xff)
goto incomplete;
}
goto invalid;
}
case enc_euctw: /* EUC-TW */
{
if (m == 1)
{
unsigned char c = (unsigned char) p[0];
if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
goto incomplete;
}
else /* m == 2 || m == 3 */
{
unsigned char c = (unsigned char) p[0];
if (c == 0x8e)
goto incomplete;
}
goto invalid;
}
case enc_gb18030: /* GB18030 */
{
if (m == 1)
{
unsigned char c = (unsigned char) p[0];
if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
goto incomplete;
}
else /* m == 2 || m == 3 */
{
unsigned char c = (unsigned char) p[0];
if (c >= 0x90 && c <= 0xe3)
{
unsigned char c2 = (unsigned char) p[1];
if (c2 >= 0x30 && c2 <= 0x39)
{
if (m == 2)
goto incomplete;
else /* m == 3 */
{
unsigned char c3 = (unsigned char) p[2];
if (c3 >= 0x81 && c3 <= 0xfe)
goto incomplete;
}
}
}
}
goto invalid;
}
case enc_sjis: /* SJIS */
{
if (m == 1)
{
unsigned char c = (unsigned char) p[0];
if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
|| (c >= 0xf0 && c <= 0xf9))
goto incomplete;
}
goto invalid;
}
default:
/* An unknown multibyte encoding. */
goto incomplete;
}
}
success:
/* res >= 0 is the corrected return value of
mbtowc_with_lock (&wc, p, m). */
if (nstate >= (res > 0 ? res : 1))
abort ();
res -= nstate;
pstate[0] = 0;
return res;
incomplete:
{
size_t k = nstate;
/* Here 0 <= k < m < 4. */
pstate[++k] = s[0];
if (k < m)
{
pstate[++k] = s[1];
if (k < m)
pstate[++k] = s[2];
}
if (k != m)
abort ();
}
pstate[0] = m;
return (size_t)(-2);
invalid:
errno = EILSEQ;
/* The conversion state is undefined, says POSIX. */
return (size_t)(-1);
}
recode-3.7.14/lib/quotearg.c 0000644 0001750 0001750 00000104526 14366047013 012545 0000000 0000000 /* quotearg.c - quote arguments for output
Copyright (C) 1998-2002, 2004-2023 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This 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 */
/* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that
the quoting_options_from_style function might be candidate for
attribute 'pure' */
#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
#endif
#include
#include "quotearg.h"
#include "quote.h"
#include "attribute.h"
#include "minmax.h"
#include "xalloc.h"
#include "c-strcaseeq.h"
#include "localcharset.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "gettext.h"
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#define INT_BITS (sizeof (int) * CHAR_BIT)
struct quoting_options
{
/* Basic quoting style. */
enum quoting_style style;
/* Additional flags. Bitwise combination of enum quoting_flags. */
int flags;
/* Quote the characters indicated by this bit vector even if the
quoting style would not normally require them to be quoted. */
unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
/* The left quote for custom_quoting_style. */
char const *left_quote;
/* The right quote for custom_quoting_style. */
char const *right_quote;
};
/* Names of quoting styles. */
char const *const quoting_style_args[] =
{
"literal",
"shell",
"shell-always",
"shell-escape",
"shell-escape-always",
"c",
"c-maybe",
"escape",
"locale",
"clocale",
0
};
/* Correspondences to quoting style names. */
enum quoting_style const quoting_style_vals[] =
{
literal_quoting_style,
shell_quoting_style,
shell_always_quoting_style,
shell_escape_quoting_style,
shell_escape_always_quoting_style,
c_quoting_style,
c_maybe_quoting_style,
escape_quoting_style,
locale_quoting_style,
clocale_quoting_style
};
/* The default quoting options. */
static struct quoting_options default_quoting_options;
/* Allocate a new set of quoting options, with contents initially identical
to O if O is not null, or to the default if O is null.
It is the caller's responsibility to free the result. */
struct quoting_options *
clone_quoting_options (struct quoting_options *o)
{
int e = errno;
struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
sizeof *o);
errno = e;
return p;
}
/* Get the value of O's quoting style. If O is null, use the default. */
enum quoting_style
get_quoting_style (struct quoting_options const *o)
{
return (o ? o : &default_quoting_options)->style;
}
/* In O (or in the default if O is null),
set the value of the quoting style to S. */
void
set_quoting_style (struct quoting_options *o, enum quoting_style s)
{
(o ? o : &default_quoting_options)->style = s;
}
/* In O (or in the default if O is null),
set the value of the quoting options for character C to I.
Return the old value. Currently, the only values defined for I are
0 (the default) and 1 (which means to quote the character even if
it would not otherwise be quoted). */
int
set_char_quoting (struct quoting_options *o, char c, int i)
{
unsigned char uc = c;
unsigned int *p =
(o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
int shift = uc % INT_BITS;
int r = (*p >> shift) & 1;
*p ^= ((i & 1) ^ r) << shift;
return r;
}
/* In O (or in the default if O is null),
set the value of the quoting options flag to I, which can be a
bitwise combination of enum quoting_flags, or 0 for default
behavior. Return the old value. */
int
set_quoting_flags (struct quoting_options *o, int i)
{
int r;
if (!o)
o = &default_quoting_options;
r = o->flags;
o->flags = i;
return r;
}
void
set_custom_quoting (struct quoting_options *o,
char const *left_quote, char const *right_quote)
{
if (!o)
o = &default_quoting_options;
o->style = custom_quoting_style;
if (!left_quote || !right_quote)
abort ();
o->left_quote = left_quote;
o->right_quote = right_quote;
}
/* Return quoting options for STYLE, with no extra quoting. */
static struct quoting_options /* NOT PURE!! */
quoting_options_from_style (enum quoting_style style)
{
struct quoting_options o = { literal_quoting_style, 0, { 0 }, NULL, NULL };
if (style == custom_quoting_style)
abort ();
o.style = style;
return o;
}
/* MSGID approximates a quotation mark. Return its translation if it
has one; otherwise, return either it or "\"", depending on S.
S is either clocale_quoting_style or locale_quoting_style. */
static char const *
gettext_quote (char const *msgid, enum quoting_style s)
{
char const *translation = _(msgid);
char const *locale_code;
if (translation != msgid)
return translation;
/* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019.
Here is a list of other locales that include U+2018 and U+2019:
ISO-8859-7 0xA1 KOI8-T 0x91
CP869 0x8B CP874 0x91
CP932 0x81 0x65 CP936 0xA1 0xAE
CP949 0xA1 0xAE CP950 0xA1 0xA5
CP1250 0x91 CP1251 0x91
CP1252 0x91 CP1253 0x91
CP1254 0x91 CP1255 0x91
CP1256 0x91 CP1257 0x91
EUC-JP 0xA1 0xC6 EUC-KR 0xA1 0xAE
EUC-TW 0xA1 0xE4 BIG5 0xA1 0xA5
BIG5-HKSCS 0xA1 0xA5 EUC-CN 0xA1 0xAE
GBK 0xA1 0xAE Georgian-PS 0x91
PT154 0x91
None of these is still in wide use; using iconv is overkill. */
locale_code = locale_charset ();
if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0))
return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99";
if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0))
return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf";
return (s == clocale_quoting_style ? "\"" : "'");
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
QUOTE_THESE_TOO to control quoting.
Terminate the output with a null character, and return the written
size of the output, not counting the terminating null.
If BUFFERSIZE is too small to store the output string, return the
value that would have been returned had BUFFERSIZE been large enough.
If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
ARGSIZE, O), except it breaks O into its component pieces and is
not careful about errno. */
static size_t
quotearg_buffer_restyled (char *buffer, size_t buffersize,
char const *arg, size_t argsize,
enum quoting_style quoting_style, int flags,
unsigned int const *quote_these_too,
char const *left_quote,
char const *right_quote)
{
size_t i;
size_t len = 0;
size_t orig_buffersize = 0;
char const *quote_string = 0;
size_t quote_string_len = 0;
bool backslash_escapes = false;
bool unibyte_locale = MB_CUR_MAX == 1;
bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
bool pending_shell_escape_end = false;
bool encountered_single_quote = false;
bool all_c_and_shell_quote_compat = true;
#define STORE(c) \
do \
{ \
if (len < buffersize) \
buffer[len] = (c); \
len++; \
} \
while (0)
#define START_ESC() \
do \
{ \
if (elide_outer_quotes) \
goto force_outer_quoting_style; \
escaping = true; \
if (quoting_style == shell_always_quoting_style \
&& ! pending_shell_escape_end) \
{ \
STORE ('\''); \
STORE ('$'); \
STORE ('\''); \
pending_shell_escape_end = true; \
} \
STORE ('\\'); \
} \
while (0)
#define END_ESC() \
do \
{ \
if (pending_shell_escape_end && ! escaping) \
{ \
STORE ('\''); \
STORE ('\''); \
pending_shell_escape_end = false; \
} \
} \
while (0)
process_input:
switch (quoting_style)
{
case c_maybe_quoting_style:
quoting_style = c_quoting_style;
elide_outer_quotes = true;
FALLTHROUGH;
case c_quoting_style:
if (!elide_outer_quotes)
STORE ('"');
backslash_escapes = true;
quote_string = "\"";
quote_string_len = 1;
break;
case escape_quoting_style:
backslash_escapes = true;
elide_outer_quotes = false;
break;
case locale_quoting_style:
case clocale_quoting_style:
case custom_quoting_style:
{
if (quoting_style != custom_quoting_style)
{
/* TRANSLATORS:
Get translations for open and closing quotation marks.
The message catalog should translate "`" to a left
quotation mark suitable for the locale, and similarly for
"'". For example, a French Unicode local should translate
these to U+00AB (LEFT-POINTING DOUBLE ANGLE
QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE
QUOTATION MARK), respectively.
If the catalog has no translation, we will try to
use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and
Unicode U+2019 (RIGHT SINGLE QUOTATION MARK). If the
current locale is not Unicode, locale_quoting_style
will quote 'like this', and clocale_quoting_style will
quote "like this". You should always include translations
for "`" and "'" even if U+2018 and U+2019 are appropriate
for your locale.
If you don't know what to put here, please see
and use glyphs suitable for your language. */
left_quote = gettext_quote (N_("`"), quoting_style);
right_quote = gettext_quote (N_("'"), quoting_style);
}
if (!elide_outer_quotes)
for (quote_string = left_quote; *quote_string; quote_string++)
STORE (*quote_string);
backslash_escapes = true;
quote_string = right_quote;
quote_string_len = strlen (quote_string);
}
break;
case shell_escape_quoting_style:
backslash_escapes = true;
FALLTHROUGH;
case shell_quoting_style:
elide_outer_quotes = true;
FALLTHROUGH;
case shell_escape_always_quoting_style:
if (!elide_outer_quotes)
backslash_escapes = true;
FALLTHROUGH;
case shell_always_quoting_style:
quoting_style = shell_always_quoting_style;
if (!elide_outer_quotes)
STORE ('\'');
quote_string = "'";
quote_string_len = 1;
break;
case literal_quoting_style:
elide_outer_quotes = false;
break;
default:
abort ();
}
for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
{
unsigned char c;
unsigned char esc;
bool is_right_quote = false;
bool escaping = false;
bool c_and_shell_quote_compat = false;
if (backslash_escapes
&& quoting_style != shell_always_quoting_style
&& quote_string_len
&& (i + quote_string_len
<= (argsize == SIZE_MAX && 1 < quote_string_len
/* Use strlen only if we must: when argsize is SIZE_MAX,
and when the quote string is more than 1 byte long.
If we do call strlen, save the result. */
? (argsize = strlen (arg)) : argsize))
&& memcmp (arg + i, quote_string, quote_string_len) == 0)
{
if (elide_outer_quotes)
goto force_outer_quoting_style;
is_right_quote = true;
}
c = arg[i];
switch (c)
{
case '\0':
if (backslash_escapes)
{
START_ESC ();
/* If quote_string were to begin with digits, we'd need to
test for the end of the arg as well. However, it's
hard to imagine any locale that would use digits in
quotes, and set_custom_quoting is documented not to
accept them. Use only a single \0 with shell-escape
as currently digits are not printed within $'...' */
if (quoting_style != shell_always_quoting_style
&& i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
{
STORE ('0');
STORE ('0');
}
c = '0';
/* We don't have to worry that this last '0' will be
backslash-escaped because, again, quote_string should
not start with it and because quote_these_too is
documented as not accepting it. */
}
else if (flags & QA_ELIDE_NULL_BYTES)
continue;
break;
case '?':
switch (quoting_style)
{
case shell_always_quoting_style:
if (elide_outer_quotes)
goto force_outer_quoting_style;
break;
case c_quoting_style:
if ((flags & QA_SPLIT_TRIGRAPHS)
&& i + 2 < argsize && arg[i + 1] == '?')
switch (arg[i + 2])
{
case '!': case '\'':
case '(': case ')': case '-': case '/':
case '<': case '=': case '>':
/* Escape the second '?' in what would otherwise be
a trigraph. */
if (elide_outer_quotes)
goto force_outer_quoting_style;
c = arg[i + 2];
i += 2;
STORE ('?');
STORE ('"');
STORE ('"');
STORE ('?');
break;
default:
break;
}
break;
default:
break;
}
break;
case '\a': esc = 'a'; goto c_escape;
case '\b': esc = 'b'; goto c_escape;
case '\f': esc = 'f'; goto c_escape;
case '\n': esc = 'n'; goto c_and_shell_escape;
case '\r': esc = 'r'; goto c_and_shell_escape;
case '\t': esc = 't'; goto c_and_shell_escape;
case '\v': esc = 'v'; goto c_escape;
case '\\': esc = c;
/* Never need to escape '\' in shell case. */
if (quoting_style == shell_always_quoting_style)
{
if (elide_outer_quotes)
goto force_outer_quoting_style;
goto store_c;
}
/* No need to escape the escape if we are trying to elide
outer quotes and nothing else is problematic. */
if (backslash_escapes && elide_outer_quotes && quote_string_len)
goto store_c;
c_and_shell_escape:
if (quoting_style == shell_always_quoting_style
&& elide_outer_quotes)
goto force_outer_quoting_style;
/* fall through */
c_escape:
if (backslash_escapes)
{
c = esc;
goto store_escape;
}
break;
case '{': case '}': /* sometimes special if isolated */
if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
break;
FALLTHROUGH;
case '#': case '~':
if (i != 0)
break;
FALLTHROUGH;
case ' ':
c_and_shell_quote_compat = true;
FALLTHROUGH;
case '!': /* special in bash */
case '"': case '$': case '&':
case '(': case ')': case '*': case ';':
case '<':
case '=': /* sometimes special in 0th or (with "set -k") later args */
case '>': case '[':
case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
case '`': case '|':
/* A shell special character. In theory, '$' and '`' could
be the first bytes of multibyte characters, which means
we should check them with mbrtowc, but in practice this
doesn't happen so it's not worth worrying about. */
if (quoting_style == shell_always_quoting_style
&& elide_outer_quotes)
goto force_outer_quoting_style;
break;
case '\'':
encountered_single_quote = true;
c_and_shell_quote_compat = true;
if (quoting_style == shell_always_quoting_style)
{
if (elide_outer_quotes)
goto force_outer_quoting_style;
if (buffersize && ! orig_buffersize)
{
/* Just scan string to see if supports a more concise
representation, rather than writing a longer string
but returning the length of the more concise form. */
orig_buffersize = buffersize;
buffersize = 0;
}
STORE ('\'');
STORE ('\\');
STORE ('\'');
pending_shell_escape_end = false;
}
break;
case '%': case '+': case ',': case '-': case '.': case '/':
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': case ':':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
/* These characters don't cause problems, no matter what the
quoting style is. They cannot start multibyte sequences.
A digit or a special letter would cause trouble if it
appeared at the beginning of quote_string because we'd then
escape by prepending a backslash. However, it's hard to
imagine any locale that would use digits or letters as
quotes, and set_custom_quoting is documented not to accept
them. Also, a digit or a special letter would cause
trouble if it appeared in quote_these_too, but that's also
documented as not accepting them. */
c_and_shell_quote_compat = true;
break;
default:
/* If we have a multibyte sequence, copy it until we reach
its end, find an error, or come back to the initial shift
state. For C-like styles, if the sequence has
unprintable characters, escape the whole sequence, since
we can't easily escape single characters within it. */
{
/* Length of multibyte sequence found so far. */
size_t m;
bool printable;
if (unibyte_locale)
{
m = 1;
printable = isprint (c) != 0;
}
else
{
mbstate_t mbstate;
memset (&mbstate, 0, sizeof mbstate);
m = 0;
printable = true;
if (argsize == SIZE_MAX)
argsize = strlen (arg);
do
{
wchar_t w;
size_t bytes = mbrtowc (&w, &arg[i + m],
argsize - (i + m), &mbstate);
if (bytes == 0)
break;
else if (bytes == (size_t) -1)
{
printable = false;
break;
}
else if (bytes == (size_t) -2)
{
printable = false;
while (i + m < argsize && arg[i + m])
m++;
break;
}
else
{
/* Work around a bug with older shells that "see" a '\'
that is really the 2nd byte of a multibyte character.
In practice the problem is limited to ASCII
chars >= '@' that are shell special chars. */
if ('[' == 0x5b && elide_outer_quotes
&& quoting_style == shell_always_quoting_style)
{
size_t j;
for (j = 1; j < bytes; j++)
switch (arg[i + m + j])
{
case '[': case '\\': case '^':
case '`': case '|':
goto force_outer_quoting_style;
default:
break;
}
}
if (! iswprint (w))
printable = false;
m += bytes;
}
}
while (! mbsinit (&mbstate));
}
c_and_shell_quote_compat = printable;
if (1 < m || (backslash_escapes && ! printable))
{
/* Output a multibyte sequence, or an escaped
unprintable unibyte character. */
size_t ilim = i + m;
for (;;)
{
if (backslash_escapes && ! printable)
{
START_ESC ();
STORE ('0' + (c >> 6));
STORE ('0' + ((c >> 3) & 7));
c = '0' + (c & 7);
}
else if (is_right_quote)
{
STORE ('\\');
is_right_quote = false;
}
if (ilim <= i + 1)
break;
END_ESC ();
STORE (c);
c = arg[++i];
}
goto store_c;
}
}
}
if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
|| elide_outer_quotes)
&& quote_these_too
&& quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
&& !is_right_quote)
goto store_c;
store_escape:
START_ESC ();
store_c:
END_ESC ();
STORE (c);
if (! c_and_shell_quote_compat)
all_c_and_shell_quote_compat = false;
}
if (len == 0 && quoting_style == shell_always_quoting_style
&& elide_outer_quotes)
goto force_outer_quoting_style;
/* Single shell quotes (') are commonly enough used as an apostrophe,
that we attempt to minimize the quoting in this case. Note itʼs
better to use the apostrophe modifier "\u02BC" if possible, as that
renders better and works with the word match regex \W+ etc. */
if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
&& encountered_single_quote)
{
if (all_c_and_shell_quote_compat)
return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
c_quoting_style,
flags, quote_these_too,
left_quote, right_quote);
else if (! buffersize && orig_buffersize)
{
/* Disable read-only scan, and reprocess to write quoted string. */
buffersize = orig_buffersize;
len = 0;
goto process_input;
}
}
if (quote_string && !elide_outer_quotes)
for (; *quote_string; quote_string++)
STORE (*quote_string);
if (len < buffersize)
buffer[len] = '\0';
return len;
force_outer_quoting_style:
/* Don't reuse quote_these_too, since the addition of outer quotes
sufficiently quotes the specified characters. */
if (quoting_style == shell_always_quoting_style && backslash_escapes)
quoting_style = shell_escape_always_quoting_style;
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
quoting_style,
flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
left_quote, right_quote);
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
argument ARG (of size ARGSIZE), using O to control quoting.
If O is null, use the default.
Terminate the output with a null character, and return the written
size of the output, not counting the terminating null.
If BUFFERSIZE is too small to store the output string, return the
value that would have been returned had BUFFERSIZE been large enough.
If ARGSIZE is SIZE_MAX, use the string length of the argument for
ARGSIZE. */
size_t
quotearg_buffer (char *buffer, size_t buffersize,
char const *arg, size_t argsize,
struct quoting_options const *o)
{
struct quoting_options const *p = o ? o : &default_quoting_options;
int e = errno;
size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
p->style, p->flags, p->quote_these_too,
p->left_quote, p->right_quote);
errno = e;
return r;
}
char *
quotearg_alloc (char const *arg, size_t argsize,
struct quoting_options const *o)
{
return quotearg_alloc_mem (arg, argsize, NULL, o);
}
/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
allocated storage containing the quoted string, and store the
resulting size into *SIZE, if non-NULL. The result can contain
embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
NULL, and set_quoting_flags has not set the null byte elision
flag. */
char *
quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
struct quoting_options const *o)
{
struct quoting_options const *p = o ? o : &default_quoting_options;
int e = errno;
/* Elide embedded null bytes if we can't return a size. */
int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
flags, p->quote_these_too,
p->left_quote,
p->right_quote) + 1;
char *buf = xcharalloc (bufsize);
quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
p->quote_these_too,
p->left_quote, p->right_quote);
errno = e;
if (size)
*size = bufsize - 1;
return buf;
}
/* A storage slot with size and pointer to a value. */
struct slotvec
{
size_t size;
char *val;
};
/* Preallocate a slot 0 buffer, so that the caller can always quote
one small component of a "memory exhausted" message in slot 0. */
static char slot0[256];
static int nslots = 1;
static struct slotvec slotvec0 = {sizeof slot0, slot0};
static struct slotvec *slotvec = &slotvec0;
void
quotearg_free (void)
{
struct slotvec *sv = slotvec;
int i;
for (i = 1; i < nslots; i++)
free (sv[i].val);
if (sv[0].val != slot0)
{
free (sv[0].val);
slotvec0.size = sizeof slot0;
slotvec0.val = slot0;
}
if (sv != &slotvec0)
{
free (sv);
slotvec = &slotvec0;
}
nslots = 1;
}
/* Use storage slot N to return a quoted version of argument ARG.
ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
null-terminated string.
OPTIONS specifies the quoting options.
The returned value points to static storage that can be
reused by the next call to this function with the same value of N.
N must be nonnegative; it is typically small, and must be
less than MIN (INT_MAX, IDX_MAX). The type of N is signed
to allow for future extensions (using negative values). */
static char *
quotearg_n_options (int n, char const *arg, size_t argsize,
struct quoting_options const *options)
{
int e = errno;
struct slotvec *sv = slotvec;
int nslots_max = MIN (INT_MAX, IDX_MAX);
if (! (0 <= n && n < nslots_max))
abort ();
if (nslots <= n)
{
bool preallocated = (sv == &slotvec0);
idx_t new_nslots = nslots;
slotvec = sv = xpalloc (preallocated ? NULL : sv, &new_nslots,
n - nslots + 1, nslots_max, sizeof *sv);
if (preallocated)
*sv = slotvec0;
memset (sv + nslots, 0, (new_nslots - nslots) * sizeof *sv);
nslots = new_nslots;
}
{
size_t size = sv[n].size;
char *val = sv[n].val;
/* Elide embedded null bytes since we don't return a size. */
int flags = options->flags | QA_ELIDE_NULL_BYTES;
size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
options->style, flags,
options->quote_these_too,
options->left_quote,
options->right_quote);
if (size <= qsize)
{
sv[n].size = size = qsize + 1;
if (val != slot0)
free (val);
sv[n].val = val = xcharalloc (size);
quotearg_buffer_restyled (val, size, arg, argsize, options->style,
flags, options->quote_these_too,
options->left_quote,
options->right_quote);
}
errno = e;
return val;
}
}
char *
quotearg_n (int n, char const *arg)
{
return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
}
char *
quotearg_n_mem (int n, char const *arg, size_t argsize)
{
return quotearg_n_options (n, arg, argsize, &default_quoting_options);
}
char *
quotearg (char const *arg)
{
return quotearg_n (0, arg);
}
char *
quotearg_mem (char const *arg, size_t argsize)
{
return quotearg_n_mem (0, arg, argsize);
}
char *
quotearg_n_style (int n, enum quoting_style s, char const *arg)
{
struct quoting_options const o = quoting_options_from_style (s);
return quotearg_n_options (n, arg, SIZE_MAX, &o);
}
char *
quotearg_n_style_mem (int n, enum quoting_style s,
char const *arg, size_t argsize)
{
struct quoting_options const o = quoting_options_from_style (s);
return quotearg_n_options (n, arg, argsize, &o);
}
char *
quotearg_style (enum quoting_style s, char const *arg)
{
return quotearg_n_style (0, s, arg);
}
char *
quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
{
return quotearg_n_style_mem (0, s, arg, argsize);
}
char *
quotearg_char_mem (char const *arg, size_t argsize, char ch)
{
struct quoting_options options;
options = default_quoting_options;
set_char_quoting (&options, ch, 1);
return quotearg_n_options (0, arg, argsize, &options);
}
char *
quotearg_char (char const *arg, char ch)
{
return quotearg_char_mem (arg, SIZE_MAX, ch);
}
char *
quotearg_colon (char const *arg)
{
return quotearg_char (arg, ':');
}
char *
quotearg_colon_mem (char const *arg, size_t argsize)
{
return quotearg_char_mem (arg, argsize, ':');
}
char *
quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
{
struct quoting_options options;
options = quoting_options_from_style (s);
set_char_quoting (&options, ':', 1);
return quotearg_n_options (n, arg, SIZE_MAX, &options);
}
char *
quotearg_n_custom (int n, char const *left_quote,
char const *right_quote, char const *arg)
{
return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
SIZE_MAX);
}
char *
quotearg_n_custom_mem (int n, char const *left_quote,
char const *right_quote,
char const *arg, size_t argsize)
{
struct quoting_options o = default_quoting_options;
set_custom_quoting (&o, left_quote, right_quote);
return quotearg_n_options (n, arg, argsize, &o);
}
char *
quotearg_custom (char const *left_quote, char const *right_quote,
char const *arg)
{
return quotearg_n_custom (0, left_quote, right_quote, arg);
}
char *
quotearg_custom_mem (char const *left_quote, char const *right_quote,
char const *arg, size_t argsize)
{
return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
argsize);
}
/* The quoting option used by the functions of quote.h. */
struct quoting_options quote_quoting_options =
{
locale_quoting_style,
0,
{ 0 },
NULL, NULL
};
char const *
quote_n_mem (int n, char const *arg, size_t argsize)
{
return quotearg_n_options (n, arg, argsize, "e_quoting_options);
}
char const *
quote_mem (char const *arg, size_t argsize)
{
return quote_n_mem (0, arg, argsize);
}
char const *
quote_n (int n, char const *arg)
{
return quote_n_mem (n, arg, SIZE_MAX);
}
char const *
quote (char const *arg)
{
return quote_n (0, arg);
}
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/
recode-3.7.14/lib/bitrotate.h 0000644 0001750 0001750 00000011030 14366047013 012703 0000000 0000000 /* bitrotate.h - Rotate bits in integers
Copyright (C) 2008-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Written by Simon Josefsson , 2008. */
#ifndef _GL_BITROTATE_H
#define _GL_BITROTATE_H
#include
#include
#include
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef BITROTATE_INLINE
# define BITROTATE_INLINE _GL_INLINE
#endif
#ifdef UINT64_MAX
/* Given an unsigned 64-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
63 inclusive. */
BITROTATE_INLINE uint64_t
rotl64 (uint64_t x, int n)
{
return ((x << n) | (x >> (64 - n))) & UINT64_MAX;
}
/* Given an unsigned 64-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be between 1 to
63 inclusive.*/
BITROTATE_INLINE uint64_t
rotr64 (uint64_t x, int n)
{
return ((x >> n) | (x << (64 - n))) & UINT64_MAX;
}
#endif
/* Given an unsigned 32-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
31 inclusive. */
BITROTATE_INLINE uint32_t
rotl32 (uint32_t x, int n)
{
return ((x << n) | (x >> (32 - n))) & UINT32_MAX;
}
/* Given an unsigned 32-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be between 1 to
31 inclusive.*/
BITROTATE_INLINE uint32_t
rotr32 (uint32_t x, int n)
{
return ((x >> n) | (x << (32 - n))) & UINT32_MAX;
}
/* Given a size_t argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
(CHAR_BIT * sizeof (size_t) - 1) inclusive. */
BITROTATE_INLINE size_t
rotl_sz (size_t x, int n)
{
return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
}
/* Given a size_t argument X, return the value corresponding
to rotating the bits N steps to the right. N must be between 1 to
(CHAR_BIT * sizeof (size_t) - 1) inclusive. */
BITROTATE_INLINE size_t
rotr_sz (size_t x, int n)
{
return ((x >> n) | (x << ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
}
/* Given an unsigned 16-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 to
15 inclusive, but on most relevant targets N can also be 0 and 16
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint16_t
rotl16 (uint16_t x, int n)
{
return (((unsigned int) x << n) | ((unsigned int) x >> (16 - n)))
& UINT16_MAX;
}
/* Given an unsigned 16-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be in 1 to 15
inclusive, but on most relevant targets N can also be 0 and 16
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint16_t
rotr16 (uint16_t x, int n)
{
return (((unsigned int) x >> n) | ((unsigned int) x << (16 - n)))
& UINT16_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 to 7
inclusive, but on most relevant targets N can also be 0 and 8
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint8_t
rotl8 (uint8_t x, int n)
{
return (((unsigned int) x << n) | ((unsigned int) x >> (8 - n))) & UINT8_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be in 1 to 7
inclusive, but on most relevant targets N can also be 0 and 8
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint8_t
rotr8 (uint8_t x, int n)
{
return (((unsigned int) x >> n) | ((unsigned int) x << (8 - n))) & UINT8_MAX;
}
_GL_INLINE_HEADER_END
#endif /* _GL_BITROTATE_H */
recode-3.7.14/lib/exitfail.h 0000644 0001750 0001750 00000001424 14366047013 012521 0000000 0000000 /* Failure exit status
Copyright (C) 2002, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
extern int volatile exit_failure;
recode-3.7.14/lib/fseterr.h 0000644 0001750 0001750 00000002374 14366047013 012373 0000000 0000000 /* Set the error indicator of a stream.
Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#ifndef _FSETERR_H
#define _FSETERR_H
#include
/* Set the error indicator of the stream FP.
The "error indicator" is set when an I/O operation on the stream fails, and
is cleared (together with the "end-of-file" indicator) by clearerr (FP). */
#if HAVE___FSETERR /* musl libc */
# include
# define fseterr(fp) __fseterr (fp)
#else
# ifdef __cplusplus
extern "C" {
# endif
extern void fseterr (FILE *fp);
# ifdef __cplusplus
}
# endif
#endif
#endif /* _FSETERR_H */
recode-3.7.14/lib/printf-frexpl.h 0000644 0001750 0001750 00000002125 14366047013 013513 0000000 0000000 /* Split a 'long double' into fraction and mantissa, for hexadecimal printf.
Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* Write a finite, positive number x as
x = mantissa * 2^exp
where exp >= LDBL_MIN_EXP - 1,
mantissa < 2.0,
if x is not a denormalized number then mantissa >= 1.0.
Store exp in *EXPPTR and return mantissa. */
extern long double printf_frexpl (long double x, int *expptr);
recode-3.7.14/lib/size_max.h 0000644 0001750 0001750 00000002253 14366047013 012534 0000000 0000000 /* size_max.h -- declare SIZE_MAX through system headers
Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc.
Written by Simon Josefsson.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#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 */
recode-3.7.14/lib/c-ctype.c 0000644 0001750 0001750 00000001513 14366047013 012252 0000000 0000000 /* Character handling in C locale.
Copyright (C) 2003-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
#define C_CTYPE_INLINE _GL_EXTERN_INLINE
#include "c-ctype.h"
recode-3.7.14/lib/lstat.c 0000644 0001750 0001750 00000007236 14366047013 012045 0000000 0000000 /* Work around a bug of lstat on some systems
Copyright (C) 1997-2006, 2008-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* written by Jim Meyering */
/* If the user's config.h happens to include , let it include only
the system's here, so that orig_lstat doesn't recurse to
rpl_lstat. */
#define __need_system_sys_stat_h
#include
#if !HAVE_LSTAT
/* On systems that lack symlinks, our replacement already
defined lstat as stat, so there is nothing further to do other than
avoid an empty file. */
typedef int dummy;
#else /* HAVE_LSTAT */
/* Get the original definition of lstat. It might be defined as a macro. */
# include
# include
# undef __need_system_sys_stat_h
static int
orig_lstat (const char *filename, struct stat *buf)
{
return lstat (filename, buf);
}
/* Specification. */
# ifdef __osf__
/* 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"
# else
# include
# endif
# include "stat-time.h"
# include
# include
/* lstat works differently on Linux and Solaris systems. POSIX (see
"pathname resolution" in the glossary) requires that programs like
'ls' take into consideration the fact that FILE has a trailing slash
when FILE is a symbolic link. On Linux and Solaris 10 systems, the
lstat function already has the desired semantics (in treating
'lstat ("symlink/", sbuf)' just like 'lstat ("symlink/.", sbuf)',
but on Solaris 9 and earlier it does not.
If FILE has a trailing slash and specifies a symbolic link,
then use stat() to get more info on the referent of FILE.
If the referent is a non-directory, then set errno to ENOTDIR
and return -1. Otherwise, return stat's result. */
int
rpl_lstat (const char *file, struct stat *sbuf)
{
int result = orig_lstat (file, sbuf);
/* This replacement file can blindly check against '/' rather than
using the ISSLASH macro, because all platforms with '\\' either
lack symlinks (mingw) or have working lstat (cygwin) and thus do
not compile this file. 0 len should have already been filtered
out above, with a failure return of ENOENT. */
if (result == 0)
{
if (S_ISDIR (sbuf->st_mode) || file[strlen (file) - 1] != '/')
result = stat_time_normalize (result, sbuf);
else
{
/* At this point, a trailing slash is permitted only on
symlink-to-dir; but it should have found information on the
directory, not the symlink. Call 'stat' to get info about the
link's referent. Our replacement stat guarantees valid results,
even if the symlink is not pointing to a directory. */
if (!S_ISLNK (sbuf->st_mode))
{
errno = ENOTDIR;
return -1;
}
result = stat (file, sbuf);
}
}
return result;
}
#endif /* HAVE_LSTAT */
recode-3.7.14/lib/float.c 0000644 0001750 0001750 00000002526 14366047013 012020 0000000 0000000 /* Auxiliary definitions for .
Copyright (C) 2011-2023 Free Software Foundation, Inc.
Written by Bruno Haible , 2011.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
/* Specification. */
#include
#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__
const union gl_long_double_union gl_LDBL_MAX =
{ { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } };
#elif defined __i386__
const union gl_long_double_union gl_LDBL_MAX =
{ { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } };
#else
/* This declaration is solely to ensure that after preprocessing
this file is never empty. */
typedef int dummy;
#endif
recode-3.7.14/lib/c-strcasecmp.c 0000644 0001750 0001750 00000003066 14366047013 013277 0000000 0000000 /* c-strcasecmp.c -- case insensitive string comparator in C locale
Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
/* Specification. */
#include "c-strcase.h"
#include
#include "c-ctype.h"
int
c_strcasecmp (const char *s1, const char *s2)
{
register const unsigned char *p1 = (const unsigned char *) s1;
register const unsigned char *p2 = (const unsigned char *) s2;
unsigned char c1, c2;
if (p1 == p2)
return 0;
do
{
c1 = c_tolower (*p1);
c2 = c_tolower (*p2);
if (c1 == '\0')
break;
++p1;
++p2;
}
while (c1 == c2);
if (UCHAR_MAX <= INT_MAX)
return c1 - c2;
else
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
return _GL_CMP (c1, c2);
}
recode-3.7.14/lib/isnanl-nolibm.h 0000644 0001750 0001750 00000002502 14366047013 013454 0000000 0000000 /* Test for NaN that does not need libm.
Copyright (C) 2007-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#if HAVE_ISNANL_IN_LIBC
/* Get declaration of isnan macro or (older) isnanl function. */
# include
# if (__GNUC__ >= 4) || (__clang_major__ >= 4)
/* GCC >= 4.0 and clang provide a type-generic built-in for isnan.
GCC >= 4.0 also provides __builtin_isnanl, but clang doesn't. */
# undef isnanl
# define isnanl(x) __builtin_isnan ((long double)(x))
# elif defined isnan
# undef isnanl
# define isnanl(x) isnan ((long double)(x))
# endif
#else
/* Test whether X is a NaN. */
# undef isnanl
# define isnanl rpl_isnanl
extern int isnanl (long double x);
#endif
recode-3.7.14/lib/fcntl.in.h 0000644 0001750 0001750 00000031331 14366047013 012427 0000000 0000000 /* Like , but with non-working flags defined to 0.
Copyright (C) 2006-2023 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/* written by Paul Eggert */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
#if defined __need_system_fcntl_h
/* Special invocation convention. */
/* Needed before .
May also define off_t to a 64-bit type on native Windows. */
#include
/* On some systems other than glibc, is a prerequisite of