1 /* Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
46 #include "sequences.h"
55 # ifdef HAVE_SYS_TYPES_H
56 # include <sys/types.h>
59 # ifdef TIME_WITH_SYS_TIME
60 # include <sys/time.h>
63 # ifdef HAVE_SYS_TIME_H
64 # include <sys/time.h>
72 #ifdef HAVE_SYS_TIMES_H
73 # include <sys/times.h>
76 #ifdef HAVE_SYS_TIMEB_H
77 # include <sys/timeb.h>
80 #ifndef tzname /* For SGI. */
81 extern char *tzname
[]; /* RS6000 and others reject char **tzname. */
86 /* This should be figured out by autoconf. */
88 # define CLKTCK CLK_TCK
89 # ifdef CLOCKS_PER_SEC
90 # if defined (unix) || defined (__unix)
92 # include <sys/times.h>
95 /* This is because clock() might be POSIX rather than ANSI.
96 This occurs on HP-UX machines */
100 # ifdef CLOCKS_PER_SEC
101 # define CLKTCK CLOCKS_PER_SEC
109 # define timet time_t
118 struct tms time_buffer
;
120 return time_buffer
.tms_utime
+ time_buffer
.tms_stime
;
124 # define mytime() ((time((timet*)0) - scm_your_base) * CLKTCK)
126 # define mytime clock
134 extern int ftime (struct timeb
*);
136 struct timeb scm_your_base
= {0};
137 SCM_PROC(s_get_internal_real_time
, "get-internal-real-time", 0, 0, 0, scm_get_internal_real_time
);
139 scm_get_internal_real_time()
141 struct timeb time_buffer
;
144 time_buffer
.time
-= scm_your_base
.time
;
145 tmp
= time_buffer
.millitm
- scm_your_base
.millitm
;
146 tmp
= time_buffer
.time
*1000L + tmp
;
149 return scm_long2num (tmp
);
154 timet scm_your_base
= 0;
155 SCM_PROC(s_get_internal_real_time
, "get-internal-real-time", 0, 0, 0, scm_get_internal_real_time
);
157 scm_get_internal_real_time()
159 return scm_long2num((time((timet
*)0) - scm_your_base
) * (int)CLKTCK
);
165 static long scm_my_base
= 0;
167 SCM_PROC(s_get_internal_run_time
, "get-internal-run-time", 0, 0, 0, scm_get_internal_run_time
);
169 scm_get_internal_run_time()
171 return scm_long2num(mytime()-scm_my_base
);
174 SCM_PROC(s_current_time
, "current-time", 0, 0, 0, scm_current_time
);
181 if ((timv
= time (0)) == -1)
182 scm_syserror (s_current_time
);
184 return scm_long2num((long) timv
);
187 SCM_PROC (s_gettimeofday
, "gettimeofday", 0, 0, 0, scm_gettimeofday
);
189 scm_gettimeofday (void)
191 #ifdef HAVE_GETTIMEOFDAY
195 if (gettimeofday (&time
, NULL
) == -1)
196 scm_syserror (s_gettimeofday
);
198 return scm_cons (scm_long2num ((long) time
.tv_sec
),
199 scm_long2num ((long) time
.tv_usec
));
205 return scm_cons (scm_long2num ((long) time
.time
),
206 SCM_MAKINUM (time
.millitm
* 1000));
211 if ((timv
= time (0)) == -1)
212 scm_syserror (s_gettimeofday
);
214 return scm_cons (scm_long2num (timv
), SCM_MAKINUM (0));
220 filltime (struct tm
*bd_time
, int zoff
, char *zname
)
222 SCM result
= scm_make_vector(SCM_MAKINUM(11), SCM_UNDEFINED
, SCM_UNDEFINED
);
224 SCM_VELTS (result
)[0] = SCM_MAKINUM (bd_time
->tm_sec
);
225 SCM_VELTS (result
)[1] = SCM_MAKINUM (bd_time
->tm_min
);
226 SCM_VELTS (result
)[2] = SCM_MAKINUM (bd_time
->tm_hour
);
227 SCM_VELTS (result
)[3] = SCM_MAKINUM (bd_time
->tm_mday
);
228 SCM_VELTS (result
)[4] = SCM_MAKINUM (bd_time
->tm_mon
);
229 SCM_VELTS (result
)[5] = SCM_MAKINUM (bd_time
->tm_year
);
230 SCM_VELTS (result
)[6] = SCM_MAKINUM (bd_time
->tm_wday
);
231 SCM_VELTS (result
)[7] = SCM_MAKINUM (bd_time
->tm_yday
);
232 SCM_VELTS (result
)[8] = SCM_MAKINUM (bd_time
->tm_isdst
);
233 SCM_VELTS (result
)[9] = SCM_MAKINUM (zoff
);
234 SCM_VELTS (result
)[10] = zname
? scm_makfrom0str (zname
) : SCM_BOOL_F
;
239 setzone (SCM zone
, int pos
, char *subr
)
243 if (!SCM_UNBNDP (zone
))
247 /* if zone was supplied, set the environment variable TZ temporarily. */
248 SCM_ASSERT (SCM_NIMP (zone
) && SCM_ROSTRINGP (zone
), zone
, pos
, subr
);
249 SCM_COERCE_SUBSTR (zone
);
250 buf
= malloc (SCM_LENGTH (zone
) + 4);
252 scm_memory_error (subr
);
253 oldtz
= getenv ("TZ");
256 sprintf (buf
, "TZ=%s", SCM_ROCHARS (zone
));
257 if (putenv (buf
) < 0)
265 restorezone (SCM zone
, char *oldzone
)
267 if (!SCM_UNBNDP (zone
))
272 rv
= putenv (oldzone
);
276 scm_syserror ("restorezone");
282 SCM_PROC (s_localtime
, "localtime", 1, 1, 0, scm_localtime
);
284 scm_localtime (SCM time
, SCM zone
)
287 struct tm
*ltptr
, lt
, *utc
;
294 itime
= scm_num2long (time
, (char *) SCM_ARG1
, s_localtime
);
296 oldtz
= setzone (zone
, SCM_ARG2
, s_localtime
);
297 ltptr
= localtime (&itime
);
299 /* copied in case localtime and gmtime share a buffer. */
302 utc
= gmtime (&itime
);
311 /* must be copied before calling tzset again. */
312 char *ptr
= tzname
[ (lt
.tm_isdst
== 1) ? 1 : 0 ];
314 zname
= scm_must_malloc (strlen (ptr
) + 1, s_localtime
);
317 scm_misc_error (s_localtime
, "Not fully implemented on this platform",
322 restorezone (zone
, oldtz
);
323 /* delayed until zone has been restored. */
325 if (utc
== NULL
|| ltptr
== NULL
)
326 scm_syserror (s_localtime
);
328 /* calculate timezone offset in seconds west of UTC. */
329 zoff
= (utc
->tm_hour
- lt
.tm_hour
) * 3600 + (utc
->tm_min
- lt
.tm_min
) * 60
330 + utc
->tm_sec
- lt
.tm_sec
;
331 if (utc
->tm_year
< lt
.tm_year
)
332 zoff
-= 24 * 60 * 60;
333 else if (utc
->tm_year
> lt
.tm_year
)
334 zoff
+= 24 * 60 * 60;
335 else if (utc
->tm_yday
< lt
.tm_yday
)
336 zoff
-= 24 * 60 * 60;
337 else if (utc
->tm_yday
> lt
.tm_yday
)
338 zoff
+= 24 * 60 * 60;
340 result
= filltime (<
, zoff
, zname
);
345 SCM_PROC (s_gmtime
, "gmtime", 1, 0, 0, scm_gmtime
);
347 scm_gmtime (SCM time
)
353 itime
= scm_num2long (time
, (char *) SCM_ARG1
, s_gmtime
);
355 bd_time
= gmtime (&itime
);
357 scm_syserror (s_gmtime
);
358 result
= filltime (bd_time
, 0, "GMT");
363 /* copy time components from a Scheme object to a struct tm. */
365 bdtime2c (SCM sbd_time
, struct tm
*lt
, int pos
, char *subr
)
367 SCM_ASSERT (SCM_NIMP (sbd_time
) && SCM_VECTORP (sbd_time
)
368 && scm_obj_length (sbd_time
) == 11
369 && SCM_INUMP (SCM_VELTS (sbd_time
)[0])
370 && SCM_INUMP (SCM_VELTS (sbd_time
)[1])
371 && SCM_INUMP (SCM_VELTS (sbd_time
)[2])
372 && SCM_INUMP (SCM_VELTS (sbd_time
)[3])
373 && SCM_INUMP (SCM_VELTS (sbd_time
)[4])
374 && SCM_INUMP (SCM_VELTS (sbd_time
)[5])
375 && SCM_INUMP (SCM_VELTS (sbd_time
)[6])
376 && SCM_INUMP (SCM_VELTS (sbd_time
)[7])
377 && SCM_INUMP (SCM_VELTS (sbd_time
)[8]),
378 sbd_time
, pos
, subr
);
379 lt
->tm_sec
= SCM_INUM (SCM_VELTS (sbd_time
)[0]);
380 lt
->tm_min
= SCM_INUM (SCM_VELTS (sbd_time
)[1]);
381 lt
->tm_hour
= SCM_INUM (SCM_VELTS (sbd_time
)[2]);
382 lt
->tm_mday
= SCM_INUM (SCM_VELTS (sbd_time
)[3]);
383 lt
->tm_mon
= SCM_INUM (SCM_VELTS (sbd_time
)[4]);
384 lt
->tm_year
= SCM_INUM (SCM_VELTS (sbd_time
)[5]);
385 lt
->tm_wday
= SCM_INUM (SCM_VELTS (sbd_time
)[6]);
386 lt
->tm_yday
= SCM_INUM (SCM_VELTS (sbd_time
)[7]);
387 lt
->tm_isdst
= SCM_INUM (SCM_VELTS (sbd_time
)[8]);
390 SCM_PROC (s_mktime
, "mktime", 1, 1, 0, scm_mktime
);
392 scm_mktime (SCM sbd_time
, SCM zone
)
402 SCM_ASSERT (SCM_NIMP (sbd_time
) && SCM_VECTORP (sbd_time
), sbd_time
,
404 bdtime2c (sbd_time
, <
, SCM_ARG1
, s_mktime
);
407 oldtz
= setzone (zone
, SCM_ARG2
, s_mktime
);
408 itime
= mktime (<
);
411 /* timezone offset in seconds west of UTC. */
412 utc
= gmtime (&itime
);
422 /* must be copied before calling tzset again. */
423 char *ptr
= tzname
[ (lt
.tm_isdst
== 1) ? 1 : 0 ];
425 zname
= scm_must_malloc (strlen (ptr
) + 1, s_mktime
);
428 scm_misc_error (s_localtime
, "Not fully implemented on this platform",
433 restorezone (zone
, oldtz
);
434 /* delayed until zone has been restored. */
436 if (utc
== NULL
|| itime
== -1)
437 scm_syserror (s_mktime
);
439 zoff
= (utc
->tm_hour
- lt
.tm_hour
) * 3600 + (utc
->tm_min
- lt
.tm_min
) * 60
440 + utc
->tm_sec
- lt
.tm_sec
;
441 if (utc
->tm_year
< lt
.tm_year
)
442 zoff
-= 24 * 60 * 60;
443 else if (utc
->tm_year
> lt
.tm_year
)
444 zoff
+= 24 * 60 * 60;
445 else if (utc
->tm_yday
< lt
.tm_yday
)
446 zoff
-= 24 * 60 * 60;
447 else if (utc
->tm_yday
> lt
.tm_yday
)
448 zoff
+= 24 * 60 * 60;
450 result
= scm_cons (scm_long2num ((long) itime
),
451 filltime (<
, zoff
, zname
));
456 SCM_PROC (s_tzset
, "tzset", 0, 0, 0, scm_tzset
);
461 return SCM_UNSPECIFIED
;
464 SCM_PROC (s_strftime
, "strftime", 2, 0, 0, scm_strftime
);
467 scm_strftime (format
, stime
)
478 SCM_ASSERT (SCM_NIMP (format
) && SCM_ROSTRINGP (format
), format
, SCM_ARG1
,
480 bdtime2c (stime
, &t
, SCM_ARG2
, s_strftime
);
482 SCM_COERCE_SUBSTR (format
);
483 fmt
= SCM_ROCHARS (format
);
484 len
= SCM_ROLENGTH (format
);
486 tbuf
= scm_must_malloc (size
, s_strftime
);
487 while ((len
= strftime (tbuf
, size
, fmt
, &t
)) == size
)
489 scm_must_free (tbuf
);
491 tbuf
= scm_must_malloc (size
, s_strftime
);
493 return scm_makfromstr (tbuf
, len
, 0);
496 SCM_PROC (s_strptime
, "strptime", 2, 0, 0, scm_strptime
);
499 scm_strptime (format
, string
)
505 char *fmt
, *str
, *rest
;
507 SCM_ASSERT (SCM_NIMP (format
) && SCM_ROSTRINGP (format
), format
, SCM_ARG1
,
509 SCM_ASSERT (SCM_NIMP (string
) && SCM_ROSTRINGP (string
), string
, SCM_ARG2
,
512 SCM_COERCE_SUBSTR (format
);
513 SCM_COERCE_SUBSTR (string
);
514 fmt
= SCM_ROCHARS (format
);
515 str
= SCM_ROCHARS (string
);
517 /* initialize the struct tm */
518 #define tm_init(field) t.field = 0
531 if ((rest
= strptime (str
, fmt
, &t
)) == NULL
)
532 scm_syserror (s_strptime
);
535 return scm_cons (filltime (&t
, 0, NULL
), SCM_MAKINUM (rest
- str
));
538 scm_sysmissing (s_strptime
);
545 scm_sysintern("internal-time-units-per-second",
546 scm_long2num((long)CLKTCK
));
549 if (!scm_your_base
.time
) ftime(&scm_your_base
);
551 if (!scm_your_base
) time(&scm_your_base
);
554 if (!scm_my_base
) scm_my_base
= mytime();
556 scm_add_feature ("current-time");