blob: 5406907d670638d79a111c1f5b764a452012e9a4 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum775f4da1993-01-09 17:18:52 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Time module */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000028#include "modsupport.h"
Guido van Rossumff4949e1992-08-05 19:58:53 +000029#include "ceval.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000030
31#include "sigtype.h"
32
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000033#include <signal.h>
34#include <setjmp.h>
35
Guido van Rossuma2b7f401993-01-04 09:09:59 +000036#ifdef BSD_TIME
37#define HAVE_GETTIMEOFDAY
Guido van Rossum0b0db8e1993-01-21 16:07:51 +000038#include "myselect.h" /* Implies <sys/types.h>, <sys/time.h>, <sys/param.h> */
Guido van Rossuma2b7f401993-01-04 09:09:59 +000039#endif
40
Guido van Rossum6d946f91992-08-14 13:49:30 +000041#ifdef macintosh
42#define NO_UNISTD
43#endif
44
Guido van Rossum2762f251992-03-27 17:22:13 +000045#ifndef NO_UNISTD
46#include <unistd.h>
47#endif
48
Guido van Rossum80c9d881991-04-16 08:47:51 +000049/* What happens here is not trivial.
50 The BSD_TIME code needs <sys/time.h> (for struct timeval).
51 The rest of the code needs only time_t, except some MS-DOS
52 code which needs clock_t as well.
53 Standard C says that time_t is defined in <time.h>, and
54 does not have <sys/types.h>; THINK C agrees (MS-DOS too?).
55 What's worse, in pure 4.3 BSD, older SunOS versions, and
56 probably everything derived from BSD, you can't #include
57 both <time.h> and <sys/time.h> in the same file, since
58 <sys/time.h> includes <time.h> without any protection,
59 and <time.h> contains a typedef, which can't be parsed twice!
60 So on traditional UNIX systems we include <sys/types.h>
61 and <sys/time.h> and hope this implies <time.h> and time_t,
62 while on other systems, including conforming Standard C
63 systems (where 'unix' can't be defined), we rely on <time.h>.
64 Still one problem: BSD_TIME won't work with strict Standard C...
65*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000066
Guido van Rossum80c9d881991-04-16 08:47:51 +000067#ifdef unix
68#include <sys/types.h>
69#include <sys/time.h> /* Implies <time.h> everywhere, as far as I know */
70#else /* !unix */
71#include <time.h>
72#endif /* !unix */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000073
Guido van Rossum234f9421993-06-17 12:35:49 +000074#ifdef SYSV
Guido van Rossumb376a4a1993-11-23 17:53:17 +000075#if defined(sun) && defined(__STDC__)
76/* Temporary hack for Solaris 2. */
77#define _timezone timezone
78#define _altzone altzone
79#define _daylight daylight
80#define _tzname tzname
81#endif
Guido van Rossum234f9421993-06-17 12:35:49 +000082/* Access timezone stuff */
83#ifdef OLDTZ /* ANSI prepends underscore to these */
84#define _timezone timezone /* seconds to be added to GMT */
85#define _altzone 0 /* _timezone if daylight saving time */
86#define _daylight 0 /* if zero, _altzone is not available*/
87#define _tzname tzname /* Name of timezone and altzone */
88#endif
89#ifdef NOALTTZ /* if system doesn't support alt tz */
90#undef _daylight
91#undef _altzone
92#define _daylight 0
93#define _altzone 0
94#endif
95#endif /* SYSV */
96
97/* Forward declarations */
98static void floatsleep PROTO((double));
99static long millitimer PROTO((void));
100
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000101/* Time methods */
102
103static object *
104time_time(self, args)
105 object *self;
106 object *args;
107{
Guido van Rossuma2b7f401993-01-04 09:09:59 +0000108#ifdef HAVE_GETTIMEOFDAY
109 struct timeval t;
110 struct timezone tz;
111 if (!getnoarg(args))
112 return NULL;
113 if (gettimeofday(&t, &tz) != 0) {
114 err_errno(IOError);
115 return NULL;
116 }
117 return newfloatobject(t.tv_sec*1.0 + t.tv_usec*0.000001);
118#else /* !HAVE_GETTIMEOFDAY */
Guido van Rossum6590d4a1991-04-04 10:49:03 +0000119 time_t secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000120 if (!getnoarg(args))
121 return NULL;
Guido van Rossum80c9d881991-04-16 08:47:51 +0000122 time(&secs);
Guido van Rossum00c567c1991-07-27 23:09:30 +0000123#ifdef macintosh
124/* The Mac epoch is 1904, while UNIX uses 1970; Python prefers 1970 */
125/* Moreover, the Mac returns local time. This we cannot fix... */
Guido van Rossum6590d4a1991-04-04 10:49:03 +0000126#define TIMEDIFF ((time_t) \
127 (((1970-1904)*365L + (1970-1904)/4) * 24 * 3600))
128 secs -= TIMEDIFF;
Guido van Rossum00c567c1991-07-27 23:09:30 +0000129#endif
Guido van Rossuma2b7f401993-01-04 09:09:59 +0000130 return newfloatobject((double)secs);
131#endif /* !HAVE_GETTIMEOFDAY */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132}
133
134static jmp_buf sleep_intr;
135
Guido van Rossum2762f251992-03-27 17:22:13 +0000136/* ARGSUSED */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000137static void
138sleep_catcher(sig)
Guido van Rossum2762f251992-03-27 17:22:13 +0000139 int sig; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000140{
141 longjmp(sleep_intr, 1);
142}
143
144static object *
145time_sleep(self, args)
146 object *self;
147 object *args;
148{
Guido van Rossum775f4da1993-01-09 17:18:52 +0000149 double secs;
Guido van Rossum2762f251992-03-27 17:22:13 +0000150 SIGTYPE (*sigsave)() = 0; /* Initialized to shut lint up */
Guido van Rossum775f4da1993-01-09 17:18:52 +0000151 if (!getargs(args, "d", &secs))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000152 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000153 BGN_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154 if (setjmp(sleep_intr)) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000155 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 signal(SIGINT, sigsave);
157 err_set(KeyboardInterrupt);
158 return NULL;
159 }
160 sigsave = signal(SIGINT, SIG_IGN);
161 if (sigsave != (SIGTYPE (*)()) SIG_IGN)
162 signal(SIGINT, sleep_catcher);
Guido van Rossum775f4da1993-01-09 17:18:52 +0000163 floatsleep(secs);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000164 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165 signal(SIGINT, sigsave);
166 INCREF(None);
167 return None;
168}
169
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000170#ifdef macintosh
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000171#define DO_MILLI
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000172#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173
174#ifdef AMOEBA
175#define DO_MILLI
176extern long sys_milli();
177#define millitimer sys_milli
178#endif /* AMOEBA */
179
Guido van Rossum426035c1991-02-19 12:27:35 +0000180#ifdef BSD_TIME
181#define DO_MILLI
182#endif /* BSD_TIME */
183
Guido van Rossume22e6441993-07-09 10:51:31 +0000184#ifdef MSDOS
Guido van Rossum80c9d881991-04-16 08:47:51 +0000185#define DO_MILLI
186#endif
187
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188#ifdef DO_MILLI
189
190static object *
191time_millisleep(self, args)
192 object *self;
193 object *args;
194{
195 long msecs;
196 SIGTYPE (*sigsave)();
197 if (!getlongarg(args, &msecs))
198 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000199 BGN_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000200 if (setjmp(sleep_intr)) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000201 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000202 signal(SIGINT, sigsave);
203 err_set(KeyboardInterrupt);
204 return NULL;
205 }
206 sigsave = signal(SIGINT, SIG_IGN);
207 if (sigsave != (SIGTYPE (*)()) SIG_IGN)
208 signal(SIGINT, sleep_catcher);
Guido van Rossum775f4da1993-01-09 17:18:52 +0000209 floatsleep(msecs / 1000.0);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000210 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000211 signal(SIGINT, sigsave);
212 INCREF(None);
213 return None;
214}
215
216static object *
217time_millitimer(self, args)
218 object *self;
219 object *args;
220{
221 long msecs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000222 if (!getnoarg(args))
223 return NULL;
224 msecs = millitimer();
225 return newintobject(msecs);
226}
227
228#endif /* DO_MILLI */
229
230
Guido van Rossum234f9421993-06-17 12:35:49 +0000231static object *
232time_convert(when, function)
233 time_t when;
234 struct tm * (*function) PROTO((time_t *));
235{
236 struct tm *p = function(&when);
237 return mkvalue("(iiiiiiiii)",
238 p->tm_year + 1900,
239 p->tm_mon + 1, /* Want January == 1 */
240 p->tm_mday,
241 p->tm_hour,
242 p->tm_min,
243 p->tm_sec,
244 (p->tm_wday + 6) % 7, /* Want Monday == 0 */
Guido van Rossum9e90a671993-06-24 11:10:19 +0000245 p->tm_yday + 1, /* Want January, 1 == 1 */
Guido van Rossum234f9421993-06-17 12:35:49 +0000246 p->tm_isdst);
247}
248
249static object *
250time_gmtime(self, args)
251 object *self;
252 object *args;
253{
254 double when;
255 if (!getargs(args, "d", &when))
256 return NULL;
257 return time_convert((time_t)when, gmtime);
258}
259
260static object *
261time_localtime(self, args)
262 object *self;
263 object *args;
264{
265 double when;
266 if (!getargs(args, "d", &when))
267 return NULL;
268 return time_convert((time_t)when, localtime);
269}
270
Guido van Rossum9e90a671993-06-24 11:10:19 +0000271static int
272gettmarg(args, p)
273 object *args;
274 struct tm *p;
275{
276 if (!getargs(args, "(iiiiiiiii)",
277 &p->tm_year,
278 &p->tm_mon,
279 &p->tm_mday,
280 &p->tm_hour,
281 &p->tm_min,
282 &p->tm_sec,
283 &p->tm_wday,
284 &p->tm_yday,
285 &p->tm_isdst))
286 return 0;
287 if (p->tm_year >= 1900)
288 p->tm_year -= 1900;
289 p->tm_mon--;
290 p->tm_wday = (p->tm_wday + 1) % 7;
291 p->tm_yday--;
292 return 1;
293}
294
295static object *
296time_asctime(self, args)
297 object *self;
298 object *args;
299{
300 struct tm buf;
301 char *p;
302 if (!gettmarg(args, &buf))
303 return NULL;
304 p = asctime(&buf);
305 if (p[24] == '\n')
306 p[24] = '\0';
307 return newstringobject(p);
308}
309
310static object *
311time_ctime(self, args)
312 object *self;
313 object *args;
314{
315 double dt;
316 time_t tt;
317 char *p;
318 if (!getargs(args, "d", &dt))
319 return NULL;
320 tt = dt;
321 p = ctime(&tt);
322 if (p[24] == '\n')
323 p[24] = '\0';
324 return newstringobject(p);
325}
326
Guido van Rossum234f9421993-06-17 12:35:49 +0000327/* Some very old systems may not have mktime(). Comment it out then! */
328
329static object *
330time_mktime(self, args)
331 object *self;
332 object *args;
333{
334 struct tm buf;
Guido van Rossum9e90a671993-06-24 11:10:19 +0000335 if (!gettmarg(args, &buf))
Guido van Rossum234f9421993-06-17 12:35:49 +0000336 return NULL;
Guido van Rossum234f9421993-06-17 12:35:49 +0000337 return newintobject((long)mktime(&buf));
338}
339
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000340static struct methodlist time_methods[] = {
341#ifdef DO_MILLI
342 {"millisleep", time_millisleep},
343 {"millitimer", time_millitimer},
344#endif /* DO_MILLI */
345 {"sleep", time_sleep},
346 {"time", time_time},
Guido van Rossum234f9421993-06-17 12:35:49 +0000347 {"gmtime", time_gmtime},
348 {"localtime", time_localtime},
Guido van Rossum9e90a671993-06-24 11:10:19 +0000349 {"asctime", time_asctime},
350 {"ctime", time_ctime},
Guido van Rossum234f9421993-06-17 12:35:49 +0000351 {"mktime", time_mktime},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000352 {NULL, NULL} /* sentinel */
353};
354
355
356void
357inittime()
358{
Guido van Rossum234f9421993-06-17 12:35:49 +0000359 object *m, *d;
360 m = initmodule("time", time_methods);
361 d = getmoduledict(m);
362#ifdef SYSV
363 tzset();
364 dictinsert(d, "timezone", newintobject((long)_timezone));
365 dictinsert(d, "altzone", newintobject((long)_altzone));
366 dictinsert(d, "daylight", newintobject((long)_daylight));
367 dictinsert(d, "tzname", mkvalue("(zz)", _tzname[0], _tzname[1]));
368#else /* !SYSV */
369 {
370#define YEAR ((time_t)((365 * 24 + 6) * 3600))
371 time_t t;
372 struct tm *p;
373 long winterzone, summerzone;
374 char wintername[10], summername[10];
375 t = (time((time_t *)0) / YEAR) * YEAR;
376 p = localtime(&t);
377 winterzone = -p->tm_gmtoff;
378 strncpy(wintername, p->tm_zone ? p->tm_zone : " ", 9);
379 wintername[9] = '\0';
380 t += YEAR/2;
381 p = localtime(&t);
382 summerzone = -p->tm_gmtoff;
383 strncpy(summername, p->tm_zone ? p->tm_zone : " ", 9);
384 summername[9] = '\0';
385 dictinsert(d, "timezone", newintobject(winterzone));
386 dictinsert(d, "altzone", newintobject(summerzone));
387 dictinsert(d, "daylight",
388 newintobject((long)(winterzone != summerzone)));
389 dictinsert(d, "tzname",
390 mkvalue("(zz)", wintername, summername));
391 }
392#endif /* !SYSV */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000393}
394
395
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000396#ifdef macintosh
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000397
398#define MacTicks (* (long *)0x16A)
399
Guido van Rossum80c9d881991-04-16 08:47:51 +0000400#ifdef THINK_C_3_0
Guido van Rossumff4949e1992-08-05 19:58:53 +0000401sleep(secs)
402 int secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000403{
404 register long deadline;
405
Guido van Rossumff4949e1992-08-05 19:58:53 +0000406 deadline = MacTicks + mecs * 60;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000407 while (MacTicks < deadline) {
408 if (intrcheck())
409 sleep_catcher(SIGINT);
410 }
411}
Guido van Rossum80c9d881991-04-16 08:47:51 +0000412#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000413
Guido van Rossum234f9421993-06-17 12:35:49 +0000414static void
Guido van Rossum775f4da1993-01-09 17:18:52 +0000415floatsleep(secs)
416 double secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000417{
418 register long deadline;
419
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000420 deadline = MacTicks + (long)(secs * 60.0);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000421 while (MacTicks < deadline) {
422 if (intrcheck())
423 sleep_catcher(SIGINT);
424 }
425}
426
Guido van Rossum234f9421993-06-17 12:35:49 +0000427static long
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000428millitimer()
429{
430 return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
431}
432
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000433#endif /* macintosh */
Guido van Rossum426035c1991-02-19 12:27:35 +0000434
435
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000436#ifdef unix
Guido van Rossum426035c1991-02-19 12:27:35 +0000437
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000438#ifdef BSD_TIME
Guido van Rossum6a1f54c1991-05-05 20:15:54 +0000439
Guido van Rossum234f9421993-06-17 12:35:49 +0000440static long
Guido van Rossum426035c1991-02-19 12:27:35 +0000441millitimer()
442{
443 struct timeval t;
444 struct timezone tz;
445 if (gettimeofday(&t, &tz) != 0)
446 return -1;
447 return t.tv_sec*1000 + t.tv_usec/1000;
Guido van Rossum426035c1991-02-19 12:27:35 +0000448}
449
Guido van Rossum234f9421993-06-17 12:35:49 +0000450static void
Guido van Rossum775f4da1993-01-09 17:18:52 +0000451floatsleep(secs)
452 double secs;
Guido van Rossum426035c1991-02-19 12:27:35 +0000453{
454 struct timeval t;
Guido van Rossum775f4da1993-01-09 17:18:52 +0000455 double frac;
456 extern double fmod PROTO((double, double));
457 extern double floor PROTO((double));
458 frac = fmod(secs, 1.0);
459 secs = floor(secs);
460 t.tv_sec = (long)secs;
461 t.tv_usec = (long)(frac*1000000.0);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000462 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
463}
464
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000465#else /* !BSD_TIME */
466
Guido van Rossum234f9421993-06-17 12:35:49 +0000467static void
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000468floatsleep(secs)
469 double secs;
470{
471 sleep((int)secs);
472}
473
474#endif /* !BSD_TIME */
475
476#endif /* unix */
Guido van Rossum426035c1991-02-19 12:27:35 +0000477
Guido van Rossum80c9d881991-04-16 08:47:51 +0000478
Guido van Rossume22e6441993-07-09 10:51:31 +0000479#ifdef MSDOS
Guido van Rossum80c9d881991-04-16 08:47:51 +0000480
481#ifndef CLOCKS_PER_SEC
482#define CLOCKS_PER_SEC 55 /* 54.945 msec per tick (18.2 HZ clock) */
483#endif
484
Guido van Rossum234f9421993-06-17 12:35:49 +0000485static void
Guido van Rossum775f4da1993-01-09 17:18:52 +0000486floatsleep(secs)
487 double secs;
Guido van Rossum80c9d881991-04-16 08:47:51 +0000488{
Guido van Rossum775f4da1993-01-09 17:18:52 +0000489 delay(long(secs/1000.0));
Guido van Rossum80c9d881991-04-16 08:47:51 +0000490}
491
Guido van Rossum234f9421993-06-17 12:35:49 +0000492static long
Guido van Rossum80c9d881991-04-16 08:47:51 +0000493millitimer()
494{
495 clock_t ticks;
496
497 ticks = clock(); /* ticks since program start */
Guido van Rossum775f4da1993-01-09 17:18:52 +0000498 return ticks * CLOCKS_PER_SEC;/* XXX shouldn't this be different? */
Guido van Rossum80c9d881991-04-16 08:47:51 +0000499}
500
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000501floatsleep(secs)
502 double secs;
503{
504 clock_t t= clock( );
505 while( (clock()-t)/CLOCKS_PER_SEC<secs )
506 ;
507}
Guido van Rossume22e6441993-07-09 10:51:31 +0000508
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000509#endif /* MSDOS */