about summary refs log tree commit diff
path: root/time/strftime.c
diff options
context:
space:
mode:
Diffstat (limited to 'time/strftime.c')
-rw-r--r--time/strftime.c56
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.  */