(scm_gmtime): Return bd_time->tm_zone when available, rather than "GMT" always.
[bpt/guile.git] / libguile / stime.c
index 6bf2122..0b70920 100644 (file)
 # include <sys/timeb.h>
 #endif
 
+#if HAVE_CRT_EXTERNS_H
+#include <crt_externs.h>  /* for Darwin _NSGetEnviron */
+#endif
+
 #ifndef tzname /* For SGI.  */
 extern char *tzname[]; /* RS6000 and others reject char **tzname.  */
 #endif
@@ -71,6 +75,16 @@ extern char *strptime ();
 # define timet long
 #endif
 
+extern char ** environ;
+
+/* On Apple Darwin in a shared library there's no "environ" to access
+   directly, instead the address of that variable must be obtained with
+   _NSGetEnviron().  */
+#if HAVE__NSGETENVIRON && defined (PIC)
+#define environ (*_NSGetEnviron())
+#endif
+
+
 #ifdef HAVE_TIMES
 static
 timet mytime()
@@ -241,7 +255,7 @@ SCM_DEFINE (scm_gettimeofday, "gettimeofday", 0, 0, 0,
 #undef FUNC_NAME
 
 static SCM
-filltime (struct tm *bd_time, int zoff, char *zname)
+filltime (struct tm *bd_time, int zoff, const char *zname)
 {
   SCM result = scm_c_make_vector (11, SCM_UNDEFINED);
 
@@ -260,7 +274,6 @@ filltime (struct tm *bd_time, int zoff, char *zname)
 }
 
 static char tzvar[3] = "TZ";
-extern char ** environ;
 
 /* if zone is set, create a temporary environment with only a TZ
    string.  other threads or interrupt handlers shouldn't be allowed
@@ -327,6 +340,9 @@ SCM_DEFINE (scm_localtime, "localtime", 1, 1, 0,
 #ifdef LOCALTIME_CACHE
   tzset ();
 #endif
+  /* POSIX says localtime sets errno, but C99 doesn't say that.
+     Give a sensible default value in case localtime doesn't set it.  */
+  errno = EINVAL;
   ltptr = localtime (&itime);
   err = errno;
   if (ltptr)
@@ -347,6 +363,9 @@ SCM_DEFINE (scm_localtime, "localtime", 1, 1, 0,
   /* the struct is copied in case localtime and gmtime share a buffer.  */
   if (ltptr)
     lt = *ltptr;
+  /* POSIX says gmtime sets errno, but C99 doesn't say that.
+     Give a sensible default value in case gmtime doesn't set it.  */
+  errno = EINVAL;
   utc = gmtime (&itime);
   if (utc == NULL)
     err = errno;
@@ -386,13 +405,22 @@ SCM_DEFINE (scm_gmtime, "gmtime", 1, 0, 0,
   timet itime;
   struct tm *bd_time;
   SCM result;
+  const char *zname;
 
   itime = SCM_NUM2LONG (1, time);
   SCM_DEFER_INTS;
+  /* POSIX says gmtime sets errno, but C99 doesn't say that.
+     Give a sensible default value in case gmtime doesn't set it.  */
+  errno = EINVAL;
   bd_time = gmtime (&itime);
   if (bd_time == NULL)
     SCM_SYSERROR;
-  result = filltime (bd_time, 0, "GMT");
+#if HAVE_STRUCT_TM_TM_ZONE
+  zname = bd_time->tm_zone;
+#else
+  zname = "GMT";
+#endif
+  result = filltime (bd_time, 0, zname);
   SCM_ALLOW_INTS;
   return result;
 }
@@ -461,7 +489,9 @@ SCM_DEFINE (scm_mktime, "mktime", 1, 1, 0,
   tzset ();
 #endif
   itime = mktime (&lt);
-  err = errno;
+  /* POSIX doesn't say mktime sets errno, and on glibc 2.3.2 for instance it
+     doesn't.  Force a sensible value for our error message.  */
+  err = EINVAL;
 
   if (itime != -1)
     {
@@ -480,6 +510,8 @@ SCM_DEFINE (scm_mktime, "mktime", 1, 1, 0,
     }
 
   /* get timezone offset in seconds west of UTC.  */
+  /* POSIX says gmtime sets errno, but C99 doesn't say that.
+     Give a sensible default value in case gmtime doesn't set it.  */
   utc = gmtime (&itime);
   if (utc == NULL)
     err = errno;
@@ -660,7 +692,13 @@ SCM_DEFINE (scm_strptime, "strptime", 2, 0, 0,
   t.tm_isdst = -1;
   SCM_DEFER_INTS;
   if ((rest = strptime (str, fmt, &t)) == NULL)
-    SCM_SYSERROR;
+    {
+      /* POSIX doesn't say strptime sets errno, and on glibc 2.3.2 for
+         instance it doesn't.  Force a sensible value for our error
+         message.  */
+      errno = EINVAL;
+      SCM_SYSERROR;
+    }
 
   SCM_ALLOW_INTS;
   return scm_cons (filltime (&t, 0, NULL),  SCM_MAKINUM (rest - str));