strftime_l.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  1. /* Copyright (C) 2002-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #ifdef HAVE_CONFIG_H
  15. # include <config.h>
  16. #endif
  17. #ifdef _LIBC
  18. # define USE_IN_EXTENDED_LOCALE_MODEL 1
  19. # define HAVE_LIMITS_H 1
  20. # define HAVE_MBLEN 1
  21. # define HAVE_MBRLEN 1
  22. # define HAVE_STRUCT_ERA_ENTRY 1
  23. # define HAVE_TM_GMTOFF 1
  24. # define HAVE_TM_ZONE 1
  25. # define HAVE_TZNAME 1
  26. # define HAVE_TZSET 1
  27. # define HAVE_STRFTIME 0
  28. # define MULTIBYTE_IS_FORMAT_SAFE 1
  29. # define STDC_HEADERS 1
  30. # include "../locale/localeinfo.h"
  31. #endif
  32. #if defined emacs && !defined HAVE_BCOPY
  33. # define HAVE_MEMCPY 1
  34. #endif
  35. #include <ctype.h>
  36. #include <errno.h>
  37. #include <sys/types.h> /* Some systems define `time_t' here. */
  38. #ifdef TIME_WITH_SYS_TIME
  39. # include <sys/time.h>
  40. # include <time.h>
  41. #else
  42. # ifdef HAVE_SYS_TIME_H
  43. # include <sys/time.h>
  44. # else
  45. # include <time.h>
  46. # endif
  47. #endif
  48. #if HAVE_TZNAME
  49. extern char *tzname[];
  50. #endif
  51. /* Do multibyte processing if multibytes are supported, unless
  52. multibyte sequences are safe in formats. Multibyte sequences are
  53. safe if they cannot contain byte sequences that look like format
  54. conversion specifications. The GNU C Library uses UTF8 multibyte
  55. encoding, which is safe for formats, but strftime.c can be used
  56. with other C libraries that use unsafe encodings. */
  57. #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
  58. #if DO_MULTIBYTE
  59. # if HAVE_MBRLEN
  60. # include <wchar.h>
  61. # else
  62. /* Simulate mbrlen with mblen as best we can. */
  63. # define mbstate_t int
  64. # define mbrlen(s, n, ps) mblen (s, n)
  65. # define mbsinit(ps) (*(ps) == 0)
  66. # endif
  67. static const mbstate_t mbstate_zero;
  68. #endif
  69. #if HAVE_LIMITS_H
  70. # include <limits.h>
  71. #endif
  72. #if STDC_HEADERS
  73. # include <stddef.h>
  74. # include <stdlib.h>
  75. # include <string.h>
  76. # include <stdbool.h>
  77. #else
  78. # ifndef HAVE_MEMCPY
  79. # define memcpy(d, s, n) bcopy ((s), (d), (n))
  80. # endif
  81. #endif
  82. #ifdef COMPILE_WIDE
  83. # include <endian.h>
  84. # define CHAR_T wchar_t
  85. # define UCHAR_T unsigned int
  86. # define L_(Str) L##Str
  87. # define NLW(Sym) _NL_W##Sym
  88. # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
  89. # define STRLEN(s) __wcslen (s)
  90. #else
  91. # define CHAR_T char
  92. # define UCHAR_T unsigned char
  93. # define L_(Str) Str
  94. # define NLW(Sym) Sym
  95. # define ABALTMON_1 _NL_ABALTMON_1
  96. # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
  97. # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
  98. # else
  99. # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
  100. # endif
  101. # define STRLEN(s) strlen (s)
  102. # ifdef _LIBC
  103. # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
  104. # else
  105. # ifndef HAVE_MEMPCPY
  106. # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
  107. # endif
  108. # endif
  109. #endif
  110. #ifndef PTR
  111. # define PTR void *
  112. #endif
  113. #ifndef CHAR_BIT
  114. # define CHAR_BIT 8
  115. #endif
  116. #ifndef NULL
  117. # define NULL 0
  118. #endif
  119. #define TYPE_SIGNED(t) ((t) -1 < 0)
  120. /* Bound on length of the string representing an integer value of type t.
  121. Subtract one for the sign bit if t is signed;
  122. 302 / 1000 is log10 (2) rounded up;
  123. add one for integer division truncation;
  124. add one more for a minus sign if t is signed. */
  125. #define INT_STRLEN_BOUND(t) \
  126. ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
  127. #define TM_YEAR_BASE 1900
  128. #ifndef __isleap
  129. /* Nonzero if YEAR is a leap year (every 4 years,
  130. except every 100th isn't, and every 400th is). */
  131. # define __isleap(year) \
  132. ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  133. #endif
  134. #ifdef _LIBC
  135. # define tzname __tzname
  136. # define tzset __tzset
  137. # define time_t __time64_t
  138. # define __gmtime_r(t, tp) __gmtime64_r (t, tp)
  139. # define mktime(tp) __mktime64 (tp)
  140. #endif
  141. #if !HAVE_TM_GMTOFF
  142. /* Portable standalone applications should supply a "time_r.h" that
  143. declares a POSIX-compliant localtime_r, for the benefit of older
  144. implementations that lack localtime_r or have a nonstandard one.
  145. Similarly for gmtime_r. See the gnulib time_r module for one way
  146. to implement this. */
  147. # include "time_r.h"
  148. # undef __gmtime_r
  149. # undef __localtime_r
  150. # define __gmtime_r gmtime_r
  151. # define __localtime_r localtime_r
  152. #endif
  153. #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
  154. /* Some systems lack the `memset' function and we don't want to
  155. introduce additional dependencies. */
  156. /* The SGI compiler reportedly barfs on the trailing null
  157. if we use a string constant as the initializer. 28 June 1997, rms. */
  158. static const CHAR_T spaces[16] = /* " " */
  159. {
  160. L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
  161. L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
  162. };
  163. static const CHAR_T zeroes[16] = /* "0000000000000000" */
  164. {
  165. L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
  166. L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
  167. };
  168. # define memset_space(P, Len) \
  169. do { \
  170. int _len = (Len); \
  171. \
  172. do \
  173. { \
  174. int _this = _len > 16 ? 16 : _len; \
  175. (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
  176. _len -= _this; \
  177. } \
  178. while (_len > 0); \
  179. } while (0)
  180. # define memset_zero(P, Len) \
  181. do { \
  182. int _len = (Len); \
  183. \
  184. do \
  185. { \
  186. int _this = _len > 16 ? 16 : _len; \
  187. (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
  188. _len -= _this; \
  189. } \
  190. while (_len > 0); \
  191. } while (0)
  192. #else
  193. # ifdef COMPILE_WIDE
  194. # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
  195. # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
  196. # else
  197. # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
  198. # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
  199. # endif
  200. #endif
  201. #define add(n, f) \
  202. do \
  203. { \
  204. int _n = (n); \
  205. int _delta = width - _n; \
  206. int _incr = _n + (_delta > 0 ? _delta : 0); \
  207. if ((size_t) _incr >= maxsize - i) \
  208. return 0; \
  209. if (p) \
  210. { \
  211. if (_delta > 0) \
  212. { \
  213. if (pad == L_('0')) \
  214. memset_zero (p, _delta); \
  215. else \
  216. memset_space (p, _delta); \
  217. } \
  218. f; \
  219. p += _n; \
  220. } \
  221. i += _incr; \
  222. } while (0)
  223. #define cpy(n, s) \
  224. add ((n), \
  225. if (to_lowcase) \
  226. memcpy_lowcase (p, (s), _n LOCALE_ARG); \
  227. else if (to_uppcase) \
  228. memcpy_uppcase (p, (s), _n LOCALE_ARG); \
  229. else \
  230. MEMCPY ((PTR) p, (const PTR) (s), _n))
  231. #ifdef COMPILE_WIDE
  232. # ifndef USE_IN_EXTENDED_LOCALE_MODEL
  233. # undef __mbsrtowcs_l
  234. # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
  235. # endif
  236. #endif
  237. #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
  238. /* We use this code also for the extended locale handling where the
  239. function gets as an additional argument the locale which has to be
  240. used. To access the values we have to redefine the _NL_CURRENT
  241. macro. */
  242. # define strftime __strftime_l
  243. # define wcsftime __wcsftime_l
  244. # undef _NL_CURRENT
  245. # define _NL_CURRENT(category, item) \
  246. (current->values[_NL_ITEM_INDEX (item)].string)
  247. # define LOCALE_PARAM , locale_t loc
  248. # define LOCALE_ARG , loc
  249. # define HELPER_LOCALE_ARG , current
  250. #else
  251. # define LOCALE_PARAM
  252. # define LOCALE_ARG
  253. # ifdef _LIBC
  254. # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
  255. # else
  256. # define HELPER_LOCALE_ARG
  257. # endif
  258. #endif
  259. #ifdef COMPILE_WIDE
  260. # ifdef USE_IN_EXTENDED_LOCALE_MODEL
  261. # define TOUPPER(Ch, L) __towupper_l (Ch, L)
  262. # define TOLOWER(Ch, L) __towlower_l (Ch, L)
  263. # else
  264. # define TOUPPER(Ch, L) towupper (Ch)
  265. # define TOLOWER(Ch, L) towlower (Ch)
  266. # endif
  267. #else
  268. # ifdef _LIBC
  269. # ifdef USE_IN_EXTENDED_LOCALE_MODEL
  270. # define TOUPPER(Ch, L) __toupper_l (Ch, L)
  271. # define TOLOWER(Ch, L) __tolower_l (Ch, L)
  272. # else
  273. # define TOUPPER(Ch, L) toupper (Ch)
  274. # define TOLOWER(Ch, L) tolower (Ch)
  275. # endif
  276. # else
  277. # define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
  278. # define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
  279. # endif
  280. #endif
  281. /* We don't use `isdigit' here since the locale dependent
  282. interpretation is not what we want here. We only need to accept
  283. the arabic digits in the ASCII range. One day there is perhaps a
  284. more reliable way to accept other sets of digits. */
  285. #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
  286. static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
  287. size_t len LOCALE_PARAM) __THROW;
  288. static CHAR_T *
  289. memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
  290. {
  291. while (len-- > 0)
  292. dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
  293. return dest;
  294. }
  295. static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
  296. size_t len LOCALE_PARAM) __THROW;
  297. static CHAR_T *
  298. memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
  299. {
  300. while (len-- > 0)
  301. dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
  302. return dest;
  303. }
  304. #if ! HAVE_TM_GMTOFF
  305. /* Yield the difference between *A and *B,
  306. measured in seconds, ignoring leap seconds. */
  307. # define tm_diff ftime_tm_diff
  308. static int tm_diff (const struct tm *, const struct tm *) __THROW;
  309. static int
  310. tm_diff (const struct tm *a, const struct tm *b)
  311. {
  312. /* Compute intervening leap days correctly even if year is negative.
  313. Take care to avoid int overflow in leap day calculations,
  314. but it's OK to assume that A and B are close to each other. */
  315. int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
  316. int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
  317. int a100 = a4 / 25 - (a4 % 25 < 0);
  318. int b100 = b4 / 25 - (b4 % 25 < 0);
  319. int a400 = a100 >> 2;
  320. int b400 = b100 >> 2;
  321. int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
  322. int years = a->tm_year - b->tm_year;
  323. int days = (365 * years + intervening_leap_days
  324. + (a->tm_yday - b->tm_yday));
  325. return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
  326. + (a->tm_min - b->tm_min))
  327. + (a->tm_sec - b->tm_sec));
  328. }
  329. #endif /* ! HAVE_TM_GMTOFF */
  330. /* The number of days from the first day of the first ISO week of this
  331. year to the year day YDAY with week day WDAY. ISO weeks start on
  332. Monday; the first ISO week has the year's first Thursday. YDAY may
  333. be as small as YDAY_MINIMUM. */
  334. #define ISO_WEEK_START_WDAY 1 /* Monday */
  335. #define ISO_WEEK1_WDAY 4 /* Thursday */
  336. #define YDAY_MINIMUM (-366)
  337. static int iso_week_days (int, int) __THROW;
  338. #ifdef __GNUC__
  339. __inline__
  340. #endif
  341. static int
  342. iso_week_days (int yday, int wday)
  343. {
  344. /* Add enough to the first operand of % to make it nonnegative. */
  345. int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
  346. return (yday
  347. - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
  348. + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
  349. }
  350. #if !(defined _NL_CURRENT || HAVE_STRFTIME)
  351. static CHAR_T const weekday_name[][10] =
  352. {
  353. L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
  354. L_("Thursday"), L_("Friday"), L_("Saturday")
  355. };
  356. static CHAR_T const month_name[][10] =
  357. {
  358. L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
  359. L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
  360. L_("November"), L_("December")
  361. };
  362. #endif
  363. #ifdef emacs
  364. # define my_strftime emacs_strftimeu
  365. # define ut_argument , ut
  366. # define ut_argument_spec , int ut
  367. #else
  368. # ifdef COMPILE_WIDE
  369. # define my_strftime wcsftime
  370. # define nl_get_alt_digit _nl_get_walt_digit
  371. # else
  372. # define my_strftime strftime
  373. # define nl_get_alt_digit _nl_get_alt_digit
  374. # endif
  375. # define ut_argument
  376. # define ut_argument_spec
  377. /* We don't have this information in general. */
  378. # define ut 0
  379. #endif
  380. static size_t __strftime_internal (CHAR_T *, size_t, const CHAR_T *,
  381. const struct tm *, int, bool *
  382. ut_argument_spec
  383. LOCALE_PARAM) __THROW;
  384. /* Write information from TP into S according to the format
  385. string FORMAT, writing no more that MAXSIZE characters
  386. (including the terminating '\0') and returning number of
  387. characters written. If S is NULL, nothing will be written
  388. anywhere, so to determine how many characters would be
  389. written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
  390. size_t
  391. my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format,
  392. const struct tm *tp ut_argument_spec LOCALE_PARAM)
  393. {
  394. #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
  395. /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
  396. Work around this bug by copying *tp before it might be munged. */
  397. struct tm tmcopy;
  398. tmcopy = *tp;
  399. tp = &tmcopy;
  400. #endif
  401. bool tzset_called = false;
  402. return __strftime_internal (s, maxsize, format, tp, 0, &tzset_called
  403. ut_argument LOCALE_ARG);
  404. }
  405. #ifdef _LIBC
  406. libc_hidden_def (my_strftime)
  407. #endif
  408. static size_t
  409. __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
  410. const struct tm *tp, int yr_spec, bool *tzset_called
  411. ut_argument_spec LOCALE_PARAM)
  412. {
  413. #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
  414. struct __locale_data *const current = loc->__locales[LC_TIME];
  415. #endif
  416. int hour12 = tp->tm_hour;
  417. #ifdef _NL_CURRENT
  418. /* We cannot make the following values variables since we must delay
  419. the evaluation of these values until really needed since some
  420. expressions might not be valid in every situation. The `struct tm'
  421. might be generated by a strptime() call that initialized
  422. only a few elements. Dereference the pointers only if the format
  423. requires this. Then it is ok to fail if the pointers are invalid. */
  424. # define a_wkday \
  425. ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
  426. ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
  427. # define f_wkday \
  428. ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
  429. ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
  430. # define a_month \
  431. ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
  432. ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
  433. # define f_month \
  434. ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
  435. ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
  436. # define a_altmonth \
  437. ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
  438. ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon)))
  439. # define f_altmonth \
  440. ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
  441. ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
  442. # define ampm \
  443. ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
  444. ? NLW(PM_STR) : NLW(AM_STR)))
  445. # define aw_len STRLEN (a_wkday)
  446. # define am_len STRLEN (a_month)
  447. # define aam_len STRLEN (a_altmonth)
  448. # define ap_len STRLEN (ampm)
  449. #else
  450. # if !HAVE_STRFTIME
  451. # define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \
  452. ? "?" : weekday_name[tp->tm_wday])
  453. # define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \
  454. ? "?" : month_name[tp->tm_mon])
  455. # define a_wkday f_wkday
  456. # define a_month f_month
  457. # define a_altmonth a_month
  458. # define f_altmonth f_month
  459. # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
  460. size_t aw_len = 3;
  461. size_t am_len = 3;
  462. size_t aam_len = 3;
  463. size_t ap_len = 2;
  464. # endif
  465. #endif
  466. const char *zone;
  467. size_t i = 0;
  468. CHAR_T *p = s;
  469. const CHAR_T *f;
  470. #if DO_MULTIBYTE && !defined COMPILE_WIDE
  471. const char *format_end = NULL;
  472. #endif
  473. zone = NULL;
  474. #if HAVE_TM_ZONE
  475. /* The POSIX test suite assumes that setting
  476. the environment variable TZ to a new value before calling strftime()
  477. will influence the result (the %Z format) even if the information in
  478. TP is computed with a totally different time zone.
  479. This is bogus: though POSIX allows bad behavior like this,
  480. POSIX does not require it. Do the right thing instead. */
  481. zone = (const char *) tp->tm_zone;
  482. #endif
  483. #if HAVE_TZNAME
  484. if (ut)
  485. {
  486. if (! (zone && *zone))
  487. zone = "GMT";
  488. }
  489. #endif
  490. if (hour12 > 12)
  491. hour12 -= 12;
  492. else
  493. if (hour12 == 0)
  494. hour12 = 12;
  495. for (f = format; *f != '\0'; ++f)
  496. {
  497. int pad = 0; /* Padding for number ('-', '_', or 0). */
  498. int modifier; /* Field modifier ('E', 'O', or 0). */
  499. int digits; /* Max digits for numeric format. */
  500. int number_value; /* Numeric value to be printed. */
  501. int negative_number; /* 1 if the number is negative. */
  502. const CHAR_T *subfmt;
  503. CHAR_T *bufp;
  504. CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
  505. ? INT_STRLEN_BOUND (time_t)
  506. : INT_STRLEN_BOUND (int))];
  507. int width = -1;
  508. int to_lowcase = 0;
  509. int to_uppcase = 0;
  510. int change_case = 0;
  511. int format_char;
  512. #if DO_MULTIBYTE && !defined COMPILE_WIDE
  513. switch (*f)
  514. {
  515. case L_('%'):
  516. break;
  517. case L_('\b'): case L_('\t'): case L_('\n'):
  518. case L_('\v'): case L_('\f'): case L_('\r'):
  519. case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
  520. case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
  521. case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
  522. case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
  523. case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
  524. case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
  525. case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
  526. case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
  527. case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
  528. case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
  529. case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
  530. case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
  531. case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
  532. case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
  533. case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
  534. case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
  535. case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
  536. case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
  537. case L_('~'):
  538. /* The C Standard requires these 98 characters (plus '%') to
  539. be in the basic execution character set. None of these
  540. characters can start a multibyte sequence, so they need
  541. not be analyzed further. */
  542. add (1, *p = *f);
  543. continue;
  544. default:
  545. /* Copy this multibyte sequence until we reach its end, find
  546. an error, or come back to the initial shift state. */
  547. {
  548. mbstate_t mbstate = mbstate_zero;
  549. size_t len = 0;
  550. size_t fsize;
  551. if (! format_end)
  552. format_end = f + strlen (f) + 1;
  553. fsize = format_end - f;
  554. do
  555. {
  556. size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
  557. if (bytes == 0)
  558. break;
  559. if (bytes == (size_t) -2)
  560. {
  561. len += strlen (f + len);
  562. break;
  563. }
  564. if (bytes == (size_t) -1)
  565. {
  566. len++;
  567. break;
  568. }
  569. len += bytes;
  570. }
  571. while (! mbsinit (&mbstate));
  572. cpy (len, f);
  573. f += len - 1;
  574. continue;
  575. }
  576. }
  577. #else /* ! DO_MULTIBYTE */
  578. /* Either multibyte encodings are not supported, they are
  579. safe for formats, so any non-'%' byte can be copied through,
  580. or this is the wide character version. */
  581. if (*f != L_('%'))
  582. {
  583. add (1, *p = *f);
  584. continue;
  585. }
  586. #endif /* ! DO_MULTIBYTE */
  587. /* Check for flags that can modify a format. */
  588. while (1)
  589. {
  590. switch (*++f)
  591. {
  592. /* This influences the number formats. */
  593. case L_('_'):
  594. case L_('-'):
  595. case L_('0'):
  596. pad = *f;
  597. continue;
  598. /* This changes textual output. */
  599. case L_('^'):
  600. to_uppcase = 1;
  601. continue;
  602. case L_('#'):
  603. change_case = 1;
  604. continue;
  605. default:
  606. break;
  607. }
  608. break;
  609. }
  610. /* As a GNU extension we allow to specify the field width. */
  611. if (ISDIGIT (*f))
  612. {
  613. width = 0;
  614. do
  615. {
  616. if (width > INT_MAX / 10
  617. || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
  618. /* Avoid overflow. */
  619. width = INT_MAX;
  620. else
  621. {
  622. width *= 10;
  623. width += *f - L_('0');
  624. }
  625. ++f;
  626. }
  627. while (ISDIGIT (*f));
  628. }
  629. /* Check for modifiers. */
  630. switch (*f)
  631. {
  632. case L_('E'):
  633. case L_('O'):
  634. modifier = *f++;
  635. break;
  636. default:
  637. modifier = 0;
  638. break;
  639. }
  640. /* Now do the specified format. */
  641. format_char = *f;
  642. switch (format_char)
  643. {
  644. #define DO_NUMBER(d, v) \
  645. do \
  646. { \
  647. digits = d > width ? d : width; \
  648. number_value = v; \
  649. goto do_number; \
  650. } \
  651. while (0)
  652. #define DO_NUMBER_SPACEPAD(d, v) \
  653. do \
  654. { \
  655. digits = d > width ? d : width; \
  656. number_value = v; \
  657. goto do_number_spacepad; \
  658. } \
  659. while (0)
  660. case L_('%'):
  661. if (modifier != 0)
  662. goto bad_format;
  663. add (1, *p = *f);
  664. break;
  665. case L_('a'):
  666. if (modifier != 0)
  667. goto bad_format;
  668. if (change_case)
  669. {
  670. to_uppcase = 1;
  671. to_lowcase = 0;
  672. }
  673. #if defined _NL_CURRENT || !HAVE_STRFTIME
  674. cpy (aw_len, a_wkday);
  675. break;
  676. #else
  677. goto underlying_strftime;
  678. #endif
  679. case 'A':
  680. if (modifier != 0)
  681. goto bad_format;
  682. if (change_case)
  683. {
  684. to_uppcase = 1;
  685. to_lowcase = 0;
  686. }
  687. #if defined _NL_CURRENT || !HAVE_STRFTIME
  688. cpy (STRLEN (f_wkday), f_wkday);
  689. break;
  690. #else
  691. goto underlying_strftime;
  692. #endif
  693. case L_('b'):
  694. case L_('h'):
  695. if (change_case)
  696. {
  697. to_uppcase = 1;
  698. to_lowcase = 0;
  699. }
  700. if (modifier == L_('E'))
  701. goto bad_format;
  702. #if defined _NL_CURRENT || !HAVE_STRFTIME
  703. if (modifier == L_('O'))
  704. cpy (aam_len, a_altmonth);
  705. else
  706. cpy (am_len, a_month);
  707. break;
  708. #else
  709. goto underlying_strftime;
  710. #endif
  711. case L_('B'):
  712. if (modifier == L_('E'))
  713. goto bad_format;
  714. if (change_case)
  715. {
  716. to_uppcase = 1;
  717. to_lowcase = 0;
  718. }
  719. #if defined _NL_CURRENT || !HAVE_STRFTIME
  720. if (modifier == L_('O'))
  721. cpy (STRLEN (f_altmonth), f_altmonth);
  722. else
  723. cpy (STRLEN (f_month), f_month);
  724. break;
  725. #else
  726. goto underlying_strftime;
  727. #endif
  728. case L_('c'):
  729. if (modifier == L_('O'))
  730. goto bad_format;
  731. #ifdef _NL_CURRENT
  732. if (! (modifier == L_('E')
  733. && (*(subfmt =
  734. (const CHAR_T *) _NL_CURRENT (LC_TIME,
  735. NLW(ERA_D_T_FMT)))
  736. != '\0')))
  737. subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
  738. #else
  739. # if HAVE_STRFTIME
  740. goto underlying_strftime;
  741. # else
  742. subfmt = L_("%a %b %e %H:%M:%S %Y");
  743. # endif
  744. #endif
  745. subformat:
  746. {
  747. CHAR_T *old_start = p;
  748. size_t len = __strftime_internal (NULL, (size_t) -1, subfmt,
  749. tp, yr_spec, tzset_called
  750. ut_argument LOCALE_ARG);
  751. add (len, __strftime_internal (p, maxsize - i, subfmt,
  752. tp, yr_spec, tzset_called
  753. ut_argument LOCALE_ARG));
  754. if (to_uppcase)
  755. while (old_start < p)
  756. {
  757. *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
  758. ++old_start;
  759. }
  760. }
  761. break;
  762. #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
  763. underlying_strftime:
  764. {
  765. /* The relevant information is available only via the
  766. underlying strftime implementation, so use that. */
  767. char ufmt[4];
  768. char *u = ufmt;
  769. char ubuf[1024]; /* enough for any single format in practice */
  770. size_t len;
  771. /* Make sure we're calling the actual underlying strftime.
  772. In some cases, config.h contains something like
  773. "#define strftime rpl_strftime". */
  774. # ifdef strftime
  775. # undef strftime
  776. size_t strftime ();
  777. # endif
  778. *u++ = '%';
  779. if (modifier != 0)
  780. *u++ = modifier;
  781. *u++ = format_char;
  782. *u = '\0';
  783. len = strftime (ubuf, sizeof ubuf, ufmt, tp);
  784. if (len == 0 && ubuf[0] != '\0')
  785. return 0;
  786. cpy (len, ubuf);
  787. }
  788. break;
  789. #endif
  790. case L_('C'):
  791. if (modifier == L_('E'))
  792. {
  793. #if HAVE_STRUCT_ERA_ENTRY
  794. struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
  795. if (era)
  796. {
  797. # ifdef COMPILE_WIDE
  798. size_t len = __wcslen (era->era_wname);
  799. cpy (len, era->era_wname);
  800. # else
  801. size_t len = strlen (era->era_name);
  802. cpy (len, era->era_name);
  803. # endif
  804. break;
  805. }
  806. #else
  807. # if HAVE_STRFTIME
  808. goto underlying_strftime;
  809. # endif
  810. #endif
  811. }
  812. {
  813. int year = tp->tm_year + TM_YEAR_BASE;
  814. DO_NUMBER (1, year / 100 - (year % 100 < 0));
  815. }
  816. case L_('x'):
  817. if (modifier == L_('O'))
  818. goto bad_format;
  819. #ifdef _NL_CURRENT
  820. if (! (modifier == L_('E')
  821. && (*(subfmt =
  822. (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
  823. != L_('\0'))))
  824. subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
  825. goto subformat;
  826. #else
  827. # if HAVE_STRFTIME
  828. goto underlying_strftime;
  829. # else
  830. /* Fall through. */
  831. # endif
  832. #endif
  833. case L_('D'):
  834. if (modifier != 0)
  835. goto bad_format;
  836. subfmt = L_("%m/%d/%y");
  837. goto subformat;
  838. case L_('d'):
  839. if (modifier == L_('E'))
  840. goto bad_format;
  841. DO_NUMBER (2, tp->tm_mday);
  842. case L_('e'):
  843. if (modifier == L_('E'))
  844. goto bad_format;
  845. DO_NUMBER_SPACEPAD (2, tp->tm_mday);
  846. /* All numeric formats set DIGITS and NUMBER_VALUE and then
  847. jump to one of these two labels. */
  848. do_number_spacepad:
  849. /* Force `_' flag unless overwritten by `0' or '-' flag. */
  850. if (pad != L_('0') && pad != L_('-'))
  851. pad = L_('_');
  852. do_number:
  853. /* Format the number according to the MODIFIER flag. */
  854. if (modifier == L_('O') && 0 <= number_value)
  855. {
  856. #ifdef _NL_CURRENT
  857. /* Get the locale specific alternate representation of
  858. the number NUMBER_VALUE. If none exist NULL is returned. */
  859. const CHAR_T *cp = nl_get_alt_digit (number_value
  860. HELPER_LOCALE_ARG);
  861. if (cp != NULL)
  862. {
  863. size_t digitlen = STRLEN (cp);
  864. if (digitlen != 0)
  865. {
  866. cpy (digitlen, cp);
  867. break;
  868. }
  869. }
  870. #else
  871. # if HAVE_STRFTIME
  872. goto underlying_strftime;
  873. # endif
  874. #endif
  875. }
  876. {
  877. unsigned int u = number_value;
  878. bufp = buf + sizeof (buf) / sizeof (buf[0]);
  879. negative_number = number_value < 0;
  880. if (negative_number)
  881. u = -u;
  882. do
  883. *--bufp = u % 10 + L_('0');
  884. while ((u /= 10) != 0);
  885. }
  886. do_number_sign_and_padding:
  887. if (negative_number)
  888. *--bufp = L_('-');
  889. if (pad != L_('-'))
  890. {
  891. int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
  892. - bufp);
  893. if (padding > 0)
  894. {
  895. if (pad == L_('_'))
  896. {
  897. if ((size_t) padding >= maxsize - i)
  898. return 0;
  899. if (p)
  900. memset_space (p, padding);
  901. i += padding;
  902. width = width > padding ? width - padding : 0;
  903. }
  904. else
  905. {
  906. if ((size_t) digits >= maxsize - i)
  907. return 0;
  908. if (negative_number)
  909. {
  910. ++bufp;
  911. if (p)
  912. *p++ = L_('-');
  913. ++i;
  914. }
  915. if (p)
  916. memset_zero (p, padding);
  917. i += padding;
  918. width = 0;
  919. }
  920. }
  921. }
  922. cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
  923. break;
  924. case L_('F'):
  925. if (modifier != 0)
  926. goto bad_format;
  927. subfmt = L_("%Y-%m-%d");
  928. goto subformat;
  929. case L_('H'):
  930. if (modifier == L_('E'))
  931. goto bad_format;
  932. DO_NUMBER (2, tp->tm_hour);
  933. case L_('I'):
  934. if (modifier == L_('E'))
  935. goto bad_format;
  936. DO_NUMBER (2, hour12);
  937. case L_('k'): /* GNU extension. */
  938. if (modifier == L_('E'))
  939. goto bad_format;
  940. DO_NUMBER_SPACEPAD (2, tp->tm_hour);
  941. case L_('l'): /* GNU extension. */
  942. if (modifier == L_('E'))
  943. goto bad_format;
  944. DO_NUMBER_SPACEPAD (2, hour12);
  945. case L_('j'):
  946. if (modifier == L_('E'))
  947. goto bad_format;
  948. DO_NUMBER (3, 1 + tp->tm_yday);
  949. case L_('M'):
  950. if (modifier == L_('E'))
  951. goto bad_format;
  952. DO_NUMBER (2, tp->tm_min);
  953. case L_('m'):
  954. if (modifier == L_('E'))
  955. goto bad_format;
  956. DO_NUMBER (2, tp->tm_mon + 1);
  957. case L_('n'):
  958. add (1, *p = L_('\n'));
  959. break;
  960. case L_('P'):
  961. to_lowcase = 1;
  962. #if !defined _NL_CURRENT && HAVE_STRFTIME
  963. format_char = L_('p');
  964. #endif
  965. [[fallthrough]];
  966. case L_('p'):
  967. if (change_case)
  968. {
  969. to_uppcase = 0;
  970. to_lowcase = 1;
  971. }
  972. #if defined _NL_CURRENT || !HAVE_STRFTIME
  973. cpy (ap_len, ampm);
  974. break;
  975. #else
  976. goto underlying_strftime;
  977. #endif
  978. case L_('R'):
  979. subfmt = L_("%H:%M");
  980. goto subformat;
  981. case L_('r'):
  982. #if !defined _NL_CURRENT && HAVE_STRFTIME
  983. goto underlying_strftime;
  984. #else
  985. # ifdef _NL_CURRENT
  986. if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
  987. NLW(T_FMT_AMPM)))
  988. == L_('\0'))
  989. # endif
  990. subfmt = L_("%I:%M:%S %p");
  991. goto subformat;
  992. #endif
  993. case L_('S'):
  994. if (modifier == L_('E'))
  995. goto bad_format;
  996. DO_NUMBER (2, tp->tm_sec);
  997. case L_('s'): /* GNU extension. */
  998. {
  999. struct tm ltm;
  1000. time_t t;
  1001. ltm = *tp;
  1002. t = mktime (&ltm);
  1003. /* Generate string value for T using time_t arithmetic;
  1004. this works even if sizeof (long) < sizeof (time_t). */
  1005. bufp = buf + sizeof (buf) / sizeof (buf[0]);
  1006. negative_number = t < 0;
  1007. do
  1008. {
  1009. int d = t % 10;
  1010. t /= 10;
  1011. if (negative_number)
  1012. {
  1013. d = -d;
  1014. /* Adjust if division truncates to minus infinity. */
  1015. if (0 < -1 % 10 && d < 0)
  1016. {
  1017. t++;
  1018. d += 10;
  1019. }
  1020. }
  1021. *--bufp = d + L_('0');
  1022. }
  1023. while (t != 0);
  1024. digits = 1;
  1025. goto do_number_sign_and_padding;
  1026. }
  1027. case L_('X'):
  1028. if (modifier == L_('O'))
  1029. goto bad_format;
  1030. #ifdef _NL_CURRENT
  1031. if (! (modifier == L_('E')
  1032. && (*(subfmt =
  1033. (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
  1034. != L_('\0'))))
  1035. subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
  1036. goto subformat;
  1037. #else
  1038. # if HAVE_STRFTIME
  1039. goto underlying_strftime;
  1040. # else
  1041. /* Fall through. */
  1042. # endif
  1043. #endif
  1044. case L_('T'):
  1045. subfmt = L_("%H:%M:%S");
  1046. goto subformat;
  1047. case L_('t'):
  1048. add (1, *p = L_('\t'));
  1049. break;
  1050. case L_('u'):
  1051. DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
  1052. case L_('U'):
  1053. if (modifier == L_('E'))
  1054. goto bad_format;
  1055. DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
  1056. case L_('V'):
  1057. case L_('g'):
  1058. case L_('G'):
  1059. if (modifier == L_('E'))
  1060. goto bad_format;
  1061. {
  1062. int year = tp->tm_year + TM_YEAR_BASE;
  1063. int days = iso_week_days (tp->tm_yday, tp->tm_wday);
  1064. if (days < 0)
  1065. {
  1066. /* This ISO week belongs to the previous year. */
  1067. year--;
  1068. days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
  1069. tp->tm_wday);
  1070. }
  1071. else
  1072. {
  1073. int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
  1074. tp->tm_wday);
  1075. if (0 <= d)
  1076. {
  1077. /* This ISO week belongs to the next year. */
  1078. year++;
  1079. days = d;
  1080. }
  1081. }
  1082. switch (*f)
  1083. {
  1084. case L_('g'):
  1085. DO_NUMBER (2, (year % 100 + 100) % 100);
  1086. case L_('G'):
  1087. DO_NUMBER (1, year);
  1088. default:
  1089. DO_NUMBER (2, days / 7 + 1);
  1090. }
  1091. }
  1092. case L_('W'):
  1093. if (modifier == L_('E'))
  1094. goto bad_format;
  1095. DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
  1096. case L_('w'):
  1097. if (modifier == L_('E'))
  1098. goto bad_format;
  1099. DO_NUMBER (1, tp->tm_wday);
  1100. case L_('Y'):
  1101. if (modifier == L_('E'))
  1102. {
  1103. #if HAVE_STRUCT_ERA_ENTRY
  1104. struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
  1105. if (era)
  1106. {
  1107. # ifdef COMPILE_WIDE
  1108. subfmt = era->era_wformat;
  1109. # else
  1110. subfmt = era->era_format;
  1111. # endif
  1112. if (pad != 0)
  1113. yr_spec = pad;
  1114. goto subformat;
  1115. }
  1116. #else
  1117. # if HAVE_STRFTIME
  1118. goto underlying_strftime;
  1119. # endif
  1120. #endif
  1121. }
  1122. if (modifier == L_('O'))
  1123. goto bad_format;
  1124. else
  1125. DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
  1126. case L_('y'):
  1127. if (modifier == L_('E'))
  1128. {
  1129. #if HAVE_STRUCT_ERA_ENTRY
  1130. struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
  1131. if (era)
  1132. {
  1133. int delta = tp->tm_year - era->start_date[0];
  1134. if (yr_spec != 0)
  1135. pad = yr_spec;
  1136. DO_NUMBER (2, (era->offset
  1137. + delta * era->absolute_direction));
  1138. }
  1139. #else
  1140. # if HAVE_STRFTIME
  1141. goto underlying_strftime;
  1142. # endif
  1143. #endif
  1144. }
  1145. DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
  1146. case L_('Z'):
  1147. if (change_case)
  1148. {
  1149. to_uppcase = 0;
  1150. to_lowcase = 1;
  1151. }
  1152. #if HAVE_TZNAME
  1153. /* The tzset() call might have changed the value. */
  1154. if (!(zone && *zone) && tp->tm_isdst >= 0)
  1155. {
  1156. /* POSIX.1 requires that local time zone information is used as
  1157. though strftime called tzset. */
  1158. # if HAVE_TZSET
  1159. if (!*tzset_called)
  1160. {
  1161. tzset ();
  1162. *tzset_called = true;
  1163. }
  1164. # endif
  1165. zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
  1166. }
  1167. #endif
  1168. if (! zone)
  1169. zone = "";
  1170. #ifdef COMPILE_WIDE
  1171. {
  1172. /* The zone string is always given in multibyte form. We have
  1173. to convert it to wide character. */
  1174. size_t w = pad == L_('-') || width < 0 ? 0 : width;
  1175. char const *z = zone;
  1176. mbstate_t st = {0};
  1177. size_t len = __mbsrtowcs_l (p, &z, maxsize - i, &st, loc);
  1178. if (len == (size_t) -1)
  1179. return 0;
  1180. size_t incr = len < w ? w : len;
  1181. if (incr >= maxsize - i)
  1182. {
  1183. errno = ERANGE;
  1184. return 0;
  1185. }
  1186. if (p)
  1187. {
  1188. if (len < w)
  1189. {
  1190. size_t delta = w - len;
  1191. __wmemmove (p + delta, p, len);
  1192. wchar_t wc = pad == L_('0') || pad == L_('+') ? L'0' : L' ';
  1193. wmemset (p, wc, delta);
  1194. }
  1195. p += incr;
  1196. }
  1197. i += incr;
  1198. }
  1199. #else
  1200. cpy (strlen (zone), zone);
  1201. #endif
  1202. break;
  1203. case L_('z'):
  1204. if (tp->tm_isdst < 0)
  1205. break;
  1206. {
  1207. int diff;
  1208. #if HAVE_TM_GMTOFF
  1209. diff = tp->tm_gmtoff;
  1210. #else
  1211. if (ut)
  1212. diff = 0;
  1213. else
  1214. {
  1215. struct tm gtm;
  1216. struct tm ltm;
  1217. time_t lt;
  1218. /* POSIX.1 requires that local time zone information is used as
  1219. though strftime called tzset. */
  1220. # if HAVE_TZSET
  1221. if (!*tzset_called)
  1222. {
  1223. tzset ();
  1224. *tzset_called = true;
  1225. }
  1226. # endif
  1227. ltm = *tp;
  1228. lt = mktime (&ltm);
  1229. if (lt == (time_t) -1)
  1230. {
  1231. /* mktime returns -1 for errors, but -1 is also a
  1232. valid time_t value. Check whether an error really
  1233. occurred. */
  1234. struct tm tm;
  1235. if (! __localtime_r (&lt, &tm)
  1236. || ((ltm.tm_sec ^ tm.tm_sec)
  1237. | (ltm.tm_min ^ tm.tm_min)
  1238. | (ltm.tm_hour ^ tm.tm_hour)
  1239. | (ltm.tm_mday ^ tm.tm_mday)
  1240. | (ltm.tm_mon ^ tm.tm_mon)
  1241. | (ltm.tm_year ^ tm.tm_year)))
  1242. break;
  1243. }
  1244. if (! __gmtime_r (&lt, &gtm))
  1245. break;
  1246. diff = tm_diff (&ltm, &gtm);
  1247. }
  1248. #endif
  1249. if (diff < 0)
  1250. {
  1251. add (1, *p = L_('-'));
  1252. diff = -diff;
  1253. }
  1254. else
  1255. add (1, *p = L_('+'));
  1256. diff /= 60;
  1257. DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
  1258. }
  1259. case L_('\0'): /* GNU extension: % at end of format. */
  1260. --f;
  1261. [[fallthrough]];
  1262. default:
  1263. /* Unknown format; output the format, including the '%',
  1264. since this is most likely the right thing to do if a
  1265. multibyte string has been misparsed. */
  1266. bad_format:
  1267. {
  1268. int flen;
  1269. for (flen = 1; f[1 - flen] != L_('%'); flen++)
  1270. continue;
  1271. cpy (flen, &f[1 - flen]);
  1272. }
  1273. break;
  1274. }
  1275. }
  1276. if (p && maxsize != 0)
  1277. *p = L_('\0');
  1278. return i;
  1279. }
  1280. #ifdef emacs
  1281. /* For Emacs we have a separate interface which corresponds to the normal
  1282. strftime function and does not have the extra information whether the
  1283. TP arguments comes from a `gmtime' call or not. */
  1284. size_t
  1285. emacs_strftime (char *s, size_t maxsize, const char *format,
  1286. const struct tm *tp)
  1287. {
  1288. return my_strftime (s, maxsize, format, tp, 0);
  1289. }
  1290. #endif
  1291. #if defined _LIBC && !defined COMPILE_WIDE
  1292. weak_alias (__strftime_l, strftime_l)
  1293. #endif