This commit was manufactured by cvs2svn to create tag 'r22a4-fork'.
[python/dscho.git] / Modules / timemodule.c
blob2834738b87c8bd87e93871cfbf8040df32d73d16
2 /* Time module */
4 #include "Python.h"
6 #include <ctype.h>
8 #ifdef macintosh
9 #include <time.h>
10 #include <OSUtils.h>
11 #ifdef USE_GUSI211
12 /* GUSI, the I/O library which has the time() function and such uses the
13 ** Mac epoch of 1904. MSL, the C library which has localtime() and so uses
14 ** the ANSI epoch of 1900.
16 #define GUSI_TO_MSL_EPOCH (4*365*24*60*60)
17 #endif /* USE_GUSI2 */
18 #else
19 #ifndef RISCOS
20 #include <sys/types.h>
21 #endif /* RISCOS */
22 #endif
24 #ifdef QUICKWIN
25 #include <io.h>
26 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
32 #ifdef HAVE_FTIME
33 #include <sys/timeb.h>
34 #if !defined(MS_WINDOWS) && !defined(PYOS_OS2)
35 extern int ftime(struct timeb *);
36 #endif /* MS_WINDOWS */
37 #endif /* HAVE_FTIME */
39 #if defined(__WATCOMC__) && !defined(__QNX__)
40 #include <i86.h>
41 #else
42 #ifdef MS_WINDOWS
43 #include <windows.h>
44 #if defined(MS_WIN16) || defined(__BORLANDC__)
45 /* These overrides not needed for Win32 */
46 #define timezone _timezone
47 #define tzname _tzname
48 #define daylight _daylight
49 #endif /* MS_WIN16 || __BORLANDC__ */
50 #ifdef MS_WIN16
51 #define altzone _altzone
52 #endif /* MS_WIN16 */
53 #endif /* MS_WINDOWS */
54 #endif /* !__WATCOMC__ || __QNX__ */
56 #if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(__BORLANDC__)
57 /* Win32 has better clock replacement
58 XXX Win64 does not yet, but might when the platform matures. */
59 #include <largeint.h>
60 #undef HAVE_CLOCK /* We have our own version down below */
61 #endif /* MS_WIN32 && !MS_WIN64 */
63 #if defined(PYCC_VACPP)
64 #include <sys/time.h>
65 #endif
67 #ifdef __BEOS__
68 #include <time.h>
69 /* For bigtime_t, snooze(). - [cjh] */
70 #include <support/SupportDefs.h>
71 #include <kernel/OS.h>
72 #endif
74 /* Forward declarations */
75 static int floatsleep(double);
76 static double floattime(void);
78 /* For Y2K check */
79 static PyObject *moddict;
81 #ifdef macintosh
82 /* Our own timezone. We have enough information to deduce whether
83 ** DST is on currently, but unfortunately we cannot put it to good
84 ** use because we don't know the rules (and that is needed to have
85 ** localtime() return correct tm_isdst values for times other than
86 ** the current time. So, we cop out and only tell the user the current
87 ** timezone.
89 static long timezone;
91 static void
92 initmactimezone(void)
94 MachineLocation loc;
95 long delta;
97 ReadLocation(&loc);
99 if (loc.latitude == 0 && loc.longitude == 0 && loc.u.gmtDelta == 0)
100 return;
102 delta = loc.u.gmtDelta & 0x00FFFFFF;
104 if (delta & 0x00800000)
105 delta |= 0xFF000000;
107 timezone = -delta;
109 #endif /* macintosh */
112 static PyObject *
113 time_time(PyObject *self, PyObject *args)
115 double secs;
116 if (!PyArg_ParseTuple(args, ":time"))
117 return NULL;
118 secs = floattime();
119 if (secs == 0.0) {
120 PyErr_SetFromErrno(PyExc_IOError);
121 return NULL;
123 return PyFloat_FromDouble(secs);
126 static char time_doc[] =
127 "time() -> floating point number\n\
129 Return the current time in seconds since the Epoch.\n\
130 Fractions of a second may be present if the system clock provides them.";
132 #ifdef HAVE_CLOCK
134 #ifndef CLOCKS_PER_SEC
135 #ifdef CLK_TCK
136 #define CLOCKS_PER_SEC CLK_TCK
137 #else
138 #define CLOCKS_PER_SEC 1000000
139 #endif
140 #endif
142 static PyObject *
143 time_clock(PyObject *self, PyObject *args)
145 if (!PyArg_ParseTuple(args, ":clock"))
146 return NULL;
147 return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC);
149 #endif /* HAVE_CLOCK */
151 #if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(__BORLANDC__)
152 /* Due to Mark Hammond */
153 static PyObject *
154 time_clock(PyObject *self, PyObject *args)
156 static LARGE_INTEGER ctrStart;
157 static LARGE_INTEGER divisor = {0,0};
158 LARGE_INTEGER now, diff, rem;
160 if (!PyArg_ParseTuple(args, ":clock"))
161 return NULL;
163 if (LargeIntegerEqualToZero(divisor)) {
164 QueryPerformanceCounter(&ctrStart);
165 if (!QueryPerformanceFrequency(&divisor) ||
166 LargeIntegerEqualToZero(divisor)) {
167 /* Unlikely to happen -
168 this works on all intel machines at least!
169 Revert to clock() */
170 return PyFloat_FromDouble(clock());
173 QueryPerformanceCounter(&now);
174 diff = LargeIntegerSubtract(now, ctrStart);
175 diff = LargeIntegerDivide(diff, divisor, &rem);
176 /* XXX - we assume both divide results fit in 32 bits. This is
177 true on Intels. First person who can afford a machine that
178 doesnt deserves to fix it :-)
180 return PyFloat_FromDouble((double)diff.LowPart +
181 ((double)rem.LowPart / (double)divisor.LowPart));
184 #define HAVE_CLOCK /* So it gets included in the methods */
185 #endif /* MS_WIN32 && !MS_WIN64 */
187 #ifdef HAVE_CLOCK
188 static char clock_doc[] =
189 "clock() -> floating point number\n\
191 Return the CPU time or real time since the start of the process or since\n\
192 the first call to clock(). This has as much precision as the system records.";
193 #endif
195 static PyObject *
196 time_sleep(PyObject *self, PyObject *args)
198 double secs;
199 if (!PyArg_ParseTuple(args, "d:sleep", &secs))
200 return NULL;
201 if (floatsleep(secs) != 0)
202 return NULL;
203 Py_INCREF(Py_None);
204 return Py_None;
207 static char sleep_doc[] =
208 "sleep(seconds)\n\
210 Delay execution for a given number of seconds. The argument may be\n\
211 a floating point number for subsecond precision.";
213 static PyObject *
214 tmtotuple(struct tm *p)
216 return Py_BuildValue("(iiiiiiiii)",
217 p->tm_year + 1900,
218 p->tm_mon + 1, /* Want January == 1 */
219 p->tm_mday,
220 p->tm_hour,
221 p->tm_min,
222 p->tm_sec,
223 (p->tm_wday + 6) % 7, /* Want Monday == 0 */
224 p->tm_yday + 1, /* Want January, 1 == 1 */
225 p->tm_isdst);
228 static PyObject *
229 time_convert(time_t when, struct tm * (*function)(const time_t *))
231 struct tm *p;
232 errno = 0;
233 #if defined(macintosh) && defined(USE_GUSI204)
234 when = when + GUSI_TO_MSL_EPOCH;
235 #endif
236 p = function(&when);
237 if (p == NULL) {
238 #ifdef EINVAL
239 if (errno == 0)
240 errno = EINVAL;
241 #endif
242 return PyErr_SetFromErrno(PyExc_IOError);
244 return tmtotuple(p);
247 static PyObject *
248 time_gmtime(PyObject *self, PyObject *args)
250 double when;
251 if (PyTuple_Size(args) == 0)
252 when = floattime();
253 if (!PyArg_ParseTuple(args, "|d:gmtime", &when))
254 return NULL;
255 return time_convert((time_t)when, gmtime);
258 static char gmtime_doc[] =
259 "gmtime([seconds]) -> tuple\n\
261 Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\
262 GMT). When 'seconds' is not passed in, convert the current time instead.";
264 static PyObject *
265 time_localtime(PyObject *self, PyObject *args)
267 double when;
268 if (PyTuple_Size(args) == 0)
269 when = floattime();
270 if (!PyArg_ParseTuple(args, "|d:localtime", &when))
271 return NULL;
272 return time_convert((time_t)when, localtime);
275 static char localtime_doc[] =
276 "localtime([seconds]) -> tuple\n\
277 Convert seconds since the Epoch to a time tuple expressing local time.\n\
278 When 'seconds' is not passed in, convert the current time instead.";
280 static int
281 gettmarg(PyObject *args, struct tm *p)
283 int y;
284 memset((void *) p, '\0', sizeof(struct tm));
286 if (!PyArg_Parse(args, "(iiiiiiiii)",
288 &p->tm_mon,
289 &p->tm_mday,
290 &p->tm_hour,
291 &p->tm_min,
292 &p->tm_sec,
293 &p->tm_wday,
294 &p->tm_yday,
295 &p->tm_isdst))
296 return 0;
297 if (y < 1900) {
298 PyObject *accept = PyDict_GetItemString(moddict,
299 "accept2dyear");
300 if (accept == NULL || !PyInt_Check(accept) ||
301 PyInt_AsLong(accept) == 0) {
302 PyErr_SetString(PyExc_ValueError,
303 "year >= 1900 required");
304 return 0;
306 if (69 <= y && y <= 99)
307 y += 1900;
308 else if (0 <= y && y <= 68)
309 y += 2000;
310 else {
311 PyErr_SetString(PyExc_ValueError,
312 "year out of range");
313 return 0;
316 p->tm_year = y - 1900;
317 p->tm_mon--;
318 p->tm_wday = (p->tm_wday + 1) % 7;
319 p->tm_yday--;
320 return 1;
323 #ifdef HAVE_STRFTIME
324 static PyObject *
325 time_strftime(PyObject *self, PyObject *args)
327 PyObject *tup = NULL;
328 struct tm buf;
329 const char *fmt;
330 size_t fmtlen, buflen;
331 char *outbuf = 0;
332 size_t i;
334 memset((void *) &buf, '\0', sizeof(buf));
336 if (!PyArg_ParseTuple(args, "s|O:strftime", &fmt, &tup))
337 return NULL;
339 if (tup == NULL) {
340 time_t tt = time(NULL);
341 buf = *localtime(&tt);
342 } else if (!gettmarg(tup, &buf))
343 return NULL;
345 fmtlen = strlen(fmt);
347 /* I hate these functions that presume you know how big the output
348 * will be ahead of time...
350 for (i = 1024; ; i += i) {
351 outbuf = malloc(i);
352 if (outbuf == NULL) {
353 return PyErr_NoMemory();
355 buflen = strftime(outbuf, i, fmt, &buf);
356 if (buflen > 0 || i >= 256 * fmtlen) {
357 /* If the buffer is 256 times as long as the format,
358 it's probably not failing for lack of room!
359 More likely, the format yields an empty result,
360 e.g. an empty format, or %Z when the timezone
361 is unknown. */
362 PyObject *ret;
363 ret = PyString_FromStringAndSize(outbuf, buflen);
364 free(outbuf);
365 return ret;
367 free(outbuf);
371 static char strftime_doc[] =
372 "strftime(format[, tuple]) -> string\n\
374 Convert a time tuple to a string according to a format specification.\n\
375 See the library reference manual for formatting codes. When the time tuple\n\
376 is not present, current time as returned by localtime() is used.";
377 #endif /* HAVE_STRFTIME */
379 #ifdef HAVE_STRPTIME
381 #if 0
382 /* Enable this if it's not declared in <time.h> */
383 extern char *strptime(const char *, const char *, struct tm *);
384 #endif
386 static PyObject *
387 time_strptime(PyObject *self, PyObject *args)
389 struct tm tm;
390 char *fmt = "%a %b %d %H:%M:%S %Y";
391 char *buf;
392 char *s;
394 if (!PyArg_ParseTuple(args, "s|s:strptime", &buf, &fmt))
395 return NULL;
396 memset((void *) &tm, '\0', sizeof(tm));
397 s = strptime(buf, fmt, &tm);
398 if (s == NULL) {
399 PyErr_SetString(PyExc_ValueError, "format mismatch");
400 return NULL;
402 while (*s && isspace(Py_CHARMASK(*s)))
403 s++;
404 if (*s) {
405 PyErr_Format(PyExc_ValueError,
406 "unconverted data remains: '%.400s'", s);
407 return NULL;
409 return tmtotuple(&tm);
412 static char strptime_doc[] =
413 "strptime(string, format) -> tuple\n\
414 Parse a string to a time tuple according to a format specification.\n\
415 See the library reference manual for formatting codes (same as strftime()).";
416 #endif /* HAVE_STRPTIME */
418 static PyObject *
419 time_asctime(PyObject *self, PyObject *args)
421 PyObject *tup = NULL;
422 struct tm buf;
423 char *p;
424 if (!PyArg_ParseTuple(args, "|O:asctime", &tup))
425 return NULL;
426 if (tup == NULL) {
427 time_t tt = time(NULL);
428 buf = *localtime(&tt);
429 } else if (!gettmarg(tup, &buf))
430 return NULL;
431 p = asctime(&buf);
432 if (p[24] == '\n')
433 p[24] = '\0';
434 return PyString_FromString(p);
437 static char asctime_doc[] =
438 "asctime([tuple]) -> string\n\
440 Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.\n\
441 When the time tuple is not present, current time as returned by localtime()\n\
442 is used.";
444 static PyObject *
445 time_ctime(PyObject *self, PyObject *args)
447 double dt;
448 time_t tt;
449 char *p;
451 if (PyTuple_Size(args) == 0)
452 tt = time(NULL);
453 else {
454 if (!PyArg_ParseTuple(args, "|d:ctime", &dt))
455 return NULL;
456 tt = (time_t)dt;
458 #if defined(macintosh) && defined(USE_GUSI204)
459 tt = tt + GUSI_TO_MSL_EPOCH;
460 #endif
461 p = ctime(&tt);
462 if (p == NULL) {
463 PyErr_SetString(PyExc_ValueError, "unconvertible time");
464 return NULL;
466 if (p[24] == '\n')
467 p[24] = '\0';
468 return PyString_FromString(p);
471 static char ctime_doc[] =
472 "ctime(seconds) -> string\n\
474 Convert a time in seconds since the Epoch to a string in local time.\n\
475 This is equivalent to asctime(localtime(seconds)). When the time tuple is\n\
476 not present, current time as returned by localtime() is used.";
478 #ifdef HAVE_MKTIME
479 static PyObject *
480 time_mktime(PyObject *self, PyObject *args)
482 PyObject *tup;
483 struct tm buf;
484 time_t tt;
485 if (!PyArg_ParseTuple(args, "O:mktime", &tup))
486 return NULL;
487 tt = time(&tt);
488 buf = *localtime(&tt);
489 if (!gettmarg(tup, &buf))
490 return NULL;
491 tt = mktime(&buf);
492 if (tt == (time_t)(-1)) {
493 PyErr_SetString(PyExc_OverflowError,
494 "mktime argument out of range");
495 return NULL;
497 #if defined(macintosh) && defined(USE_GUSI211)
498 tt = tt - GUSI_TO_MSL_EPOCH;
499 #endif
500 return PyFloat_FromDouble((double)tt);
503 static char mktime_doc[] =
504 "mktime(tuple) -> floating point number\n\
506 Convert a time tuple in local time to seconds since the Epoch.";
507 #endif /* HAVE_MKTIME */
509 static PyMethodDef time_methods[] = {
510 {"time", time_time, METH_VARARGS, time_doc},
511 #ifdef HAVE_CLOCK
512 {"clock", time_clock, METH_VARARGS, clock_doc},
513 #endif
514 {"sleep", time_sleep, METH_VARARGS, sleep_doc},
515 {"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
516 {"localtime", time_localtime, METH_VARARGS, localtime_doc},
517 {"asctime", time_asctime, METH_VARARGS, asctime_doc},
518 {"ctime", time_ctime, METH_VARARGS, ctime_doc},
519 #ifdef HAVE_MKTIME
520 {"mktime", time_mktime, METH_VARARGS, mktime_doc},
521 #endif
522 #ifdef HAVE_STRFTIME
523 {"strftime", time_strftime, METH_VARARGS, strftime_doc},
524 #endif
525 #ifdef HAVE_STRPTIME
526 {"strptime", time_strptime, METH_VARARGS, strptime_doc},
527 #endif
528 {NULL, NULL} /* sentinel */
531 static void
532 ins(PyObject *d, char *name, PyObject *v)
534 /* Don't worry too much about errors, they'll be caught by the
535 * caller of inittime().
537 if (v)
538 PyDict_SetItemString(d, name, v);
539 Py_XDECREF(v);
543 static char module_doc[] =
544 "This module provides various functions to manipulate time values.\n\
546 There are two standard representations of time. One is the number\n\
547 of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
548 or a floating point number (to represent fractions of seconds).\n\
549 The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
550 The actual value can be retrieved by calling gmtime(0).\n\
552 The other representation is a tuple of 9 integers giving local time.\n\
553 The tuple items are:\n\
554 year (four digits, e.g. 1998)\n\
555 month (1-12)\n\
556 day (1-31)\n\
557 hours (0-23)\n\
558 minutes (0-59)\n\
559 seconds (0-59)\n\
560 weekday (0-6, Monday is 0)\n\
561 Julian day (day in the year, 1-366)\n\
562 DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
563 If the DST flag is 0, the time is given in the regular time zone;\n\
564 if it is 1, the time is given in the DST time zone;\n\
565 if it is -1, mktime() should guess based on the date and time.\n\
567 Variables:\n\
569 timezone -- difference in seconds between UTC and local standard time\n\
570 altzone -- difference in seconds between UTC and local DST time\n\
571 daylight -- whether local time should reflect DST\n\
572 tzname -- tuple of (standard time zone name, DST time zone name)\n\
574 Functions:\n\
576 time() -- return current time in seconds since the Epoch as a float\n\
577 clock() -- return CPU time since process start as a float\n\
578 sleep() -- delay for a number of seconds given as a float\n\
579 gmtime() -- convert seconds since Epoch to UTC tuple\n\
580 localtime() -- convert seconds since Epoch to local time tuple\n\
581 asctime() -- convert time tuple to string\n\
582 ctime() -- convert time in seconds to string\n\
583 mktime() -- convert local time tuple to seconds since Epoch\n\
584 strftime() -- convert time tuple to string according to format specification\n\
585 strptime() -- parse string to time tuple according to format specification\n\
589 DL_EXPORT(void)
590 inittime(void)
592 PyObject *m, *d;
593 char *p;
594 m = Py_InitModule3("time", time_methods, module_doc);
595 d = PyModule_GetDict(m);
596 /* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
597 p = Py_GETENV("PYTHONY2K");
598 ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p)));
599 /* Squirrel away the module's dictionary for the y2k check */
600 Py_INCREF(d);
601 moddict = d;
602 #if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__)
603 tzset();
604 #ifdef PYOS_OS2
605 ins(d, "timezone", PyInt_FromLong((long)_timezone));
606 #else /* !PYOS_OS2 */
607 ins(d, "timezone", PyInt_FromLong((long)timezone));
608 #endif /* PYOS_OS2 */
609 #ifdef HAVE_ALTZONE
610 ins(d, "altzone", PyInt_FromLong((long)altzone));
611 #else
612 #ifdef PYOS_OS2
613 ins(d, "altzone", PyInt_FromLong((long)_timezone-3600));
614 #else /* !PYOS_OS2 */
615 ins(d, "altzone", PyInt_FromLong((long)timezone-3600));
616 #endif /* PYOS_OS2 */
617 #endif
618 ins(d, "daylight", PyInt_FromLong((long)daylight));
619 ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1]));
620 #else /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
621 #ifdef HAVE_TM_ZONE
623 #define YEAR ((time_t)((365 * 24 + 6) * 3600))
624 time_t t;
625 struct tm *p;
626 long janzone, julyzone;
627 char janname[10], julyname[10];
628 t = (time((time_t *)0) / YEAR) * YEAR;
629 p = localtime(&t);
630 janzone = -p->tm_gmtoff;
631 strncpy(janname, p->tm_zone ? p->tm_zone : " ", 9);
632 janname[9] = '\0';
633 t += YEAR/2;
634 p = localtime(&t);
635 julyzone = -p->tm_gmtoff;
636 strncpy(julyname, p->tm_zone ? p->tm_zone : " ", 9);
637 julyname[9] = '\0';
639 if( janzone < julyzone ) {
640 /* DST is reversed in the southern hemisphere */
641 ins(d, "timezone", PyInt_FromLong(julyzone));
642 ins(d, "altzone", PyInt_FromLong(janzone));
643 ins(d, "daylight",
644 PyInt_FromLong((long)(janzone != julyzone)));
645 ins(d, "tzname",
646 Py_BuildValue("(zz)", julyname, janname));
647 } else {
648 ins(d, "timezone", PyInt_FromLong(janzone));
649 ins(d, "altzone", PyInt_FromLong(julyzone));
650 ins(d, "daylight",
651 PyInt_FromLong((long)(janzone != julyzone)));
652 ins(d, "tzname",
653 Py_BuildValue("(zz)", janname, julyname));
656 #else
657 #ifdef macintosh
658 /* The only thing we can obtain is the current timezone
659 ** (and whether dst is currently _active_, but that is not what
660 ** we're looking for:-( )
662 initmactimezone();
663 ins(d, "timezone", PyInt_FromLong(timezone));
664 ins(d, "altzone", PyInt_FromLong(timezone));
665 ins(d, "daylight", PyInt_FromLong((long)0));
666 ins(d, "tzname", Py_BuildValue("(zz)", "", ""));
667 #endif /* macintosh */
668 #endif /* HAVE_TM_ZONE */
669 #ifdef __CYGWIN__
670 tzset();
671 ins(d, "timezone", PyInt_FromLong(_timezone));
672 ins(d, "altzone", PyInt_FromLong(_timezone));
673 ins(d, "daylight", PyInt_FromLong(_daylight));
674 ins(d, "tzname", Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
675 #endif /* __CYGWIN__ */
676 #endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
680 /* Implement floattime() for various platforms */
682 static double
683 floattime(void)
685 /* There are three ways to get the time:
686 (1) gettimeofday() -- resolution in microseconds
687 (2) ftime() -- resolution in milliseconds
688 (3) time() -- resolution in seconds
689 In all cases the return value is a float in seconds.
690 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
691 fail, so we fall back on ftime() or time().
692 Note: clock resolution does not imply clock accuracy! */
693 #ifdef HAVE_GETTIMEOFDAY
695 struct timeval t;
696 #ifdef GETTIMEOFDAY_NO_TZ
697 if (gettimeofday(&t) == 0)
698 return (double)t.tv_sec + t.tv_usec*0.000001;
699 #else /* !GETTIMEOFDAY_NO_TZ */
700 if (gettimeofday(&t, (struct timezone *)NULL) == 0)
701 return (double)t.tv_sec + t.tv_usec*0.000001;
702 #endif /* !GETTIMEOFDAY_NO_TZ */
704 #endif /* !HAVE_GETTIMEOFDAY */
706 #if defined(HAVE_FTIME)
707 struct timeb t;
708 ftime(&t);
709 return (double)t.time + (double)t.millitm * (double)0.001;
710 #else /* !HAVE_FTIME */
711 time_t secs;
712 time(&secs);
713 return (double)secs;
714 #endif /* !HAVE_FTIME */
719 /* Implement floatsleep() for various platforms.
720 When interrupted (or when another error occurs), return -1 and
721 set an exception; else return 0. */
723 static int
724 floatsleep(double secs)
726 /* XXX Should test for MS_WIN32 first! */
727 #if defined(HAVE_SELECT) && !defined(__BEOS__)
728 struct timeval t;
729 double frac;
730 frac = fmod(secs, 1.0);
731 secs = floor(secs);
732 t.tv_sec = (long)secs;
733 t.tv_usec = (long)(frac*1000000.0);
734 Py_BEGIN_ALLOW_THREADS
735 if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
736 #ifdef EINTR
737 if (errno != EINTR) {
738 #else
739 if (1) {
740 #endif
741 Py_BLOCK_THREADS
742 PyErr_SetFromErrno(PyExc_IOError);
743 return -1;
746 Py_END_ALLOW_THREADS
747 #else /* !HAVE_SELECT || __BEOS__ */
748 #ifdef macintosh
749 #define MacTicks (* (long *)0x16A)
750 long deadline;
751 deadline = MacTicks + (long)(secs * 60.0);
752 while (MacTicks < deadline) {
753 /* XXX Should call some yielding function here */
754 if (PyErr_CheckSignals())
755 return -1;
757 #else /* !macintosh */
758 #if defined(__WATCOMC__) && !defined(__QNX__)
759 /* XXX Can't interrupt this sleep */
760 Py_BEGIN_ALLOW_THREADS
761 delay((int)(secs * 1000 + 0.5)); /* delay() uses milliseconds */
762 Py_END_ALLOW_THREADS
763 #else /* !__WATCOMC__ || __QNX__ */
764 #ifdef MSDOS
765 struct timeb t1, t2;
766 double frac;
767 extern double fmod(double, double);
768 extern double floor(double);
769 if (secs <= 0.0)
770 return;
771 frac = fmod(secs, 1.0);
772 secs = floor(secs);
773 ftime(&t1);
774 t2.time = t1.time + (int)secs;
775 t2.millitm = t1.millitm + (int)(frac*1000.0);
776 while (t2.millitm >= 1000) {
777 t2.time++;
778 t2.millitm -= 1000;
780 for (;;) {
781 #ifdef QUICKWIN
782 Py_BEGIN_ALLOW_THREADS
783 _wyield();
784 Py_END_ALLOW_THREADS
785 #endif
786 if (PyErr_CheckSignals())
787 return -1;
788 ftime(&t1);
789 if (t1.time > t2.time ||
790 t1.time == t2.time && t1.millitm >= t2.millitm)
791 break;
793 #else /* !MSDOS */
794 #ifdef MS_WIN32
796 double millisecs = secs * 1000.0;
797 if (millisecs > (double)ULONG_MAX) {
798 PyErr_SetString(PyExc_OverflowError, "sleep length is too large");
799 return -1;
801 /* XXX Can't interrupt this sleep */
802 Py_BEGIN_ALLOW_THREADS
803 Sleep((unsigned long)millisecs);
804 Py_END_ALLOW_THREADS
806 #else /* !MS_WIN32 */
807 #ifdef PYOS_OS2
808 /* This Sleep *IS* Interruptable by Exceptions */
809 Py_BEGIN_ALLOW_THREADS
810 if (DosSleep(secs * 1000) != NO_ERROR) {
811 Py_BLOCK_THREADS
812 PyErr_SetFromErrno(PyExc_IOError);
813 return -1;
815 Py_END_ALLOW_THREADS
816 #else /* !PYOS_OS2 */
817 #ifdef __BEOS__
818 /* This sleep *CAN BE* interrupted. */
820 if( secs <= 0.0 ) {
821 return;
824 Py_BEGIN_ALLOW_THREADS
825 /* BeOS snooze() is in microseconds... */
826 if( snooze( (bigtime_t)( secs * 1000.0 * 1000.0 ) ) == B_INTERRUPTED ) {
827 Py_BLOCK_THREADS
828 PyErr_SetFromErrno( PyExc_IOError );
829 return -1;
831 Py_END_ALLOW_THREADS
833 #else /* !__BEOS__ */
834 #ifdef RISCOS
835 if (secs <= 0.0)
836 return 0;
837 Py_BEGIN_ALLOW_THREADS
838 /* This sleep *CAN BE* interrupted. */
839 if ( sleep(secs) )
840 return -1;
841 Py_END_ALLOW_THREADS
842 #else /* !RISCOS */
843 /* XXX Can't interrupt this sleep */
844 Py_BEGIN_ALLOW_THREADS
845 sleep((int)secs);
846 Py_END_ALLOW_THREADS
847 #endif /* !RISCOS */
848 #endif /* !__BEOS__ */
849 #endif /* !PYOS_OS2 */
850 #endif /* !MS_WIN32 */
851 #endif /* !MSDOS */
852 #endif /* !__WATCOMC__ || __QNX__ */
853 #endif /* !macintosh */
854 #endif /* !HAVE_SELECT */
855 return 0;