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