Remove a ?? in the description of Mac OS support.
[python/dscho.git] / Modules / timemodule.c
blob116b377e8ef7459d770f1927f029ff6e5a16c7b6
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_GUSI2
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 #include <sys/types.h>
20 #endif
22 #ifdef QUICKWIN
23 #include <io.h>
24 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
30 #ifdef HAVE_FTIME
31 #include <sys/timeb.h>
32 #if !defined(MS_WINDOWS) && !defined(PYOS_OS2)
33 extern int ftime(struct timeb *);
34 #endif /* MS_WINDOWS */
35 #endif /* HAVE_FTIME */
37 #if defined(__WATCOMC__) && !defined(__QNX__)
38 #include <i86.h>
39 #else
40 #ifdef MS_WINDOWS
41 #include <windows.h>
42 #ifdef MS_WIN16
43 /* These overrides not needed for Win32 */
44 #define timezone _timezone
45 #define tzname _tzname
46 #define daylight _daylight
47 #define altzone _altzone
48 #endif /* MS_WIN16 */
49 #endif /* MS_WINDOWS */
50 #endif /* !__WATCOMC__ || __QNX__ */
52 #if defined(MS_WIN32) && !defined(MS_WIN64)
53 /* Win32 has better clock replacement
54 XXX Win64 does not yet, but might when the platform matures. */
55 #include <largeint.h>
56 #undef HAVE_CLOCK /* We have our own version down below */
57 #endif /* MS_WIN32 && !MS_WIN64 */
59 #if defined(PYCC_VACPP)
60 #include <sys/time.h>
61 #endif
63 #ifdef __BEOS__
64 #include <time.h>
65 /* For bigtime_t, snooze(). - [cjh] */
66 #include <support/SupportDefs.h>
67 #include <kernel/OS.h>
68 #endif
70 /* Forward declarations */
71 static int floatsleep(double);
72 static double floattime(void);
74 /* For Y2K check */
75 static PyObject *moddict;
77 #ifdef macintosh
78 /* Our own timezone. We have enough information to deduce whether
79 ** DST is on currently, but unfortunately we cannot put it to good
80 ** use because we don't know the rules (and that is needed to have
81 ** localtime() return correct tm_isdst values for times other than
82 ** the current time. So, we cop out and only tell the user the current
83 ** timezone.
85 static long timezone;
87 static void
88 initmactimezone(void)
90 MachineLocation loc;
91 long delta;
93 ReadLocation(&loc);
95 if (loc.latitude == 0 && loc.longitude == 0 && loc.u.gmtDelta == 0)
96 return;
98 delta = loc.u.gmtDelta & 0x00FFFFFF;
100 if (delta & 0x00800000)
101 delta |= 0xFF000000;
103 timezone = -delta;
105 #endif /* macintosh */
108 static PyObject *
109 time_time(PyObject *self, PyObject *args)
111 double secs;
112 if (!PyArg_NoArgs(args))
113 return NULL;
114 secs = floattime();
115 if (secs == 0.0) {
116 PyErr_SetFromErrno(PyExc_IOError);
117 return NULL;
119 return PyFloat_FromDouble(secs);
122 static char time_doc[] =
123 "time() -> floating point number\n\
125 Return the current time in seconds since the Epoch.\n\
126 Fractions of a second may be present if the system clock provides them.";
128 #ifdef HAVE_CLOCK
130 #ifndef CLOCKS_PER_SEC
131 #ifdef CLK_TCK
132 #define CLOCKS_PER_SEC CLK_TCK
133 #else
134 #define CLOCKS_PER_SEC 1000000
135 #endif
136 #endif
138 static PyObject *
139 time_clock(PyObject *self, PyObject *args)
141 if (!PyArg_NoArgs(args))
142 return NULL;
143 return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC);
145 #endif /* HAVE_CLOCK */
147 #if defined(MS_WIN32) && !defined(MS_WIN64)
148 /* Due to Mark Hammond */
149 static PyObject *
150 time_clock(PyObject *self, PyObject *args)
152 static LARGE_INTEGER ctrStart;
153 static LARGE_INTEGER divisor = {0,0};
154 LARGE_INTEGER now, diff, rem;
156 if (!PyArg_NoArgs(args))
157 return NULL;
159 if (LargeIntegerEqualToZero(divisor)) {
160 QueryPerformanceCounter(&ctrStart);
161 if (!QueryPerformanceFrequency(&divisor) ||
162 LargeIntegerEqualToZero(divisor)) {
163 /* Unlikely to happen -
164 this works on all intel machines at least!
165 Revert to clock() */
166 return PyFloat_FromDouble(clock());
169 QueryPerformanceCounter(&now);
170 diff = LargeIntegerSubtract(now, ctrStart);
171 diff = LargeIntegerDivide(diff, divisor, &rem);
172 /* XXX - we assume both divide results fit in 32 bits. This is
173 true on Intels. First person who can afford a machine that
174 doesnt deserves to fix it :-)
176 return PyFloat_FromDouble((double)diff.LowPart +
177 ((double)rem.LowPart / (double)divisor.LowPart));
180 #define HAVE_CLOCK /* So it gets included in the methods */
181 #endif /* MS_WIN32 && !MS_WIN64 */
183 #ifdef HAVE_CLOCK
184 static char clock_doc[] =
185 "clock() -> floating point number\n\
187 Return the CPU time or real time since the start of the process or since\n\
188 the first call to clock(). This has as much precision as the system records.";
189 #endif
191 static PyObject *
192 time_sleep(PyObject *self, PyObject *args)
194 double secs;
195 if (!PyArg_Parse(args, "d", &secs))
196 return NULL;
197 if (floatsleep(secs) != 0)
198 return NULL;
199 Py_INCREF(Py_None);
200 return Py_None;
203 static char sleep_doc[] =
204 "sleep(seconds)\n\
206 Delay execution for a given number of seconds. The argument may be\n\
207 a floating point number for subsecond precision.";
209 static PyObject *
210 tmtotuple(struct tm *p)
212 return Py_BuildValue("(iiiiiiiii)",
213 p->tm_year + 1900,
214 p->tm_mon + 1, /* Want January == 1 */
215 p->tm_mday,
216 p->tm_hour,
217 p->tm_min,
218 p->tm_sec,
219 (p->tm_wday + 6) % 7, /* Want Monday == 0 */
220 p->tm_yday + 1, /* Want January, 1 == 1 */
221 p->tm_isdst);
224 static PyObject *
225 time_convert(time_t when, struct tm * (*function)(const time_t *))
227 struct tm *p;
228 errno = 0;
229 #if defined(macintosh) && defined(USE_GUSI204)
230 when = when + GUSI_TO_MSL_EPOCH;
231 #endif
232 p = function(&when);
233 if (p == NULL) {
234 #ifdef EINVAL
235 if (errno == 0)
236 errno = EINVAL;
237 #endif
238 return PyErr_SetFromErrno(PyExc_IOError);
240 return tmtotuple(p);
243 static PyObject *
244 time_gmtime(PyObject *self, PyObject *args)
246 double when;
247 if (!PyArg_Parse(args, "d", &when))
248 return NULL;
249 return time_convert((time_t)when, gmtime);
252 static char gmtime_doc[] =
253 "gmtime(seconds) -> tuple\n\
255 Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a. GMT).";
257 static PyObject *
258 time_localtime(PyObject *self, PyObject *args)
260 double when;
261 if (!PyArg_Parse(args, "d", &when))
262 return NULL;
263 return time_convert((time_t)when, localtime);
266 static char localtime_doc[] =
267 "localtime(seconds) -> tuple\n\
268 Convert seconds since the Epoch to a time tuple expressing local time.";
270 static int
271 gettmarg(PyObject *args, struct tm *p)
273 int y;
274 memset((void *) p, '\0', sizeof(struct tm));
276 if (!PyArg_Parse(args, "(iiiiiiiii)",
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 (y < 1900) {
288 PyObject *accept = PyDict_GetItemString(moddict,
289 "accept2dyear");
290 if (accept == NULL || !PyInt_Check(accept) ||
291 PyInt_AsLong(accept) == 0) {
292 PyErr_SetString(PyExc_ValueError,
293 "year >= 1900 required");
294 return 0;
296 if (69 <= y && y <= 99)
297 y += 1900;
298 else if (0 <= y && y <= 68)
299 y += 2000;
300 else {
301 PyErr_SetString(PyExc_ValueError,
302 "year out of range (00-99, 1900-*)");
303 return 0;
306 p->tm_year = y - 1900;
307 p->tm_mon--;
308 p->tm_wday = (p->tm_wday + 1) % 7;
309 p->tm_yday--;
310 return 1;
313 #ifdef HAVE_STRFTIME
314 static PyObject *
315 time_strftime(PyObject *self, PyObject *args)
317 PyObject *tup;
318 struct tm buf;
319 const char *fmt;
320 size_t fmtlen, buflen;
321 char *outbuf = 0;
322 size_t i;
324 memset((void *) &buf, '\0', sizeof(buf));
326 if (!PyArg_ParseTuple(args, "sO:strftime", &fmt, &tup)
327 || !gettmarg(tup, &buf))
328 return NULL;
329 fmtlen = strlen(fmt);
331 /* I hate these functions that presume you know how big the output
332 * will be ahead of time...
334 for (i = 1024; ; i += i) {
335 outbuf = malloc(i);
336 if (outbuf == NULL) {
337 return PyErr_NoMemory();
339 buflen = strftime(outbuf, i, fmt, &buf);
340 if (buflen > 0 || i >= 256 * fmtlen) {
341 /* If the buffer is 256 times as long as the format,
342 it's probably not failing for lack of room!
343 More likely, the format yields an empty result,
344 e.g. an empty format, or %Z when the timezone
345 is unknown. */
346 PyObject *ret;
347 ret = PyString_FromStringAndSize(outbuf, buflen);
348 free(outbuf);
349 return ret;
351 free(outbuf);
355 static char strftime_doc[] =
356 "strftime(format, tuple) -> string\n\
358 Convert a time tuple to a string according to a format specification.\n\
359 See the library reference manual for formatting codes.";
360 #endif /* HAVE_STRFTIME */
362 #ifdef HAVE_STRPTIME
364 #if 0
365 /* Enable this if it's not declared in <time.h> */
366 extern char *strptime(const char *, const char *, struct tm *);
367 #endif
369 static PyObject *
370 time_strptime(PyObject *self, PyObject *args)
372 struct tm tm;
373 char *fmt = "%a %b %d %H:%M:%S %Y";
374 char *buf;
375 char *s;
377 if (!PyArg_ParseTuple(args, "s|s:strptime", &buf, &fmt))
378 return NULL;
379 memset((void *) &tm, '\0', sizeof(tm));
380 s = strptime(buf, fmt, &tm);
381 if (s == NULL) {
382 PyErr_SetString(PyExc_ValueError, "format mismatch");
383 return NULL;
385 while (*s && isspace(*s))
386 s++;
387 if (*s) {
388 PyErr_Format(PyExc_ValueError,
389 "unconverted data remains: '%.400s'", s);
390 return NULL;
392 return tmtotuple(&tm);
395 static char strptime_doc[] =
396 "strptime(string, format) -> tuple\n\
397 Parse a string to a time tuple according to a format specification.\n\
398 See the library reference manual for formatting codes (same as strftime()).";
399 #endif /* HAVE_STRPTIME */
401 static PyObject *
402 time_asctime(PyObject *self, PyObject *args)
404 PyObject *tup;
405 struct tm buf;
406 char *p;
407 if (!PyArg_ParseTuple(args, "O:asctime", &tup))
408 return NULL;
409 if (!gettmarg(tup, &buf))
410 return NULL;
411 p = asctime(&buf);
412 if (p[24] == '\n')
413 p[24] = '\0';
414 return PyString_FromString(p);
417 static char asctime_doc[] =
418 "asctime(tuple) -> string\n\
420 Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.";
422 static PyObject *
423 time_ctime(PyObject *self, PyObject *args)
425 double dt;
426 time_t tt;
427 char *p;
428 if (!PyArg_Parse(args, "d", &dt))
429 return NULL;
430 tt = (time_t)dt;
431 #if defined(macintosh) && defined(USE_GUSI204)
432 tt = tt + GUSI_TO_MSL_EPOCH;
433 #endif
434 p = ctime(&tt);
435 if (p == NULL) {
436 PyErr_SetString(PyExc_ValueError, "unconvertible time");
437 return NULL;
439 if (p[24] == '\n')
440 p[24] = '\0';
441 return PyString_FromString(p);
444 static char ctime_doc[] =
445 "ctime(seconds) -> string\n\
447 Convert a time in seconds since the Epoch to a string in local time.\n\
448 This is equivalent to asctime(localtime(seconds)).";
450 #ifdef HAVE_MKTIME
451 static PyObject *
452 time_mktime(PyObject *self, PyObject *args)
454 PyObject *tup;
455 struct tm buf;
456 time_t tt;
457 if (!PyArg_ParseTuple(args, "O:mktime", &tup))
458 return NULL;
459 tt = time(&tt);
460 buf = *localtime(&tt);
461 if (!gettmarg(tup, &buf))
462 return NULL;
463 tt = mktime(&buf);
464 if (tt == (time_t)(-1)) {
465 PyErr_SetString(PyExc_OverflowError,
466 "mktime argument out of range");
467 return NULL;
469 #if defined(macintosh) && defined(USE_GUSI2)
470 tt = tt - GUSI_TO_MSL_EPOCH;
471 #endif
472 return PyFloat_FromDouble((double)tt);
475 static char mktime_doc[] =
476 "mktime(tuple) -> floating point number\n\
478 Convert a time tuple in local time to seconds since the Epoch.";
479 #endif /* HAVE_MKTIME */
481 static PyMethodDef time_methods[] = {
482 {"time", time_time, METH_OLDARGS, time_doc},
483 #ifdef HAVE_CLOCK
484 {"clock", time_clock, METH_OLDARGS, clock_doc},
485 #endif
486 {"sleep", time_sleep, METH_OLDARGS, sleep_doc},
487 {"gmtime", time_gmtime, METH_OLDARGS, gmtime_doc},
488 {"localtime", time_localtime, METH_OLDARGS, localtime_doc},
489 {"asctime", time_asctime, METH_VARARGS, asctime_doc},
490 {"ctime", time_ctime, METH_OLDARGS, ctime_doc},
491 #ifdef HAVE_MKTIME
492 {"mktime", time_mktime, METH_VARARGS, mktime_doc},
493 #endif
494 #ifdef HAVE_STRFTIME
495 {"strftime", time_strftime, METH_VARARGS, strftime_doc},
496 #endif
497 #ifdef HAVE_STRPTIME
498 {"strptime", time_strptime, METH_VARARGS, strptime_doc},
499 #endif
500 {NULL, NULL} /* sentinel */
503 static void
504 ins(PyObject *d, char *name, PyObject *v)
506 /* Don't worry too much about errors, they'll be caught by the
507 * caller of inittime().
509 if (v)
510 PyDict_SetItemString(d, name, v);
511 Py_XDECREF(v);
515 static char module_doc[] =
516 "This module provides various functions to manipulate time values.\n\
518 There are two standard representations of time. One is the number\n\
519 of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
520 or a floating point number (to represent fractions of seconds).\n\
521 The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
522 The actual value can be retrieved by calling gmtime(0).\n\
524 The other representation is a tuple of 9 integers giving local time.\n\
525 The tuple items are:\n\
526 year (four digits, e.g. 1998)\n\
527 month (1-12)\n\
528 day (1-31)\n\
529 hours (0-23)\n\
530 minutes (0-59)\n\
531 seconds (0-59)\n\
532 weekday (0-6, Monday is 0)\n\
533 Julian day (day in the year, 1-366)\n\
534 DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
535 If the DST flag is 0, the time is given in the regular time zone;\n\
536 if it is 1, the time is given in the DST time zone;\n\
537 if it is -1, mktime() should guess based on the date and time.\n\
539 Variables:\n\
541 timezone -- difference in seconds between UTC and local standard time\n\
542 altzone -- difference in seconds between UTC and local DST time\n\
543 daylight -- whether local time should reflect DST\n\
544 tzname -- tuple of (standard time zone name, DST time zone name)\n\
546 Functions:\n\
548 time() -- return current time in seconds since the Epoch as a float\n\
549 clock() -- return CPU time since process start as a float\n\
550 sleep() -- delay for a number of seconds given as a float\n\
551 gmtime() -- convert seconds since Epoch to UTC tuple\n\
552 localtime() -- convert seconds since Epoch to local time tuple\n\
553 asctime() -- convert time tuple to string\n\
554 ctime() -- convert time in seconds to string\n\
555 mktime() -- convert local time tuple to seconds since Epoch\n\
556 strftime() -- convert time tuple to string according to format specification\n\
557 strptime() -- parse string to time tuple according to format specification\n\
561 DL_EXPORT(void)
562 inittime(void)
564 PyObject *m, *d;
565 char *p;
566 m = Py_InitModule3("time", time_methods, module_doc);
567 d = PyModule_GetDict(m);
568 /* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
569 p = getenv("PYTHONY2K");
570 ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p)));
571 /* Squirrel away the module's dictionary for the y2k check */
572 Py_INCREF(d);
573 moddict = d;
574 #if defined(HAVE_TZNAME) && !defined(__GLIBC__)
575 tzset();
576 #ifdef PYOS_OS2
577 ins(d, "timezone", PyInt_FromLong((long)_timezone));
578 #else /* !PYOS_OS2 */
579 ins(d, "timezone", PyInt_FromLong((long)timezone));
580 #endif /* PYOS_OS2 */
581 #ifdef HAVE_ALTZONE
582 ins(d, "altzone", PyInt_FromLong((long)altzone));
583 #else
584 #ifdef PYOS_OS2
585 ins(d, "altzone", PyInt_FromLong((long)_timezone-3600));
586 #else /* !PYOS_OS2 */
587 ins(d, "altzone", PyInt_FromLong((long)timezone-3600));
588 #endif /* PYOS_OS2 */
589 #endif
590 ins(d, "daylight", PyInt_FromLong((long)daylight));
591 ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1]));
592 #else /* !HAVE_TZNAME || __GLIBC__ */
593 #ifdef HAVE_TM_ZONE
595 #define YEAR ((time_t)((365 * 24 + 6) * 3600))
596 time_t t;
597 struct tm *p;
598 long janzone, julyzone;
599 char janname[10], julyname[10];
600 t = (time((time_t *)0) / YEAR) * YEAR;
601 p = localtime(&t);
602 janzone = -p->tm_gmtoff;
603 strncpy(janname, p->tm_zone ? p->tm_zone : " ", 9);
604 janname[9] = '\0';
605 t += YEAR/2;
606 p = localtime(&t);
607 julyzone = -p->tm_gmtoff;
608 strncpy(julyname, p->tm_zone ? p->tm_zone : " ", 9);
609 julyname[9] = '\0';
611 if( janzone < julyzone ) {
612 /* DST is reversed in the southern hemisphere */
613 ins(d, "timezone", PyInt_FromLong(julyzone));
614 ins(d, "altzone", PyInt_FromLong(janzone));
615 ins(d, "daylight",
616 PyInt_FromLong((long)(janzone != julyzone)));
617 ins(d, "tzname",
618 Py_BuildValue("(zz)", julyname, janname));
619 } else {
620 ins(d, "timezone", PyInt_FromLong(janzone));
621 ins(d, "altzone", PyInt_FromLong(julyzone));
622 ins(d, "daylight",
623 PyInt_FromLong((long)(janzone != julyzone)));
624 ins(d, "tzname",
625 Py_BuildValue("(zz)", janname, julyname));
628 #else
629 #ifdef macintosh
630 /* The only thing we can obtain is the current timezone
631 ** (and whether dst is currently _active_, but that is not what
632 ** we're looking for:-( )
634 initmactimezone();
635 ins(d, "timezone", PyInt_FromLong(timezone));
636 ins(d, "altzone", PyInt_FromLong(timezone));
637 ins(d, "daylight", PyInt_FromLong((long)0));
638 ins(d, "tzname", Py_BuildValue("(zz)", "", ""));
639 #endif /* macintosh */
640 #endif /* HAVE_TM_ZONE */
641 #endif /* !HAVE_TZNAME || __GLIBC__ */
645 /* Implement floattime() for various platforms */
647 static double
648 floattime(void)
650 /* There are three ways to get the time:
651 (1) gettimeofday() -- resolution in microseconds
652 (2) ftime() -- resolution in milliseconds
653 (3) time() -- resolution in seconds
654 In all cases the return value is a float in seconds.
655 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
656 fail, so we fall back on ftime() or time().
657 Note: clock resolution does not imply clock accuracy! */
658 #ifdef HAVE_GETTIMEOFDAY
660 struct timeval t;
661 #ifdef GETTIMEOFDAY_NO_TZ
662 if (gettimeofday(&t) == 0)
663 return (double)t.tv_sec + t.tv_usec*0.000001;
664 #else /* !GETTIMEOFDAY_NO_TZ */
665 if (gettimeofday(&t, (struct timezone *)NULL) == 0)
666 return (double)t.tv_sec + t.tv_usec*0.000001;
667 #endif /* !GETTIMEOFDAY_NO_TZ */
669 #endif /* !HAVE_GETTIMEOFDAY */
671 #if defined(HAVE_FTIME)
672 struct timeb t;
673 ftime(&t);
674 return (double)t.time + (double)t.millitm * (double)0.001;
675 #else /* !HAVE_FTIME */
676 time_t secs;
677 time(&secs);
678 return (double)secs;
679 #endif /* !HAVE_FTIME */
684 /* Implement floatsleep() for various platforms.
685 When interrupted (or when another error occurs), return -1 and
686 set an exception; else return 0. */
688 static int
689 floatsleep(double secs)
691 /* XXX Should test for MS_WIN32 first! */
692 #if defined(HAVE_SELECT) && !defined(__BEOS__)
693 struct timeval t;
694 double frac;
695 frac = fmod(secs, 1.0);
696 secs = floor(secs);
697 t.tv_sec = (long)secs;
698 t.tv_usec = (long)(frac*1000000.0);
699 Py_BEGIN_ALLOW_THREADS
700 if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
701 #ifdef EINTR
702 if (errno != EINTR) {
703 #else
704 if (1) {
705 #endif
706 Py_BLOCK_THREADS
707 PyErr_SetFromErrno(PyExc_IOError);
708 return -1;
711 Py_END_ALLOW_THREADS
712 #else /* !HAVE_SELECT || __BEOS__ */
713 #ifdef macintosh
714 #define MacTicks (* (long *)0x16A)
715 long deadline;
716 deadline = MacTicks + (long)(secs * 60.0);
717 while (MacTicks < deadline) {
718 /* XXX Should call some yielding function here */
719 if (PyErr_CheckSignals())
720 return -1;
722 #else /* !macintosh */
723 #if defined(__WATCOMC__) && !defined(__QNX__)
724 /* XXX Can't interrupt this sleep */
725 Py_BEGIN_ALLOW_THREADS
726 delay((int)(secs * 1000 + 0.5)); /* delay() uses milliseconds */
727 Py_END_ALLOW_THREADS
728 #else /* !__WATCOMC__ || __QNX__ */
729 #ifdef MSDOS
730 struct timeb t1, t2;
731 double frac;
732 extern double fmod(double, double);
733 extern double floor(double);
734 if (secs <= 0.0)
735 return;
736 frac = fmod(secs, 1.0);
737 secs = floor(secs);
738 ftime(&t1);
739 t2.time = t1.time + (int)secs;
740 t2.millitm = t1.millitm + (int)(frac*1000.0);
741 while (t2.millitm >= 1000) {
742 t2.time++;
743 t2.millitm -= 1000;
745 for (;;) {
746 #ifdef QUICKWIN
747 Py_BEGIN_ALLOW_THREADS
748 _wyield();
749 Py_END_ALLOW_THREADS
750 #endif
751 if (PyErr_CheckSignals())
752 return -1;
753 ftime(&t1);
754 if (t1.time > t2.time ||
755 t1.time == t2.time && t1.millitm >= t2.millitm)
756 break;
758 #else /* !MSDOS */
759 #ifdef MS_WIN32
761 double millisecs = secs * 1000.0;
762 if (millisecs > (double)ULONG_MAX) {
763 PyErr_SetString(PyExc_OverflowError, "sleep length is too large");
764 return -1;
766 /* XXX Can't interrupt this sleep */
767 Py_BEGIN_ALLOW_THREADS
768 Sleep((unsigned long)millisecs);
769 Py_END_ALLOW_THREADS
771 #else /* !MS_WIN32 */
772 #ifdef PYOS_OS2
773 /* This Sleep *IS* Interruptable by Exceptions */
774 Py_BEGIN_ALLOW_THREADS
775 if (DosSleep(secs * 1000) != NO_ERROR) {
776 Py_BLOCK_THREADS
777 PyErr_SetFromErrno(PyExc_IOError);
778 return -1;
780 Py_END_ALLOW_THREADS
781 #else /* !PYOS_OS2 */
782 #ifdef __BEOS__
783 /* This sleep *CAN BE* interrupted. */
785 if( secs <= 0.0 ) {
786 return;
789 Py_BEGIN_ALLOW_THREADS
790 /* BeOS snooze() is in microseconds... */
791 if( snooze( (bigtime_t)( secs * 1000.0 * 1000.0 ) ) == B_INTERRUPTED ) {
792 Py_BLOCK_THREADS
793 PyErr_SetFromErrno( PyExc_IOError );
794 return -1;
796 Py_END_ALLOW_THREADS
798 #else /* !__BEOS__ */
799 /* XXX Can't interrupt this sleep */
800 Py_BEGIN_ALLOW_THREADS
801 sleep((int)secs);
802 Py_END_ALLOW_THREADS
803 #endif /* !__BEOS__ */
804 #endif /* !PYOS_OS2 */
805 #endif /* !MS_WIN32 */
806 #endif /* !MSDOS */
807 #endif /* !__WATCOMC__ || __QNX__ */
808 #endif /* !macintosh */
809 #endif /* !HAVE_SELECT */
810 return 0;