comparison src/strftime.c @ 51648:73b3b97a1595

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