1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
27 #include "allobjects.h"
28 #include "modsupport.h"
35 #include <sys/types.h>
53 #include <sys/timeb.h>
56 /* Forward declarations */
57 static void floatsleep
PROTO((double));
58 static double floattime
PROTO(());
73 return newfloatobject(secs
);
78 #ifndef CLOCKS_PER_SEC
79 #define CLOCKS_PER_SEC 1000000
83 time_clock(self
, args
)
89 return newfloatobject(((double)clock()) / CLOCKS_PER_SEC
);
91 #endif /* HAVE_CLOCK */
94 static jmp_buf sleep_intr
;
99 int sig
; /* Not used but required by interface */
101 longjmp(sleep_intr
, 1);
106 time_sleep(self
, args
)
112 /* We must set the signal handler *after* calling setjmp, to
113 avoid a race condition. Unfortunately some compilers put
114 the sigsave variable in a register. Sometimes auto is
115 enough, sometimes static is needed to avoid this (Microsoft
122 RETSIGTYPE (*sigsave
)() = 0; /* Initialized to shut lint up */
124 if (!getargs(args
, "d", &secs
))
128 if (setjmp(sleep_intr
)) {
130 signal(SIGINT
, sigsave
);
131 err_set(KeyboardInterrupt
);
134 sigsave
= signal(SIGINT
, SIG_IGN
);
135 if (sigsave
!= (RETSIGTYPE (*)()) SIG_IGN
)
136 signal(SIGINT
, sleep_catcher
);
141 signal(SIGINT
, sigsave
);
148 time_convert(when
, function
)
150 struct tm
* (*function
) PROTO((time_t *));
152 struct tm
*p
= function(&when
);
153 return mkvalue("(iiiiiiiii)",
155 p
->tm_mon
+ 1, /* Want January == 1 */
160 (p
->tm_wday
+ 6) % 7, /* Want Monday == 0 */
161 p
->tm_yday
+ 1, /* Want January, 1 == 1 */
166 time_gmtime(self
, args
)
171 if (!getargs(args
, "d", &when
))
173 return time_convert((time_t)when
, gmtime
);
177 time_localtime(self
, args
)
182 if (!getargs(args
, "d", &when
))
184 return time_convert((time_t)when
, localtime
);
192 if (!getargs(args
, "(iiiiiiiii)",
203 if (p
->tm_year
>= 1900)
206 p
->tm_wday
= (p
->tm_wday
+ 1) % 7;
212 time_asctime(self
, args
)
218 if (!gettmarg(args
, &buf
))
223 return newstringobject(p
);
227 time_ctime(self
, args
)
234 if (!getargs(args
, "d", &dt
))
240 return newstringobject(p
);
244 time_mktime(self
, args
)
249 if (!gettmarg(args
, &buf
))
251 return newintobject((long)mktime(&buf
));
254 static struct methodlist time_methods
[] = {
257 {"clock", time_clock
},
259 {"sleep", time_sleep
},
260 {"gmtime", time_gmtime
},
261 {"localtime", time_localtime
},
262 {"asctime", time_asctime
},
263 {"ctime", time_ctime
},
264 {"mktime", time_mktime
},
265 {NULL
, NULL
} /* sentinel */
272 m
= initmodule("time", time_methods
);
273 d
= getmoduledict(m
);
276 dictinsert(d
, "timezone", newintobject((long)timezone
));
278 dictinsert(d
, "altzone", newintobject((long)altzone
));
280 dictinsert(d
, "altzone", newintobject((long)timezone
-3600));
282 dictinsert(d
, "daylight", newintobject((long)daylight
));
283 dictinsert(d
, "tzname", mkvalue("(zz)", tzname
[0], tzname
[1]));
284 #else /* !HAVE_TZNAME */
287 #define YEAR ((time_t)((365 * 24 + 6) * 3600))
290 long winterzone
, summerzone
;
291 char wintername
[10], summername
[10];
292 /* XXX This won't work on the southern hemisphere.
293 XXX Anybody got a better idea? */
294 t
= (time((time_t *)0) / YEAR
) * YEAR
;
296 winterzone
= -p
->tm_gmtoff
;
297 strncpy(wintername
, p
->tm_zone
? p
->tm_zone
: " ", 9);
298 wintername
[9] = '\0';
301 summerzone
= -p
->tm_gmtoff
;
302 strncpy(summername
, p
->tm_zone
? p
->tm_zone
: " ", 9);
303 summername
[9] = '\0';
304 dictinsert(d
, "timezone", newintobject(winterzone
));
305 dictinsert(d
, "altzone", newintobject(summerzone
));
306 dictinsert(d
, "daylight",
307 newintobject((long)(winterzone
!= summerzone
)));
308 dictinsert(d
, "tzname",
309 mkvalue("(zz)", wintername
, summername
));
311 #endif /* HAVE_TM_ZONE */
312 #endif /* !HAVE_TZNAME */
316 /* Implement floattime() for various platforms */
321 /* There are three ways to get the time:
322 (1) gettimeofday() -- resolution in microseconds
323 (2) ftime() -- resolution in milliseconds
324 (3) time() -- resolution in seconds
325 In all cases the return value is a float in seconds.
326 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
327 fail, so we fall back on ftime() or time().
328 Note: clock resolution does not imply clock accuracy! */
329 #ifdef HAVE_GETTIMEOFDAY
332 if (gettimeofday(&t
, (struct timezone
*)NULL
) == 0)
333 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
335 #endif /* !HAVE_GETTIMEOFDAY */
340 return (double)t
.time
+ t
.millitm
*0.001;
341 #else /* !HAVE_FTIME */
345 #endif /* !HAVE_FTIME */
350 /* Implement floatsleep() for various platforms */
360 extern double fmod
PROTO((double, double));
361 extern double floor
PROTO((double));
362 frac
= fmod(secs
, 1.0);
364 t
.tv_sec
= (long)secs
;
365 t
.tv_usec
= (long)(frac
*1000000.0);
366 (void) select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
367 #else /* !HAVE_SELECT */
369 #define MacTicks (* (long *)0x16A)
371 deadline
= MacTicks
+ (long)(secs
* 60.0);
372 while (MacTicks
< deadline
) {
374 sleep_catcher(SIGINT
);
376 #else /* !macintosh */
380 extern double fmod
PROTO((double, double));
381 extern double floor
PROTO((double));
384 frac
= fmod(secs
, 1.0);
387 t2
.time
= t1
.time
+ (int)secs
;
388 t2
.millitm
= t1
.millitm
+ (int)(frac
*1000.0);
389 while (t2
.millitm
>= 1000) {
398 if (t1
.time
> t2
.time
||
399 t1
.time
== t2
.time
&& t1
.millitm
>= t2
.millitm
)
405 #endif /* !macintosh */
406 #endif /* !HAVE_SELECT */