This is the mail archive of the newlib@sources.redhat.com 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]

strftime followup


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Oops, I had an incorrect statement in the docs (not all years have 53
weeks), and missed a case of negative years (the expansion of %x) the
first time around.  Meanwhile, since __tzrule.offset[0] is supposed to
match _timezone, I made sure the time functions don't overflow
architectures with a 16-bit int when a 32-bit long is required.

2005-02-24  Eric Blake  <ebb9@byu.net>

	* libc/include/time.h (__tzrule_struct): Make offset long, since
	a 16-bit int overflows on a 12-hour offset.
	* libc/sys/linux/include/time.h: Ditto.
	* libc/time/mktime.c (mktime): Use new type of __tzrule.offset.
	* libc/time/mktm_r.c: Ditto.
	* libc/time/gettzinfo.c: Ditto.
	* libc/time/strftime.c (strftime): Fix '%x' to deal with negative
	years.  Fix '%z' to use long, not int.

- --
Life is short - so eat dessert first!

Eric Blake             ebb9@byu.net

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCHzQk84KuGfSFAYARAk6LAJsFqrw7io5mJFDoBOIMaFhAqwWK2ACfYTXY
in7uj3hkEsVlV0F0Z9uulIY=
=v7+A
-----END PGP SIGNATURE-----
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/newlib/ChangeLog,v
retrieving revision 1.759
diff -u -p -r1.759 ChangeLog
Index: libc/include/time.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/time.h,v
retrieving revision 1.15
diff -u -p -r1.15 time.h
--- libc/include/time.h	23 Feb 2005 22:20:55 -0000	1.15
+++ libc/include/time.h	25 Feb 2005 04:55:13 -0000
@@ -79,7 +79,7 @@ typedef struct __tzrule_struct
   int d;
   int s;
   time_t change;
-  int offset;
+  long offset; /* Match type of _timezone. */
 } __tzrule_type;
 
 typedef struct __tzinfo_struct
Index: libc/sys/linux/include/time.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/sys/linux/include/time.h,v
retrieving revision 1.4
diff -u -p -r1.4 time.h
--- libc/sys/linux/include/time.h	23 Feb 2005 19:08:57 -0000	1.4
+++ libc/sys/linux/include/time.h	25 Feb 2005 04:55:14 -0000
@@ -92,7 +92,7 @@ typedef struct __tzrule_struct
   int d;
   int s;
   time_t change;
-  int offset;
+  long offset; /* Match type of _timezone. */
 } __tzrule_type;
 
 typedef struct __tzinfo_struct
Index: libc/time/gettzinfo.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/gettzinfo.c,v
retrieving revision 1.1
diff -u -p -r1.1 gettzinfo.c
--- libc/time/gettzinfo.c	23 Feb 2005 19:08:58 -0000	1.1
+++ libc/time/gettzinfo.c	25 Feb 2005 04:55:14 -0000
@@ -3,8 +3,8 @@
 
 /* Shared timezone information for libc/time functions.  */
 static __tzinfo_type tzinfo = {1, 0,
-    { {'J', 0, 0, 0, 0, (time_t)0, 0 },
-      {'J', 0, 0, 0, 0, (time_t)0, 0 } 
+    { {'J', 0, 0, 0, 0, (time_t)0, 0L },
+      {'J', 0, 0, 0, 0, (time_t)0, 0L } 
     } 
 };
 
Index: libc/time/mktime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/mktime.c,v
retrieving revision 1.4
diff -u -p -r1.4 mktime.c
--- libc/time/mktime.c	23 Feb 2005 19:08:58 -0000	1.4
+++ libc/time/mktime.c	25 Feb 2005 04:55:14 -0000
@@ -211,9 +211,12 @@ mktime (tim_p)
 	{
 	  /* calculate start of dst in dst local time and 
 	     start of std in both std local time and dst local time */
-          time_t startdst_dst = tz->__tzrule[0].change - tz->__tzrule[1].offset;
-	  time_t startstd_dst = tz->__tzrule[1].change - tz->__tzrule[1].offset;
-	  time_t startstd_std = tz->__tzrule[1].change - tz->__tzrule[0].offset;
+          time_t startdst_dst = tz->__tzrule[0].change
+	    - (time_t) tz->__tzrule[1].offset;
+	  time_t startstd_dst = tz->__tzrule[1].change
+	    - (time_t) tz->__tzrule[1].offset;
+	  time_t startstd_std = tz->__tzrule[1].change
+	    - (time_t) tz->__tzrule[0].offset;
 	  /* if the time is in the overlap between dst and std local times */
 	  if (tim >= startstd_std && tim < startstd_dst)
 	    ; /* we let user decide or leave as -1 */
@@ -226,8 +229,12 @@ mktime (tim_p)
 	      if ((isdst ^ tim_p->tm_isdst) == 1)
 		{
 		  /* we either subtract or add the difference between
-		     time zone offsets, depending on which way the user got it wrong */
-		  int diff = tz->__tzrule[0].offset - tz->__tzrule[1].offset;
+		     time zone offsets, depending on which way the user got it
+		     wrong. The diff is typically one hour, or 3600 seconds,
+		     and should fit in a 16-bit int, even though offset
+		     is a long to accomodate 12 hours. */
+		  int diff = (int) (tz->__tzrule[0].offset
+				    - tz->__tzrule[1].offset);
 		  if (!isdst)
 		    diff = -diff;
 		  tim_p->tm_sec += diff;
@@ -240,9 +247,9 @@ mktime (tim_p)
 
   /* add appropriate offset to put time in gmt format */
   if (isdst == 1)
-    tim += tz->__tzrule[1].offset;
+    tim += (time_t) tz->__tzrule[1].offset;
   else /* otherwise assume std time */
-    tim += tz->__tzrule[0].offset;
+    tim += (time_t) tz->__tzrule[0].offset;
 
   /* reset isdst flag to what we have calculated */
   tim_p->tm_isdst = isdst;
Index: libc/time/mktm_r.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/mktm_r.c,v
retrieving revision 1.3
diff -u -p -r1.3 mktm_r.c
--- libc/time/mktm_r.c	23 Feb 2005 19:08:58 -0000	1.3
+++ libc/time/mktm_r.c	25 Feb 2005 04:55:14 -0000
@@ -95,7 +95,7 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime)
 
   if (!is_gmtime)
     {
-      int offset;
+      long offset;
       int hours, mins, secs;
 
       TZ_LOCK;
@@ -117,11 +117,11 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime)
 		  ? tz->__tzrule[1].offset 
 		  : tz->__tzrule[0].offset);
 
-      hours = offset / SECSPERHOUR;
+      hours = (int) (offset / SECSPERHOUR);
       offset = offset % SECSPERHOUR;
       
-      mins = offset / SECSPERMIN;
-      secs = offset % SECSPERMIN;
+      mins = (int) (offset / SECSPERMIN);
+      secs = (int) (offset % SECSPERMIN);
 
       res->tm_sec -= secs;
       res->tm_min -= mins;
Index: libc/time/strftime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/strftime.c,v
retrieving revision 1.9
diff -u -p -r1.9 strftime.c
--- libc/time/strftime.c	24 Feb 2005 06:14:44 -0000	1.9
+++ libc/time/strftime.c	25 Feb 2005 04:55:16 -0000
@@ -1,6 +1,7 @@
 /*
  * strftime.c
  * Original Author:	G. Haley
+ * Additions from:	Eric Blake
  *
  * Places characters into the array pointed to by s as controlled by the string
  * pointed to by format. If the total number of resulting characters including
@@ -102,9 +103,9 @@ The last two digits of the week-based ye
 o %G
 The week-based year. In the ISO 8601:2000 calendar, week 1 of the year
 includes January 4th, and begin on Mondays. Therefore, if January 1st,
-2nd, or 3rd falls on a Sunday, that day and earlier belong to week 53
-of the previous year; and if December 29th, 30th, or 31st falls on
-Monday, that day and later belong to week 1 of the next year.  For
+2nd, or 3rd falls on a Sunday, that day and earlier belong to the last
+week of the previous year; and if December 29th, 30th, or 31st falls
+on Monday, that day and later belong to week 1 of the next year.  For
 consistency with %Y, it always has at least four characters. 
 Example: "%G" for Saturday 2nd January 1999 gives "1998", and for
 Tuesday 30th December 1997 gives "1998". [tm_year, tm_wday, tm_yday]
@@ -447,7 +448,8 @@ _DEFUN (strftime, (s, maxsize, format, t
 	    {
 	      sprintf (&s[count], "%.2d/%.2d/%.2d",
 		       tim_p->tm_mon + 1, tim_p->tm_mday,
-		       (tim_p->tm_year % 100 + 100) % 100);
+		       tim_p->tm_year >= 0 ? tim_p->tm_year % 100
+		       : abs (tim_p->tm_year + YEAR_BASE) % 100);
 	      count += 8;
 	    }
 	  else
@@ -756,7 +758,7 @@ _DEFUN (strftime, (s, maxsize, format, t
             {
 	      if (count < maxsize - 5)
 		{
-		  int offset;
+		  long offset;
 		  __tzinfo_type *tz = __gettzinfo ();
 		  TZ_LOCK;
 		  /* The sign of this is exactly opposite the envvar TZ.  We
@@ -764,8 +766,8 @@ _DEFUN (strftime, (s, maxsize, format, t
 		     but have to use __tzrule for daylight savings.  */
 		  offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset;
 		  TZ_UNLOCK;
-		  sprintf (&s[count], "%+03ld%.2d", offset / SECSPERHOUR,
-			   abs (offset / SECSPERMIN) % 60);
+		  sprintf (&s[count], "%+03ld%.2ld", offset / SECSPERHOUR,
+			   labs (offset / SECSPERMIN) % 60L);
 		  count += 5;
 		}
 	      else


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