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