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