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