blob: 097c4dabb289b8a67f45aa816ac0b027e59ee69c [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
75/* Access timezone stuff */
76#ifdef OLDTZ /* ANSI prepends underscore to these */
77#define _timezone timezone /* seconds to be added to GMT */
78#define _altzone 0 /* _timezone if daylight saving time */
79#define _daylight 0 /* if zero, _altzone is not available*/
80#define _tzname tzname /* Name of timezone and altzone */
81#endif
82#ifdef NOALTTZ /* if system doesn't support alt tz */
83#undef _daylight
84#undef _altzone
85#define _daylight 0
86#define _altzone 0
87#endif
88#endif /* SYSV */
89
90/* Forward declarations */
91static void floatsleep PROTO((double));
92static long millitimer PROTO((void));
93
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000094/* Time methods */
95
96static object *
97time_time(self, args)
98 object *self;
99 object *args;
100{
Guido van Rossuma2b7f401993-01-04 09:09:59 +0000101#ifdef HAVE_GETTIMEOFDAY
102 struct timeval t;
103 struct timezone tz;
104 if (!getnoarg(args))
105 return NULL;
106 if (gettimeofday(&t, &tz) != 0) {
107 err_errno(IOError);
108 return NULL;
109 }
110 return newfloatobject(t.tv_sec*1.0 + t.tv_usec*0.000001);
111#else /* !HAVE_GETTIMEOFDAY */
Guido van Rossum6590d4a1991-04-04 10:49:03 +0000112 time_t secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000113 if (!getnoarg(args))
114 return NULL;
Guido van Rossum80c9d881991-04-16 08:47:51 +0000115 time(&secs);
Guido van Rossum00c567c1991-07-27 23:09:30 +0000116#ifdef macintosh
117/* The Mac epoch is 1904, while UNIX uses 1970; Python prefers 1970 */
118/* Moreover, the Mac returns local time. This we cannot fix... */
Guido van Rossum6590d4a1991-04-04 10:49:03 +0000119#define TIMEDIFF ((time_t) \
120 (((1970-1904)*365L + (1970-1904)/4) * 24 * 3600))
121 secs -= TIMEDIFF;
Guido van Rossum00c567c1991-07-27 23:09:30 +0000122#endif
Guido van Rossuma2b7f401993-01-04 09:09:59 +0000123 return newfloatobject((double)secs);
124#endif /* !HAVE_GETTIMEOFDAY */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000125}
126
127static jmp_buf sleep_intr;
128
Guido van Rossum2762f251992-03-27 17:22:13 +0000129/* ARGSUSED */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130static void
131sleep_catcher(sig)
Guido van Rossum2762f251992-03-27 17:22:13 +0000132 int sig; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000133{
134 longjmp(sleep_intr, 1);
135}
136
137static object *
138time_sleep(self, args)
139 object *self;
140 object *args;
141{
Guido van Rossum775f4da1993-01-09 17:18:52 +0000142 double secs;
Guido van Rossum2762f251992-03-27 17:22:13 +0000143 SIGTYPE (*sigsave)() = 0; /* Initialized to shut lint up */
Guido van Rossum775f4da1993-01-09 17:18:52 +0000144 if (!getargs(args, "d", &secs))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000145 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000146 BGN_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000147 if (setjmp(sleep_intr)) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000148 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000149 signal(SIGINT, sigsave);
150 err_set(KeyboardInterrupt);
151 return NULL;
152 }
153 sigsave = signal(SIGINT, SIG_IGN);
154 if (sigsave != (SIGTYPE (*)()) SIG_IGN)
155 signal(SIGINT, sleep_catcher);
Guido van Rossum775f4da1993-01-09 17:18:52 +0000156 floatsleep(secs);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000157 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000158 signal(SIGINT, sigsave);
159 INCREF(None);
160 return None;
161}
162
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000163#ifdef macintosh
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000164#define DO_MILLI
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000165#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166
167#ifdef AMOEBA
168#define DO_MILLI
169extern long sys_milli();
170#define millitimer sys_milli
171#endif /* AMOEBA */
172
Guido van Rossum426035c1991-02-19 12:27:35 +0000173#ifdef BSD_TIME
174#define DO_MILLI
175#endif /* BSD_TIME */
176
Guido van Rossum80c9d881991-04-16 08:47:51 +0000177#ifdef TURBO_C
178#define DO_MILLI
179#endif
180
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000181#ifdef DO_MILLI
182
183static object *
184time_millisleep(self, args)
185 object *self;
186 object *args;
187{
188 long msecs;
189 SIGTYPE (*sigsave)();
190 if (!getlongarg(args, &msecs))
191 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000192 BGN_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000193 if (setjmp(sleep_intr)) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000194 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000195 signal(SIGINT, sigsave);
196 err_set(KeyboardInterrupt);
197 return NULL;
198 }
199 sigsave = signal(SIGINT, SIG_IGN);
200 if (sigsave != (SIGTYPE (*)()) SIG_IGN)
201 signal(SIGINT, sleep_catcher);
Guido van Rossum775f4da1993-01-09 17:18:52 +0000202 floatsleep(msecs / 1000.0);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000203 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204 signal(SIGINT, sigsave);
205 INCREF(None);
206 return None;
207}
208
209static object *
210time_millitimer(self, args)
211 object *self;
212 object *args;
213{
214 long msecs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000215 if (!getnoarg(args))
216 return NULL;
217 msecs = millitimer();
218 return newintobject(msecs);
219}
220
221#endif /* DO_MILLI */
222
223
Guido van Rossum234f9421993-06-17 12:35:49 +0000224static object *
225time_convert(when, function)
226 time_t when;
227 struct tm * (*function) PROTO((time_t *));
228{
229 struct tm *p = function(&when);
230 return mkvalue("(iiiiiiiii)",
231 p->tm_year + 1900,
232 p->tm_mon + 1, /* Want January == 1 */
233 p->tm_mday,
234 p->tm_hour,
235 p->tm_min,
236 p->tm_sec,
237 (p->tm_wday + 6) % 7, /* Want Monday == 0 */
Guido van Rossum9e90a671993-06-24 11:10:19 +0000238 p->tm_yday + 1, /* Want January, 1 == 1 */
Guido van Rossum234f9421993-06-17 12:35:49 +0000239 p->tm_isdst);
240}
241
242static object *
243time_gmtime(self, args)
244 object *self;
245 object *args;
246{
247 double when;
248 if (!getargs(args, "d", &when))
249 return NULL;
250 return time_convert((time_t)when, gmtime);
251}
252
253static object *
254time_localtime(self, args)
255 object *self;
256 object *args;
257{
258 double when;
259 if (!getargs(args, "d", &when))
260 return NULL;
261 return time_convert((time_t)when, localtime);
262}
263
Guido van Rossum9e90a671993-06-24 11:10:19 +0000264static int
265gettmarg(args, p)
266 object *args;
267 struct tm *p;
268{
269 if (!getargs(args, "(iiiiiiiii)",
270 &p->tm_year,
271 &p->tm_mon,
272 &p->tm_mday,
273 &p->tm_hour,
274 &p->tm_min,
275 &p->tm_sec,
276 &p->tm_wday,
277 &p->tm_yday,
278 &p->tm_isdst))
279 return 0;
280 if (p->tm_year >= 1900)
281 p->tm_year -= 1900;
282 p->tm_mon--;
283 p->tm_wday = (p->tm_wday + 1) % 7;
284 p->tm_yday--;
285 return 1;
286}
287
288static object *
289time_asctime(self, args)
290 object *self;
291 object *args;
292{
293 struct tm buf;
294 char *p;
295 if (!gettmarg(args, &buf))
296 return NULL;
297 p = asctime(&buf);
298 if (p[24] == '\n')
299 p[24] = '\0';
300 return newstringobject(p);
301}
302
303static object *
304time_ctime(self, args)
305 object *self;
306 object *args;
307{
308 double dt;
309 time_t tt;
310 char *p;
311 if (!getargs(args, "d", &dt))
312 return NULL;
313 tt = dt;
314 p = ctime(&tt);
315 if (p[24] == '\n')
316 p[24] = '\0';
317 return newstringobject(p);
318}
319
Guido van Rossum234f9421993-06-17 12:35:49 +0000320/* Some very old systems may not have mktime(). Comment it out then! */
321
322static object *
323time_mktime(self, args)
324 object *self;
325 object *args;
326{
327 struct tm buf;
Guido van Rossum9e90a671993-06-24 11:10:19 +0000328 if (!gettmarg(args, &buf))
Guido van Rossum234f9421993-06-17 12:35:49 +0000329 return NULL;
Guido van Rossum234f9421993-06-17 12:35:49 +0000330 return newintobject((long)mktime(&buf));
331}
332
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000333static struct methodlist time_methods[] = {
334#ifdef DO_MILLI
335 {"millisleep", time_millisleep},
336 {"millitimer", time_millitimer},
337#endif /* DO_MILLI */
338 {"sleep", time_sleep},
339 {"time", time_time},
Guido van Rossum234f9421993-06-17 12:35:49 +0000340 {"gmtime", time_gmtime},
341 {"localtime", time_localtime},
Guido van Rossum9e90a671993-06-24 11:10:19 +0000342 {"asctime", time_asctime},
343 {"ctime", time_ctime},
Guido van Rossum234f9421993-06-17 12:35:49 +0000344 {"mktime", time_mktime},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000345 {NULL, NULL} /* sentinel */
346};
347
348
349void
350inittime()
351{
Guido van Rossum234f9421993-06-17 12:35:49 +0000352 object *m, *d;
353 m = initmodule("time", time_methods);
354 d = getmoduledict(m);
355#ifdef SYSV
356 tzset();
357 dictinsert(d, "timezone", newintobject((long)_timezone));
358 dictinsert(d, "altzone", newintobject((long)_altzone));
359 dictinsert(d, "daylight", newintobject((long)_daylight));
360 dictinsert(d, "tzname", mkvalue("(zz)", _tzname[0], _tzname[1]));
361#else /* !SYSV */
362 {
363#define YEAR ((time_t)((365 * 24 + 6) * 3600))
364 time_t t;
365 struct tm *p;
366 long winterzone, summerzone;
367 char wintername[10], summername[10];
368 t = (time((time_t *)0) / YEAR) * YEAR;
369 p = localtime(&t);
370 winterzone = -p->tm_gmtoff;
371 strncpy(wintername, p->tm_zone ? p->tm_zone : " ", 9);
372 wintername[9] = '\0';
373 t += YEAR/2;
374 p = localtime(&t);
375 summerzone = -p->tm_gmtoff;
376 strncpy(summername, p->tm_zone ? p->tm_zone : " ", 9);
377 summername[9] = '\0';
378 dictinsert(d, "timezone", newintobject(winterzone));
379 dictinsert(d, "altzone", newintobject(summerzone));
380 dictinsert(d, "daylight",
381 newintobject((long)(winterzone != summerzone)));
382 dictinsert(d, "tzname",
383 mkvalue("(zz)", wintername, summername));
384 }
385#endif /* !SYSV */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000386}
387
388
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000389#ifdef macintosh
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000390
391#define MacTicks (* (long *)0x16A)
392
Guido van Rossum80c9d881991-04-16 08:47:51 +0000393#ifdef THINK_C_3_0
Guido van Rossumff4949e1992-08-05 19:58:53 +0000394sleep(secs)
395 int secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000396{
397 register long deadline;
398
Guido van Rossumff4949e1992-08-05 19:58:53 +0000399 deadline = MacTicks + mecs * 60;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000400 while (MacTicks < deadline) {
401 if (intrcheck())
402 sleep_catcher(SIGINT);
403 }
404}
Guido van Rossum80c9d881991-04-16 08:47:51 +0000405#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000406
Guido van Rossum234f9421993-06-17 12:35:49 +0000407static void
Guido van Rossum775f4da1993-01-09 17:18:52 +0000408floatsleep(secs)
409 double secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000410{
411 register long deadline;
412
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000413 deadline = MacTicks + (long)(secs * 60.0);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000414 while (MacTicks < deadline) {
415 if (intrcheck())
416 sleep_catcher(SIGINT);
417 }
418}
419
Guido van Rossum234f9421993-06-17 12:35:49 +0000420static long
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000421millitimer()
422{
423 return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
424}
425
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000426#endif /* macintosh */
Guido van Rossum426035c1991-02-19 12:27:35 +0000427
428
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000429#ifdef unix
Guido van Rossum426035c1991-02-19 12:27:35 +0000430
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000431#ifdef BSD_TIME
Guido van Rossum6a1f54c1991-05-05 20:15:54 +0000432
Guido van Rossum234f9421993-06-17 12:35:49 +0000433static long
Guido van Rossum426035c1991-02-19 12:27:35 +0000434millitimer()
435{
436 struct timeval t;
437 struct timezone tz;
438 if (gettimeofday(&t, &tz) != 0)
439 return -1;
440 return t.tv_sec*1000 + t.tv_usec/1000;
Guido van Rossum426035c1991-02-19 12:27:35 +0000441}
442
Guido van Rossum234f9421993-06-17 12:35:49 +0000443static void
Guido van Rossum775f4da1993-01-09 17:18:52 +0000444floatsleep(secs)
445 double secs;
Guido van Rossum426035c1991-02-19 12:27:35 +0000446{
447 struct timeval t;
Guido van Rossum775f4da1993-01-09 17:18:52 +0000448 double frac;
449 extern double fmod PROTO((double, double));
450 extern double floor PROTO((double));
451 frac = fmod(secs, 1.0);
452 secs = floor(secs);
453 t.tv_sec = (long)secs;
454 t.tv_usec = (long)(frac*1000000.0);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000455 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
456}
457
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000458#else /* !BSD_TIME */
459
Guido van Rossum234f9421993-06-17 12:35:49 +0000460static void
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000461floatsleep(secs)
462 double secs;
463{
464 sleep((int)secs);
465}
466
467#endif /* !BSD_TIME */
468
469#endif /* unix */
Guido van Rossum426035c1991-02-19 12:27:35 +0000470
Guido van Rossum80c9d881991-04-16 08:47:51 +0000471
472#ifdef TURBO_C /* Maybe also for MS-DOS? */
473
474#ifndef CLOCKS_PER_SEC
475#define CLOCKS_PER_SEC 55 /* 54.945 msec per tick (18.2 HZ clock) */
476#endif
477
Guido van Rossum234f9421993-06-17 12:35:49 +0000478static void
Guido van Rossum775f4da1993-01-09 17:18:52 +0000479floatsleep(secs)
480 double secs;
Guido van Rossum80c9d881991-04-16 08:47:51 +0000481{
Guido van Rossum775f4da1993-01-09 17:18:52 +0000482 delay(long(secs/1000.0));
Guido van Rossum80c9d881991-04-16 08:47:51 +0000483}
484
Guido van Rossum234f9421993-06-17 12:35:49 +0000485static long
Guido van Rossum80c9d881991-04-16 08:47:51 +0000486millitimer()
487{
488 clock_t ticks;
489
490 ticks = clock(); /* ticks since program start */
Guido van Rossum775f4da1993-01-09 17:18:52 +0000491 return ticks * CLOCKS_PER_SEC;/* XXX shouldn't this be different? */
Guido van Rossum80c9d881991-04-16 08:47:51 +0000492}
493
494#endif /* TURBO_C */