(py-indent-right, py-outdent-left): new commands, bound to C-c C-r and
[python/dscho.git] / Modules / timemodule.c
blobf7738354cd51bb5ed9068f0688a8a27f88bfcb00
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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 ******************************************************************/
25 /* Time module */
27 #include "allobjects.h"
28 #include "modsupport.h"
29 #include "ceval.h"
31 #ifdef macintosh
32 #include <time.h>
33 #else
34 #include <sys/types.h>
35 #endif
37 #ifdef QUICKWIN
38 #include <io.h>
39 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
45 #ifdef HAVE_SELECT
46 #include "myselect.h"
47 #else
48 #include "mytime.h"
49 #endif
51 #ifdef HAVE_FTIME
52 #include <sys/timeb.h>
53 #endif
55 #ifdef _M_IX86
56 #include <windows.h>
57 #define timezone _timezone
58 #define tzname _tzname
59 #define daylight _daylight
60 #define altzone _altzone
61 #endif
63 /* Forward declarations */
64 static int floatsleep PROTO((double));
65 static double floattime PROTO(());
67 static object *
68 time_time(self, args)
69 object *self;
70 object *args;
72 double secs;
73 if (!getnoarg(args))
74 return NULL;
75 secs = floattime();
76 if (secs == 0.0) {
77 err_errno(IOError);
78 return NULL;
80 return newfloatobject(secs);
83 #ifdef HAVE_CLOCK
85 #ifndef CLOCKS_PER_SEC
86 #define CLOCKS_PER_SEC 1000000
87 #endif
89 static object *
90 time_clock(self, args)
91 object *self;
92 object *args;
94 if (!getnoarg(args))
95 return NULL;
96 return newfloatobject(((double)clock()) / CLOCKS_PER_SEC);
98 #endif /* HAVE_CLOCK */
100 static object *
101 time_sleep(self, args)
102 object *self;
103 object *args;
105 double secs;
106 if (!getargs(args, "d", &secs))
107 return NULL;
108 BGN_SAVE
109 if (floatsleep(secs) != 0) {
110 RET_SAVE
111 return NULL;
113 END_SAVE
114 INCREF(None);
115 return None;
118 static object *
119 time_convert(when, function)
120 time_t when;
121 struct tm * (*function) PROTO((const time_t *));
123 struct tm *p = function(&when);
124 return mkvalue("(iiiiiiiii)",
125 p->tm_year + 1900,
126 p->tm_mon + 1, /* Want January == 1 */
127 p->tm_mday,
128 p->tm_hour,
129 p->tm_min,
130 p->tm_sec,
131 (p->tm_wday + 6) % 7, /* Want Monday == 0 */
132 p->tm_yday + 1, /* Want January, 1 == 1 */
133 p->tm_isdst);
136 static object *
137 time_gmtime(self, args)
138 object *self;
139 object *args;
141 double when;
142 if (!getargs(args, "d", &when))
143 return NULL;
144 return time_convert((time_t)when, gmtime);
147 static object *
148 time_localtime(self, args)
149 object *self;
150 object *args;
152 double when;
153 if (!getargs(args, "d", &when))
154 return NULL;
155 return time_convert((time_t)when, localtime);
158 static int
159 gettmarg(args, p)
160 object *args;
161 struct tm *p;
163 if (!getargs(args, "(iiiiiiiii)",
164 &p->tm_year,
165 &p->tm_mon,
166 &p->tm_mday,
167 &p->tm_hour,
168 &p->tm_min,
169 &p->tm_sec,
170 &p->tm_wday,
171 &p->tm_yday,
172 &p->tm_isdst))
173 return 0;
174 if (p->tm_year >= 1900)
175 p->tm_year -= 1900;
176 p->tm_mon--;
177 p->tm_wday = (p->tm_wday + 1) % 7;
178 p->tm_yday--;
179 return 1;
182 static object *
183 time_asctime(self, args)
184 object *self;
185 object *args;
187 struct tm buf;
188 char *p;
189 if (!gettmarg(args, &buf))
190 return NULL;
191 p = asctime(&buf);
192 if (p[24] == '\n')
193 p[24] = '\0';
194 return newstringobject(p);
197 static object *
198 time_ctime(self, args)
199 object *self;
200 object *args;
202 double dt;
203 time_t tt;
204 char *p;
205 if (!getargs(args, "d", &dt))
206 return NULL;
207 tt = dt;
208 p = ctime(&tt);
209 if (p[24] == '\n')
210 p[24] = '\0';
211 return newstringobject(p);
214 static object *
215 time_mktime(self, args)
216 object *self;
217 object *args;
219 struct tm buf;
220 if (!gettmarg(args, &buf))
221 return NULL;
222 return newintobject((long)mktime(&buf));
225 static struct methodlist time_methods[] = {
226 {"time", time_time},
227 #ifdef HAVE_CLOCK
228 {"clock", time_clock},
229 #endif
230 {"sleep", time_sleep},
231 {"gmtime", time_gmtime},
232 {"localtime", time_localtime},
233 {"asctime", time_asctime},
234 {"ctime", time_ctime},
235 {"mktime", time_mktime},
236 {NULL, NULL} /* sentinel */
239 static void
240 ins(d, name, v)
241 object *d;
242 char *name;
243 object *v;
245 if (v == NULL)
246 fatal("Can't initialize time module -- NULL value");
247 if (dictinsert(d, name, v) != 0)
248 fatal("Can't initialize time module -- dictinsert failed");
249 DECREF(v);
252 void
253 inittime()
255 object *m, *d, *v;
256 m = initmodule("time", time_methods);
257 d = getmoduledict(m);
258 #ifdef HAVE_TZNAME
259 tzset();
260 ins(d, "timezone", newintobject((long)timezone));
261 #ifdef HAVE_ALTZONE
262 ins(d, "altzone", newintobject((long)altzone));
263 #else
264 ins(d, "altzone", newintobject((long)timezone-3600));
265 #endif
266 ins(d, "daylight", newintobject((long)daylight));
267 ins(d, "tzname", mkvalue("(zz)", tzname[0], tzname[1]));
268 #else /* !HAVE_TZNAME */
269 #if HAVE_TM_ZONE
271 #define YEAR ((time_t)((365 * 24 + 6) * 3600))
272 time_t t;
273 struct tm *p;
274 long winterzone, summerzone;
275 char wintername[10], summername[10];
276 /* XXX This won't work on the southern hemisphere.
277 XXX Anybody got a better idea? */
278 t = (time((time_t *)0) / YEAR) * YEAR;
279 p = localtime(&t);
280 winterzone = -p->tm_gmtoff;
281 strncpy(wintername, p->tm_zone ? p->tm_zone : " ", 9);
282 wintername[9] = '\0';
283 t += YEAR/2;
284 p = localtime(&t);
285 summerzone = -p->tm_gmtoff;
286 strncpy(summername, p->tm_zone ? p->tm_zone : " ", 9);
287 summername[9] = '\0';
288 ins(d, "timezone", newintobject(winterzone));
289 ins(d, "altzone", newintobject(summerzone));
290 ins(d, "daylight", newintobject((long)(winterzone != summerzone)));
291 ins(d, "tzname", mkvalue("(zz)", wintername, summername));
293 #endif /* HAVE_TM_ZONE */
294 #endif /* !HAVE_TZNAME */
298 /* Implement floattime() for various platforms */
300 static double
301 floattime()
303 /* There are three ways to get the time:
304 (1) gettimeofday() -- resolution in microseconds
305 (2) ftime() -- resolution in milliseconds
306 (3) time() -- resolution in seconds
307 In all cases the return value is a float in seconds.
308 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
309 fail, so we fall back on ftime() or time().
310 Note: clock resolution does not imply clock accuracy! */
311 #ifdef HAVE_GETTIMEOFDAY
313 struct timeval t;
314 #ifdef GETTIMEOFDAY_NO_TZ
315 if (gettimeofday(&t) == 0)
316 return (double)t.tv_sec + t.tv_usec*0.000001;
317 #else /* !GETTIMEOFDAY_NO_TZ */
318 if (gettimeofday(&t, (struct timezone *)NULL) == 0)
319 return (double)t.tv_sec + t.tv_usec*0.000001;
320 #endif /* !GETTIMEOFDAY_NO_TZ */
322 #endif /* !HAVE_GETTIMEOFDAY */
324 #ifdef HAVE_FTIME
325 struct timeb t;
326 ftime(&t);
327 return (double)t.time + (double)t.millitm * (double)0.001;
328 #else /* !HAVE_FTIME */
329 time_t secs;
330 time(&secs);
331 return (double)secs;
332 #endif /* !HAVE_FTIME */
337 /* Implement floatsleep() for various platforms.
338 When interrupted (or when another error occurs), return -1 and
339 set an exception; else return 0. */
341 static int
342 #ifdef MPW
343 floatsleep(double secs)
344 #else
345 floatsleep(secs)
346 double secs;
347 #endif /* MPW */
349 #ifdef HAVE_SELECT
350 struct timeval t;
351 double frac;
352 extern double fmod PROTO((double, double));
353 extern double floor PROTO((double));
354 frac = fmod(secs, 1.0);
355 secs = floor(secs);
356 t.tv_sec = (long)secs;
357 t.tv_usec = (long)(frac*1000000.0);
358 if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
359 err_errno(IOError);
360 return -1;
362 #else /* !HAVE_SELECT */
363 #ifdef macintosh
364 #define MacTicks (* (long *)0x16A)
365 long deadline;
366 deadline = MacTicks + (long)(secs * 60.0);
367 while (MacTicks < deadline) {
368 if (sigcheck())
369 return -1;
371 #else /* !macintosh */
372 #ifdef MSDOS
373 struct timeb t1, t2;
374 double frac;
375 extern double fmod PROTO((double, double));
376 extern double floor PROTO((double));
377 if (secs <= 0.0)
378 return;
379 frac = fmod(secs, 1.0);
380 secs = floor(secs);
381 ftime(&t1);
382 t2.time = t1.time + (int)secs;
383 t2.millitm = t1.millitm + (int)(frac*1000.0);
384 while (t2.millitm >= 1000) {
385 t2.time++;
386 t2.millitm -= 1000;
388 for (;;) {
389 #ifdef QUICKWIN
390 _wyield();
391 #endif
392 if (sigcheck())
393 return -1;
394 ftime(&t1);
395 if (t1.time > t2.time ||
396 t1.time == t2.time && t1.millitm >= t2.millitm)
397 break;
399 #else /* !MSDOS */
400 #ifdef _M_IX86
401 /* XXX Can't interrupt this sleep */
402 Sleep((int)(secs*1000));
403 #else /* _M_IX86 */
404 /* XXX Can't interrupt this sleep */
405 sleep((int)secs);
406 #endif /* _M_IX86 */
407 #endif /* !MSDOS */
408 #endif /* !macintosh */
409 #endif /* !HAVE_SELECT */
410 return 0;