1 /* Copyright (C) 1995,1996,1997,1998 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. */
54 # ifdef HAVE_SYS_TYPES_H
55 # include <sys/types.h>
58 # ifdef TIME_WITH_SYS_TIME
59 # include <sys/time.h>
62 # ifdef HAVE_SYS_TIME_H
63 # include <sys/time.h>
71 #ifdef HAVE_SYS_TIMES_H
72 # include <sys/times.h>
75 #ifdef HAVE_SYS_TIMEB_H
76 # include <sys/timeb.h>
79 #ifndef tzname /* For SGI. */
80 extern char *tzname
[]; /* RS6000 and others reject char **tzname. */
83 #ifdef MISSING_STRPTIME_DECL
84 extern char *strptime ();
87 /* This should be figured out by autoconf. */
88 #if ! defined(CLKTCK) && defined(CLK_TCK)
89 # define CLKTCK CLK_TCK
91 #if ! defined(CLKTCK) && defined(CLOCKS_PER_SEC)
92 # define CLKTCK CLOCKS_PER_SEC
100 # define timet time_t
109 struct tms time_buffer
;
111 return time_buffer
.tms_utime
+ time_buffer
.tms_stime
;
115 # define mytime() ((time((timet*)0) - scm_your_base) * CLKTCK)
117 # define mytime clock
125 extern int ftime (struct timeb
*);
127 struct timeb scm_your_base
= {0};
128 SCM_PROC(s_get_internal_real_time
, "get-internal-real-time", 0, 0, 0, scm_get_internal_real_time
);
130 scm_get_internal_real_time()
132 struct timeb time_buffer
;
135 ftime (&time_buffer
);
136 time_buffer
.time
-= scm_your_base
.time
;
137 tmp
= scm_long2num (time_buffer
.millitm
- scm_your_base
.millitm
);
139 scm_product (SCM_MAKINUM (1000),
140 SCM_MAKINUM (time_buffer
.time
)));
141 return scm_quotient (scm_product (tmp
, SCM_MAKINUM (CLKTCK
)),
147 timet scm_your_base
= 0;
148 SCM_PROC(s_get_internal_real_time
, "get-internal-real-time", 0, 0, 0, scm_get_internal_real_time
);
150 scm_get_internal_real_time()
152 return scm_long2num((time((timet
*)0) - scm_your_base
) * (int)CLKTCK
);
156 SCM_PROC (s_times
, "times", 0, 0, 0, scm_times
);
164 SCM result
= scm_make_vector (SCM_MAKINUM(5), SCM_UNDEFINED
);
167 scm_syserror (s_times
);
168 SCM_VELTS (result
)[0] = scm_long2num (rv
);
169 SCM_VELTS (result
)[1] = scm_long2num (t
.tms_utime
);
170 SCM_VELTS (result
)[2] = scm_long2num (t
.tms_stime
);
171 SCM_VELTS (result
)[3] = scm_long2num (t
.tms_cutime
);
172 SCM_VELTS (result
)[4] = scm_long2num (t
.tms_cstime
);
175 scm_sysmissing (s_times
);
180 /* GNU-WIN32's cygwin.dll doesn't have this. */
185 static long scm_my_base
= 0;
187 SCM_PROC(s_get_internal_run_time
, "get-internal-run-time", 0, 0, 0, scm_get_internal_run_time
);
189 scm_get_internal_run_time()
191 return scm_long2num(mytime()-scm_my_base
);
194 SCM_PROC(s_current_time
, "current-time", 0, 0, 0, scm_current_time
);
201 if ((timv
= time (0)) == -1)
202 scm_syserror (s_current_time
);
204 return scm_long2num((long) timv
);
207 SCM_PROC (s_gettimeofday
, "gettimeofday", 0, 0, 0, scm_gettimeofday
);
209 scm_gettimeofday (void)
211 #ifdef HAVE_GETTIMEOFDAY
215 if (gettimeofday (&time
, NULL
) == -1)
216 scm_syserror (s_gettimeofday
);
218 return scm_cons (scm_long2num ((long) time
.tv_sec
),
219 scm_long2num ((long) time
.tv_usec
));
225 return scm_cons (scm_long2num ((long) time
.time
),
226 SCM_MAKINUM (time
.millitm
* 1000));
231 if ((timv
= time (0)) == -1)
232 scm_syserror (s_gettimeofday
);
234 return scm_cons (scm_long2num (timv
), SCM_MAKINUM (0));
240 filltime (struct tm
*bd_time
, int zoff
, char *zname
)
242 SCM result
= scm_make_vector (SCM_MAKINUM(11), SCM_UNDEFINED
);
244 SCM_VELTS (result
)[0] = SCM_MAKINUM (bd_time
->tm_sec
);
245 SCM_VELTS (result
)[1] = SCM_MAKINUM (bd_time
->tm_min
);
246 SCM_VELTS (result
)[2] = SCM_MAKINUM (bd_time
->tm_hour
);
247 SCM_VELTS (result
)[3] = SCM_MAKINUM (bd_time
->tm_mday
);
248 SCM_VELTS (result
)[4] = SCM_MAKINUM (bd_time
->tm_mon
);
249 SCM_VELTS (result
)[5] = SCM_MAKINUM (bd_time
->tm_year
);
250 SCM_VELTS (result
)[6] = SCM_MAKINUM (bd_time
->tm_wday
);
251 SCM_VELTS (result
)[7] = SCM_MAKINUM (bd_time
->tm_yday
);
252 SCM_VELTS (result
)[8] = SCM_MAKINUM (bd_time
->tm_isdst
);
253 SCM_VELTS (result
)[9] = SCM_MAKINUM (zoff
);
254 SCM_VELTS (result
)[10] = zname
? scm_makfrom0str (zname
) : SCM_BOOL_F
;
258 static char tzvar
[3] = "TZ";
259 extern char ** environ
;
262 setzone (SCM zone
, int pos
, const char *subr
)
266 if (!SCM_UNBNDP (zone
))
268 static char *tmpenv
[2];
271 /* if zone was supplied, set the environment temporarily. */
272 SCM_ASSERT (SCM_NIMP (zone
) && SCM_ROSTRINGP (zone
), zone
, pos
, subr
);
273 SCM_COERCE_SUBSTR (zone
);
274 buf
= scm_must_malloc (SCM_LENGTH (zone
) + sizeof (tzvar
) + 1,
276 sprintf (buf
, "%s=%s", tzvar
, SCM_ROCHARS (zone
));
287 restorezone (SCM zone
, char **oldenv
, const char *subr
)
289 if (!SCM_UNBNDP (zone
))
291 scm_must_free (environ
[0]);
298 SCM_PROC (s_localtime
, "localtime", 1, 1, 0, scm_localtime
);
300 scm_localtime (SCM time
, SCM zone
)
303 struct tm
*ltptr
, lt
, *utc
;
310 itime
= scm_num2long (time
, (char *) SCM_ARG1
, s_localtime
);
312 oldenv
= setzone (zone
, SCM_ARG2
, s_localtime
);
313 ltptr
= localtime (&itime
);
319 /* copy zone name before calling gmtime or tzset. */
321 ptr
= ltptr
->tm_zone
;
324 ptr
= tzname
[ (ltptr
->tm_isdst
== 1) ? 1 : 0 ];
326 scm_misc_error (s_localtime
, "Not fully implemented on this platform",
330 zname
= scm_must_malloc (strlen (ptr
) + 1, s_localtime
);
333 /* the struct is copied in case localtime and gmtime share a buffer. */
336 utc
= gmtime (&itime
);
339 restorezone (zone
, oldenv
, s_localtime
);
340 /* delayed until zone has been restored. */
342 if (utc
== NULL
|| ltptr
== NULL
)
343 scm_syserror (s_localtime
);
345 /* calculate timezone offset in seconds west of UTC. */
346 zoff
= (utc
->tm_hour
- lt
.tm_hour
) * 3600 + (utc
->tm_min
- lt
.tm_min
) * 60
347 + utc
->tm_sec
- lt
.tm_sec
;
348 if (utc
->tm_year
< lt
.tm_year
)
349 zoff
-= 24 * 60 * 60;
350 else if (utc
->tm_year
> lt
.tm_year
)
351 zoff
+= 24 * 60 * 60;
352 else if (utc
->tm_yday
< lt
.tm_yday
)
353 zoff
-= 24 * 60 * 60;
354 else if (utc
->tm_yday
> lt
.tm_yday
)
355 zoff
+= 24 * 60 * 60;
357 result
= filltime (<
, zoff
, zname
);
359 scm_must_free (zname
);
363 SCM_PROC (s_gmtime
, "gmtime", 1, 0, 0, scm_gmtime
);
365 scm_gmtime (SCM time
)
371 itime
= scm_num2long (time
, (char *) SCM_ARG1
, s_gmtime
);
373 bd_time
= gmtime (&itime
);
375 scm_syserror (s_gmtime
);
376 result
= filltime (bd_time
, 0, "GMT");
381 /* copy time components from a Scheme object to a struct tm. */
383 bdtime2c (SCM sbd_time
, struct tm
*lt
, int pos
, const char *subr
)
385 SCM_ASSERT (SCM_NIMP (sbd_time
) && SCM_VECTORP (sbd_time
)
386 && SCM_LENGTH (sbd_time
) == 11
387 && SCM_INUMP (SCM_VELTS (sbd_time
)[0])
388 && SCM_INUMP (SCM_VELTS (sbd_time
)[1])
389 && SCM_INUMP (SCM_VELTS (sbd_time
)[2])
390 && SCM_INUMP (SCM_VELTS (sbd_time
)[3])
391 && SCM_INUMP (SCM_VELTS (sbd_time
)[4])
392 && SCM_INUMP (SCM_VELTS (sbd_time
)[5])
393 && SCM_INUMP (SCM_VELTS (sbd_time
)[6])
394 && SCM_INUMP (SCM_VELTS (sbd_time
)[7])
395 && SCM_INUMP (SCM_VELTS (sbd_time
)[8]),
396 sbd_time
, pos
, subr
);
397 lt
->tm_sec
= SCM_INUM (SCM_VELTS (sbd_time
)[0]);
398 lt
->tm_min
= SCM_INUM (SCM_VELTS (sbd_time
)[1]);
399 lt
->tm_hour
= SCM_INUM (SCM_VELTS (sbd_time
)[2]);
400 lt
->tm_mday
= SCM_INUM (SCM_VELTS (sbd_time
)[3]);
401 lt
->tm_mon
= SCM_INUM (SCM_VELTS (sbd_time
)[4]);
402 lt
->tm_year
= SCM_INUM (SCM_VELTS (sbd_time
)[5]);
403 lt
->tm_wday
= SCM_INUM (SCM_VELTS (sbd_time
)[6]);
404 lt
->tm_yday
= SCM_INUM (SCM_VELTS (sbd_time
)[7]);
405 lt
->tm_isdst
= SCM_INUM (SCM_VELTS (sbd_time
)[8]);
408 SCM_PROC (s_mktime
, "mktime", 1, 1, 0, scm_mktime
);
410 scm_mktime (SCM sbd_time
, SCM zone
)
420 SCM_ASSERT (SCM_NIMP (sbd_time
) && SCM_VECTORP (sbd_time
), sbd_time
,
422 bdtime2c (sbd_time
, <
, SCM_ARG1
, s_mktime
);
425 oldenv
= setzone (zone
, SCM_ARG2
, s_mktime
);
426 itime
= mktime (<
);
433 /* copy zone name before calling gmtime or tzset. */
438 ptr
= tzname
[ (lt
.tm_isdst
== 1) ? 1 : 0 ];
440 scm_misc_error (s_mktime
, "Not fully implemented on this platform",
444 zname
= scm_must_malloc (strlen (ptr
) + 1, s_mktime
);
448 /* get timezone offset in seconds west of UTC. */
449 utc
= gmtime (&itime
);
453 restorezone (zone
, oldenv
, s_mktime
);
454 /* delayed until zone has been restored. */
456 if (utc
== NULL
|| itime
== -1)
457 scm_syserror (s_mktime
);
459 zoff
= (utc
->tm_hour
- lt
.tm_hour
) * 3600 + (utc
->tm_min
- lt
.tm_min
) * 60
460 + utc
->tm_sec
- lt
.tm_sec
;
461 if (utc
->tm_year
< lt
.tm_year
)
462 zoff
-= 24 * 60 * 60;
463 else if (utc
->tm_year
> lt
.tm_year
)
464 zoff
+= 24 * 60 * 60;
465 else if (utc
->tm_yday
< lt
.tm_yday
)
466 zoff
-= 24 * 60 * 60;
467 else if (utc
->tm_yday
> lt
.tm_yday
)
468 zoff
+= 24 * 60 * 60;
470 result
= scm_cons (scm_long2num ((long) itime
),
471 filltime (<
, zoff
, zname
));
473 scm_must_free (zname
);
477 SCM_PROC (s_tzset
, "tzset", 0, 0, 0, scm_tzset
);
482 return SCM_UNSPECIFIED
;
485 SCM_PROC (s_strftime
, "strftime", 2, 0, 0, scm_strftime
);
488 scm_strftime (format
, stime
)
500 SCM_ASSERT (SCM_NIMP (format
) && SCM_ROSTRINGP (format
), format
, SCM_ARG1
,
502 bdtime2c (stime
, &t
, SCM_ARG2
, s_strftime
);
504 SCM_COERCE_SUBSTR (format
);
505 fmt
= SCM_ROCHARS (format
);
506 len
= SCM_ROLENGTH (format
);
508 tbuf
= scm_must_malloc (size
, s_strftime
);
509 while ((len
= strftime (tbuf
, size
, fmt
, &t
)) == size
)
511 scm_must_free (tbuf
);
513 tbuf
= scm_must_malloc (size
, s_strftime
);
515 result
= scm_makfromstr (tbuf
, len
, 0);
516 scm_must_free (tbuf
);
520 SCM_PROC (s_strptime
, "strptime", 2, 0, 0, scm_strptime
);
523 scm_strptime (format
, string
)
529 char *fmt
, *str
, *rest
;
531 SCM_ASSERT (SCM_NIMP (format
) && SCM_ROSTRINGP (format
), format
, SCM_ARG1
,
533 SCM_ASSERT (SCM_NIMP (string
) && SCM_ROSTRINGP (string
), string
, SCM_ARG2
,
536 SCM_COERCE_SUBSTR (format
);
537 SCM_COERCE_SUBSTR (string
);
538 fmt
= SCM_ROCHARS (format
);
539 str
= SCM_ROCHARS (string
);
541 /* initialize the struct tm */
542 #define tm_init(field) t.field = 0
555 if ((rest
= strptime (str
, fmt
, &t
)) == NULL
)
556 scm_syserror (s_strptime
);
559 return scm_cons (filltime (&t
, 0, NULL
), SCM_MAKINUM (rest
- str
));
562 scm_sysmissing (s_strptime
);
569 scm_sysintern("internal-time-units-per-second",
570 scm_long2num((long)CLKTCK
));
573 if (!scm_your_base
.time
) ftime(&scm_your_base
);
575 if (!scm_your_base
) time(&scm_your_base
);
578 if (!scm_my_base
) scm_my_base
= mytime();
580 scm_add_feature ("current-time");