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