00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #ifdef _LIBC
00024 # define HAVE_LIMITS_H 1
00025 # define HAVE_MBLEN 1
00026 # define HAVE_MBRLEN 1
00027 # define HAVE_STRUCT_ERA_ENTRY 1
00028 # define HAVE_TM_GMTOFF 1
00029 # define HAVE_TM_ZONE 1
00030 # define HAVE_TZNAME 1
00031 # define HAVE_TZSET 1
00032 # define MULTIBYTE_IS_FORMAT_SAFE 1
00033 # define STDC_HEADERS 1
00034 # include "../locale/localeinfo.h"
00035 #endif
00036
00037 #if defined emacs && !defined HAVE_BCOPY
00038 # define HAVE_MEMCPY 1
00039 #endif
00040
00041 #include <ctype.h>
00042 #include <sys/types.h>
00043
00044 #ifdef TIME_WITH_SYS_TIME
00045 # include <sys/time.h>
00046 # include <time.h>
00047 #else
00048 # ifdef HAVE_SYS_TIME_H
00049 # include <sys/time.h>
00050 # else
00051 # include <time.h>
00052 # endif
00053 #endif
00054 #if HAVE_TZNAME
00055 extern char *tzname[];
00056 #endif
00057
00058
00059
00060
00061
00062
00063
00064 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
00065
00066 #if DO_MULTIBYTE
00067 # if HAVE_MBRLEN
00068 # include <wchar.h>
00069 # else
00070
00071 # define mbstate_t int
00072 # define mbrlen(s, n, ps) mblen (s, n)
00073 # define mbsinit(ps) (*(ps) == 0)
00074 # endif
00075 static const mbstate_t mbstate_zero;
00076 #endif
00077
00078 #if HAVE_LIMITS_H
00079 # include <limits.h>
00080 #endif
00081
00082 #if STDC_HEADERS
00083 # include <stddef.h>
00084 # include <stdlib.h>
00085 # include <string.h>
00086 #else
00087 # ifndef HAVE_MEMCPY
00088 # define memcpy(d, s, n) bcopy ((s), (d), (n))
00089 # endif
00090 #endif
00091
00092 #ifdef _LIBC
00093 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
00094 #else
00095 # ifndef HAVE_MEMPCPY
00096 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
00097 # endif
00098 #endif
00099
00100 #ifndef __P
00101 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
00102 # define __P(args) args
00103 # else
00104 # define __P(args) ()
00105 # endif
00106 #endif
00107
00108 #ifndef PTR
00109 # ifdef __STDC__
00110 # define PTR void *
00111 # else
00112 # define PTR char *
00113 # endif
00114 #endif
00115
00116 #ifndef CHAR_BIT
00117 # define CHAR_BIT 8
00118 #endif
00119
00120 #ifndef NULL
00121 # define NULL 0
00122 #endif
00123
00124 #define TYPE_SIGNED(t) ((t) -1 < 0)
00125
00126
00127
00128
00129
00130
00131 #define INT_STRLEN_BOUND(t) \
00132 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
00133
00134 #define TM_YEAR_BASE 1900
00135
00136 #ifndef __isleap
00137
00138
00139 # define __isleap(year) \
00140 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
00141 #endif
00142
00143
00144 #ifdef _LIBC
00145 # define my_strftime_gmtime_r __gmtime_r
00146 # define my_strftime_localtime_r __localtime_r
00147 # define tzname __tzname
00148 # define tzset __tzset
00149 #else
00150
00151
00152
00153
00154
00155 # if ! HAVE_TM_GMTOFF
00156 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
00157 static struct tm *
00158 my_strftime_gmtime_r (t, tp)
00159 const time_t *t;
00160 struct tm *tp;
00161 {
00162 struct tm *l = gmtime (t);
00163 if (! l)
00164 return 0;
00165 *tp = *l;
00166 return tp;
00167 }
00168 # endif
00169
00170 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
00171 static struct tm *
00172 my_strftime_localtime_r (t, tp)
00173 const time_t *t;
00174 struct tm *tp;
00175 {
00176 struct tm *l = localtime (t);
00177 if (! l)
00178 return 0;
00179 *tp = *l;
00180 return tp;
00181 }
00182 #endif
00183
00184
00185 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
00186
00187
00188
00189
00190 static const char spaces[16] =
00191 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
00192 static const char zeroes[16] =
00193 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
00194
00195 # define memset_space(P, Len) \
00196 do { \
00197 int _len = (Len); \
00198 \
00199 do \
00200 { \
00201 int _this = _len > 16 ? 16 : _len; \
00202 (P) = MEMPCPY ((P), spaces, _this); \
00203 _len -= _this; \
00204 } \
00205 while (_len > 0); \
00206 } while (0)
00207
00208 # define memset_zero(P, Len) \
00209 do { \
00210 int _len = (Len); \
00211 \
00212 do \
00213 { \
00214 int _this = _len > 16 ? 16 : _len; \
00215 (P) = MEMPCPY ((P), zeroes, _this); \
00216 _len -= _this; \
00217 } \
00218 while (_len > 0); \
00219 } while (0)
00220 #else
00221 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
00222 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
00223 #endif
00224
00225 #define add(n, f) \
00226 do \
00227 { \
00228 int _n = (n); \
00229 int _delta = width - _n; \
00230 int _incr = _n + (_delta > 0 ? _delta : 0); \
00231 if (i + _incr >= maxsize) \
00232 return 0; \
00233 if (p) \
00234 { \
00235 if (_delta > 0) \
00236 { \
00237 if (pad == '0') \
00238 memset_zero (p, _delta); \
00239 else \
00240 memset_space (p, _delta); \
00241 } \
00242 f; \
00243 p += _n; \
00244 } \
00245 i += _incr; \
00246 } while (0)
00247
00248 #define cpy(n, s) \
00249 add ((n), \
00250 if (to_lowcase) \
00251 memcpy_lowcase (p, (s), _n); \
00252 else if (to_uppcase) \
00253 memcpy_uppcase (p, (s), _n); \
00254 else \
00255 memcpy ((PTR) p, (PTR) (s), _n))
00256
00257
00258
00259 #ifdef _LIBC
00260 # define TOUPPER(Ch) toupper (Ch)
00261 # define TOLOWER(Ch) tolower (Ch)
00262 #else
00263 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
00264 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
00265 #endif
00266
00267
00268
00269
00270 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
00271
00272 static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
00273
00274 static char *
00275 memcpy_lowcase (dest, src, len)
00276 char *dest;
00277 const char *src;
00278 size_t len;
00279 {
00280 while (len-- > 0)
00281 dest[len] = TOLOWER ((unsigned char) src[len]);
00282 return dest;
00283 }
00284
00285 static char *memcpy_uppcase __P ((char *dest, const char *src, size_t len));
00286
00287 static char *
00288 memcpy_uppcase (dest, src, len)
00289 char *dest;
00290 const char *src;
00291 size_t len;
00292 {
00293 while (len-- > 0)
00294 dest[len] = TOUPPER ((unsigned char) src[len]);
00295 return dest;
00296 }
00297
00298
00299 #if ! HAVE_TM_GMTOFF
00300
00301
00302 # define tm_diff ftime_tm_diff
00303 static int tm_diff __P ((const struct tm *, const struct tm *));
00304 static int
00305 tm_diff (a, b)
00306 const struct tm *a;
00307 const struct tm *b;
00308 {
00309
00310
00311
00312 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
00313 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
00314 int a100 = a4 / 25 - (a4 % 25 < 0);
00315 int b100 = b4 / 25 - (b4 % 25 < 0);
00316 int a400 = a100 >> 2;
00317 int b400 = b100 >> 2;
00318 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
00319 int years = a->tm_year - b->tm_year;
00320 int days = (365 * years + intervening_leap_days
00321 + (a->tm_yday - b->tm_yday));
00322 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
00323 + (a->tm_min - b->tm_min))
00324 + (a->tm_sec - b->tm_sec));
00325 }
00326 #endif
00327
00328
00329
00330
00331
00332
00333
00334 #define ISO_WEEK_START_WDAY 1
00335 #define ISO_WEEK1_WDAY 4
00336 #define YDAY_MINIMUM (-366)
00337 static int iso_week_days __P ((int, int));
00338 #ifdef __GNUC__
00339 __inline__
00340 #endif
00341 static int
00342 iso_week_days (yday, wday)
00343 int yday;
00344 int wday;
00345 {
00346
00347 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
00348 return (yday
00349 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
00350 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
00351 }
00352
00353
00354 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
00355 static char const weekday_name[][10] =
00356 {
00357 "Sunday", "Monday", "Tuesday", "Wednesday",
00358 "Thursday", "Friday", "Saturday"
00359 };
00360 static char const month_name[][10] =
00361 {
00362 "January", "February", "March", "April", "May", "June",
00363 "July", "August", "September", "October", "November", "December"
00364 };
00365 #endif
00366
00367
00368 #ifdef emacs
00369 # define my_strftime emacs_strftimeu
00370 # define ut_argument , ut
00371 # define ut_argument_spec int ut;
00372 # define ut_argument_spec_iso , int ut
00373 #else
00374 # define my_strftime strftime
00375 # define ut_argument
00376 # define ut_argument_spec
00377 # define ut_argument_spec_iso
00378
00379 # define ut 0
00380 #endif
00381
00382 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
00383
00384
00385 size_t _strftime_copytm __P ((char *, size_t, const char *,
00386 const struct tm * ut_argument_spec_iso));
00387 size_t
00388 my_strftime (s, maxsize, format, tp ut_argument)
00389 char *s;
00390 size_t maxsize;
00391 const char *format;
00392 const struct tm *tp;
00393 ut_argument_spec
00394 {
00395 struct tm tmcopy;
00396 tmcopy = *tp;
00397 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
00398 }
00399 # undef my_strftime
00400 # define my_strftime(S, Maxsize, Format, Tp) \
00401 _strftime_copytm (S, Maxsize, Format, Tp)
00402 #endif
00403
00404
00405
00406
00407
00408
00409
00410
00411 size_t
00412 my_strftime (s, maxsize, format, tp ut_argument)
00413 char *s;
00414 size_t maxsize;
00415 const char *format;
00416 const struct tm *tp;
00417 ut_argument_spec
00418 {
00419 int hour12 = tp->tm_hour;
00420 #ifdef _NL_CURRENT
00421
00422
00423
00424
00425
00426
00427 # define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday)
00428 # define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday)
00429 # define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon)
00430 # define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon)
00431 # define ampm _NL_CURRENT (LC_TIME, tp->tm_hour > 11 ? PM_STR : AM_STR)
00432
00433 # define aw_len strlen (a_wkday)
00434 # define am_len strlen (a_month)
00435 # define ap_len strlen (ampm)
00436 #else
00437 # if !HAVE_STRFTIME
00438 # define f_wkday (weekday_name[tp->tm_wday])
00439 # define f_month (month_name[tp->tm_mon])
00440 # define a_wkday f_wkday
00441 # define a_month f_month
00442 # define ampm ("AMPM" + 2 * (tp->tm_hour > 11))
00443
00444 size_t aw_len = 3;
00445 size_t am_len = 3;
00446 size_t ap_len = 2;
00447 # endif
00448 #endif
00449 const char *zone;
00450 size_t i = 0;
00451 char *p = s;
00452 const char *f;
00453
00454 zone = NULL;
00455 #if HAVE_TM_ZONE
00456
00457
00458
00459
00460
00461
00462 zone = (const char *) tp->tm_zone;
00463 #endif
00464 #if HAVE_TZNAME
00465 if (ut)
00466 {
00467 if (! (zone && *zone))
00468 zone = "GMT";
00469 }
00470 else
00471 {
00472
00473
00474
00475 # if HAVE_TZSET
00476 tzset ();
00477 # endif
00478 }
00479 #endif
00480
00481 if (hour12 > 12)
00482 hour12 -= 12;
00483 else
00484 if (hour12 == 0)
00485 hour12 = 12;
00486
00487 for (f = format; *f != '\0'; ++f)
00488 {
00489 int pad = 0;
00490 int modifier;
00491 int digits;
00492 int number_value;
00493 int negative_number;
00494 const char *subfmt;
00495 char *bufp;
00496 char buf[1 + (sizeof (int) < sizeof (time_t)
00497 ? INT_STRLEN_BOUND (time_t)
00498 : INT_STRLEN_BOUND (int))];
00499 int width = -1;
00500 int to_lowcase = 0;
00501 int to_uppcase = 0;
00502 int change_case = 0;
00503 int format_char;
00504
00505 #if DO_MULTIBYTE
00506
00507 switch (*f)
00508 {
00509 case '%':
00510 break;
00511
00512 case '\a': case '\b': case '\t': case '\n':
00513 case '\v': case '\f': case '\r':
00514 case ' ': case '!': case '"': case '#': case '&': case'\'':
00515 case '(': case ')': case '*': case '+': case ',': case '-':
00516 case '.': case '/': case '0': case '1': case '2': case '3':
00517 case '4': case '5': case '6': case '7': case '8': case '9':
00518 case ':': case ';': case '<': case '=': case '>': case '?':
00519 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00520 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
00521 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00522 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00523 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
00524 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
00525 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
00526 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
00527 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
00528 case 'x': case 'y': case 'z': case '{': case '|': case '}':
00529 case '~':
00530
00531
00532
00533
00534 add (1, *p = *f);
00535 continue;
00536
00537 default:
00538
00539
00540 {
00541 mbstate_t mbstate = mbstate_zero;
00542 size_t len = 0;
00543
00544 do
00545 {
00546 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
00547
00548 if (bytes == 0)
00549 break;
00550
00551 if (bytes == (size_t) -2)
00552 {
00553 len += strlen (f + len);
00554 break;
00555 }
00556
00557 if (bytes == (size_t) -1)
00558 {
00559 len++;
00560 break;
00561 }
00562
00563 len += bytes;
00564 }
00565 while (! mbsinit (&mbstate));
00566
00567 cpy (len, f);
00568 f += len - 1;
00569 continue;
00570 }
00571 }
00572
00573 #else
00574
00575
00576
00577 if (*f != '%')
00578 {
00579 add (1, *p = *f);
00580 continue;
00581 }
00582
00583 #endif
00584
00585
00586 while (1)
00587 {
00588 switch (*++f)
00589 {
00590
00591 case '_':
00592 case '-':
00593 case '0':
00594 pad = *f;
00595 continue;
00596
00597
00598 case '^':
00599 to_uppcase = 1;
00600 continue;
00601 case '#':
00602 change_case = 1;
00603 continue;
00604
00605 default:
00606 break;
00607 }
00608 break;
00609 }
00610
00611
00612 if (ISDIGIT (*f))
00613 {
00614 width = 0;
00615 do
00616 {
00617 width *= 10;
00618 width += *f - '0';
00619 ++f;
00620 }
00621 while (ISDIGIT (*f));
00622 }
00623
00624
00625 switch (*f)
00626 {
00627 case 'E':
00628 case 'O':
00629 modifier = *f++;
00630 break;
00631
00632 default:
00633 modifier = 0;
00634 break;
00635 }
00636
00637
00638 format_char = *f;
00639 switch (format_char)
00640 {
00641 #define DO_NUMBER(d, v) \
00642 digits = width == -1 ? d : width; \
00643 number_value = v; goto do_number
00644 #define DO_NUMBER_SPACEPAD(d, v) \
00645 digits = width == -1 ? d : width; \
00646 number_value = v; goto do_number_spacepad
00647
00648 case '%':
00649 if (modifier != 0)
00650 goto bad_format;
00651 add (1, *p = *f);
00652 break;
00653
00654 case 'a':
00655 if (modifier != 0)
00656 goto bad_format;
00657 if (change_case)
00658 {
00659 to_uppcase = 1;
00660 to_lowcase = 0;
00661 }
00662 #if defined _NL_CURRENT || !HAVE_STRFTIME
00663 cpy (aw_len, a_wkday);
00664 break;
00665 #else
00666 goto underlying_strftime;
00667 #endif
00668
00669 case 'A':
00670 if (modifier != 0)
00671 goto bad_format;
00672 if (change_case)
00673 {
00674 to_uppcase = 1;
00675 to_lowcase = 0;
00676 }
00677 #if defined _NL_CURRENT || !HAVE_STRFTIME
00678 cpy (strlen (f_wkday), f_wkday);
00679 break;
00680 #else
00681 goto underlying_strftime;
00682 #endif
00683
00684 case 'b':
00685 case 'h':
00686 if (modifier != 0)
00687 goto bad_format;
00688 #if defined _NL_CURRENT || !HAVE_STRFTIME
00689 cpy (am_len, a_month);
00690 break;
00691 #else
00692 goto underlying_strftime;
00693 #endif
00694
00695 case 'B':
00696 if (modifier != 0)
00697 goto bad_format;
00698 if (change_case)
00699 {
00700 to_uppcase = 1;
00701 to_lowcase = 0;
00702 }
00703 #if defined _NL_CURRENT || !HAVE_STRFTIME
00704 cpy (strlen (f_month), f_month);
00705 break;
00706 #else
00707 goto underlying_strftime;
00708 #endif
00709
00710 case 'c':
00711 if (modifier == 'O')
00712 goto bad_format;
00713 #ifdef _NL_CURRENT
00714 if (! (modifier == 'E'
00715 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
00716 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
00717 #else
00718 # if HAVE_STRFTIME
00719 goto underlying_strftime;
00720 # else
00721 subfmt = "%a %b %e %H:%M:%S %Y";
00722 # endif
00723 #endif
00724
00725 subformat:
00726 {
00727 char *old_start = p;
00728 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
00729 add (len, my_strftime (p, maxsize - i, subfmt, tp));
00730
00731 if (to_uppcase)
00732 while (old_start < p)
00733 {
00734 *old_start = TOUPPER ((unsigned char) *old_start);
00735 ++old_start;
00736 }
00737 }
00738 break;
00739
00740 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
00741 underlying_strftime:
00742 {
00743
00744
00745 char ufmt[4];
00746 char *u = ufmt;
00747 char ubuf[1024];
00748 size_t len;
00749 *u++ = '%';
00750 if (modifier != 0)
00751 *u++ = modifier;
00752 *u++ = format_char;
00753 *u = '\0';
00754 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
00755 if (len == 0 && ubuf[0] != '\0')
00756 return 0;
00757 cpy (len, ubuf);
00758 }
00759 break;
00760 #endif
00761
00762 case 'C':
00763 if (modifier == 'O')
00764 goto bad_format;
00765 if (modifier == 'E')
00766 {
00767 #if HAVE_STRUCT_ERA_ENTRY
00768 struct era_entry *era = _nl_get_era_entry (tp);
00769 if (era)
00770 {
00771 size_t len = strlen (era->name_fmt);
00772 cpy (len, era->name_fmt);
00773 break;
00774 }
00775 #else
00776 # if HAVE_STRFTIME
00777 goto underlying_strftime;
00778 # endif
00779 #endif
00780 }
00781
00782 {
00783 int year = tp->tm_year + TM_YEAR_BASE;
00784 DO_NUMBER (1, year / 100 - (year % 100 < 0));
00785 }
00786
00787 case 'x':
00788 if (modifier == 'O')
00789 goto bad_format;
00790 #ifdef _NL_CURRENT
00791 if (! (modifier == 'E'
00792 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
00793 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
00794 goto subformat;
00795 #else
00796 # if HAVE_STRFTIME
00797 goto underlying_strftime;
00798 # else
00799
00800 # endif
00801 #endif
00802 case 'D':
00803 if (modifier != 0)
00804 goto bad_format;
00805 subfmt = "%m/%d/%y";
00806 goto subformat;
00807
00808 case 'd':
00809 if (modifier == 'E')
00810 goto bad_format;
00811
00812 DO_NUMBER (2, tp->tm_mday);
00813
00814 case 'e':
00815 if (modifier == 'E')
00816 goto bad_format;
00817
00818 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
00819
00820
00821
00822
00823 do_number_spacepad:
00824
00825 if (pad != '0')
00826 pad = '_';
00827
00828 do_number:
00829
00830
00831 if (modifier == 'O' && 0 <= number_value)
00832 {
00833 #ifdef _NL_CURRENT
00834
00835
00836 const char *cp = _nl_get_alt_digit (number_value);
00837
00838 if (cp != NULL)
00839 {
00840 size_t digitlen = strlen (cp);
00841 if (digitlen != 0)
00842 {
00843 cpy (digitlen, cp);
00844 break;
00845 }
00846 }
00847 #else
00848 # if HAVE_STRFTIME
00849 goto underlying_strftime;
00850 # endif
00851 #endif
00852 }
00853 {
00854 unsigned int u = number_value;
00855
00856 bufp = buf + sizeof (buf);
00857 negative_number = number_value < 0;
00858
00859 if (negative_number)
00860 u = -u;
00861
00862 do
00863 *--bufp = u % 10 + '0';
00864 while ((u /= 10) != 0);
00865 }
00866
00867 do_number_sign_and_padding:
00868 if (negative_number)
00869 *--bufp = '-';
00870
00871 if (pad != '-')
00872 {
00873 int padding = digits - (buf + sizeof (buf) - bufp);
00874
00875 if (pad == '_')
00876 {
00877 while (0 < padding--)
00878 *--bufp = ' ';
00879 }
00880 else
00881 {
00882 bufp += negative_number;
00883 while (0 < padding--)
00884 *--bufp = '0';
00885 if (negative_number)
00886 *--bufp = '-';
00887 }
00888 }
00889
00890 cpy (buf + sizeof (buf) - bufp, bufp);
00891 break;
00892
00893 case 'F':
00894 if (modifier != 0)
00895 goto bad_format;
00896 subfmt = "%Y-%m-%d";
00897 goto subformat;
00898
00899 case 'H':
00900 if (modifier == 'E')
00901 goto bad_format;
00902
00903 DO_NUMBER (2, tp->tm_hour);
00904
00905 case 'I':
00906 if (modifier == 'E')
00907 goto bad_format;
00908
00909 DO_NUMBER (2, hour12);
00910
00911 case 'k':
00912 if (modifier == 'E')
00913 goto bad_format;
00914
00915 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
00916
00917 case 'l':
00918 if (modifier == 'E')
00919 goto bad_format;
00920
00921 DO_NUMBER_SPACEPAD (2, hour12);
00922
00923 case 'j':
00924 if (modifier == 'E')
00925 goto bad_format;
00926
00927 DO_NUMBER (3, 1 + tp->tm_yday);
00928
00929 case 'M':
00930 if (modifier == 'E')
00931 goto bad_format;
00932
00933 DO_NUMBER (2, tp->tm_min);
00934
00935 case 'm':
00936 if (modifier == 'E')
00937 goto bad_format;
00938
00939 DO_NUMBER (2, tp->tm_mon + 1);
00940
00941 case 'n':
00942 add (1, *p = '\n');
00943 break;
00944
00945 case 'P':
00946 to_lowcase = 1;
00947 #if !defined _NL_CURRENT && HAVE_STRFTIME
00948 format_char = 'p';
00949 #endif
00950
00951
00952 case 'p':
00953 if (change_case)
00954 {
00955 to_uppcase = 0;
00956 to_lowcase = 1;
00957 }
00958 #if defined _NL_CURRENT || !HAVE_STRFTIME
00959 cpy (ap_len, ampm);
00960 break;
00961 #else
00962 goto underlying_strftime;
00963 #endif
00964
00965 case 'R':
00966 subfmt = "%H:%M";
00967 goto subformat;
00968
00969 case 'r':
00970 #ifdef _NL_CURRENT
00971 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
00972 #endif
00973 subfmt = "%I:%M:%S %p";
00974 goto subformat;
00975
00976 case 'S':
00977 if (modifier == 'E')
00978 goto bad_format;
00979
00980 DO_NUMBER (2, tp->tm_sec);
00981
00982 case 's':
00983 {
00984 struct tm ltm;
00985 time_t t;
00986
00987 ltm = *tp;
00988 t = mktime (<m);
00989
00990
00991
00992
00993 bufp = buf + sizeof (buf);
00994 negative_number = t < 0;
00995
00996 do
00997 {
00998 int d = t % 10;
00999 t /= 10;
01000
01001 if (negative_number)
01002 {
01003 d = -d;
01004
01005
01006 if (0 < -1 % 10 && d < 0)
01007 {
01008 t++;
01009 d += 10;
01010 }
01011 }
01012
01013 *--bufp = d + '0';
01014 }
01015 while (t != 0);
01016
01017 digits = 1;
01018 goto do_number_sign_and_padding;
01019 }
01020
01021 case 'X':
01022 if (modifier == 'O')
01023 goto bad_format;
01024 #ifdef _NL_CURRENT
01025 if (! (modifier == 'E'
01026 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
01027 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
01028 goto subformat;
01029 #else
01030 # if HAVE_STRFTIME
01031 goto underlying_strftime;
01032 # else
01033
01034 # endif
01035 #endif
01036 case 'T':
01037 subfmt = "%H:%M:%S";
01038 goto subformat;
01039
01040 case 't':
01041 add (1, *p = '\t');
01042 break;
01043
01044 case 'u':
01045 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
01046
01047 case 'U':
01048 if (modifier == 'E')
01049 goto bad_format;
01050
01051 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
01052
01053 case 'V':
01054 case 'g':
01055 case 'G':
01056 if (modifier == 'E')
01057 goto bad_format;
01058 {
01059 int year = tp->tm_year + TM_YEAR_BASE;
01060 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
01061
01062 if (days < 0)
01063 {
01064
01065 year--;
01066 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
01067 tp->tm_wday);
01068 }
01069 else
01070 {
01071 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
01072 tp->tm_wday);
01073 if (0 <= d)
01074 {
01075
01076 year++;
01077 days = d;
01078 }
01079 }
01080
01081 switch (*f)
01082 {
01083 case 'g':
01084 DO_NUMBER (2, (year % 100 + 100) % 100);
01085
01086 case 'G':
01087 DO_NUMBER (1, year);
01088
01089 default:
01090 DO_NUMBER (2, days / 7 + 1);
01091 }
01092 }
01093
01094 case 'W':
01095 if (modifier == 'E')
01096 goto bad_format;
01097
01098 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
01099
01100 case 'w':
01101 if (modifier == 'E')
01102 goto bad_format;
01103
01104 DO_NUMBER (1, tp->tm_wday);
01105
01106 case 'Y':
01107 if (modifier == 'E')
01108 {
01109 #if HAVE_STRUCT_ERA_ENTRY
01110 struct era_entry *era = _nl_get_era_entry (tp);
01111 if (era)
01112 {
01113 subfmt = strchr (era->name_fmt, '\0') + 1;
01114 goto subformat;
01115 }
01116 #else
01117 # if HAVE_STRFTIME
01118 goto underlying_strftime;
01119 # endif
01120 #endif
01121 }
01122 if (modifier == 'O')
01123 goto bad_format;
01124 else
01125 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
01126
01127 case 'y':
01128 if (modifier == 'E')
01129 {
01130 #if HAVE_STRUCT_ERA_ENTRY
01131 struct era_entry *era = _nl_get_era_entry (tp);
01132 if (era)
01133 {
01134 int delta = tp->tm_year - era->start_date[0];
01135 DO_NUMBER (1, (era->offset
01136 + (era->direction == '-' ? -delta : delta)));
01137 }
01138 #else
01139 # if HAVE_STRFTIME
01140 goto underlying_strftime;
01141 # endif
01142 #endif
01143 }
01144 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
01145
01146 case 'Z':
01147 if (change_case)
01148 {
01149 to_uppcase = 0;
01150 to_lowcase = 1;
01151 }
01152
01153 #if HAVE_TZNAME
01154
01155 if (!(zone && *zone) && tp->tm_isdst >= 0)
01156 zone = tzname[tp->tm_isdst];
01157 #endif
01158 if (! zone)
01159 zone = "";
01160
01161 cpy (strlen (zone), zone);
01162 break;
01163
01164 case 'z':
01165 if (tp->tm_isdst < 0)
01166 break;
01167
01168 {
01169 int diff;
01170 #if HAVE_TM_GMTOFF
01171 diff = tp->tm_gmtoff;
01172 #else
01173 if (ut)
01174 diff = 0;
01175 else
01176 {
01177 struct tm gtm;
01178 struct tm ltm;
01179 time_t lt;
01180
01181 ltm = *tp;
01182 lt = mktime (<m);
01183
01184 if (lt == (time_t) -1)
01185 {
01186
01187
01188
01189 struct tm tm;
01190
01191 if (! my_strftime_localtime_r (<, &tm)
01192 || ((ltm.tm_sec ^ tm.tm_sec)
01193 | (ltm.tm_min ^ tm.tm_min)
01194 | (ltm.tm_hour ^ tm.tm_hour)
01195 | (ltm.tm_mday ^ tm.tm_mday)
01196 | (ltm.tm_mon ^ tm.tm_mon)
01197 | (ltm.tm_year ^ tm.tm_year)))
01198 break;
01199 }
01200
01201 if (! my_strftime_gmtime_r (<, >m))
01202 break;
01203
01204 diff = tm_diff (<m, >m);
01205 }
01206 #endif
01207
01208 if (diff < 0)
01209 {
01210 add (1, *p = '-');
01211 diff = -diff;
01212 }
01213 else
01214 add (1, *p = '+');
01215
01216 diff /= 60;
01217 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
01218 }
01219
01220 case '\0':
01221 --f;
01222
01223 default:
01224
01225
01226
01227 bad_format:
01228 {
01229 int flen;
01230 for (flen = 1; f[1 - flen] != '%'; flen++)
01231 continue;
01232 cpy (flen, &f[1 - flen]);
01233 }
01234 break;
01235 }
01236 }
01237
01238 if (p && maxsize != 0)
01239 *p = '\0';
01240 return i;
01241 }
01242
01243
01244 #ifdef emacs
01245
01246
01247
01248 size_t
01249 emacs_strftime (s, maxsize, format, tp)
01250 char *s;
01251 size_t maxsize;
01252 const char *format;
01253 const struct tm *tp;
01254 {
01255 return my_strftime (s, maxsize, format, tp, 0);
01256 }
01257 #endif