From 3797484608c5bba2057d819215e6ce4d48cacf94 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 29 Jul 2025 15:00:36 -0700 Subject: [PATCH] Update from Gnulib by running admin/merge-gnulib --- build-aux/config.guess | 17 +++-- build-aux/config.sub | 28 ++++--- doc/misc/texinfo.tex | 170 ++++++++++++++++++++++++++++++++++------- lib/_Noreturn.h | 3 +- lib/fpending.c | 2 +- lib/ftoastr.c | 10 ++- lib/gnulib.mk.in | 11 +-- lib/stdio-impl.h | 29 ++++--- lib/strftime.c | 166 +++++++++++++++++++++++++++++++++------- lib/strftime.h | 9 +++ lib/string.in.h | 60 ++++++++++----- m4/gnulib-common.m4 | 5 +- m4/gnulib-comp.m4 | 6 +- 13 files changed, 398 insertions(+), 118 deletions(-) diff --git a/build-aux/config.guess b/build-aux/config.guess index 48a684601bd..a9d01fde461 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2024 Free Software Foundation, Inc. +# Copyright 1992-2025 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2024-07-27' +timestamp='2025-07-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -60,7 +60,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2024 Free Software Foundation, Inc. +Copyright 1992-2025 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -1597,8 +1597,11 @@ EOF *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; - *:Ironclad:*:*) - GUESS=$UNAME_MACHINE-unknown-ironclad + x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*) + GUESS=$UNAME_MACHINE-pc-ironclad-mlibc + ;; + *:[Ii]ronclad:*:*) + GUESS=$UNAME_MACHINE-unknown-ironclad-mlibc ;; esac @@ -1808,8 +1811,8 @@ fi exit 1 # Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp nil t) # time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-format: "%Y-%02m-%02d" # time-stamp-end: "'" # End: diff --git a/build-aux/config.sub b/build-aux/config.sub index 4aaae46f6f7..3d35cde174d 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2024 Free Software Foundation, Inc. +# Copyright 1992-2025 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale -timestamp='2024-05-27' +timestamp='2025-07-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,7 +76,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2024 Free Software Foundation, Inc. +Copyright 1992-2025 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -145,6 +145,7 @@ case $1 in | kfreebsd*-gnu* \ | knetbsd*-gnu* \ | kopensolaris*-gnu* \ + | ironclad-* \ | linux-* \ | managarm-* \ | netbsd*-eabi* \ @@ -242,7 +243,6 @@ case $1 in | rombug \ | semi \ | sequent* \ - | siemens \ | sgi* \ | siemens \ | sim \ @@ -261,7 +261,7 @@ case $1 in basic_machine=$field1-$field2 basic_os= ;; - zephyr*) + tock* | zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; @@ -1194,7 +1194,7 @@ case $cpu-$vendor in xscale-* | xscalee[bl]-*) cpu=`echo "$cpu" | sed 's/^xscale/arm/'` ;; - arm64-* | aarch64le-*) + arm64-* | aarch64le-* | arm64_32-*) cpu=aarch64 ;; @@ -1321,6 +1321,7 @@ case $cpu-$vendor in | i960 \ | ia16 \ | ia64 \ + | intelgt \ | ip2k \ | iq2000 \ | javascript \ @@ -1522,6 +1523,10 @@ EOF kernel=nto os=`echo "$basic_os" | sed -e 's|nto|qnx|'` ;; + ironclad*) + kernel=ironclad + os=`echo "$basic_os" | sed -e 's|ironclad|mlibc|'` + ;; linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|linux|gnu|'` @@ -1976,6 +1981,7 @@ case $os in | atheos* \ | auroraux* \ | aux* \ + | banan_os* \ | beos* \ | bitrig* \ | bme* \ @@ -2022,7 +2028,6 @@ case $os in | ios* \ | iris* \ | irix* \ - | ironclad* \ | isc* \ | its* \ | l4re* \ @@ -2118,6 +2123,7 @@ case $os in | sysv* \ | tenex* \ | tirtos* \ + | tock* \ | toppers* \ | tops10* \ | tops20* \ @@ -2214,6 +2220,8 @@ case $kernel-$os-$obj in ;; uclinux-uclibc*- | uclinux-gnu*- ) ;; + ironclad-mlibc*-) + ;; managarm-mlibc*- | managarm-kernel*- ) ;; windows*-msvc*-) @@ -2249,6 +2257,8 @@ case $kernel-$os-$obj in ;; *-eabi*- | *-gnueabi*-) ;; + ios*-simulator- | tvos*-simulator- | watchos*-simulator- ) + ;; none--*) # None (no kernel, i.e. freestanding / bare metal), # can be paired with an machine code file format @@ -2347,8 +2357,8 @@ echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}" exit # Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp nil t) # time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-format: "%Y-%02m-%02d" # time-stamp-end: "'" # End: diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 3907525cf56..42e686ce705 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2025-06-18.21} +\def\texinfoversion{2025-07-15.21} % % Copyright 1985, 1986, 1988, 1990-2025 Free Software Foundation, Inc. % @@ -483,8 +483,8 @@ % \envdef\foo{...} % \def\Efoo{...} % -% It's the responsibility of \envdef to insert \begingroup before the -% actual body; @end closes the group after calling \Efoo. \envdef also +% \envdef inserts \begingroup before the actual body; @end calls +% \Efoo then closes the group with \endgroup. \envdef also % defines \thisenv, so the current environment is known; @end checks % whether the environment name matches. The \checkenv macro can also be % used to check whether the current environment is the one expected. @@ -3888,7 +3888,8 @@ $$% } \def\finishtitlepage{% - \vskip4pt \hrule height 2pt width \hsize + \ifseenauthor \vskip4pt \else \vskip 0pt plus 1filll \fi + \hrule height 2pt width \hsize \vskip\titlepagebottomglue \finishedtitlepagetrue } @@ -3911,33 +3912,105 @@ $$% \let\subtitlerm=\rmfont \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} +\let\savedtitle\empty +\let\savedsubtitlegroup\empty +\let\savedauthorgroup\empty + \parseargdef\title{% - \checkenv\titlepage - \vbox{\titlefonts \raggedtitlesettings #1\par}% - % print a rule at the page bottom also. - \finishedtitlepagefalse - \vskip4pt \hrule height 4pt width \hsize \vskip4pt + \expandafter\ifx\thisenv\documentinfo + \gdef\savedtitle{#1}% + \else + \checkenv\titlepage + \vbox{\titlefonts \raggedtitlesettings #1\par}% + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt + \fi } \parseargdef\subtitle{% - \checkenv\titlepage - {\subtitlefont \rightline{#1}}% + \expandafter\ifx\thisenv\documentinfo + \ifx\savedsubtitlegroup\empty + \gdef\savedsubtitlegroup{\savedsubtitle{#1}}% + \else + \expandafter\gdef\expandafter\savedsubtitlegroup\expandafter{% + \savedsubtitlegroup\savedsubtitle{#1}}% + \fi + \else + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% + \fi } % @author should come last, but may come many times. % It can also be used inside @quotation. % \parseargdef\author{% - \def\temp{\quotation}% - \ifx\thisenv\temp - \def\quotationauthor{#1}% printed in \Equotation. + \expandafter\ifx\thisenv\documentinfo + \ifx\savedauthorgroup\empty + \gdef\savedauthorgroup{\savedauthor{#1}}% + \else + \expandafter\gdef\expandafter\savedauthorgroup\expandafter{% + \savedauthorgroup\savedauthor{#1}}% + \fi \else - \checkenv\titlepage - \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi - {\secfonts\rm \leftline{#1}}% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\secfonts\rm \leftline{#1}}% + \fi \fi } +% @maketitle +{\obeylines +\gdef\maketitle{% +\titlepage +\ifx\savedtitle\empty\else + \title \savedtitle + \ifx\savedsubtitlegroup\empty\else + \savedsubtitlegroup +\fi\fi +\ifx\savedauthorgroup\empty\else + \savedauthorgroup +\fi +% start verso page if either copying or publication text is given +\ifx\copyingtext\relax + \ifx\publicationtext\relax\else + \page \vskip 0pt plus 1filll + \fi +\else + \page \vskip 0pt plus 1filll +\fi +\ifx\publicationtext\relax\else + \insertpublication + \sp 1 +\fi +\ifx\copyingtext\relax\else + \insertcopying +\fi +\end titlepage +} + +% \savedauthor{#1}, called with braces. output an @author line. +\gdef\savedauthor#1{% +\author#1 +} + +% \savedsubtitle{#1}, called with braces. output a @subtitle line. +\gdef\savedsubtitle#1{% +\subtitle#1 +} +} % \obeylines + +% @documentinfo block +\envdef\documentinfo{% +} +\def\Edocumentinfo{}% + % Set up page headings and footings. @@ -6973,7 +7046,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% % \raggedbottom in plain.tex hardcodes \topskip so override it \catcode`\@=11 -\def\raggedbottom{\advance\topskip by 0pt plus60pt \r@ggedbottomtrue} +\def\raggedbottom{\advance\topskip by 0pt plus30pt \r@ggedbottomtrue} \catcode`\@=\other % redefined for the two-volume lispref. We always output on @@ -6986,6 +7059,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \def\contents{% \startcontents{\putwordTOC}{\contentsmkdest}% \ifxetex\xetexpreauxfile\fi + \penalty2 % mark beginning of contents \openin 1 \tocreadfilename\space \ifeof 1 \else \findsecnowidths @@ -7078,25 +7152,34 @@ might help (with 'rm \jobname.?? \jobname.??s')% % #3 - level of section (e.g "chap", "sec") % #4 - page number -% Parts, in the main contents. Replace the part number, which doesn't -% exist, with an empty box. Let's hope all the numbers have the same width. -% Also ignore the page number, which is conventionally not printed. -\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} +% Parts, in the main contents. Ignore the page number, which is +% conventionally not printed. \def\partentry#1#2#3#4{% + \ifnum\lastpenalty = 2 + % use less space if at very first entry of contents + \vskip 1\baselineskip plus .33\baselineskip minus .25\baselineskip + \else + \vskip 2\baselineskip plus .66\baselineskip minus .5\baselineskip + \fi % Add stretch and a bonus for breaking the page before the part heading. % This reduces the chance of the page being broken immediately after the % part heading, before a following chapter heading. - \vskip 0pt plus 5\baselineskip + \vskip 0pt plus 3\baselineskip \penalty-300 - \vskip 0pt plus -5\baselineskip - \dochapentry{#1}{\numeralbox}{#3}{}% + \vskip 0pt plus -3\baselineskip + \begingroup + \secfonts \rm + \entryinternal{#1}{}% + \endgroup + \afterpartentrytrue } +\newif\ifafterpartentry % % Parts, in the short toc. \def\shortpartentry#1#2#3#4{% \penalty-300 \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip - \shortchapentry{{\bf #1}}{\numeralbox}{}{}% + \tocentry{{\bf #1}}{}{}{}% } % Chapters, in the main contents. @@ -7164,7 +7247,13 @@ might help (with 'rm \jobname.?? \jobname.??s')% % If the toc has to be broken over pages, we want it to be at chapters % if at all possible; hence the \penalty. \def\dochapentry#1#2#3#4{% - \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \ifafterpartentry + \afterpartentryfalse + \penalty5000 + \else + \penalty-300 + \fi + \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup % Move the page numbers slightly to the right \advance\entryrightmargin by -0.05em @@ -7793,6 +7882,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% {\catcode`\ =\other \gdef\docopying#1@end copying{\endgroup\def\copyingtext{#1}} } +\let\copyingtext\relax \def\insertcopying{% \begingroup @@ -7801,6 +7891,18 @@ might help (with 'rm \jobname.?? \jobname.??s')% \endgroup } +\def\publication{\checkenv{}\begingroup\macrobodyctxt\dopublication} +{\catcode`\ =\other +\gdef\dopublication#1@end publication{\endgroup\def\publicationtext{#1}} +} +\let\publicationtext\relax + +\def\insertpublication{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\publicationtext + \endgroup +} \message{defuns,} % @defun etc. @@ -10058,8 +10160,18 @@ might help (with 'rm \jobname.?? \jobname.??s')% \gdef\documentlanguagetrywithoutunderscore#1_#2\finish{% \openin 1 txi-#1.tex \ifeof 1 - \errhelp = \nolanghelp - \errmessage{Cannot read language file txi-#1.tex}% + \def\lang{#1}% + \def\enword{en}% + \ifx\lang\enword + % for English only, keep on going rather than issuing a fatal error + % message, as txi-en.tex likely doesn't contain any changes from the + % defaults. note that this is a problem if we already loaded another + % language file and want to switch back to English. + \message{Cannot read language file txi-#1.tex}% + \else + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \fi \else \globaldefs = 1 % everything in the txi-LL files needs to persist \input txi-#1.tex diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h index 8e63387914c..d42f15eee62 100644 --- a/lib/_Noreturn.h +++ b/lib/_Noreturn.h @@ -27,7 +27,8 @@ This rare bug can be worked around by compiling with 'clang -D_Noreturn=', though the workaround may generate many false-alarm warnings. */ #ifndef _Noreturn -# if 201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) +# if ((!defined __cplusplus || defined __clang__) \ + && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0))) /* _Noreturn works as-is. */ # elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \ || 0x5110 <= __SUNPRO_C) diff --git a/lib/fpending.c b/lib/fpending.c index be8a9877349..529bc7f6517 100644 --- a/lib/fpending.c +++ b/lib/fpending.c @@ -39,7 +39,7 @@ __fpending (FILE *fp) #if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */ return fp->_IO_write_ptr - fp->_IO_write_base; -#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__ +#elif defined __sferror || defined __OpenBSD__ || defined __DragonFly__ || defined __ANDROID__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */ return fp_->_p - fp_->_bf._base; #elif defined __EMX__ /* emx+gcc */ diff --git a/lib/ftoastr.c b/lib/ftoastr.c index 250b840365e..2438ffe837f 100644 --- a/lib/ftoastr.c +++ b/lib/ftoastr.c @@ -114,10 +114,12 @@ FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x) /* The following method is simple but slow. For ideas about speeding things up, please see: - Andrysco M, Jhala R, Lerner S. Printing floating-point numbers: - a faster, always correct method. ACM SIGPLAN notices - POPL '16. - 2016;51(1):555-67 ; draft at - . */ + Jeon J. Dragonbox: a new floating-point binary-to-decimal + conversion algorithm. 2024. . + Used in {fmt} . + + Adams U. Ryū: fast float-to-string conversion. + PLDI 2018. 270–282. . */ PROMOTED_FLOAT promoted_x = x; char format[sizeof "%-+ 0*.*Lg"]; diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index bb147b69eed..b3774a648b8 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -49,6 +49,7 @@ # --avoid=iswxdigit \ # --avoid=langinfo-h \ # --avoid=libgmp-mpq \ +# --avoid=localcharset \ # --avoid=locale-h \ # --avoid=localename-unsafe-limited \ # --avoid=lock \ @@ -144,7 +145,7 @@ # mktime \ # nanosleep \ # nproc \ -# nstrftime \ +# nstrftime-limited \ # pathmax \ # pipe2 \ # pselect \ @@ -2836,17 +2837,17 @@ EXTRA_DIST += nproc.h endif ## end gnulib module nproc -## begin gnulib module nstrftime -ifeq (,$(OMIT_GNULIB_MODULE_nstrftime)) +## begin gnulib module nstrftime-limited +ifeq (,$(OMIT_GNULIB_MODULE_nstrftime-limited)) libgnu_a_SOURCES += nstrftime.c -EXTRA_DIST += strftime.c strftime.h +EXTRA_DIST += calendar-ethiopian.h calendar-persian.h calendar-thai.h calendars.h strftime.c strftime.h EXTRA_libgnu_a_SOURCES += strftime.c endif -## end gnulib module nstrftime +## end gnulib module nstrftime-limited ## begin gnulib module open ifeq (,$(OMIT_GNULIB_MODULE_open)) diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h index 4b4263fe908..4abf9e68b23 100644 --- a/lib/stdio-impl.h +++ b/lib/stdio-impl.h @@ -82,7 +82,7 @@ #include /* For detecting Plan9. */ -#if defined __sferror || defined __DragonFly__ || defined __ANDROID__ +#if defined __sferror || defined __OpenBSD__ || defined __DragonFly__ || defined __ANDROID__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */ # if defined __DragonFly__ /* DragonFly */ @@ -108,13 +108,15 @@ # define _flags pub._flags # define _r pub._r # define _w pub._w -# elif defined __ANDROID__ /* Android */ -# ifdef __LP64__ +# elif defined __ANDROID__ || defined __OpenBSD__ /* Android, OpenBSD */ +# if defined __LP64__ && !defined __OpenBSD__ # define _gl_flags_file_t int # else # define _gl_flags_file_t short # endif -# ifdef __LP64__ +# if defined __OpenBSD__ +# define _gl_file_offset_t fpos_t +# elif defined __LP64__ # define _gl_file_offset_t int64_t # else /* see https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */ @@ -122,10 +124,12 @@ # endif /* Up to this commit from 2015-10-12 - the innards of FILE were public, and fp_ub could be defined like for OpenBSD, + the innards of FILE were public, see and . - After this commit, the innards of FILE are hidden. */ + After this commit, the innards of FILE are hidden. Likewise for OpenBSD + up to this commit from 2025-07-16 + . */ # define fp_ ((struct { unsigned char *_p; \ int _r; \ int _w; \ @@ -152,9 +156,8 @@ # define fp_ fp # endif -# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ || defined __minix /* NetBSD >= 1.5ZA, OpenBSD, Minix 3 */ +# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __minix /* NetBSD >= 1.5ZA, Minix 3 */ /* See - and and */ struct __sfileext { @@ -162,7 +165,7 @@ /* More fields, not relevant here. */ }; # define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub -# elif defined __ANDROID__ /* Android */ +# elif defined __ANDROID__ || defined __OpenBSD__ /* Android, OpenBSD */ struct __sfileext { struct { unsigned char *_base; size_t _size; } _ub; /* ungetc buffer */ @@ -175,9 +178,11 @@ # define HASUB(fp) (fp_ub._base != NULL) -# if defined __ANDROID__ /* Android */ - /* Needed after this commit from 2016-01-25 - */ +# if defined __ANDROID__ || defined __OpenBSD__ /* Android, OpenBSD */ + /* Needed after this Android commit from 2016-01-25 + + And after this OpenBSD commit from 2025-07-16 + . */ # ifndef __SEOF # define __SLBF 1 # define __SNBF 2 diff --git a/lib/strftime.c b/lib/strftime.c index 64a1f0456a2..537172d8be6 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -53,7 +53,7 @@ /* Whether to require GNU behavior for AM and PM indicators, even on other platforms. This matters only in non-C locales. The default is to require it; you can override this via - AC_DEFINE([REQUIRE_GNUISH_STRFTIME_AM_PM], 1) and if you do that + AC_DEFINE([REQUIRE_GNUISH_STRFTIME_AM_PM], [false]) and if you do that you may be able to omit Gnulib's localename module and its dependencies. */ #ifndef REQUIRE_GNUISH_STRFTIME_AM_PM # define REQUIRE_GNUISH_STRFTIME_AM_PM true @@ -63,6 +63,25 @@ # define REQUIRE_GNUISH_STRFTIME_AM_PM false #endif +/* Whether to include support for non-Gregorian calendars (outside of the scope + of ISO C, POSIX, and glibc). This matters only in non-C locales. + The default is to include it, except on platforms where retrieving the locale + name drags in too many dependencies + (LOCALENAME_ENHANCE_LOCALE_FUNCS || !SETLOCALE_NULL_ONE_MTSAFE). + You can override this via + AC_DEFINE([SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME], [false]) + and if you do that you may be able to omit Gnulib's localename module and its + dependencies. */ +#ifndef SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME +# define SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME true +#endif +#if defined _LIBC || (HAVE_ONLY_C_LOCALE || USE_C_LOCALE) \ + || ((defined __OpenBSD__ || defined _AIX || defined __ANDROID__) \ + && !GNULIB_NSTRFTIME) +# undef SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME +# define SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME false +#endif + #if HAVE_ONLY_C_LOCALE || USE_C_LOCALE # include "c-ctype.h" #else @@ -78,14 +97,8 @@ C library on the various platforms (UTF-8, GB2312, GBK, CP936, GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949, SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%' - cannot occur in a multibyte character except in the first byte. - - The DEC-HANYU encoding used on OSF/1 is not safe for formats, but - this encoding has never been seen in real-life use, so we ignore - it. */ -#if !(defined __osf__ && 0) -# define MULTIBYTE_IS_FORMAT_SAFE 1 -#endif + cannot occur in a multibyte character except in the first byte. */ +#define MULTIBYTE_IS_FORMAT_SAFE 1 #define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE) #if DO_MULTIBYTE @@ -164,6 +177,16 @@ enum pad_style ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) #endif +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME +/* Support for non-Gregorian calendars. */ +# include "localcharset.h" +# include "localename.h" +# include "calendars.h" +# define CAL_ARGS(x,y) x, y, +#else +# define CAL_ARGS(x,y) /* empty */ +#endif + #ifdef _LIBC # define mktime_z(tz, tm) mktime (tm) @@ -873,6 +896,8 @@ static CHAR_T const c_month_names[][sizeof "September"] = static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t) const CHAR_T *, const struct tm *, + CAL_ARGS (const struct calendar *, + struct calendar_date *) bool, enum pad_style, int, bool * extra_args_spec LOCALE_PARAM); @@ -1087,9 +1112,36 @@ my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) const CHAR_T *format, const struct tm *tp extra_args_spec LOCALE_PARAM) { +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + /* Recognize whether to use a non-Gregorian calendar. */ + const struct calendar *cal = NULL; + struct calendar_date caldate; + if (strcmp (locale_charset (), "UTF-8") == 0) + { + const char *loc = gl_locale_name_unsafe (LC_TIME, "LC_TIME"); + if (strlen (loc) >= 5 && !(loc[5] >= 'A' && loc[5] <= 'Z')) + { + if (memcmp (loc, "th_TH", 5) == 0) + cal = &thai_calendar; + else if (memcmp (loc, "fa_IR", 5) == 0) + cal = &persian_calendar; + else if (memcmp (loc, "am_ET", 5) == 0) + cal = ðiopian_calendar; + if (cal != NULL) + { + if (cal->from_gregorian (&caldate, + tp->tm_year + 1900, + tp->tm_mon, + tp->tm_mday) < 0) + cal = NULL; + } + } + } +#endif bool tzset_called = false; - return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false, - ZERO_PAD, -1, + return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, + CAL_ARGS (cal, &caldate) + false, ZERO_PAD, -1, &tzset_called extra_args LOCALE_ARG); } libc_hidden_def (my_strftime) @@ -1101,7 +1153,10 @@ libc_hidden_def (my_strftime) static size_t __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) const CHAR_T *format, - const struct tm *tp, bool upcase, + const struct tm *tp, + CAL_ARGS (const struct calendar *cal, + struct calendar_date *caldate) + bool upcase, enum pad_style yr_spec, int width, bool *tzset_called extra_args_spec LOCALE_PARAM) { @@ -1113,7 +1168,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) #endif int saved_errno = errno; - int hour12 = tp->tm_hour; + #ifdef _NL_CURRENT /* We cannot make the following values variables since we must delay the evaluation of these values until really needed since some @@ -1173,6 +1228,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) const char *format_end = NULL; #endif + int hour12 = tp->tm_hour; if (hour12 > 12) hour12 -= 12; else @@ -1189,6 +1245,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) bool negative_number; /* The number is negative. */ bool always_output_a_sign; /* +/- should always be output. */ int tz_colon_mask; /* Bitmask of where ':' should appear. */ +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + unsigned int digits_base = '0'; /* '0' or some UCS-2 value. */ +#endif const CHAR_T *subfmt; CHAR_T *bufp; CHAR_T buf[1 @@ -1436,6 +1495,14 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) } if (modifier == L_('E')) goto bad_format; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + { + cpy (STRLEN (caldate->month_names[caldate->month].abbrev), + caldate->month_names[caldate->month].abbrev); + break; + } +#endif #ifdef _NL_CURRENT if (modifier == L_('O')) cpy (aam_len, a_altmonth); @@ -1460,6 +1527,14 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) to_uppcase = true; to_lowcase = false; } +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + { + cpy (STRLEN (caldate->month_names[caldate->month].full), + caldate->month_names[caldate->month].full); + break; + } +#endif #ifdef _NL_CURRENT if (modifier == L_('O')) cpy (STRLEN (f_altmonth), f_altmonth); @@ -1511,13 +1586,17 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) subformat_width: { size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1) - subfmt, tp, to_uppcase, - pad, subwidth, tzset_called + subfmt, tp, + CAL_ARGS (cal, caldate) + to_uppcase, pad, subwidth, + tzset_called extra_args LOCALE_ARG); add (len, __strftime_internal (p, STRFTIME_ARG (maxsize - i) - subfmt, tp, to_uppcase, - pad, subwidth, tzset_called + subfmt, tp, + CAL_ARGS (cal, caldate) + to_uppcase, pad, subwidth, + tzset_called extra_args LOCALE_ARG)); } break; @@ -1639,6 +1718,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) case L_('x'): if (modifier == L_('O')) goto bad_format; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + { + subfmt = cal->d_fmt; + goto subformat; + } +#endif #ifdef _NL_CURRENT if (! (modifier == L_('E') && (*(subfmt = @@ -1652,6 +1738,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) #else goto underlying_strftime; #endif + case L_('D'): if (modifier != 0) goto bad_format; @@ -1662,12 +1749,20 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) if (modifier == L_('E')) goto bad_format; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + DO_NUMBER (2, caldate->day); +#endif DO_NUMBER (2, tp->tm_mday); case L_('e'): if (modifier == L_('E')) goto bad_format; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + DO_NUMBER_SPACEPAD (2, caldate->day); +#endif DO_NUMBER_SPACEPAD (2, tp->tm_mday); /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE) @@ -1709,7 +1804,10 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) negating it. */ if (modifier == L_('O') && !negative_number) { -#ifdef _NL_CURRENT +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + digits_base = cal->alt_digits_base; +#elif defined _NL_CURRENT /* Get the locale specific alternate representation of the number. If none exist NULL is returned. */ const CHAR_T *cp = nl_get_alt_digit (u_number_value @@ -1724,9 +1822,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) break; } } -#elif HAVE_ONLY_C_LOCALE || (USE_C_LOCALE && !HAVE_STRFTIME_L) -#else - goto underlying_strftime; #endif } @@ -1740,7 +1835,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) if (tz_colon_mask & 1) *--bufp = ':'; tz_colon_mask >>= 1; - *--bufp = u_number_value % 10 + L_('0'); +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + *--bufp = u_number_value % 10 + (digits_base & 0xFF); + if (digits_base >= 0x100) + *--bufp = digits_base >> 8; +#else + *--bufp = u_number_value % 10 + '0'; +#endif u_number_value /= 10; } while (u_number_value != 0 || tz_colon_mask != 0); @@ -1755,8 +1856,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) CHAR_T sign_char = (negative_number ? L_('-') : always_output_a_sign ? L_('+') : 0); - int numlen = buf + sizeof buf / sizeof buf[0] - bufp; - int shortage = width - !!sign_char - numlen; + int number_bytes = buf + sizeof buf / sizeof buf[0] - bufp; + int number_digits = number_bytes; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (digits_base >= 0x100) + number_digits = number_bytes / 2; +#endif + int shortage = width - !!sign_char - number_digits; int padding = pad == NO_PAD || shortage <= 0 ? 0 : shortage; if (sign_char) @@ -1772,7 +1878,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) width--; } - cpy (numlen, bufp); + cpy (number_bytes, bufp); } break; @@ -1833,6 +1939,10 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) if (modifier == L_('E')) goto bad_format; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + DO_SIGNED_NUMBER (2, false, caldate->month + 1U); +#endif DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U); #ifndef _LIBC @@ -2070,9 +2180,11 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) goto underlying_strftime; #endif } - if (modifier == L_('O')) - goto bad_format; +#if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME + if (cal != NULL) + DO_YEARISH (4, false, caldate->year); +#endif DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE, tp->tm_year + (unsigned int) TM_YEAR_BASE); diff --git a/lib/strftime.h b/lib/strftime.h index 3b7e20f236a..a76c98c9c82 100644 --- a/lib/strftime.h +++ b/lib/strftime.h @@ -59,6 +59,15 @@ extern "C" { date and time: %c time zone: %z %Z nanosecond %N + In locales with non-Gregorian calendars, the following conversions don't + apply in the expected way: + date: + century %C + year %y + week-based year %G %g + week in year %U %W %V + day in year %j + year, month, day %D Store the result, as a string with a trailing NUL character, at the beginning of the array __S[0..__MAXSIZE-1] and return the length of diff --git a/lib/string.in.h b/lib/string.in.h index e3d94b76c17..9a039c7ba06 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -214,65 +214,85 @@ _GL_EXTERN_C void free (void *); /* Declarations for ISO C N3322. */ #if defined __GNUC__ && __GNUC__ >= 15 && !defined __clang__ +# ifndef memcpy _GL_EXTERN_C void *memcpy (void *__dest, const void *__src, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); -_GL_EXTERN_C void *memccpy (void *__dest, const void *__src, int __c, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 - _GL_ATTRIBUTE_NOTHROW # endif +# ifndef memccpy +_GL_EXTERN_C void *memccpy (void *__dest, const void *__src, int __c, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 4) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 4); +# endif +# ifndef memmove _GL_EXTERN_C void *memmove (void *__dest, const void *__src, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); +# endif +# ifndef strncpy _GL_EXTERN_C char *strncpy (char *__dest, const char *__src, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); +# endif +# ifndef strndup _GL_EXTERN_C char *strndup (const char *__s, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2); +# endif +# ifndef strncat _GL_EXTERN_C char *strncat (char *__dest, const char *__src, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ARG_NONNULL ((1)) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); +# endif +# ifndef memcmp _GL_EXTERN_C int memcmp (const void *__s1, const void *__s2, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); +# endif +# ifndef strncmp _GL_EXTERN_C int strncmp (const char *__s1, const char *__s2, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); -# ifndef __cplusplus +# endif +# if !defined memchr && !defined __cplusplus _GL_EXTERN_C void *memchr (const void *__s, int __c, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); _GL_EXTERN_C void *memrchr (const void *__s, int __c, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); # endif +# ifndef memset _GL_EXTERN_C void *memset (void *__s, int __c, size_t __n) -# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 _GL_ATTRIBUTE_NOTHROW -# endif +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); +# endif +# ifndef memset_explicit _GL_EXTERN_C void *memset_explicit (void *__s, int __c, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); +# endif #endif diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index d525d8b1faa..034dae69e68 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,5 +1,5 @@ # gnulib-common.m4 -# serial 112 +# serial 113 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -70,7 +70,8 @@ AC_DEFUN([gl_COMMON_BODY], [ This rare bug can be worked around by compiling with 'clang -D_Noreturn=', though the workaround may generate many false-alarm warnings. */ #ifndef _Noreturn -# if 201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) +# if ((!defined __cplusplus || defined __clang__) \ + && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0))) /* _Noreturn works as-is. */ # elif _GL_GNUC_PREREQ (2, 8) || defined __clang__ || 0x5110 <= __SUNPRO_C /* Prefer __attribute__ ((__noreturn__)) to plain _Noreturn even if the diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 7e6a8a5494f..83d5f1bfa0f 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -154,7 +154,7 @@ AC_DEFUN([gl_EARLY], # Code from module nanosleep: # Code from module nocrash: # Code from module nproc: - # Code from module nstrftime: + # Code from module nstrftime-limited: # Code from module open: # Code from module openat-h: # Code from module pathmax: @@ -1248,6 +1248,10 @@ AC_DEFUN([gl_FILE_LIST], [ lib/c-strcase.h lib/c-strcasecmp.c lib/c-strncasecmp.c + lib/calendar-ethiopian.h + lib/calendar-persian.h + lib/calendar-thai.h + lib/calendars.h lib/canonicalize-lgpl.c lib/careadlinkat.c lib/careadlinkat.h