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