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