[project @ 2002-04-24 16:31:37 by simonmar]
[ghc-base.git] / System / Time.hsc
index b8d79b4..4db1d61 100644 (file)
@@ -1,8 +1,5 @@
-{-# OPTIONS -optc-DNON_POSIX_SOURCE #-}
--- JRS 010117: we had to say NON_POSIX_SOURCE to get the resulting .hc
--- to compile on sparc-solaris.  Blargh.
 -----------------------------------------------------------------------------
--- 
+-- |
 -- Module      :  System.Time
 -- Copyright   :  (c) The University of Glasgow 2001
 -- License     :  BSD-style (see the file libraries/core/LICENSE)
@@ -11,7 +8,7 @@
 -- Stability   :  provisional
 -- Portability :  portable
 --
--- $Id: Time.hsc,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+-- $Id: Time.hsc,v 1.12 2002/04/24 16:31:45 simonmar Exp $
 --
 -- The standard Time library.
 --
@@ -101,7 +98,7 @@ module System.Time
 
      ) where
 
-#include "HsCore.h"
+#include "HsBase.h"
 
 import Prelude
 
@@ -208,9 +205,9 @@ noTimeDiff = TimeDiff 0 0 0 0 0 0 0
 getClockTime = do
   allocaBytes (#const sizeof(struct timeval)) $ \ p_timeval -> do
     throwErrnoIfMinus1_ "getClockTime" $ gettimeofday p_timeval nullPtr
-    sec  <- (#peek struct timeval,tv_sec)  p_timeval :: IO CLong
-    usec <- (#peek struct timeval,tv_usec) p_timeval :: IO CLong
-    return (TOD (fromIntegral sec) ((fromIntegral usec) * 1000))
+    sec  <- (#peek struct timeval,tv_sec)  p_timeval :: IO CTime
+    usec <- (#peek struct timeval,tv_usec) p_timeval :: IO CTime
+    return (TOD (fromIntegral sec) ((fromIntegral usec) * 1000000))
  
 #elif HAVE_FTIME
 getClockTime = do
@@ -218,7 +215,7 @@ getClockTime = do
   ftime p_timeb
   sec  <- (#peek struct timeb,time) p_timeb :: IO CTime
   msec <- (#peek struct timeb,millitm) p_timeb :: IO CUShort
-  return (TOD (fromIntegral sec) (fromIntegral msec * 1000{-ToDo: correct???-}))
+  return (TOD (fromIntegral sec) (fromIntegral msec * 1000000000))
 
 #else /* use POSIX time() */
 getClockTime = do
@@ -320,12 +317,11 @@ gmtoff x    = (#peek struct tm,tm_gmtoff) x
 #   define tzname _tzname
 #  endif
 #  ifndef mingw32_TARGET_OS
-foreign label tzname :: Ptr (Ptr CChar)
+foreign import ccall unsafe "&tzname" tzname :: Ptr (Ptr CChar)
+foreign import ccall unsafe "timezone" timezone :: Ptr CLong
 #  else
-foreign import "ghcTimezone" unsafe timezone :: Ptr CLong
-foreign import "ghcTzname" unsafe tzname :: Ptr (Ptr CChar)
-#   def inline long  *ghcTimezone(void) { return &_timezone; }
-#   def inline char **ghcTzname(void) { return _tzname; }
+foreign import ccall unsafe "__hscore_timezone" timezone :: Ptr CLong
+foreign import ccall unsafe "__hscore_tzname"   tzname :: Ptr (Ptr CChar)
 #  endif
 zone x = do 
   dst <- (#peek struct tm,tm_isdst) x
@@ -336,13 +332,13 @@ zone x = do
 # endif /* ! HAVE_TZNAME */
 
 -- Get the offset in secs from UTC, if (struct tm) doesn't supply it. */
-#if defined(mingw32_TARGET_OS) || defined(cygwin32_TARGET_OS)
+#if defined(mingw32_TARGET_OS)
 #define timezone _timezone
 #endif
 
 # if HAVE_ALTZONE
-foreign label altzone  :: Ptr CTime
-foreign label timezone :: Ptr CTime
+foreign import ccall "&altzone"  :: Ptr CTime
+foreign import ccall "&timezone" :: Ptr CTime
 gmtoff x = do 
   dst <- (#peek struct tm,tm_isdst) x
   tz <- if dst then peek altzone else peek timezone
@@ -366,18 +362,40 @@ gmtoff x = do
 
 
 toCalendarTime :: ClockTime -> IO CalendarTime
-toCalendarTime =  clockToCalendarTime localtime False
+#if HAVE_LOCALTIME_R
+toCalendarTime =  clockToCalendarTime_reentrant (throwAwayReturnPointer localtime_r) False
+#else
+toCalendarTime =  clockToCalendarTime_static localtime False
+#endif
 
 toUTCTime      :: ClockTime -> CalendarTime
-toUTCTime      =  unsafePerformIO . clockToCalendarTime gmtime True
+#if HAVE_GMTIME_R
+toUTCTime      =  unsafePerformIO . clockToCalendarTime_reentrant (throwAwayReturnPointer gmtime_r) True
+#else
+toUTCTime      =  unsafePerformIO . clockToCalendarTime_static gmtime True
+#endif
+
+throwAwayReturnPointer :: (Ptr CTime -> Ptr CTm -> IO (Ptr CTm))
+                       -> (Ptr CTime -> Ptr CTm -> IO (       ))
+throwAwayReturnPointer fun x y = fun x y >> return ()
 
--- ToDo: should be made thread safe, because localtime uses static storage,
--- or use the localtime_r version.
-clockToCalendarTime :: (Ptr CTime -> IO (Ptr CTm)) -> Bool -> ClockTime
+clockToCalendarTime_static :: (Ptr CTime -> IO (Ptr CTm)) -> Bool -> ClockTime
         -> IO CalendarTime
-clockToCalendarTime fun is_utc (TOD secs psec) = do
+clockToCalendarTime_static fun is_utc (TOD secs psec) = do
   withObject (fromIntegral secs :: CTime)  $ \ p_timer -> do
     p_tm <- fun p_timer        -- can't fail, according to POSIX
+    clockToCalendarTime_aux is_utc p_tm psec
+
+clockToCalendarTime_reentrant :: (Ptr CTime -> Ptr CTm -> IO ()) -> Bool -> ClockTime
+        -> IO CalendarTime
+clockToCalendarTime_reentrant fun is_utc (TOD secs psec) = do
+  withObject (fromIntegral secs :: CTime)  $ \ p_timer -> do
+    allocaBytes (#const sizeof(struct tm)) $ \ p_tm -> do
+      fun p_timer p_tm
+      clockToCalendarTime_aux is_utc p_tm psec
+
+clockToCalendarTime_aux :: Bool -> Ptr CTm -> Integer -> IO CalendarTime
+clockToCalendarTime_aux is_utc p_tm psec = do
     sec   <-  (#peek struct tm,tm_sec  ) p_tm :: IO CInt
     min   <-  (#peek struct tm,tm_min  ) p_tm :: IO CInt
     hour  <-  (#peek struct tm,tm_hour ) p_tm :: IO CInt
@@ -451,7 +469,7 @@ toClockTime (CalendarTime year mon mday hour min sec psec
         -- 
         gmtoff <- gmtoff p_tm
        let res = fromIntegral t - tz + fromIntegral gmtoff
-       return (TOD (fromIntegral res) 0)
+       return (TOD (fromIntegral res) psec)
 
 -- -----------------------------------------------------------------------------
 -- Converting time values to strings.
@@ -599,21 +617,29 @@ formatTimeDiff l fmt td@(TimeDiff year month day hour min sec _)
 
 type CTm = () -- struct tm
 
-foreign import unsafe localtime :: Ptr CTime -> IO (Ptr CTm)
-foreign import unsafe gmtime    :: Ptr CTime -> IO (Ptr CTm)
-foreign import unsafe mktime    :: Ptr CTm   -> IO CTime
-foreign import unsafe time      :: Ptr CTime -> IO CTime
+#if HAVE_LOCALTIME_R
+foreign import ccall unsafe localtime_r :: Ptr CTime -> Ptr CTm -> IO (Ptr CTm)
+#else
+foreign import ccall unsafe localtime   :: Ptr CTime -> IO (Ptr CTm)
+#endif
+#if HAVE_GMTIME_R
+foreign import ccall unsafe gmtime_r    :: Ptr CTime -> Ptr CTm -> IO (Ptr CTm)
+#else
+foreign import ccall unsafe gmtime      :: Ptr CTime -> IO (Ptr CTm)
+#endif
+foreign import ccall unsafe mktime      :: Ptr CTm   -> IO CTime
+foreign import ccall unsafe time        :: Ptr CTime -> IO CTime
 
 #if HAVE_GETTIMEOFDAY
 type CTimeVal = ()
-foreign import unsafe gettimeofday :: Ptr CTimeVal -> Ptr () -> IO CInt
+foreign import ccall unsafe gettimeofday :: Ptr CTimeVal -> Ptr () -> IO CInt
 #endif
 
 #if HAVE_FTIME
 type CTimeB = ()
 #ifndef mingw32_TARGET_OS
-foreign import unsafe ftime :: Ptr CTimeB -> IO CInt
+foreign import ccall unsafe ftime :: Ptr CTimeB -> IO CInt
 #else
-foreign import unsafe ftime :: Ptr CTimeB -> IO ()
+foreign import ccall unsafe ftime :: Ptr CTimeB -> IO ()
 #endif
 #endif