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