aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann2000-10-18 19:12:39 +0000
committerGerd Moellmann2000-10-18 19:12:39 +0000
commite50517d90e8d95c0eb2363d834cf95319288f6fd (patch)
tree22738e8297bb15604a63c4f89a4e595c6f6caf50 /src
parent776ca44f002152d91889b6e4061926eebf1e66c7 (diff)
downloademacs-e50517d90e8d95c0eb2363d834cf95319288f6fd.tar.gz
emacs-e50517d90e8d95c0eb2363d834cf95319288f6fd.zip
Sync with glibc, file version 1.78.
(my_strftime) [HAVE_TZNAME]: Use `UTC' instead of `GMT' which should no longer be used according to ISO 8601.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog4
-rw-r--r--src/strftime.c1585
2 files changed, 862 insertions, 727 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c3d23086ff9..dd0d70169b4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,9 @@
12000-10-18 Gerd Moellmann <gerd@gnu.org> 12000-10-18 Gerd Moellmann <gerd@gnu.org>
2 2
3 * strftime.c: Sync with glibc, file version 1.78.
4 (my_strftime) [HAVE_TZNAME]: Use `UTC' instead of `GMT' which
5 should no longer be used according to ISO 8601.
6
3 * keymap.c (access_keymap): If IDX has a meta prefix, and there's 7 * keymap.c (access_keymap): If IDX has a meta prefix, and there's
4 no map for meta_prefix_char, don't try to use it as a keymap. 8 no map for meta_prefix_char, don't try to use it as a keymap.
5 Instead, if T_OK is non-zero, look up a default binding, if any, 9 Instead, if T_OK is non-zero, look up a default binding, if any,
diff --git a/src/strftime.c b/src/strftime.c
index 462e8a2a6c2..ef7189e6dda 100644
--- a/src/strftime.c
+++ b/src/strftime.c
@@ -1,20 +1,20 @@
1/* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc. 1/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
2 NOTE: The canonical source of this file is maintained with the GNU C Library. 2 This file is part of the GNU Emacs.
3 Bugs can be reported to bug-glibc@gnu.org.
4 3
5 This program is free software; you can redistribute it and/or modify it 4 The GNU C Library is free software; you can redistribute it and/or
6 under the terms of the GNU General Public License as published by the 5 modify it under the terms of the GNU Library General Public License as
7 Free Software Foundation; either version 2, or (at your option) any 6 published by the Free Software Foundation; either version 2 of the
8 later version. 7 License, or (at your option) any later version.
9 8
10 This program is distributed in the hope that it will be useful, 9 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 GNU General Public License for more details. 12 Library General Public License for more details.
14 13
15 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU Library General Public
16 along with this program; if not, write to the Free Software Foundation, 15 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18 18
19#ifdef HAVE_CONFIG_H 19#ifdef HAVE_CONFIG_H
20# include <config.h> 20# include <config.h>
@@ -39,7 +39,7 @@
39#endif 39#endif
40 40
41#include <ctype.h> 41#include <ctype.h>
42#include <sys/types.h> /* Some systems define `time_t' here. */ 42#include <sys/types.h> /* Some systems define `time_t' here. */
43 43
44#ifdef TIME_WITH_SYS_TIME 44#ifdef TIME_WITH_SYS_TIME
45# include <sys/time.h> 45# include <sys/time.h>
@@ -91,16 +91,42 @@ extern char *tzname[];
91# endif 91# endif
92#endif 92#endif
93 93
94#ifdef _LIBC 94#ifdef COMPILE_WIDE
95# define MEMPCPY(d, s, n) __mempcpy (d, s, n) 95# include <endian.h>
96# define CHAR_T wchar_t
97# define UCHAR_T unsigned int
98# define L_(Str) L##Str
99# define NLW(Sym) _NL_W##Sym
100
101# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
102# define STRLEN(s) __wcslen (s)
103
96#else 104#else
97# ifndef HAVE_MEMPCPY 105# define CHAR_T char
98# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n))) 106# define UCHAR_T unsigned char
107# define L_(Str) Str
108# define NLW(Sym) Sym
109
110# if !defined STDC_HEADERS && !defined HAVE_MEMCPY
111# define MEMCPY(d, s, n) bcopy ((s), (d), (n))
112# else
113# define MEMCPY(d, s, n) memcpy ((d), (s), (n))
114# endif
115# define STRLEN(s) strlen (s)
116
117# ifdef _LIBC
118# define MEMPCPY(d, s, n) __mempcpy (d, s, n)
119# else
120# ifndef HAVE_MEMPCPY
121# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
122# endif
99# endif 123# endif
100#endif 124#endif
101 125
102#ifndef __P 126#ifndef __P
103# if defined (PROTOTYPES) 127# if defined emacs && defined PROTOTYPES
128# define __P(args) args
129# elif defined __GNUC__ || (defined __STDC__ && __STDC__)
104# define __P(args) args 130# define __P(args) args
105# else 131# else
106# define __P(args) () 132# define __P(args) ()
@@ -138,7 +164,7 @@ extern char *tzname[];
138#ifndef __isleap 164#ifndef __isleap
139/* Nonzero if YEAR is a leap year (every 4 years, 165/* Nonzero if YEAR is a leap year (every 4 years,
140 except every 100th isn't, and every 400th is). */ 166 except every 100th isn't, and every 400th is). */
141# define __isleap(year) \ 167# define __isleap(year) \
142 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) 168 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
143#endif 169#endif
144 170
@@ -189,111 +215,140 @@ my_strftime_localtime_r (t, tp)
189 introduce additional dependencies. */ 215 introduce additional dependencies. */
190/* The SGI compiler reportedly barfs on the trailing null 216/* The SGI compiler reportedly barfs on the trailing null
191 if we use a string constant as the initializer. 28 June 1997, rms. */ 217 if we use a string constant as the initializer. 28 June 1997, rms. */
192static const char spaces[16] = /* " " */ 218static const CHAR_T spaces[16] = /* " " */
193 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' }; 219{
194static const char zeroes[16] = /* "0000000000000000" */ 220 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
195 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' }; 221 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
222};
223static const CHAR_T zeroes[16] = /* "0000000000000000" */
224{
225 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
226 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
227};
196 228
197# define memset_space(P, Len) \ 229# define memset_space(P, Len) \
198 do { \ 230 do { \
199 int _len = (Len); \ 231 int _len = (Len); \
200 \ 232 \
201 do \ 233 do \
202 { \ 234 { \
203 int _this = _len > 16 ? 16 : _len; \ 235 int _this = _len > 16 ? 16 : _len; \
204 (P) = MEMPCPY ((P), spaces, _this); \ 236 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
205 _len -= _this; \ 237 _len -= _this; \
206 } \ 238 } \
207 while (_len > 0); \ 239 while (_len > 0); \
208 } while (0) 240 } while (0)
209 241
210# define memset_zero(P, Len) \ 242# define memset_zero(P, Len) \
211 do { \ 243 do { \
212 int _len = (Len); \ 244 int _len = (Len); \
213 \ 245 \
214 do \ 246 do \
215 { \ 247 { \
216 int _this = _len > 16 ? 16 : _len; \ 248 int _this = _len > 16 ? 16 : _len; \
217 (P) = MEMPCPY ((P), zeroes, _this); \ 249 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
218 _len -= _this; \ 250 _len -= _this; \
219 } \ 251 } \
220 while (_len > 0); \ 252 while (_len > 0); \
221 } while (0) 253 } while (0)
222#else 254#else
223# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len)) 255# ifdef COMPILE_WIDE
224# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len)) 256# define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
257# define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
258# else
259# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
260# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
261# endif
225#endif 262#endif
226 263
227#define add(n, f) \ 264#define add(n, f) \
228 do \ 265 do \
229 { \ 266 { \
230 int _n = (n); \ 267 int _n = (n); \
231 int _delta = width - _n; \ 268 int _delta = width - _n; \
232 int _incr = _n + (_delta > 0 ? _delta : 0); \ 269 int _incr = _n + (_delta > 0 ? _delta : 0); \
233 if (i + _incr >= maxsize) \ 270 if (i + _incr >= maxsize) \
234 return 0; \ 271 return 0; \
235 if (p) \ 272 if (p) \
236 { \ 273 { \
237 if (_delta > 0) \ 274 if (_delta > 0) \
238 { \ 275 { \
239 if (pad == '0') \ 276 if (pad == L_('0')) \
240 memset_zero (p, _delta); \ 277 memset_zero (p, _delta); \
241 else \ 278 else \
242 memset_space (p, _delta); \ 279 memset_space (p, _delta); \
243 } \ 280 } \
244 f; \ 281 f; \
245 p += _n; \ 282 p += _n; \
246 } \ 283 } \
247 i += _incr; \ 284 i += _incr; \
248 } while (0) 285 } while (0)
249 286
250#define cpy(n, s) \ 287#define cpy(n, s) \
251 add ((n), \ 288 add ((n), \
252 if (to_lowcase) \ 289 if (to_lowcase) \
253 memcpy_lowcase (p, (s), _n); \ 290 memcpy_lowcase (p, (s), _n); \
254 else if (to_uppcase) \ 291 else if (to_uppcase) \
255 memcpy_uppcase (p, (s), _n); \ 292 memcpy_uppcase (p, (s), _n); \
256 else \ 293 else \
257 memcpy ((PTR) p, (PTR) (s), _n)) 294 MEMCPY ((PTR) p, (PTR) (s), _n))
258 295
296#ifdef COMPILE_WIDE
297# define widen(os, ws, l) \
298 { \
299 mbstate_t __st; \
300 const char *__s = os; \
301 memset (&__st, '\0', sizeof (__st)); \
302 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
303 ws = alloca ((l + 1) * sizeof (wchar_t)); \
304 (void) __mbsrtowcs (ws, &__s, l, &__st); \
305 }
306#endif
259 307
260 308
261#ifdef _LIBC 309#ifdef COMPILE_WIDE
262# define TOUPPER(Ch) toupper (Ch) 310# define TOUPPER(Ch) towupper (Ch)
263# define TOLOWER(Ch) tolower (Ch) 311# define TOLOWER(Ch) towlower (Ch)
264#else 312#else
265# define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch)) 313# ifdef _LIBC
266# define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) 314# define TOUPPER(Ch) toupper (Ch)
315# define TOLOWER(Ch) tolower (Ch)
316# else
317# define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
318# define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
319# endif
267#endif 320#endif
268/* We don't use `isdigit' here since the locale dependent 321/* We don't use `isdigit' here since the locale dependent
269 interpretation is not what we want here. We only need to accept 322 interpretation is not what we want here. We only need to accept
270 the arabic digits in the ASCII range. One day there is perhaps a 323 the arabic digits in the ASCII range. One day there is perhaps a
271 more reliable way to accept other sets of digits. */ 324 more reliable way to accept other sets of digits. */
272#define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9) 325#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
273 326
274static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len)); 327static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
328 size_t len));
275 329
276static char * 330static CHAR_T *
277memcpy_lowcase (dest, src, len) 331memcpy_lowcase (dest, src, len)
278 char *dest; 332 CHAR_T *dest;
279 const char *src; 333 const CHAR_T *src;
280 size_t len; 334 size_t len;
281{ 335{
282 while (len-- > 0) 336 while (len-- > 0)
283 dest[len] = TOLOWER ((unsigned char) src[len]); 337 dest[len] = TOLOWER ((UCHAR_T) src[len]);
284 return dest; 338 return dest;
285} 339}
286 340
287static char *memcpy_uppcase __P ((char *dest, const char *src, size_t len)); 341static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
342 size_t len));
288 343
289static char * 344static CHAR_T *
290memcpy_uppcase (dest, src, len) 345memcpy_uppcase (dest, src, len)
291 char *dest; 346 CHAR_T *dest;
292 const char *src; 347 const CHAR_T *src;
293 size_t len; 348 size_t len;
294{ 349{
295 while (len-- > 0) 350 while (len-- > 0)
296 dest[len] = TOUPPER ((unsigned char) src[len]); 351 dest[len] = TOUPPER ((UCHAR_T) src[len]);
297 return dest; 352 return dest;
298} 353}
299 354
@@ -320,10 +375,10 @@ tm_diff (a, b)
320 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); 375 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
321 int years = a->tm_year - b->tm_year; 376 int years = a->tm_year - b->tm_year;
322 int days = (365 * years + intervening_leap_days 377 int days = (365 * years + intervening_leap_days
323 + (a->tm_yday - b->tm_yday)); 378 + (a->tm_yday - b->tm_yday));
324 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) 379 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
325 + (a->tm_min - b->tm_min)) 380 + (a->tm_min - b->tm_min))
326 + (a->tm_sec - b->tm_sec)); 381 + (a->tm_sec - b->tm_sec));
327} 382}
328#endif /* ! HAVE_TM_GMTOFF */ 383#endif /* ! HAVE_TM_GMTOFF */
329 384
@@ -348,21 +403,22 @@ iso_week_days (yday, wday)
348 /* Add enough to the first operand of % to make it nonnegative. */ 403 /* Add enough to the first operand of % to make it nonnegative. */
349 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; 404 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
350 return (yday 405 return (yday
351 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 406 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
352 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); 407 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
353} 408}
354 409
355 410
356#if !(defined _NL_CURRENT || HAVE_STRFTIME) 411#if !(defined _NL_CURRENT || HAVE_STRFTIME)
357static char const weekday_name[][10] = 412static CHAR_T const weekday_name[][10] =
358 { 413 {
359 "Sunday", "Monday", "Tuesday", "Wednesday", 414 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
360 "Thursday", "Friday", "Saturday" 415 L_("Thursday"), L_("Friday"), L_("Saturday")
361 }; 416 };
362static char const month_name[][10] = 417static CHAR_T const month_name[][10] =
363 { 418 {
364 "January", "February", "March", "April", "May", "June", 419 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
365 "July", "August", "September", "October", "November", "December" 420 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
421 L_("November"), L_("December")
366 }; 422 };
367#endif 423#endif
368 424
@@ -373,7 +429,11 @@ static char const month_name[][10] =
373# define ut_argument_spec int ut; 429# define ut_argument_spec int ut;
374# define ut_argument_spec_iso , int ut 430# define ut_argument_spec_iso , int ut
375#else 431#else
376# define my_strftime strftime 432# ifdef COMPILE_WIDE
433# define my_strftime wcsftime
434# else
435# define my_strftime strftime
436# endif
377# define ut_argument 437# define ut_argument
378# define ut_argument_spec 438# define ut_argument_spec
379# define ut_argument_spec_iso 439# define ut_argument_spec_iso
@@ -385,12 +445,12 @@ static char const month_name[][10] =
385 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime. 445 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
386 Work around this bug by copying *tp before it might be munged. */ 446 Work around this bug by copying *tp before it might be munged. */
387 size_t _strftime_copytm __P ((char *, size_t, const char *, 447 size_t _strftime_copytm __P ((char *, size_t, const char *,
388 const struct tm * ut_argument_spec_iso)); 448 const struct tm * ut_argument_spec_iso));
389 size_t 449 size_t
390 my_strftime (s, maxsize, format, tp ut_argument) 450 my_strftime (s, maxsize, format, tp ut_argument)
391 char *s; 451 CHAR_T *s;
392 size_t maxsize; 452 size_t maxsize;
393 const char *format; 453 const CHAR_T *format;
394 const struct tm *tp; 454 const struct tm *tp;
395 ut_argument_spec 455 ut_argument_spec
396 { 456 {
@@ -399,7 +459,8 @@ static char const month_name[][10] =
399 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument); 459 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
400 } 460 }
401# undef my_strftime 461# undef my_strftime
402# define my_strftime _strftime_copytm 462# define my_strftime(S, Maxsize, Format, Tp) \
463 _strftime_copytm (S, Maxsize, Format, Tp)
403#endif 464#endif
404 465
405 466
@@ -411,9 +472,9 @@ static char const month_name[][10] =
411 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */ 472 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
412size_t 473size_t
413my_strftime (s, maxsize, format, tp ut_argument) 474my_strftime (s, maxsize, format, tp ut_argument)
414 char *s; 475 CHAR_T *s;
415 size_t maxsize; 476 size_t maxsize;
416 const char *format; 477 const CHAR_T *format;
417 const struct tm *tp; 478 const struct tm *tp;
418 ut_argument_spec 479 ut_argument_spec
419{ 480{
@@ -425,22 +486,28 @@ my_strftime (s, maxsize, format, tp ut_argument)
425 might be generated by a strptime() call that initialized 486 might be generated by a strptime() call that initialized
426 only a few elements. Dereference the pointers only if the format 487 only a few elements. Dereference the pointers only if the format
427 requires this. Then it is ok to fail if the pointers are invalid. */ 488 requires this. Then it is ok to fail if the pointers are invalid. */
428# define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday) 489# define a_wkday \
429# define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday) 490 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
430# define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon) 491# define f_wkday \
431# define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon) 492 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
432# define ampm _NL_CURRENT (LC_TIME, tp->tm_hour > 11 ? PM_STR : AM_STR) 493# define a_month \
433 494 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
434# define aw_len strlen (a_wkday) 495# define f_month \
435# define am_len strlen (a_month) 496 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
436# define ap_len strlen (ampm) 497# define ampm \
498 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
499 ? NLW(PM_STR) : NLW(AM_STR)))
500
501# define aw_len STRLEN (a_wkday)
502# define am_len STRLEN (a_month)
503# define ap_len STRLEN (ampm)
437#else 504#else
438# if !HAVE_STRFTIME 505# if !HAVE_STRFTIME
439# define f_wkday (weekday_name[tp->tm_wday]) 506# define f_wkday (weekday_name[tp->tm_wday])
440# define f_month (month_name[tp->tm_mon]) 507# define f_month (month_name[tp->tm_mon])
441# define a_wkday f_wkday 508# define a_wkday f_wkday
442# define a_month f_month 509# define a_month f_month
443# define ampm ("AMPM" + 2 * (tp->tm_hour > 11)) 510# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
444 511
445 size_t aw_len = 3; 512 size_t aw_len = 3;
446 size_t am_len = 3; 513 size_t am_len = 3;
@@ -449,8 +516,8 @@ my_strftime (s, maxsize, format, tp ut_argument)
449#endif 516#endif
450 const char *zone; 517 const char *zone;
451 size_t i = 0; 518 size_t i = 0;
452 char *p = s; 519 CHAR_T *p = s;
453 const char *f; 520 const CHAR_T *f;
454 521
455 zone = NULL; 522 zone = NULL;
456#if HAVE_TM_ZONE 523#if HAVE_TM_ZONE
@@ -466,13 +533,13 @@ my_strftime (s, maxsize, format, tp ut_argument)
466 if (ut) 533 if (ut)
467 { 534 {
468 if (! (zone && *zone)) 535 if (! (zone && *zone))
469 zone = "GMT"; 536 zone = "UTC";
470 } 537 }
471 else 538 else
472 { 539 {
473 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the 540 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
474 time zone names contained in the external variable `tzname' shall 541 time zone names contained in the external variable `tzname' shall
475 be set as if the tzset() function had been called. */ 542 be set as if the tzset() function had been called. */
476# if HAVE_TZSET 543# if HAVE_TZSET
477 tzset (); 544 tzset ();
478# endif 545# endif
@@ -487,758 +554,822 @@ my_strftime (s, maxsize, format, tp ut_argument)
487 554
488 for (f = format; *f != '\0'; ++f) 555 for (f = format; *f != '\0'; ++f)
489 { 556 {
490 int pad = 0; /* Padding for number ('-', '_', or 0). */ 557 int pad = 0; /* Padding for number ('-', '_', or 0). */
491 int modifier; /* Field modifier ('E', 'O', or 0). */ 558 int modifier; /* Field modifier ('E', 'O', or 0). */
492 int digits; /* Max digits for numeric format. */ 559 int digits; /* Max digits for numeric format. */
493 int number_value; /* Numeric value to be printed. */ 560 int number_value; /* Numeric value to be printed. */
494 int negative_number; /* 1 if the number is negative. */ 561 int negative_number; /* 1 if the number is negative. */
495 const char *subfmt; 562 const CHAR_T *subfmt;
496 char *bufp; 563 CHAR_T *bufp;
497 char buf[1 + (sizeof (int) < sizeof (time_t) 564 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
498 ? INT_STRLEN_BOUND (time_t) 565 ? INT_STRLEN_BOUND (time_t)
499 : INT_STRLEN_BOUND (int))]; 566 : INT_STRLEN_BOUND (int))];
500 int width = -1; 567 int width = -1;
501 int to_lowcase = 0; 568 int to_lowcase = 0;
502 int to_uppcase = 0; 569 int to_uppcase = 0;
503 int change_case = 0; 570 int change_case = 0;
504 int format_char; 571 int format_char;
505 572
506#if DO_MULTIBYTE 573#if DO_MULTIBYTE && !defined COMPILE_WIDE
507 574 switch (*f)
508 switch (*f) 575 {
509 { 576 case L_('%'):
510 case '%': 577 break;
511 break; 578
512 579 case L_('\b'): case L_('\t'): case L_('\n'):
513 case '\b': case '\t': case '\n': 580 case L_('\v'): case L_('\f'): case L_('\r'):
514 case '\v': case '\f': case '\r': 581 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
515 case ' ': case '!': case '"': case '#': case '&': case'\'': 582 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
516 case '(': case ')': case '*': case '+': case ',': case '-': 583 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
517 case '.': case '/': case '0': case '1': case '2': case '3': 584 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
518 case '4': case '5': case '6': case '7': case '8': case '9': 585 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
519 case ':': case ';': case '<': case '=': case '>': case '?': 586 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
520 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 587 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
521 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': 588 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
522 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': 589 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
523 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': 590 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
524 case 'Y': case 'Z': case '[': case'\\': case ']': case '^': 591 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
525 case '_': case 'a': case 'b': case 'c': case 'd': case 'e': 592 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
526 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': 593 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
527 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': 594 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
528 case 'r': case 's': case 't': case 'u': case 'v': case 'w': 595 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
529 case 'x': case 'y': case 'z': case '{': case '|': case '}': 596 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
530 case '~': 597 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
531 /* The C Standard requires these 97 characters (plus '%', '\a') to 598 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
532 be in the basic execution character set. None of these 599 case L_('~'):
533 characters can start a multibyte sequence, so they need 600 /* The C Standard requires these 97 characters (plus '%', `\a') to
534 not be analyzed further. Some old compilers object to 601 be in the basic execution character set. None of these
535 '\a', so don't bother optimizing for it. */ 602 characters can start a multibyte sequence, so they need
536 add (1, *p = *f); 603 not be analyzed further. Some old compilers object to
537 continue; 604 `\a', so don't bother optimizing for it. */
538 605 add (1, *p = *f);
539 default: 606 continue;
540 /* Copy this multibyte sequence until we reach its end, find 607
541 an error, or come back to the initial shift state. */ 608 default:
542 { 609 /* Copy this multibyte sequence until we reach its end, find
543 mbstate_t mbstate = mbstate_zero; 610 an error, or come back to the initial shift state. */
544 size_t len = 0; 611 {
545 612 mbstate_t mbstate = mbstate_zero;
546 do 613 size_t len = 0;
547 { 614
548 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate); 615 do
549 616 {
550 if (bytes == 0) 617 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
551 break; 618
552 619 if (bytes == 0)
553 if (bytes == (size_t) -2) 620 break;
554 { 621
555 len += strlen (f + len); 622 if (bytes == (size_t) -2)
556 break; 623 {
557 } 624 len += strlen (f + len);
558 625 break;
559 if (bytes == (size_t) -1) 626 }
560 { 627
561 len++; 628 if (bytes == (size_t) -1)
562 break; 629 {
563 } 630 len++;
564 631 break;
565 len += bytes; 632 }
566 } 633
567 while (! mbsinit (&mbstate)); 634 len += bytes;
568 635 }
569 cpy (len, f); 636 while (! mbsinit (&mbstate));
570 f += len - 1; 637
571 continue; 638 cpy (len, f);
572 } 639 f += len - 1;
573 } 640 continue;
641 }
642 }
574 643
575#else /* ! DO_MULTIBYTE */ 644#else /* ! DO_MULTIBYTE */
576 645
577 /* Either multibyte encodings are not supported, or they are 646 /* Either multibyte encodings are not supported, they are
578 safe for formats, so any non-'%' byte can be copied through. */ 647 safe for formats, so any non-'%' byte can be copied through,
579 if (*f != '%') 648 or this is the wide character version. */
580 { 649 if (*f != L_('%'))
581 add (1, *p = *f); 650 {
582 continue; 651 add (1, *p = *f);
583 } 652 continue;
653 }
584 654
585#endif /* ! DO_MULTIBYTE */ 655#endif /* ! DO_MULTIBYTE */
586 656
587 /* Check for flags that can modify a format. */ 657 /* Check for flags that can modify a format. */
588 while (1) 658 while (1)
589 { 659 {
590 switch (*++f) 660 switch (*++f)
591 { 661 {
592 /* This influences the number formats. */ 662 /* This influences the number formats. */
593 case '_': 663 case L_('_'):
594 case '-': 664 case L_('-'):
595 case '0': 665 case L_('0'):
596 pad = *f; 666 pad = *f;
597 continue; 667 continue;
598 668
599 /* This changes textual output. */ 669 /* This changes textual output. */
600 case '^': 670 case L_('^'):
601 to_uppcase = 1; 671 to_uppcase = 1;
602 continue; 672 continue;
603 case '#': 673 case L_('#'):
604 change_case = 1; 674 change_case = 1;
605 continue; 675 continue;
606 676
607 default: 677 default:
608 break; 678 break;
609 } 679 }
610 break; 680 break;
611 } 681 }
612 682
613 /* As a GNU extension we allow to specify the field width. */ 683 /* As a GNU extension we allow to specify the field width. */
614 if (ISDIGIT (*f)) 684 if (ISDIGIT (*f))
615 { 685 {
616 width = 0; 686 width = 0;
617 do 687 do
618 { 688 {
619 width *= 10; 689 width *= 10;
620 width += *f - '0'; 690 width += *f - L_('0');
621 ++f; 691 ++f;
622 } 692 }
623 while (ISDIGIT (*f)); 693 while (ISDIGIT (*f));
624 } 694 }
625 695
626 /* Check for modifiers. */ 696 /* Check for modifiers. */
627 switch (*f) 697 switch (*f)
628 { 698 {
629 case 'E': 699 case L_('E'):
630 case 'O': 700 case L_('O'):
631 modifier = *f++; 701 modifier = *f++;
632 break; 702 break;
633 703
634 default: 704 default:
635 modifier = 0; 705 modifier = 0;
636 break; 706 break;
637 } 707 }
638 708
639 /* Now do the specified format. */ 709 /* Now do the specified format. */
640 format_char = *f; 710 format_char = *f;
641 switch (format_char) 711 switch (format_char)
642 { 712 {
643#define DO_NUMBER(d, v) \ 713#define DO_NUMBER(d, v) \
644 digits = width == -1 ? d : width; \ 714 digits = width == -1 ? d : width; \
645 number_value = v; goto do_number 715 number_value = v; goto do_number
646#define DO_NUMBER_SPACEPAD(d, v) \ 716#define DO_NUMBER_SPACEPAD(d, v) \
647 digits = width == -1 ? d : width; \ 717 digits = width == -1 ? d : width; \
648 number_value = v; goto do_number_spacepad 718 number_value = v; goto do_number_spacepad
649 719
650 case '%': 720 case L_('%'):
651 if (modifier != 0) 721 if (modifier != 0)
652 goto bad_format; 722 goto bad_format;
653 add (1, *p = *f); 723 add (1, *p = *f);
654 break; 724 break;
655 725
656 case 'a': 726 case L_('a'):
657 if (modifier != 0) 727 if (modifier != 0)
658 goto bad_format; 728 goto bad_format;
659 if (change_case) 729 if (change_case)
660 { 730 {
661 to_uppcase = 1; 731 to_uppcase = 1;
662 to_lowcase = 0; 732 to_lowcase = 0;
663 } 733 }
664#if defined _NL_CURRENT || !HAVE_STRFTIME 734#if defined _NL_CURRENT || !HAVE_STRFTIME
665 cpy (aw_len, a_wkday); 735 cpy (aw_len, a_wkday);
666 break; 736 break;
667#else 737#else
668 goto underlying_strftime; 738 goto underlying_strftime;
669#endif 739#endif
670 740
671 case 'A': 741 case 'A':
672 if (modifier != 0) 742 if (modifier != 0)
673 goto bad_format; 743 goto bad_format;
674 if (change_case) 744 if (change_case)
675 { 745 {
676 to_uppcase = 1; 746 to_uppcase = 1;
677 to_lowcase = 0; 747 to_lowcase = 0;
678 } 748 }
679#if defined _NL_CURRENT || !HAVE_STRFTIME 749#if defined _NL_CURRENT || !HAVE_STRFTIME
680 cpy (strlen (f_wkday), f_wkday); 750 cpy (STRLEN (f_wkday), f_wkday);
681 break; 751 break;
682#else 752#else
683 goto underlying_strftime; 753 goto underlying_strftime;
684#endif 754#endif
685 755
686 case 'b': 756 case L_('b'):
687 case 'h': /* POSIX.2 extension. */ 757 case L_('h'): /* POSIX.2 extension. */
688 if (modifier != 0) 758 if (change_case)
689 goto bad_format; 759 {
760 to_uppcase = 1;
761 to_lowcase = 0;
762 }
763 if (modifier != 0)
764 goto bad_format;
690#if defined _NL_CURRENT || !HAVE_STRFTIME 765#if defined _NL_CURRENT || !HAVE_STRFTIME
691 cpy (am_len, a_month); 766 cpy (am_len, a_month);
692 break; 767 break;
693#else 768#else
694 goto underlying_strftime; 769 goto underlying_strftime;
695#endif 770#endif
696 771
697 case 'B': 772 case L_('B'):
698 if (modifier != 0) 773 if (modifier != 0)
699 goto bad_format; 774 goto bad_format;
700 if (change_case) 775 if (change_case)
701 { 776 {
702 to_uppcase = 1; 777 to_uppcase = 1;
703 to_lowcase = 0; 778 to_lowcase = 0;
704 } 779 }
705#if defined _NL_CURRENT || !HAVE_STRFTIME 780#if defined _NL_CURRENT || !HAVE_STRFTIME
706 cpy (strlen (f_month), f_month); 781 cpy (STRLEN (f_month), f_month);
707 break; 782 break;
708#else 783#else
709 goto underlying_strftime; 784 goto underlying_strftime;
710#endif 785#endif
711 786
712 case 'c': 787 case L_('c'):
713 if (modifier == 'O') 788 if (modifier == L_('O'))
714 goto bad_format; 789 goto bad_format;
715#ifdef _NL_CURRENT 790#ifdef _NL_CURRENT
716 if (! (modifier == 'E' 791 if (! (modifier == 'E'
717 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0')) 792 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
718 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT); 793 NLW(ERA_D_T_FMT)))
794 != '\0')))
795 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
719#else 796#else
720# if HAVE_STRFTIME 797# if HAVE_STRFTIME
721 goto underlying_strftime; 798 goto underlying_strftime;
722# else 799# else
723 subfmt = "%a %b %e %H:%M:%S %Y"; 800 subfmt = L_("%a %b %e %H:%M:%S %Y");
724# endif 801# endif
725#endif 802#endif
726 803
727 subformat: 804 subformat:
728 { 805 {
729 char *old_start = p; 806 CHAR_T *old_start = p;
730 size_t len = my_strftime (NULL, (size_t) -1, subfmt, 807 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
731 tp ut_argument); 808 add (len, my_strftime (p, maxsize - i, subfmt, tp));
732 add (len, my_strftime (p, maxsize - i, subfmt, tp ut_argument)); 809
733 810 if (to_uppcase)
734 if (to_uppcase) 811 while (old_start < p)
735 while (old_start < p) 812 {
736 { 813 *old_start = TOUPPER ((UCHAR_T) *old_start);
737 *old_start = TOUPPER ((unsigned char) *old_start); 814 ++old_start;
738 ++old_start; 815 }
739 } 816 }
740 } 817 break;
741 break;
742 818
743#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) 819#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
744 underlying_strftime: 820 underlying_strftime:
745 { 821 {
746 /* The relevant information is available only via the 822 /* The relevant information is available only via the
747 underlying strftime implementation, so use that. */ 823 underlying strftime implementation, so use that. */
748 char ufmt[4]; 824 char ufmt[4];
749 char *u = ufmt; 825 char *u = ufmt;
750 char ubuf[1024]; /* enough for any single format in practice */ 826 char ubuf[1024]; /* enough for any single format in practice */
751 size_t len; 827 size_t len;
752 *u++ = '%'; 828 /* Make sure we're calling the actual underlying strftime.
753 if (modifier != 0) 829 In some cases, config.h contains something like
754 *u++ = modifier; 830 "#define strftime rpl_strftime". */
755 *u++ = format_char; 831# ifdef strftime
756 *u = '\0'; 832# undef strftime
757 len = strftime (ubuf, sizeof ubuf, ufmt, tp); 833 size_t strftime ();
758 if (len == 0 && ubuf[0] != '\0') 834# endif
759 return 0; 835
760 cpy (len, ubuf); 836 *u++ = '%';
761 } 837 if (modifier != 0)
762 break; 838 *u++ = modifier;
839 *u++ = format_char;
840 *u = '\0';
841 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
842 if (len == 0 && ubuf[0] != '\0')
843 return 0;
844 cpy (len, ubuf);
845 }
846 break;
763#endif 847#endif
764 848
765 case 'C': /* POSIX.2 extension. */ 849 case L_('C'): /* POSIX.2 extension. */
766 if (modifier == 'O') 850 if (modifier == L_('O'))
767 goto bad_format; 851 goto bad_format;
768 if (modifier == 'E') 852 if (modifier == L_('E'))
769 { 853 {
770#if HAVE_STRUCT_ERA_ENTRY 854#if HAVE_STRUCT_ERA_ENTRY
771 struct era_entry *era = _nl_get_era_entry (tp); 855 struct era_entry *era = _nl_get_era_entry (tp);
772 if (era) 856 if (era)
773 { 857 {
774 size_t len = strlen (era->name_fmt); 858# ifdef COMPILE_WIDE
775 cpy (len, era->name_fmt); 859 size_t len = __wcslen (era->era_wname);
776 break; 860 cpy (len, era->era_wname);
777 } 861# else
862 size_t len = strlen (era->era_name);
863 cpy (len, era->era_name);
864# endif
865 break;
866 }
778#else 867#else
779# if HAVE_STRFTIME 868# if HAVE_STRFTIME
780 goto underlying_strftime; 869 goto underlying_strftime;
781# endif 870# endif
782#endif 871#endif
783 } 872 }
784 873
785 { 874 {
786 int year = tp->tm_year + TM_YEAR_BASE; 875 int year = tp->tm_year + TM_YEAR_BASE;
787 DO_NUMBER (1, year / 100 - (year % 100 < 0)); 876 DO_NUMBER (1, year / 100 - (year % 100 < 0));
788 } 877 }
789 878
790 case 'x': 879 case L_('x'):
791 if (modifier == 'O') 880 if (modifier == L_('O'))
792 goto bad_format; 881 goto bad_format;
793#ifdef _NL_CURRENT 882#ifdef _NL_CURRENT
794 if (! (modifier == 'E' 883 if (! (modifier == L_('E')
795 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0')) 884 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
796 subfmt = _NL_CURRENT (LC_TIME, D_FMT); 885 NLW(ERA_D_FMT)))
797 goto subformat; 886 != L_('\0'))))
887 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
888 goto subformat;
798#else 889#else
799# if HAVE_STRFTIME 890# if HAVE_STRFTIME
800 goto underlying_strftime; 891 goto underlying_strftime;
801# else 892# else
802 /* Fall through. */ 893 /* Fall through. */
803# endif 894# endif
804#endif 895#endif
805 case 'D': /* POSIX.2 extension. */ 896 case L_('D'): /* POSIX.2 extension. */
806 if (modifier != 0) 897 if (modifier != 0)
807 goto bad_format; 898 goto bad_format;
808 subfmt = "%m/%d/%y"; 899 subfmt = L_("%m/%d/%y");
809 goto subformat; 900 goto subformat;
810 901
811 case 'd': 902 case L_('d'):
812 if (modifier == 'E') 903 if (modifier == L_('E'))
813 goto bad_format; 904 goto bad_format;
814 905
815 DO_NUMBER (2, tp->tm_mday); 906 DO_NUMBER (2, tp->tm_mday);
816 907
817 case 'e': /* POSIX.2 extension. */ 908 case L_('e'): /* POSIX.2 extension. */
818 if (modifier == 'E') 909 if (modifier == L_('E'))
819 goto bad_format; 910 goto bad_format;
820 911
821 DO_NUMBER_SPACEPAD (2, tp->tm_mday); 912 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
822 913
823 /* All numeric formats set DIGITS and NUMBER_VALUE and then 914 /* All numeric formats set DIGITS and NUMBER_VALUE and then
824 jump to one of these two labels. */ 915 jump to one of these two labels. */
825 916
826 do_number_spacepad: 917 do_number_spacepad:
827 /* Force `_' flag unless overwritten by `0' flag. */ 918 /* Force `_' flag unless overwritten by `0' flag. */
828 if (pad != '0') 919 if (pad != L_('0'))
829 pad = '_'; 920 pad = L_('_');
830 921
831 do_number: 922 do_number:
832 /* Format the number according to the MODIFIER flag. */ 923 /* Format the number according to the MODIFIER flag. */
833 924
834 if (modifier == 'O' && 0 <= number_value) 925 if (modifier == L_('O') && 0 <= number_value)
835 { 926 {
836#ifdef _NL_CURRENT 927#ifdef _NL_CURRENT
837 /* Get the locale specific alternate representation of 928 /* Get the locale specific alternate representation of
838 the number NUMBER_VALUE. If none exist NULL is returned. */ 929 the number NUMBER_VALUE. If none exist NULL is returned. */
839 const char *cp = _nl_get_alt_digit (number_value); 930# ifdef COMPILE_WIDE
840 931 const wchar_t *cp = _nl_get_walt_digit (number_value);
841 if (cp != NULL) 932# else
842 { 933 const char *cp = _nl_get_alt_digit (number_value);
843 size_t digitlen = strlen (cp); 934# endif
844 if (digitlen != 0) 935
845 { 936 if (cp != NULL)
846 cpy (digitlen, cp); 937 {
847 break; 938 size_t digitlen = STRLEN (cp);
848 } 939 if (digitlen != 0)
849 } 940 {
941 cpy (digitlen, cp);
942 break;
943 }
944 }
850#else 945#else
851# if HAVE_STRFTIME 946# if HAVE_STRFTIME
852 goto underlying_strftime; 947 goto underlying_strftime;
853# endif 948# endif
854#endif 949#endif
855 } 950 }
856 { 951 {
857 unsigned int u = number_value; 952 unsigned int u = number_value;
858 953
859 bufp = buf + sizeof (buf); 954 bufp = buf + sizeof (buf) / sizeof (buf[0]);
860 negative_number = number_value < 0; 955 negative_number = number_value < 0;
861 956
862 if (negative_number) 957 if (negative_number)
863 u = -u; 958 u = -u;
864 959
865 do 960 do
866 *--bufp = u % 10 + '0'; 961 *--bufp = u % 10 + L_('0');
867 while ((u /= 10) != 0); 962 while ((u /= 10) != 0);
868 } 963 }
869 964
870 do_number_sign_and_padding: 965 do_number_sign_and_padding:
871 if (negative_number) 966 if (negative_number)
872 *--bufp = '-'; 967 *--bufp = L_('-');
873 968
874 if (pad != '-') 969 if (pad != L_('-'))
875 { 970 {
876 int padding = digits - (buf + sizeof (buf) - bufp); 971 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
972 - bufp);
877 973
878 if (pad == '_') 974 if (pad == L_('_'))
879 { 975 {
880 while (0 < padding--) 976 while (0 < padding--)
881 *--bufp = ' '; 977 *--bufp = L_(' ');
882 } 978 }
883 else 979 else
884 { 980 {
885 bufp += negative_number; 981 bufp += negative_number;
886 while (0 < padding--) 982 while (0 < padding--)
887 *--bufp = '0'; 983 *--bufp = L_('0');
888 if (negative_number) 984 if (negative_number)
889 *--bufp = '-'; 985 *--bufp = L_('-');
890 } 986 }
891 } 987 }
892 988
893 cpy (buf + sizeof (buf) - bufp, bufp); 989 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
894 break; 990 break;
895 991
896 case 'F': 992 case L_('F'):
897 if (modifier != 0) 993 if (modifier != 0)
898 goto bad_format; 994 goto bad_format;
899 subfmt = "%Y-%m-%d"; 995 subfmt = L_("%Y-%m-%d");
900 goto subformat; 996 goto subformat;
901 997
902 case 'H': 998 case L_('H'):
903 if (modifier == 'E') 999 if (modifier == L_('E'))
904 goto bad_format; 1000 goto bad_format;
905 1001
906 DO_NUMBER (2, tp->tm_hour); 1002 DO_NUMBER (2, tp->tm_hour);
907 1003
908 case 'I': 1004 case L_('I'):
909 if (modifier == 'E') 1005 if (modifier == L_('E'))
910 goto bad_format; 1006 goto bad_format;
911 1007
912 DO_NUMBER (2, hour12); 1008 DO_NUMBER (2, hour12);
913 1009
914 case 'k': /* GNU extension. */ 1010 case L_('k'): /* GNU extension. */
915 if (modifier == 'E') 1011 if (modifier == L_('E'))
916 goto bad_format; 1012 goto bad_format;
917 1013
918 DO_NUMBER_SPACEPAD (2, tp->tm_hour); 1014 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
919 1015
920 case 'l': /* GNU extension. */ 1016 case L_('l'): /* GNU extension. */
921 if (modifier == 'E') 1017 if (modifier == L_('E'))
922 goto bad_format; 1018 goto bad_format;
923 1019
924 DO_NUMBER_SPACEPAD (2, hour12); 1020 DO_NUMBER_SPACEPAD (2, hour12);
925 1021
926 case 'j': 1022 case L_('j'):
927 if (modifier == 'E') 1023 if (modifier == L_('E'))
928 goto bad_format; 1024 goto bad_format;
929 1025
930 DO_NUMBER (3, 1 + tp->tm_yday); 1026 DO_NUMBER (3, 1 + tp->tm_yday);
931 1027
932 case 'M': 1028 case L_('M'):
933 if (modifier == 'E') 1029 if (modifier == L_('E'))
934 goto bad_format; 1030 goto bad_format;
935 1031
936 DO_NUMBER (2, tp->tm_min); 1032 DO_NUMBER (2, tp->tm_min);
937 1033
938 case 'm': 1034 case L_('m'):
939 if (modifier == 'E') 1035 if (modifier == L_('E'))
940 goto bad_format; 1036 goto bad_format;
941 1037
942 DO_NUMBER (2, tp->tm_mon + 1); 1038 DO_NUMBER (2, tp->tm_mon + 1);
943 1039
944 case 'n': /* POSIX.2 extension. */ 1040 case L_('n'): /* POSIX.2 extension. */
945 add (1, *p = '\n'); 1041 add (1, *p = L_('\n'));
946 break; 1042 break;
947 1043
948 case 'P': 1044 case L_('P'):
949 to_lowcase = 1; 1045 to_lowcase = 1;
950#if !defined _NL_CURRENT && HAVE_STRFTIME 1046#if !defined _NL_CURRENT && HAVE_STRFTIME
951 format_char = 'p'; 1047 format_char = L_('p');
952#endif 1048#endif
953 /* FALLTHROUGH */ 1049 /* FALLTHROUGH */
954 1050
955 case 'p': 1051 case L_('p'):
956 if (change_case) 1052 if (change_case)
957 { 1053 {
958 to_uppcase = 0; 1054 to_uppcase = 0;
959 to_lowcase = 1; 1055 to_lowcase = 1;
960 } 1056 }
961#if defined _NL_CURRENT || !HAVE_STRFTIME 1057#if defined _NL_CURRENT || !HAVE_STRFTIME
962 cpy (ap_len, ampm); 1058 cpy (ap_len, ampm);
963 break; 1059 break;
964#else 1060#else
965 goto underlying_strftime; 1061 goto underlying_strftime;
966#endif 1062#endif
967 1063
968 case 'R': /* GNU extension. */ 1064 case L_('R'): /* GNU extension. */
969 subfmt = "%H:%M"; 1065 subfmt = L_("%H:%M");
970 goto subformat; 1066 goto subformat;
971 1067
972 case 'r': /* POSIX.2 extension. */ 1068 case L_('r'): /* POSIX.2 extension. */
973#ifdef _NL_CURRENT 1069#ifdef _NL_CURRENT
974 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0') 1070 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1071 NLW(T_FMT_AMPM))) == L_('\0'))
975#endif 1072#endif
976 subfmt = "%I:%M:%S %p"; 1073 subfmt = L_("%I:%M:%S %p");
977 goto subformat; 1074 goto subformat;
978 1075
979 case 'S': 1076 case L_('S'):
980 if (modifier == 'E') 1077 if (modifier == L_('E'))
981 goto bad_format; 1078 goto bad_format;
982 1079
983 DO_NUMBER (2, tp->tm_sec); 1080 DO_NUMBER (2, tp->tm_sec);
984 1081
985 case 's': /* GNU extension. */ 1082 case L_('s'): /* GNU extension. */
986 { 1083 {
987 struct tm ltm; 1084 struct tm ltm;
988 time_t t; 1085 time_t t;
989 1086
990 ltm = *tp; 1087 ltm = *tp;
991 t = mktime (&ltm); 1088 t = mktime (&ltm);
992 1089
993 /* Generate string value for T using time_t arithmetic; 1090 /* Generate string value for T using time_t arithmetic;
994 this works even if sizeof (long) < sizeof (time_t). */ 1091 this works even if sizeof (long) < sizeof (time_t). */
995 1092
996 bufp = buf + sizeof (buf); 1093 bufp = buf + sizeof (buf) / sizeof (buf[0]);
997 negative_number = t < 0; 1094 negative_number = t < 0;
998 1095
999 do 1096 do
1000 { 1097 {
1001 int d = t % 10; 1098 int d = t % 10;
1002 t /= 10; 1099 t /= 10;
1003 1100
1004 if (negative_number) 1101 if (negative_number)
1005 { 1102 {
1006 d = -d; 1103 d = -d;
1007 1104
1008 /* Adjust if division truncates to minus infinity. */ 1105 /* Adjust if division truncates to minus infinity. */
1009 if (0 < -1 % 10 && d < 0) 1106 if (0 < -1 % 10 && d < 0)
1010 { 1107 {
1011 t++; 1108 t++;
1012 d += 10; 1109 d += 10;
1013 } 1110 }
1014 } 1111 }
1015 1112
1016 *--bufp = d + '0'; 1113 *--bufp = d + L_('0');
1017 } 1114 }
1018 while (t != 0); 1115 while (t != 0);
1019 1116
1020 digits = 1; 1117 digits = 1;
1021 goto do_number_sign_and_padding; 1118 goto do_number_sign_and_padding;
1022 } 1119 }
1023 1120
1024 case 'X': 1121 case L_('X'):
1025 if (modifier == 'O') 1122 if (modifier == L_('O'))
1026 goto bad_format; 1123 goto bad_format;
1027#ifdef _NL_CURRENT 1124#ifdef _NL_CURRENT
1028 if (! (modifier == 'E' 1125 if (! (modifier == L_('E')
1029 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0')) 1126 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1030 subfmt = _NL_CURRENT (LC_TIME, T_FMT); 1127 NLW(ERA_T_FMT)))
1031 goto subformat; 1128 != L_('\0'))))
1129 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1130 goto subformat;
1032#else 1131#else
1033# if HAVE_STRFTIME 1132# if HAVE_STRFTIME
1034 goto underlying_strftime; 1133 goto underlying_strftime;
1035# else 1134# else
1036 /* Fall through. */ 1135 /* Fall through. */
1037# endif 1136# endif
1038#endif 1137#endif
1039 case 'T': /* POSIX.2 extension. */ 1138 case L_('T'): /* POSIX.2 extension. */
1040 subfmt = "%H:%M:%S"; 1139 subfmt = L_("%H:%M:%S");
1041 goto subformat; 1140 goto subformat;
1042 1141
1043 case 't': /* POSIX.2 extension. */ 1142 case L_('t'): /* POSIX.2 extension. */
1044 add (1, *p = '\t'); 1143 add (1, *p = L_('\t'));
1045 break; 1144 break;
1046 1145
1047 case 'u': /* POSIX.2 extension. */ 1146 case L_('u'): /* POSIX.2 extension. */
1048 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1); 1147 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1049 1148
1050 case 'U': 1149 case L_('U'):
1051 if (modifier == 'E') 1150 if (modifier == L_('E'))
1052 goto bad_format; 1151 goto bad_format;
1053 1152
1054 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7); 1153 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1055 1154
1056 case 'V': 1155 case L_('V'):
1057 case 'g': /* GNU extension. */ 1156 case L_('g'): /* GNU extension. */
1058 case 'G': /* GNU extension. */ 1157 case L_('G'): /* GNU extension. */
1059 if (modifier == 'E') 1158 if (modifier == L_('E'))
1060 goto bad_format; 1159 goto bad_format;
1061 { 1160 {
1062 int year = tp->tm_year + TM_YEAR_BASE; 1161 int year = tp->tm_year + TM_YEAR_BASE;
1063 int days = iso_week_days (tp->tm_yday, tp->tm_wday); 1162 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1064 1163
1065 if (days < 0) 1164 if (days < 0)
1066 { 1165 {
1067 /* This ISO week belongs to the previous year. */ 1166 /* This ISO week belongs to the previous year. */
1068 year--; 1167 year--;
1069 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)), 1168 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1070 tp->tm_wday); 1169 tp->tm_wday);
1071 } 1170 }
1072 else 1171 else
1073 { 1172 {
1074 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)), 1173 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1075 tp->tm_wday); 1174 tp->tm_wday);
1076 if (0 <= d) 1175 if (0 <= d)
1077 { 1176 {
1078 /* This ISO week belongs to the next year. */ 1177 /* This ISO week belongs to the next year. */
1079 year++; 1178 year++;
1080 days = d; 1179 days = d;
1081 } 1180 }
1082 } 1181 }
1083 1182
1084 switch (*f) 1183 switch (*f)
1085 { 1184 {
1086 case 'g': 1185 case L_('g'):
1087 DO_NUMBER (2, (year % 100 + 100) % 100); 1186 DO_NUMBER (2, (year % 100 + 100) % 100);
1088 1187
1089 case 'G': 1188 case L_('G'):
1090 DO_NUMBER (1, year); 1189 DO_NUMBER (1, year);
1091 1190
1092 default: 1191 default:
1093 DO_NUMBER (2, days / 7 + 1); 1192 DO_NUMBER (2, days / 7 + 1);
1094 } 1193 }
1095 } 1194 }
1096 1195
1097 case 'W': 1196 case L_('W'):
1098 if (modifier == 'E') 1197 if (modifier == L_('E'))
1099 goto bad_format; 1198 goto bad_format;
1100 1199
1101 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7); 1200 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1102 1201
1103 case 'w': 1202 case L_('w'):
1104 if (modifier == 'E') 1203 if (modifier == L_('E'))
1105 goto bad_format; 1204 goto bad_format;
1106 1205
1107 DO_NUMBER (1, tp->tm_wday); 1206 DO_NUMBER (1, tp->tm_wday);
1108 1207
1109 case 'Y': 1208 case L_('Y'):
1110 if (modifier == 'E') 1209 if (modifier == 'E')
1111 { 1210 {
1112#if HAVE_STRUCT_ERA_ENTRY 1211#if HAVE_STRUCT_ERA_ENTRY
1113 struct era_entry *era = _nl_get_era_entry (tp); 1212 struct era_entry *era = _nl_get_era_entry (tp);
1114 if (era) 1213 if (era)
1115 { 1214 {
1116 subfmt = strchr (era->name_fmt, '\0') + 1; 1215# ifdef COMPILE_WIDE
1117 goto subformat; 1216 subfmt = era->era_wformat;
1118 } 1217# else
1218 subfmt = era->era_format;
1219# endif
1220 goto subformat;
1221 }
1119#else 1222#else
1120# if HAVE_STRFTIME 1223# if HAVE_STRFTIME
1121 goto underlying_strftime; 1224 goto underlying_strftime;
1122# endif 1225# endif
1123#endif 1226#endif
1124 } 1227 }
1125 if (modifier == 'O') 1228 if (modifier == L_('O'))
1126 goto bad_format; 1229 goto bad_format;
1127 else 1230 else
1128 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE); 1231 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1129 1232
1130 case 'y': 1233 case L_('y'):
1131 if (modifier == 'E') 1234 if (modifier == L_('E'))
1132 { 1235 {
1133#if HAVE_STRUCT_ERA_ENTRY 1236#if HAVE_STRUCT_ERA_ENTRY
1134 struct era_entry *era = _nl_get_era_entry (tp); 1237 struct era_entry *era = _nl_get_era_entry (tp);
1135 if (era) 1238 if (era)
1136 { 1239 {
1137 int delta = tp->tm_year - era->start_date[0]; 1240 int delta = tp->tm_year - era->start_date[0];
1138 DO_NUMBER (1, (era->offset 1241 DO_NUMBER (1, (era->offset
1139 + (era->direction == '-' ? -delta : delta))); 1242 + delta * era->absolute_direction));
1140 } 1243 }
1141#else 1244#else
1142# if HAVE_STRFTIME 1245# if HAVE_STRFTIME
1143 goto underlying_strftime; 1246 goto underlying_strftime;
1144# endif 1247# endif
1145#endif 1248#endif
1146 } 1249 }
1147 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100); 1250 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1148 1251
1149 case 'Z': 1252 case L_('Z'):
1150 if (change_case) 1253 if (change_case)
1151 { 1254 {
1152 to_uppcase = 0; 1255 to_uppcase = 0;
1153 to_lowcase = 1; 1256 to_lowcase = 1;
1154 } 1257 }
1155 1258
1156#if HAVE_TZNAME 1259#if HAVE_TZNAME
1157 /* The tzset() call might have changed the value. */ 1260 /* The tzset() call might have changed the value. */
1158 if (!(zone && *zone) && tp->tm_isdst >= 0) 1261 if (!(zone && *zone) && tp->tm_isdst >= 0)
1159 zone = tzname[tp->tm_isdst]; 1262 zone = tzname[tp->tm_isdst];
1160#endif 1263#endif
1161 if (! zone) 1264 if (! zone)
1162 zone = ""; /* POSIX.2 requires the empty string here. */ 1265 zone = ""; /* POSIX.2 requires the empty string here. */
1163 1266
1164 cpy (strlen (zone), zone); 1267#ifdef COMPILE_WIDE
1165 break; 1268 {
1269 /* The zone string is always given in multibyte form. We have
1270 to transform it first. */
1271 wchar_t *wczone;
1272 size_t len;
1273 widen (zone, wczone, len);
1274 cpy (len, wczone);
1275 }
1276#else
1277 cpy (strlen (zone), zone);
1278#endif
1279 break;
1166 1280
1167 case 'z': /* GNU extension. */ 1281 case L_('z'): /* GNU extension. */
1168 if (tp->tm_isdst < 0) 1282 if (tp->tm_isdst < 0)
1169 break; 1283 break;
1170 1284
1171 { 1285 {
1172 int diff; 1286 int diff;
1173#if HAVE_TM_GMTOFF 1287#if HAVE_TM_GMTOFF
1174 diff = tp->tm_gmtoff; 1288 diff = tp->tm_gmtoff;
1175#else 1289#else
1176 if (ut) 1290 if (ut)
1177 diff = 0; 1291 diff = 0;
1178 else 1292 else
1179 { 1293 {
1180 struct tm gtm; 1294 struct tm gtm;
1181 struct tm ltm; 1295 struct tm ltm;
1182 time_t lt; 1296 time_t lt;
1183 1297
1184 ltm = *tp; 1298 ltm = *tp;
1185 lt = mktime (&ltm); 1299 lt = mktime (&ltm);
1186 1300
1187 if (lt == (time_t) -1) 1301 if (lt == (time_t) -1)
1188 { 1302 {
1189 /* mktime returns -1 for errors, but -1 is also a 1303 /* mktime returns -1 for errors, but -1 is also a
1190 valid time_t value. Check whether an error really 1304 valid time_t value. Check whether an error really
1191 occurred. */ 1305 occurred. */
1192 struct tm tm; 1306 struct tm tm;
1193 1307
1194 if (! my_strftime_localtime_r (&lt, &tm) 1308 if (! my_strftime_localtime_r (&lt, &tm)
1195 || ((ltm.tm_sec ^ tm.tm_sec) 1309 || ((ltm.tm_sec ^ tm.tm_sec)
1196 | (ltm.tm_min ^ tm.tm_min) 1310 | (ltm.tm_min ^ tm.tm_min)
1197 | (ltm.tm_hour ^ tm.tm_hour) 1311 | (ltm.tm_hour ^ tm.tm_hour)
1198 | (ltm.tm_mday ^ tm.tm_mday) 1312 | (ltm.tm_mday ^ tm.tm_mday)
1199 | (ltm.tm_mon ^ tm.tm_mon) 1313 | (ltm.tm_mon ^ tm.tm_mon)
1200 | (ltm.tm_year ^ tm.tm_year))) 1314 | (ltm.tm_year ^ tm.tm_year)))
1201 break; 1315 break;
1202 } 1316 }
1203 1317
1204 if (! my_strftime_gmtime_r (&lt, &gtm)) 1318 if (! my_strftime_gmtime_r (&lt, &gtm))
1205 break; 1319 break;
1206 1320
1207 diff = tm_diff (&ltm, &gtm); 1321 diff = tm_diff (&ltm, &gtm);
1208 } 1322 }
1209#endif 1323#endif
1210 1324
1211 if (diff < 0) 1325 if (diff < 0)
1212 { 1326 {
1213 add (1, *p = '-'); 1327 add (1, *p = L_('-'));
1214 diff = -diff; 1328 diff = -diff;
1215 } 1329 }
1216 else 1330 else
1217 add (1, *p = '+'); 1331 add (1, *p = L_('+'));
1218 1332
1219 diff /= 60; 1333 diff /= 60;
1220 DO_NUMBER (4, (diff / 60) * 100 + diff % 60); 1334 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1221 } 1335 }
1222 1336
1223 case '\0': /* GNU extension: % at end of format. */ 1337 case L_('\0'): /* GNU extension: % at end of format. */
1224 --f; 1338 --f;
1225 /* Fall through. */ 1339 /* Fall through. */
1226 default: 1340 default:
1227 /* Unknown format; output the format, including the '%', 1341 /* Unknown format; output the format, including the '%',
1228 since this is most likely the right thing to do if a 1342 since this is most likely the right thing to do if a
1229 multibyte string has been misparsed. */ 1343 multibyte string has been misparsed. */
1230 bad_format: 1344 bad_format:
1231 { 1345 {
1232 int flen; 1346 int flen;
1233 for (flen = 1; f[1 - flen] != '%'; flen++) 1347 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1234 continue; 1348 continue;
1235 cpy (flen, &f[1 - flen]); 1349 cpy (flen, &f[1 - flen]);
1236 } 1350 }
1237 break; 1351 break;
1238 } 1352 }
1239 } 1353 }
1240 1354
1241 if (p && maxsize != 0) 1355 if (p && maxsize != 0)
1242 *p = '\0'; 1356 *p = L_('\0');
1243 return i; 1357 return i;
1244} 1358}
1359
1360
1361#ifdef emacs
1362/* For Emacs we have a separate interface which corresponds to the normal
1363 strftime function and does not have the extra information whether the
1364 TP arguments comes from a `gmtime' call or not. */
1365size_t
1366emacs_strftime (s, maxsize, format, tp)
1367 char *s;
1368 size_t maxsize;
1369 const char *format;
1370 const struct tm *tp;
1371{
1372 return my_strftime (s, maxsize, format, tp, 0);
1373}
1374#endif
1375