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