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