This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] strftime/wcsftime: Utilize __TM_GMTOFF and __TM_ZONE


Hi,

I just applied the below patch to strftime.c.  On systems which define
the struct tm members __TM_GMTOFF and __TM_ZONE, use them directly for
'z' and 'Z' formats.  This is more correct than always using the values
from __tzinfo and __tzname, since the latter only reflect the *current*
timezone information for *our* timezone.  The members of struct tm, on
the other hand, may reflect a date of another timezone, or of a timezone
which is valid at this time in the past.

For Cygwin I had to add a function call because Cygwin has to take
backward compatibility into account.  Pulling in Cygwin version checks
into newlib would certainly have been more ugly than to call into the
Cygwin DLL so I think this is the lesser of two evils.


Corinna


    * libc/time/strftime.c (__strftime): Utilize __TM_GMTOFF and __TM_ZONE
    on systems where available.  On Cygwin, call function to get values.
    Add comment to explain why.  Drop TZ_LOCK/TZ_UNLOCK in 'z' case since
    it's not necessary.  In 'Z' case, add a comment to document a potential
    codeset problem.


Index: libc/time/strftime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/strftime.c,v
retrieving revision 1.23
diff -u -p -r1.23 strftime.c
--- libc/time/strftime.c	4 Sep 2014 08:27:03 -0000	1.23
+++ libc/time/strftime.c	8 Jan 2015 09:50:47 -0000
@@ -1283,13 +1283,24 @@ recurse:
           if (tim_p->tm_isdst >= 0)
             {
 	      long offset;
+
+#if defined (__CYGWIN__)
+	      /* Cygwin must check if the application has been built with or
+		 without the extra tm members for backward compatibility, and
+		 then use either that or the old method fetching from tzinfo.
+		 Rather than pulling in the version check infrastructure, we
+		 just call a Cygwin function. */
+	      extern long __cygwin_gettzoffset (const struct tm *tmp);
+	      offset = __cygwin_gettzoffset (tim_p);
+#elif defined (__TM_GMTOFF)
+	      offset = tim_p->__TM_GMTOFF;
+#else
 	      __tzinfo_type *tz = __gettzinfo ();
-	      TZ_LOCK;
 	      /* The sign of this is exactly opposite the envvar TZ.  We
-	         could directly use the global _timezone for tm_isdst==0,
-	         but have to use __tzrule for daylight savings.  */
+		 could directly use the global _timezone for tm_isdst==0,
+		 but have to use __tzrule for daylight savings.  */
 	      offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset;
-	      TZ_UNLOCK;
+#endif
 	      len = snprintf (&s[count], maxsize - count, CQ("%+03ld%.2ld"),
 			      offset / SECSPERHOUR,
 			      labs (offset / SECSPERMIN) % 60L);
@@ -1300,12 +1311,27 @@ recurse:
 	  if (tim_p->tm_isdst >= 0)
 	    {
 	      size_t size;
+	      const char *tznam;
+
 	      TZ_LOCK;
-	      size = strlen(_tzname[tim_p->tm_isdst > 0]);
+#if defined (__CYGWIN__)
+	      /* See above. */
+	      extern const char *__cygwin_gettzname (const struct tm *tmp);
+	      tznam = __cygwin_gettzname (tim_p);
+#elif defined (__TM_ZONE)
+	      tznam = tim_p->__TM_ZONE;
+#else
+	      tznam = _tzname[tim_p->tm_isdst > 0];
+#endif
+	      /* Note that in case of wcsftime this loop only works for
+	         timezone abbreviations using the portable codeset (aka ASCII).
+		 This seems to be the case, but if that ever changes, this
+		 loop needs revisiting. */
+	      size = strlen (tznam);
 	      for (i = 0; i < size; i++)
 		{
 		  if (count < maxsize - 1)
-		    s[count++] = _tzname[tim_p->tm_isdst > 0][i];
+		    s[count++] = tznam[i];
 		  else
 		    {
 		      TZ_UNLOCK;


-- 
Corinna Vinschen
Cygwin Maintainer
Red Hat

Attachment: pgptmMMoZrUpM.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]