* throw.c: Doc fixes; rearranged.
[bpt/guile.git] / libguile / stime.c
CommitLineData
19468eff 1/* Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
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)
6 * any later version.
7 *
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.
12 *
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, 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
40 */
41\f
42
43#include <stdio.h>
44#include "_scm.h"
876c87ce 45#include "feature.h"
20e6290e
JB
46
47#include "stime.h"
48
0f2d19dd
JB
49#ifdef HAVE_UNISTD_H
50#include <unistd.h>
51#endif
52
53\f
54# ifdef HAVE_SYS_TYPES_H
55# include <sys/types.h>
56# endif
57
58# ifdef TIME_WITH_SYS_TIME
59# include <sys/time.h>
60# include <time.h>
61# else
62# ifdef HAVE_SYS_TIME_H
63# include <sys/time.h>
64# else
65# ifdef HAVE_TIME_H
66# include <time.h>
67# endif
68# endif
69# endif
70
71# ifdef HAVE_SYS_TIMES_H
72# include <sys/times.h>
73# else
74# ifdef HAVE_SYS_TIMEB_H
75# include <sys/timeb.h>
76# endif
77# endif
78
cda55316 79/* This should be figured out by autoconf. */
0f2d19dd
JB
80#ifdef CLK_TCK
81# define CLKTCK CLK_TCK
82# ifdef CLOCKS_PER_SEC
cda55316 83# if defined (unix) || defined (__unix)
0f2d19dd
JB
84# ifndef ARM_ULIB
85# include <sys/times.h>
86# endif
87# define LACK_CLOCK
88 /* This is because clock() might be POSIX rather than ANSI.
89 This occurs on HP-UX machines */
90# endif
91# endif
92#else
93# ifdef CLOCKS_PER_SEC
94# define CLKTCK CLOCKS_PER_SEC
95# else
96# define LACK_CLOCK
97# define CLKTCK 60
98# endif
99#endif
100
101
102# ifdef HAVE_FTIME
103# include <sys/timeb.h>
104# endif
105
106
107#ifdef __STDC__
108# define timet time_t
109#else
110# define timet long
111#endif
112
113#ifdef HAVE_TIMES
0f2d19dd
JB
114static
115long mytime()
0f2d19dd
JB
116{
117 struct tms time_buffer;
118 times(&time_buffer);
119 return time_buffer.tms_utime + time_buffer.tms_stime;
120}
121#else
122# ifdef LACK_CLOCK
123# define mytime() ((time((timet*)0) - scm_your_base) * CLKTCK)
124# else
125# define mytime clock
126# endif
127#endif
128
19468eff 129extern int errno;
0f2d19dd
JB
130
131#ifdef HAVE_FTIME
132
23858ad1
MD
133extern int ftime (struct timeb *);
134
0f2d19dd
JB
135struct timeb scm_your_base = {0};
136SCM_PROC(s_get_internal_real_time, "get-internal-real-time", 0, 0, 0, scm_get_internal_real_time);
0f2d19dd
JB
137SCM
138scm_get_internal_real_time()
0f2d19dd
JB
139{
140 struct timeb time_buffer;
141 long tmp;
142 ftime(&time_buffer);
143 time_buffer.time -= scm_your_base.time;
144 tmp = time_buffer.millitm - scm_your_base.millitm;
145 tmp = time_buffer.time*1000L + tmp;
146 tmp *= CLKTCK;
147 tmp /= 1000;
19468eff 148 return scm_long2num (tmp);
0f2d19dd
JB
149}
150
151#else
152
153timet scm_your_base = 0;
154SCM_PROC(s_get_internal_real_time, "get-internal-real-time", 0, 0, 0, scm_get_internal_real_time);
0f2d19dd
JB
155SCM
156scm_get_internal_real_time()
0f2d19dd 157{
19468eff 158 return scm_long2num((time((timet*)0) - scm_your_base) * (int)CLKTCK);
0f2d19dd
JB
159}
160#endif
161
162
163
164static long scm_my_base = 0;
165
166SCM_PROC(s_get_internal_run_time, "get-internal-run-time", 0, 0, 0, scm_get_internal_run_time);
0f2d19dd
JB
167SCM
168scm_get_internal_run_time()
0f2d19dd 169{
19468eff 170 return scm_long2num(mytime()-scm_my_base);
0f2d19dd
JB
171}
172
173SCM_PROC(s_current_time, "current-time", 0, 0, 0, scm_current_time);
0f2d19dd
JB
174SCM
175scm_current_time()
0f2d19dd 176{
19468eff
GH
177 timet timv;
178
179 SCM_DEFER_INTS;
180 if ((timv = time (0)) == -1)
181 scm_syserror (s_current_time);
182 SCM_ALLOW_INTS;
183 return scm_long2num((long) timv);
184}
185
1bf9865d 186SCM_PROC (s_gettimeofday, "gettimeofday", 0, 0, 0, scm_gettimeofday);
19468eff 187SCM
1bf9865d 188scm_gettimeofday (void)
19468eff
GH
189{
190#ifdef HAVE_GETTIMEOFDAY
191 struct timeval time;
192
193 SCM_DEFER_INTS;
194 if (gettimeofday (&time, NULL) == -1)
1bf9865d 195 scm_syserror (s_gettimeofday);
19468eff
GH
196 SCM_ALLOW_INTS;
197 return scm_cons (scm_long2num ((long) time.tv_sec),
198 scm_long2num ((long) time.tv_usec));
199#else
200# ifdef HAVE_FTIME
201 struct timeb time;
202
203 ftime(&time);
204 return scm_cons (scm_long2num ((long) time.time),
9a81afca 205 SCM_MAKINUM (time.millitm * 1000));
19468eff
GH
206# else
207 timet timv;
208
209 SCM_DEFER_INTS;
210 if ((timv = time (0)) == -1)
1bf9865d 211 scm_syserror (s_gettimeofday);
19468eff
GH
212 SCM_ALLOW_INTS;
213 return scm_cons (scm_long2num (timv), SCM_MAKINUM (0));
214# endif
215#endif
216}
217
218static SCM
219filltime (struct tm *bd_time, int zoff, char *zname)
220{
221 SCM result = scm_make_vector(SCM_MAKINUM(11), SCM_UNDEFINED, SCM_UNDEFINED);
222
223 SCM_VELTS (result)[0] = SCM_MAKINUM (bd_time->tm_sec);
224 SCM_VELTS (result)[1] = SCM_MAKINUM (bd_time->tm_min);
225 SCM_VELTS (result)[2] = SCM_MAKINUM (bd_time->tm_hour);
226 SCM_VELTS (result)[3] = SCM_MAKINUM (bd_time->tm_mday);
227 SCM_VELTS (result)[4] = SCM_MAKINUM (bd_time->tm_mon);
228 SCM_VELTS (result)[5] = SCM_MAKINUM (bd_time->tm_year);
229 SCM_VELTS (result)[6] = SCM_MAKINUM (bd_time->tm_wday);
230 SCM_VELTS (result)[7] = SCM_MAKINUM (bd_time->tm_yday);
231 SCM_VELTS (result)[8] = SCM_MAKINUM (bd_time->tm_isdst);
232 SCM_VELTS (result)[9] = SCM_MAKINUM (zoff);
233 SCM_VELTS (result)[10] = scm_makfrom0str (zname);
234 return result;
235}
236
237#if 0
238SCM_PROC (s_localtime, "localtime", 1, 1, 0, scm_localtime);
239SCM
240scm_localtime (SCM time, SCM zone)
241{
242 timet itime;
243 struct tm *lt, *utc;
244 SCM result;
245 int zoff;
246 char *zname = 0;
247 char *tzvar = "TZ";
248 char *oldtz = 0;
249 int err;
250
251 itime = scm_num2long (time, (char *) SCM_ARG1, s_localtime);
252 SCM_DEFER_INTS;
253 if (!SCM_UNBNDP (zone))
254 {
255 char *buf;
256
257 /* if zone was supplied, set the environment variable TZ temporarily. */
258 SCM_ASSERT (SCM_NIMP (zone) && SCM_STRINGP (zone), zone, SCM_ARG2,
259 s_localtime);
260 buf = malloc (SCM_LENGTH (zone) + 4);
261 if (buf == 0)
262 scm_memory_error (s_localtime);
263 oldtz = getenv (tzvar);
264 sprintf (buf, "%s=%s", tzvar, SCM_CHARS (zone));
265 putenv (buf);
266 tzset();
267 }
268 lt = localtime (&itime);
269 err = errno;
270 utc = gmtime (&itime);
271 if (utc == NULL)
272 err = errno;
273 if (lt)
274 {
275 /* must be copied before calling tzset again. */
276 char *ptr = tzname[ (lt->tm_isdst == 1) ? 1 : 0 ];
277
278 zname = scm_must_malloc (strlen (ptr) + 1, s_localtime);
279 strcpy (zname, ptr);
280 }
281 if (!SCM_UNBNDP (zone))
282 {
283 /* restore the old environment value of TZ. */
284 if (oldtz)
285 putenv (oldtz - 3);
286 else
287 putenv (tzvar);
288 tzset();
289 }
290 errno = err;
291 if (utc == NULL)
292 scm_syserror (s_localtime);
293 if (lt == NULL)
294 scm_syserror (s_localtime);
295
296 /* calculate timezone offset in seconds west of UTC. */
297 zoff = (utc->tm_hour - lt->tm_hour) * 3600 + (utc->tm_min - lt->tm_min) * 60
298 + utc->tm_sec - lt->tm_sec;
299 if (utc->tm_year < lt->tm_year)
300 zoff -= 24 * 60 * 60;
301 else if (utc->tm_year > lt->tm_year)
302 zoff += 24 * 60 * 60;
303 else if (utc->tm_yday < lt->tm_yday)
304 zoff -= 24 * 60 * 60;
305 else if (utc->tm_yday > lt->tm_yday)
306 zoff += 24 * 60 * 60;
307
308 result = filltime (lt, zoff, zname);
309 SCM_ALLOW_INTS;
310 return result;
311}
312#endif
313
314SCM_PROC (s_gmtime, "gmtime", 1, 0, 0, scm_gmtime);
315SCM
316scm_gmtime (SCM time)
317{
318 timet itime;
319 struct tm *bd_time;
320 SCM result;
321
322 itime = scm_num2long (time, (char *) SCM_ARG1, s_gmtime);
323 SCM_DEFER_INTS;
324 bd_time = gmtime (&itime);
325 if (bd_time == NULL)
326 scm_syserror (s_gmtime);
327 result = filltime (bd_time, 0, "GMT");
328 SCM_ALLOW_INTS;
329 return result;
330}
331
332#if 0
333SCM_PROC (s_mktime, "mktime", 1, 0, 0, scm_mktime);
334SCM
335scm_mktime (SCM sbd_time)
336{
337 timet itime;
338 struct tm lt, *utc;
339 SCM result;
340 int zoff;
341 char *zname;
342
343 SCM_ASSERT (SCM_VECTORP (sbd_time), sbd_time, SCM_ARG1, s_mktime);
344 SCM_ASSERT (SCM_INUMP (SCM_VELTS (sbd_time)[0])
345 && SCM_INUMP (SCM_VELTS (sbd_time)[1])
346 && SCM_INUMP (SCM_VELTS (sbd_time)[2])
347 && SCM_INUMP (SCM_VELTS (sbd_time)[3])
348 && SCM_INUMP (SCM_VELTS (sbd_time)[4])
349 && SCM_INUMP (SCM_VELTS (sbd_time)[5])
350 && SCM_INUMP (SCM_VELTS (sbd_time)[8]),
351 sbd_time, SCM_ARG1, s_mktime);
352 lt.tm_sec = SCM_INUM (SCM_VELTS (sbd_time)[0]);
353 lt.tm_min = SCM_INUM (SCM_VELTS (sbd_time)[1]);
354 lt.tm_hour = SCM_INUM (SCM_VELTS (sbd_time)[2]);
355 lt.tm_mday = SCM_INUM (SCM_VELTS (sbd_time)[3]);
356 lt.tm_mon = SCM_INUM (SCM_VELTS (sbd_time)[4]);
357 lt.tm_year = SCM_INUM (SCM_VELTS (sbd_time)[5]);
358 lt.tm_isdst = SCM_INUM (SCM_VELTS (sbd_time)[8]);
359
360 SCM_DEFER_INTS;
361 itime = mktime (&lt);
362 if (itime == -1)
363 scm_syserror (s_mktime);
364
365 /* timezone offset in seconds west of UTC. */
366 utc = gmtime (&itime);
367 zoff = (utc->tm_hour - lt.tm_hour) * 3600 + (utc->tm_min - lt.tm_min) * 60
368 + utc->tm_sec - lt.tm_sec;
369 if (utc->tm_year < lt.tm_year)
370 zoff -= 24 * 60 * 60;
371 else if (utc->tm_year > lt.tm_year)
372 zoff += 24 * 60 * 60;
373 else if (utc->tm_yday < lt.tm_yday)
374 zoff -= 24 * 60 * 60;
375 else if (utc->tm_yday > lt.tm_yday)
376 zoff += 24 * 60 * 60;
377
378 /* timezone name. */
379 zname = tzname[ (lt.tm_isdst == 1) ? 1 : 0 ];
380
381 result = scm_cons (scm_long2num ((long) itime),
382 filltime (&lt, zoff, zname));
383 SCM_ALLOW_INTS;
384 return result;
0f2d19dd 385}
19468eff 386#endif
0f2d19dd 387
19468eff
GH
388SCM_PROC (s_tzset, "tzset", 0, 0, 0, scm_tzset);
389SCM
390scm_tzset (void)
0f2d19dd 391{
19468eff
GH
392 tzset();
393 return SCM_UNSPECIFIED;
0f2d19dd
JB
394}
395
0f2d19dd
JB
396void
397scm_init_stime()
0f2d19dd
JB
398{
399 scm_sysintern("internal-time-units-per-second",
19468eff 400 scm_long2num((long)CLKTCK));
0f2d19dd
JB
401
402#ifdef HAVE_FTIME
403 if (!scm_your_base.time) ftime(&scm_your_base);
404#else
405 if (!scm_your_base) time(&scm_your_base);
406#endif
407
408 if (!scm_my_base) scm_my_base = mytime();
409
876c87ce 410 scm_add_feature ("current-time");
0f2d19dd
JB
411#include "stime.x"
412}
413