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