diff options
Diffstat (limited to 'time/strftime.c')
-rw-r--r-- | time/strftime.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/time/strftime.c b/time/strftime.c index f724bf3e3b..594cbbfe16 100644 --- a/time/strftime.c +++ b/time/strftime.c @@ -416,15 +416,25 @@ my_strftime (s, maxsize, format, tp) { int hour12 = tp->tm_hour; #ifdef _NL_CURRENT - const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday); - const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday); - const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon); - const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon); - const char *const ampm = _NL_CURRENT (LC_TIME, - hour12 > 11 ? PM_STR : AM_STR); - size_t aw_len = strlen (a_wkday); - size_t am_len = strlen (a_month); - size_t ap_len = strlen (ampm); + /* We cannot make the following values variables since we must dealy + the evaluation of these values until really needed since some + expressions might not be valid in every situation. The `struct tm' + might be generated by a strptime() call and therefore initialized + only a few elements. Dereference the pointers only if the format + requires this. Then it is ok to fail if the pointers are invalid. */ +# define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday) +# define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday) +# define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday) +# define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon) +# define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon) +# define ampm _NL_CURRENT (LC_TIME, hour12 > 11 ? PM_STR : AM_STR) + +# define aw_len strlen (a_wkday) +# define am_len strlen (a_month) +# define ap_len strlen (ampm) + +# define wkday_len strlen (f_wkday) +# define month_len strlen (f_month) #else # if !HAVE_STRFTIME const char *const f_wkday = weekday_name[tp->tm_wday]; @@ -435,14 +445,12 @@ my_strftime (s, maxsize, format, tp) size_t aw_len = 3; size_t am_len = 3; size_t ap_len = 2; -# endif -#endif -#if defined _NL_CURRENT || !HAVE_STRFTIME + size_t wkday_len = strlen (f_wkday); size_t month_len = strlen (f_month); +# endif #endif const char *zone; - size_t zonelen; size_t i = 0; char *p = s; const char *f; @@ -457,21 +465,12 @@ my_strftime (s, maxsize, format, tp) POSIX does not require it. Do the right thing instead. */ zone = (const char *) tp->tm_zone; #endif -#if HAVE_TZNAME +#if HAVE_TZNAME && HAVE_TZSET /* POSIX.1 8.1.1 requires that whenever strftime() is called, the time zone names contained in the external variable `tzname' shall be set as if the tzset() function had been called. */ -# if HAVE_TZSET tzset (); -# endif - - if (!(zone && *zone) && tp->tm_isdst >= 0) - zone = tzname[tp->tm_isdst]; #endif - if (! zone) - zone = ""; /* POSIX.2 requires the empty string here. */ - - zonelen = strlen (zone); if (hour12 > 12) hour12 -= 12; @@ -1146,7 +1145,16 @@ my_strftime (s, maxsize, format, tp) to_uppcase = 0; to_lowcase = 1; } - cpy (zonelen, zone); + +#if HAVE_TZNAME + /* The tzset() call might have changed the value. */ + if (!(zone && *zone) && tp->tm_isdst >= 0) + zone = tzname[tp->tm_isdst]; +#endif + if (! zone) + zone = ""; /* POSIX.2 requires the empty string here. */ + + cpy (strlen (zone), zone); break; case 'z': /* GNU extension. */ |