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