From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/crt32/time/asctime.c | 194 ++++++++ private/crt32/time/clock.c | 169 +++++++ private/crt32/time/ctime.c | 56 +++ private/crt32/time/days.c | 26 + private/crt32/time/difftime.c | 53 ++ private/crt32/time/dtoxtime.c | 113 +++++ private/crt32/time/ftime.c | 107 ++++ private/crt32/time/gmtime.c | 185 +++++++ private/crt32/time/i386/_initclk.asm | 17 + private/crt32/time/i386/cinitclk.asm | 93 ++++ private/crt32/time/localtim.c | 252 ++++++++++ private/crt32/time/makefile | 6 + private/crt32/time/mktime.c | 315 ++++++++++++ private/crt32/time/ppc/cinitclk.s | 49 ++ private/crt32/time/sources | 54 ++ private/crt32/time/strdate.c | 99 ++++ private/crt32/time/strftime.c | 891 +++++++++++++++++++++++++++++++++ private/crt32/time/strtime.c | 98 ++++ private/crt32/time/systime.c | 104 ++++ private/crt32/time/time.c | 78 +++ private/crt32/time/timeset.c | 92 ++++ private/crt32/time/tzset.c | 927 +++++++++++++++++++++++++++++++++++ private/crt32/time/utime.c | 202 ++++++++ private/crt32/time/wcsftime.c | 67 +++ 24 files changed, 4247 insertions(+) create mode 100644 private/crt32/time/asctime.c create mode 100644 private/crt32/time/clock.c create mode 100644 private/crt32/time/ctime.c create mode 100644 private/crt32/time/days.c create mode 100644 private/crt32/time/difftime.c create mode 100644 private/crt32/time/dtoxtime.c create mode 100644 private/crt32/time/ftime.c create mode 100644 private/crt32/time/gmtime.c create mode 100644 private/crt32/time/i386/_initclk.asm create mode 100644 private/crt32/time/i386/cinitclk.asm create mode 100644 private/crt32/time/localtim.c create mode 100644 private/crt32/time/makefile create mode 100644 private/crt32/time/mktime.c create mode 100644 private/crt32/time/ppc/cinitclk.s create mode 100644 private/crt32/time/sources create mode 100644 private/crt32/time/strdate.c create mode 100644 private/crt32/time/strftime.c create mode 100644 private/crt32/time/strtime.c create mode 100644 private/crt32/time/systime.c create mode 100644 private/crt32/time/time.c create mode 100644 private/crt32/time/timeset.c create mode 100644 private/crt32/time/tzset.c create mode 100644 private/crt32/time/utime.c create mode 100644 private/crt32/time/wcsftime.c (limited to 'private/crt32/time') diff --git a/private/crt32/time/asctime.c b/private/crt32/time/asctime.c new file mode 100644 index 000000000..01fb992c2 --- /dev/null +++ b/private/crt32/time/asctime.c @@ -0,0 +1,194 @@ +/*** +*asctime.c - convert date/time structure to ASCII string +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Contains asctime() - convert a date/time structure to ASCII string. +* +*Revision History: +* 03-??-84 RLB Module created +* 05-??-84 DCW Removed use of sprintf, to avoid loading stdio +* functions +* 04-13-87 JCR Added "const" to declarations +* 05-21-87 SKS Declare the static buffer and helper routines as NEAR +* Replace store_year() with in-line code +* +* 11-24-87 WAJ allocated a static buffer for each thread. +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-24-88 PHG Merged DLL and normal versions; Removed initializers to +* save memory +* 06-06-89 JCR 386 mthread support +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* , removed #include , fixed +* the copyright and removed some leftover 16-bit support. +* Also, cleaned up the formatting a bit. +* 08-16-90 SBM Compiles cleanly with -W3 +* 10-04-90 GJF New-style function declarators. +* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_]. +* 02-17-93 GJF Changed for new _getptd(). +* +*******************************************************************************/ + +#include +#include +#include +#include +#ifdef MTHREAD +#include +#include +#endif + +#define _ASCBUFSIZE 26 +static char buf[_ASCBUFSIZE]; + +/* +** This prototype must be local to this file since the procedure is static +*/ + +static char * _CRTAPI3 store_dt(char *, int); + +static char * _CRTAPI3 store_dt ( + REG1 char *p, + REG2 int val + ) +{ + *p++ = (char)('0' + val / 10); + *p++ = (char)('0' + val % 10); + return(p); +} + + +/*** +*char *asctime(time) - convert a structure time to ascii string +* +*Purpose: +* Converts a time stored in a struct tm to a charcater string. +* The string is always exactly 26 characters of the form +* Tue May 01 02:34:55 1984\n\0 +* +*Entry: +* struct tm *time - ptr to time structure +* +*Exit: +* returns pointer to static string with time string. +* +*Exceptions: +* +*******************************************************************************/ + +char * _CRTAPI1 asctime ( + REG1 const struct tm *tb + ) +{ +#ifdef MTHREAD + +#ifdef _CRUISER_ + + struct _tiddata * tdata; /* pointer to tid's data */ + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + _ptiddata ptd = _getptd(); + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + REG2 char *p; /* will point to asctime buffer */ + char *retval; /* holds retval pointer */ + +#else + + REG2 char *p = buf; + +#endif + + int day, mon; + int i; + +#ifdef MTHREAD + +#ifdef _CRUISER_ + + /* Use per thread buffer area (malloc space, if necessary) */ + tdata = _gettidtab(); /* get tid's data address */ + if (tdata->_asctimebuf == NULL) { + if ( (tdata->_asctimebuf = malloc(_ASCBUFSIZE)) == NULL) + p = buf; /* error: use static buffer */ + else + p = tdata->_asctimebuf; + } + else + p = tdata->_asctimebuf; + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + /* Use per thread buffer area (malloc space, if necessary) */ + + if ( (ptd->_asctimebuf != NULL) || ((ptd->_asctimebuf = + malloc(_ASCBUFSIZE)) != NULL) ) + p = ptd->_asctimebuf; + else + p = buf; /* error: use static buffer */ + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + retval = p; /* save return value for later */ + +#endif + + /* copy day and month names into the buffer */ + + day = tb->tm_wday * 3; /* index to correct day string */ + mon = tb->tm_mon * 3; /* index to correct month string */ + for (i=0; i < 3; i++,p++) { + *p = *(__dnames + day + i); + *(p+4) = *(__mnames + mon + i); + } + + *p = ' '; /* blank between day and month */ + + p += 4; + + *p++ = ' '; + p = store_dt(p, tb->tm_mday); /* day of the month (1-31) */ + *p++ = ' '; + p = store_dt(p, tb->tm_hour); /* hours (0-23) */ + *p++ = ':'; + p = store_dt(p, tb->tm_min); /* minutes (0-59) */ + *p++ = ':'; + p = store_dt(p, tb->tm_sec); /* seconds (0-59) */ + *p++ = ' '; + p = store_dt(p, 19 + (tb->tm_year/100)); /* year (after 1900) */ + p = store_dt(p, tb->tm_year%100); + *p++ = '\n'; + *p = '\0'; + +#ifdef _POSIX_ + /* Date should be padded with spaces instead of zeroes. */ + + if ('0' == buf[8]) + buf[8] = ' '; +#endif + +#ifdef MTHREAD + return (retval); +#else + return ((char *) buf); +#endif +} diff --git a/private/crt32/time/clock.c b/private/crt32/time/clock.c new file mode 100644 index 000000000..cf94837c5 --- /dev/null +++ b/private/crt32/time/clock.c @@ -0,0 +1,169 @@ +/*** +*clock.c - Contains the clock runtime +* +* Copyright (c) 1987-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* The clock runtime returns the processor time used by +* the current process. +* +*Revision History: +* 01-17-87 JCR Module created +* 06-01-87 SKS "itime" must be declared static +* 07-20-87 JCR Changes "inittime" to "_inittime" +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 03-20-90 GJF Made calling type _CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 10-04-90 GJF New-style function declarators. +* 01-22-91 GJF ANSI naming. +* 07-25-91 GJF Added _pinittime definition for new initialization +* scheme [_WIN32_]. +* 03-13-92 SKS Changed itime from static local to external as +* a part of return to initializer table scheme. +* Changed _inittime to __inittime. +* 05-19-92 DJM POSIX support. +* +*******************************************************************************/ + +#include +#include +#include + +#ifdef _POSIX_ +#include +#else +#include +#include +#endif /* _POSIX_ */ + + +#ifndef _POSIX_ + +void __cdecl __inittime(void); + +#ifdef _MSC_VER + +#pragma data_seg(".CRT$XIC") +static void (__cdecl *pinit)(void) = __inittime; + +#pragma data_seg() + +#endif /* _MSC_VER */ + +struct _timeb __itimeb = { 0, 0, 0, 0 }; + +/*** +*clock_t clock() - Return the processor time used by this process. +* +*Purpose: +* This routine calculates how much time the calling process +* has used. At startup time, startup calls __inittime which stores +* the initial time. The clock routine calculates the difference +* between the current time and the initial time. +* +* Clock must reference _cinitime so that _cinitim.asm gets linked in. +* That routine, in turn, puts __inittime in the startup initialization +* routine table. +* +*Entry: +* No parameters. +* itime is a static structure of type timeb. +* +*Exit: +* If successful, clock returns the number of CLK_TCKs (milliseconds) +* that have elapsed. If unsuccessful, clock returns -1. +* +*Exceptions: +* None. +* +*******************************************************************************/ + +clock_t _CALLTYPE1 clock ( + void + ) +{ + struct _timeb now; + clock_t elapsed; + +#ifdef _CRUISER_ + + extern int _citime; + + /* Reference _citime so __inittime gets executed at startup time.*/ + + _citime=0; + +#endif /* _CRUISER_ */ + + /* Calculate the difference between the initial time and now. */ + + _ftime(&now); + elapsed = (now.time - __itimeb.time) * CLOCKS_PER_SEC; + elapsed += (int)now.millitm - (int)__itimeb.millitm; + return(elapsed); + +} + +/*** +*void __inittime() - Initialize the time location +* +*Purpose: +* This routine stores the time of the process startup. +* It is only linked in if the user issues a clock runtime call. +* +*Entry: +* No arguments. +* +*Exit: +* No return value. +* +*Exceptions: +* None. +* +*******************************************************************************/ + +void _CALLTYPE1 __inittime ( + void + ) +{ + _ftime(&__itimeb); +} + +#else /* _POSIX_ */ + +/*** +*clock_t clock() - Return the processor time used by this process. +* +*Purpose: +* This routine calculates how much time the calling process +* has used. It uses the POSIX system call times(). +* +* +*Entry: +* No parameters. +* +*Exit: +* If successful, clock returns the number of CLK_TCKs (milliseconds) +* that have elapsed. If unsuccessful, clock returns -1. +* +*Exceptions: +* None. +* +*******************************************************************************/ + +clock_t _CALLTYPE1 clock ( + void + ) +{ + struct tms now; + clock_t elapsed; + + elapsed= times(&now); + if (elapsed == (clock_t) -1) + return((clock_t) -1); + else + return(now.tms_utime+now.tms_stime); +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/ctime.c b/private/crt32/time/ctime.c new file mode 100644 index 000000000..28e48c43b --- /dev/null +++ b/private/crt32/time/ctime.c @@ -0,0 +1,56 @@ +/*** +*ctime.c - convert time argument into ASCII string +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains ctime() - convert time value to string +* +*Revision History: +* 03-??-84 RLB initial version +* 05-??-84 DFW split off into seperate module +* 02-18-87 JCR put in NULL ptr support +* 04-10-87 JCR changed long declaration ot time_t and added const. +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 05-21-90 GJF Fixed compiler warning. +* 10-04-90 GJF New-style function declarators. +* +*******************************************************************************/ + +#include +#include +#include + +/*** +*char *ctime(time) - converts a time stored as a long to a ASCII string +* +*Purpose: +* Converts a time stored as a long (time_t) to an ASCII string of +* the form: +* Tue May 1 14:25:03 1984 +* +*Entry: +* long *time - time value in XENIX format +* +*Exit: +* returns pointer to static string or NULL if time is before +* Jan 1 1980. +* +*Exceptions: +* +*******************************************************************************/ + +char * _CALLTYPE1 ctime ( + const time_t *timp + ) +{ + struct tm *tmtemp; + + if ((tmtemp=localtime(timp)) != NULL) + return(asctime((const struct tm *)tmtemp)); + else + return(NULL); +} diff --git a/private/crt32/time/days.c b/private/crt32/time/days.c new file mode 100644 index 000000000..c259f996c --- /dev/null +++ b/private/crt32/time/days.c @@ -0,0 +1,26 @@ +/*** +*days.c - static arrays with days from beg of year for each month +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains static arrays used by gmtime and statconv to determine +* date and time values. Shows days from beg of year. +* +*Revision History: +* 03-??-84 RLB initial version +* 05-??-84 DFW split out definitions from ctime routines +* 07-03-89 PHG removed _NEAR_ for 386 +* 03-20-90 GJF Fixed copyright. +* +*******************************************************************************/ + +#include + +int _lpdays[] = { + -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 +}; + +int _days[] = { + -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 +}; diff --git a/private/crt32/time/difftime.c b/private/crt32/time/difftime.c new file mode 100644 index 000000000..76797028f --- /dev/null +++ b/private/crt32/time/difftime.c @@ -0,0 +1,53 @@ +/*** +*difftime.c - return difference between two times as a double +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Find difference between two time in seconds. +* +*Revision History: +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 08-15-89 PHG Made MTHREAD version _pascal +* 11-20-89 JCR difftime() always _cdecl (not pascal even under +* mthread) +* 03-20-90 GJF Replaced _LOAD_DS with CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 10-04-90 GJF New-style function declarator. +* 05-19-92 DJM ifndef for POSIX build. +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include + +/*** +*double difftime(b, a) - find difference between two times +* +*Purpose: +* returns difference between two times (b-a) +* +* Multi-thread version must use pascal calling convention to be re-entrant. +* +*Entry: +* long a, b - times to difference (actually are time_t values) +* +*Exit: +* returns a double with the time in seconds between two times +* +*Exceptions: +* +*******************************************************************************/ + +double _CALLTYPE1 difftime ( + time_t b, + time_t a + ) +{ + return( (double)( b - a ) ); +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/dtoxtime.c b/private/crt32/time/dtoxtime.c new file mode 100644 index 000000000..8343fb23f --- /dev/null +++ b/private/crt32/time/dtoxtime.c @@ -0,0 +1,113 @@ +/*** +*dtoxtime.c - convert broken-down UTC time to time_t +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines __gmtotime_t() - convert broken-down UTC time to internal +* format (time_t). +* +*Revision History: +* 03-??-84 RLB written +* 11-18-87 SKS change tzset() to __tzset(), change source file name +* make _dtoxtime a near procedure +* 01-26-88 SKS _dtoxtime is no longer a near procedure (for QC) +* 03-20-90 GJF Made calling type _CALLTYPE1, added #include +* , removed #include and +* fixed the copyright. Also, cleaned up the formatting +* a bit. +* 10-04-90 GJF New-style function declarator. +* 01-21-91 GJF ANSI naming. +* 05-19-92 DJM ifndef for POSIX build. +* 03-30-93 GJF Revised. Old _dtoxtime is replaced by __gmtotime_t, +* which is more useful on Win32. +* 04-06-93 GJF Rewrote computation to avoid compiler warnings. +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include +#include +#include + +/*** +*time_t __gmtotime_t(yr, mo, dy, hr, mn, sc) - convert broken down time (UTC) +* to time_t +* +*Purpose: +* Converts a broken down UTC (GMT) time to time_t. This is similar to +* _mkgmtime() except there is minimal overflow checking and no updating +* of the input values (i.e., the fields of tm structure). +* +*Entry: +* int yr, mo, dy - date +* int hr, mn, sc - time +* +*Exit: +* returns time_t value +* +*Exceptions: +* +*******************************************************************************/ + +time_t _CRTAPI1 __gmtotime_t ( + int yr, /* 0 based */ + int mo, /* 1 based */ + int dy, /* 1 based */ + int hr, + int mn, + int sc + ) +{ + int tmpdays; + long tmptim; + + /* + * Do a quick range check on the year and convert it to a delta + * off of 1900. + */ + if ( ((long)(yr -= 1900) < _BASE_YEAR) || ((long)yr > _MAX_YEAR) ) + return (time_t)(-1); + + /* + * Compute the number of elapsed days in the current year minus + * one. Note the test for leap year and the would fail in the year 2100 + * if this was in range (which it isn't). + */ + tmpdays = dy + _days[mo - 1]; + if ( !(yr & 3) && (mo > 2) ) + /* + * in a leap year, after Feb. add one day for elapsed + * Feb 29. + */ + tmpdays++; + + /* + * Compute the number of elapsed seconds since the Epoch. Note the + * computation of elapsed leap years would break down after 2100 + * if such values were in range (fortunately, they aren't). + */ + tmptim = /* 365 days for each year */ + (((long)yr - _BASE_YEAR) * 365L + + /* one day for each elapsed leap year */ + + (long)((yr - 1) >> 2) - _LEAP_YEAR_ADJUST + + /* number of elapsed days in yr */ + + tmpdays) + + /* convert to hours and add in hr */ + * 24L + hr; + + tmptim = /* convert to minutes and add in mn */ + (tmptim * 60L + mn) + + /* convert to seconds and add in sec */ + * 60L + sc; + + return (tmptim >= 0) ? (time_t)tmptim : (time_t)(-1); +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/ftime.c b/private/crt32/time/ftime.c new file mode 100644 index 000000000..c1e04f5a1 --- /dev/null +++ b/private/crt32/time/ftime.c @@ -0,0 +1,107 @@ +/*** +*ftime.c - OS/2 return system time +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Returns the system date/time in a structure form. +* +*Revision History: +* 03-??-84 RLB initial version +* 05-17-86 SKS ported to OS/2 +* 03-09-87 SKS correct Daylight Savings Time flag +* 11-18-87 SKS Change tzset() to __tzset() +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 10-03-88 JCR 386: Change DOS calls to SYS calls +* 10-04-88 JCR 386: Removed 'far' keyword +* 10-10-88 GJF Made API names match DOSCALLS.H +* 04-12-89 JCR New syscall interface +* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* , removed some leftover 16-bit support +* and fixed the copyright. Also, cleaned up the +* formatting a bit. +* 07-25-90 SBM Removed '32' from API names +* 08-13-90 SBM Compiles cleanly with -W3 +* 08-20-90 SBM Removed old incorrect, redundant tp->dstflag assignment +* 10-04-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include instead of +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-21-91 GJF ANSI naming. +* 01-23-92 GJF Change in time zone field name for Win32, to support +* crtdll.dll [_WIN32_]. +* 03-30-93 GJF Revised to use mktime(). Also purged Cruiser support. +* 06-08-93 SKS Change "tmzone" back to "timezone". See h/sys/timeb.h. +* 07-15-93 GJF Call __tzset() instead of _tzset(). +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*** +*void _ftime(timeptr) - return DOS time in a structure +* +*Purpose: +* returns the current DOS time in a struct timeb structure +* +*Entry: +* struct timeb *timeptr - structure to fill in with time +* +*Exit: +* no return value -- fills in structure +* +*Exceptions: +* +*******************************************************************************/ + +void _CRTAPI1 _ftime ( + struct _timeb *tp + ) +{ + struct tm tb; + SYSTEMTIME dt; + + __tzset(); + + /* + * NOTE: The "timezone" field was renamed "tmzone" for a while because + * of the conflict with the global variable "_timezone". Since we use + * #define to alias the old name "timezone" to "_timezone" and to + * alias _timezone to (*_timezone_dll) in the CRTDLL model, we cannot + * compatibility in both areas. See sys/timeb.h for more information. + */ + tp->timezone = (short)(_timezone / 60); + + GetLocalTime(&dt); + + tp->millitm = (unsigned short)(dt.wMilliseconds); + + tb.tm_year = dt.wYear - 1900; + tb.tm_mday = dt.wDay; + tb.tm_mon = dt.wMonth - 1; + tb.tm_hour = dt.wHour; + tb.tm_min = dt.wMinute; + tb.tm_sec = dt.wSecond; + tb.tm_isdst = -1; + + /* + * Call mktime() to compute time_t value and Daylight Savings Time + * flag. + */ + tp->time = mktime(&tb); + + tp->dstflag = (short)(tb.tm_isdst); +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/gmtime.c b/private/crt32/time/gmtime.c new file mode 100644 index 000000000..8faacaf34 --- /dev/null +++ b/private/crt32/time/gmtime.c @@ -0,0 +1,185 @@ +/*** +*gmtime.c - breaks down a time value into GMT date/time info +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines gmtime() - breaks the clock value down into GMT time/date +* information; return pointer to structure with the data. +* +*Revision History: +* 01-??-84 RLB Module created +* 05-??-84 DCW Split off from rest off ctime routines. +* 02-18-87 JCR For MS C, gmtime now returns NULL for out of range +* time/date. (This is for ANSI compatibility.) +* 04-10-87 JCR Changed long declaration to time_t and added const +* 05-21-87 SKS Declare "struct tm tb" as NEAR data +* 11-10-87 SKS Removed IBMC20 switch +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-24-88 PHG Merge DLL and regular versions +* 06-06-89 JCR 386 mthread support +* 11-06-89 KRS Add (unsigned) to handle years 2040-2099 correctly +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* , removed #include and +* fixed the copyright. Also, cleaned up the formatting +* a bit. +* 10-04-90 GJF New-style function declarator. +* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_]. +* 02-17-93 GJF Changed for new _getptd(). +* 03-24-93 GJF Propagated changes from 16-bit tree. +* +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#ifdef MTHREAD +#include +#include +#endif + +static struct tm tb = { 0 }; /* time block */ + +/*** +*struct tm *gmtime(timp) - convert *timp to a structure (UTC) +* +*Purpose: +* Converts the calendar time value, in internal format (time_t), to +* broken-down time (tm structure) with the corresponding UTC time. +* +*Entry: +* const time_t *timp - pointer to time_t value to convert +* +*Exit: +* returns pointer to filled-in tm structure. +* returns NULL if *timp < 0L +* +*Exceptions: +* +*******************************************************************************/ + +struct tm * _CRTAPI1 gmtime ( + const time_t *timp + ) +{ + + long caltim = *timp; /* calendar time to convert */ + int islpyr = 0; /* is-current-year-a-leap-year flag */ + REG1 int tmptim; + REG3 int *mdays; /* pointer to days or lpdays */ + +#ifdef MTHREAD + + REG2 struct tm *ptb; /* will point to gmtime buffer */ + _ptiddata ptd = _getptd(); + +#else + REG2 struct tm *ptb = &tb; +#endif + + if ( caltim < 0L ) + return(NULL); + +#ifdef MTHREAD + + /* Use per thread buffer area (malloc space, if necessary) */ + + if ( (ptd->_gmtimebuf != NULL) || ((ptd->_gmtimebuf = + malloc(sizeof(struct tm))) != NULL) ) + ptb = ptd->_gmtimebuf; + else + ptb = &tb; /* malloc error: use static buffer */ + +#endif + + /* + * Determine years since 1970. First, identify the four-year interval + * since this makes handling leap-years easy (note that 2000 IS a + * leap year and 2100 is out-of-range). + */ + tmptim = (int)(caltim / _FOUR_YEAR_SEC); + caltim -= ((long)tmptim * _FOUR_YEAR_SEC); + + /* + * Determine which year of the interval + */ + tmptim = (tmptim * 4) + 70; /* 1970, 1974, 1978,...,etc. */ + + if ( caltim >= _YEAR_SEC ) { + + tmptim++; /* 1971, 1975, 1979,...,etc. */ + caltim -= _YEAR_SEC; + + if ( caltim >= _YEAR_SEC ) { + + tmptim++; /* 1972, 1976, 1980,...,etc. */ + caltim -= _YEAR_SEC; + + /* + * Note, it takes 366 days-worth of seconds to get past a leap + * year. + */ + if ( caltim >= (_YEAR_SEC + _DAY_SEC) ) { + + tmptim++; /* 1973, 1977, 1981,...,etc. */ + caltim -= (_YEAR_SEC + _DAY_SEC); + } + else { + /* + * In a leap year after all, set the flag. + */ + islpyr++; + } + } + } + + /* + * tmptim now holds the value for tm_year. caltim now holds the + * number of elapsed seconds since the beginning of that year. + */ + ptb->tm_year = tmptim; + + /* + * Determine days since January 1 (0 - 365). This is the tm_yday value. + * Leave caltim with number of elapsed seconds in that day. + */ + ptb->tm_yday = (int)(caltim / _DAY_SEC); + caltim -= (long)(ptb->tm_yday) * _DAY_SEC; + + /* + * Determine months since January (0 - 11) and day of month (1 - 31) + */ + if ( islpyr ) + mdays = _lpdays; + else + mdays = _days; + + + for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ; + + ptb->tm_mon = --tmptim; + + ptb->tm_mday = ptb->tm_yday - mdays[tmptim]; + + /* + * Determine days since Sunday (0 - 6) + */ + ptb->tm_wday = ((int)(*timp / _DAY_SEC) + _BASE_DOW) % 7; + + /* + * Determine hours since midnight (0 - 23), minutes after the hour + * (0 - 59), and seconds after the minute (0 - 59). + */ + ptb->tm_hour = (int)(caltim / 3600); + caltim -= (long)ptb->tm_hour * 3600L; + + ptb->tm_min = (int)(caltim / 60); + ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60); + + ptb->tm_isdst = 0; + return( (struct tm *)ptb ); + +} diff --git a/private/crt32/time/i386/_initclk.asm b/private/crt32/time/i386/_initclk.asm new file mode 100644 index 000000000..b837872bc --- /dev/null +++ b/private/crt32/time/i386/_initclk.asm @@ -0,0 +1,17 @@ + page ,132 + +;******* +; +; Alternate form of CINITCLK.ASM +; +; The MIPS C Compiler does not prepend underscores to C +; variables and functions like the I386 C Compiler does. +; +; The EQUate below will yield an object file +; which will be appropriate for MIPS COFF format. +; +;******* + +NO_UNDERSCORE equ 1 + +include i386\cinitclk.asm diff --git a/private/crt32/time/i386/cinitclk.asm b/private/crt32/time/i386/cinitclk.asm new file mode 100644 index 000000000..e303447fc --- /dev/null +++ b/private/crt32/time/i386/cinitclk.asm @@ -0,0 +1,93 @@ + page ,132 + title cinitclk - C Run-Time Initialization for clock() +;*** +;cinitclk.asm - WIN32 C Run-Time Initialization for the clock() function +; +; Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved. +; +;Purpose: +; Initialization entry for the clock() function +; +;Notes: +; The variable _itimeb, used in clock.c, is declared in this module +; to force the inclusion of the initializer entry if clock() is +; referenced. +; +; This file declares a structure of type timeb. +; +; The include file "timeb.inc" must be kept in synch with sys/timeb.h +; and depends on the alignment behavior of the Intel 386. +; +;Revision History: +; 03-19-92 SKS Module created. +; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE) +; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs +; 08-06-92 SKS Revised to use new section names and macros +; +;******************************************************************************* + +.xlist +include cruntime.inc +include defsects.inc +.list + +ifndef _WIN32_ +.err +%out _WIN32_ MUST be defined! +endif + + +ifndef NO_UNDERSCORE ; I386 VERSION ************************* + + + extrn __inittime:NEAR + + +beginSection XIC + + dd offset FLAT: __inittime + +endSection XIC + + + .DATA + + public __itimeb + +__itimeb label dword + dd 0 + dw 0 + dw 0 + dw 0 + dw 0 ; struct _timeb has four fields plus padding + + +else ; NO_UNDERSCORE ; MIPS VERSION ************************* + + + extrn _inittime:NEAR + + +beginSection XIC + + dd offset FLAT: _inittime + +endSection XIC + + + .DATA + + public _itimeb + +_itimeb label dword + dd 0 + dw 0 + dw 0 + dw 0 + dw 0 ; struct _timeb has four fields plus padding + + +endif ; NO_UNDERSCORE ; **** VERSION ************************* + + + end diff --git a/private/crt32/time/localtim.c b/private/crt32/time/localtim.c new file mode 100644 index 000000000..59727b1ba --- /dev/null +++ b/private/crt32/time/localtim.c @@ -0,0 +1,252 @@ +/*** +*localtim.c - Convert time_t value to time structure +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Converts time stored as a time_t value to a structure of type +* struct tm expressed as local time. +* +*Revision History: +* 01-??-84 RLB Module created +* 05-??-84 DCW split off from the rest of the ctime routines +* 02-18-87 JCR made localtime work when gmtime returns null +* 03-31-87 JCR fixed bug pertaining to uninitialized _isindst(tb) +* 04-10-87 JCR changed long declaration to time_t and added const +* 11-10-87 SKS Removed IBMC20 switch +* 11-18-87 SKS Change tzset() to __tzset() +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-06-89 KRS Added (unsigned) to handle years 2040-2099 correctly. +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* , removed #include and +* fixed the copyright. Also, cleaned up the formatting +* a bit. +* 10-04-90 GJF New-style function declarator. Also, rewrote expr. +* to avoid using cast as lvalue. +* 01-21-91 GJF ANSI naming. +* 08-10-92 PBS Posix support (TZ stuff). +* 03-24-93 GJF Ported C8-16 version and adapted for exotic Daylight +* Savings Time conversions which are legal under POSIX. +* 07-15-93 GJF Replaced _tzset() call with __tzset() call. +* +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +/*** +*struct tm *localtime(ptime) - convert time_t value to tm structure +* +*Purpose: +* Convert a value in internal (time_t) format to a tm struct +* containing the corresponding local time. +* +* NOTES: +* (1) gmtime must be called before _isindst to ensure that the tb time +* structure is initialized. +* (2) gmtime and localtime use a single statically allocated buffer. +* Each call to one of these routines destroys the contents of the +* previous call. +* (3) It is assumed that time_t is a 32-bit long integer representing +* the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the +* Posix/Unix Epoch. Only non-negative values are supported. +* (4) It is assumed that the maximum adjustment for local time is +* less than three days (include Daylight Savings Time adjustment). +* This only a concern in Posix where the specification of the TZ +* environment restricts the combined offset for time zone and +* Daylight Savings Time to 2 * (24:59:59), just under 50 hours. +* +*Entry: +* time_t *ptime - pointer to a long time value +* +*Exit: +* If *ptime is non-negative, returns a pointer to the tm structure. +* Otherwise, returns NULL. +* +*Exceptions: +* See items (3) and (4) in the NOTES above. If these assumptions are +* violated, behavior is undefined. +* +*******************************************************************************/ + +struct tm * _CRTAPI1 localtime ( + const time_t *ptime + ) +{ + REG1 struct tm *ptm; + long ltime; + + /* + * Check for illegal time_t value + */ + if ( (long)*ptime < 0L ) + return( NULL ); + +#ifdef _POSIX_ + tzset(); +#else + __tzset(); +#endif + + if ( (*ptime > 3 * _DAY_SEC) && (*ptime < LONG_MAX - 3 * _DAY_SEC) ) { + /* + * The date does not fall within the first three, or last + * three, representable days of the Epoch. Therefore, there + * is no possibility of overflowing or underflowing the + * time_t representation as we compensate for timezone and + * Daylight Savings Time. + */ + + ltime = (long)*ptime - _timezone; + ptm = gmtime( <ime ); + + /* + * Check and adjust for Daylight Saving Time. + */ + if ( _daylight && _isindst( ptm ) ) { +#ifdef _POSIX_ + ltime -= _dstoffset - _timezone; +#else + ltime += 3600L; +#endif + ptm = gmtime( (time_t *)<ime ); + ptm->tm_isdst = 1; + } + } + else { + ptm = gmtime( ptime ); + /* + * The date falls with the first three, or last three days + * of the Epoch. It is possible the time_t representation + * would overflow or underflow while compensating for + * timezone and Daylight Savings Time. Therefore, make the + * timezone and Daylight Savings Time adjustments directly + * in the tm structure. The beginning of the Epoch is + * 00:00:00, 01-01-70 (UTC) and the last representable second + * in theEpoch is 03:14:07, 01-19-2038 (UTC). This will be + * used in the calculations below. + * + * First, adjust for the timezone. + */ + ltime = (long)ptm->tm_sec - _timezone; + ptm->tm_sec = (int)(ltime % 60); + if ( ptm->tm_sec < 0 ) { + ptm->tm_sec += 60; + ltime -= 60; + } + + ltime = (long)ptm->tm_min + ltime/60; + ptm->tm_min = (int)(ltime % 60); + if ( ptm->tm_min < 0 ) { + ptm->tm_min += 60; + ltime -= 60; + } + + ltime = (long)ptm->tm_hour + ltime/60; + ptm->tm_hour = (int)(ltime % 24); + if ( ptm->tm_hour < 0 ) { + ptm->tm_hour += 24; + ltime -=24; + } + + ltime /= 24; + + if ( ltime > 0L ) { + /* + * There is no possibility of overflowing the tm_mday + * and tm_yday fields since the date can be no later + * than January 19. + */ + ptm->tm_wday = (ptm->tm_wday + ltime) % 7; + ptm->tm_mday += ltime; + ptm->tm_yday += ltime; + } + else if ( ltime < 0L ) { + /* + * It is possible to underflow the tm_mday and tm_yday + * fields. If this happens, then adjusted date must + * lie in December 1969. + */ + ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7; + if ( (ptm->tm_mday += ltime) <= 0 ) { + ptm->tm_mday += 31; + ptm->tm_yday = 365; + ptm->tm_mon = 11; + ptm->tm_year--; + } + else { + ptm->tm_yday += ltime; + } + } + +#ifdef _POSIX_ + /* + * In Posix, it is possible either the first or last three + * days of the Epoch might lie with Daylight Savings Time in + * certain time zones. + */ + if ( _isindst(ptm) ) { + + ltime = (long)ptm->tm_sec + _dstoffset; + ptm->tm_sec = (int)(ltime % 60); + if ( ptm->tm_sec < 0 ) { + ptm->tm_sec += 60; + ltime -= 60; + } + + ltime = (long)ptm->tm_min + ltime/60; + ptm->tm_min = (int)(ltime % 60); + if ( ptm->tm_min < 0 ) { + ptm->tm_min += 60; + ltime -= 60; + } + + ltime = (long)ptm->tm_hour + ltime/60; + ptm->tm_hour = (int)(ltime % 24); + if ( ptm->tm_hour < 0 ) { + ptm->tm_hour += 24; + ltime -=24; + } + + ltime /= 24; + + if ( ltime > 0L ) { + /* + * There is no possibility of overflowing the + * tm_mday and tm_yday fields since the date + * can be no later than January 19. + */ + ptm->tm_wday = (ptm->tm_wday + ltime) % 7; + ptm->tm_mday += ltime; + ptm->tm_yday += ltime; + } + else if ( ltime < 0L ) { + /* + * It is possible to underflow the tm_mday + * and tm_yday fields. If this happens, then + * adjusted date must lie in December 1969. + */ + ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7; + if ( (ptm->tm_mday += ltime) <= 0 ) { + ptm->tm_mday += 31; + ptm->tm_yday = 365; + ptm->tm_mon = 12; + ptm->tm_year--; + } + else { + ptm->tm_yday += ltime; + } + } + } + +#endif + + } + + + return(ptm); +} diff --git a/private/crt32/time/makefile b/private/crt32/time/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/crt32/time/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/crt32/time/mktime.c b/private/crt32/time/mktime.c new file mode 100644 index 000000000..7eb6e4e11 --- /dev/null +++ b/private/crt32/time/mktime.c @@ -0,0 +1,315 @@ +/*** +*mktime.c - Convert struct tm value to time_t value. +* +* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines mktime() and _mkgmtime(), routines to converts a time value +* in a tm structure (possibly incomplete) into a time_t value, then +* update (all) the structure fields with "normalized" values. +* +*Revision History: +* 01-14-87 JCR Module created +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 06-15-89 PHG Now allows negative values and does DST by ANSI rules +* 11-06-89 KRS Added (unsigned) to handle years 2040-2099 correctly. +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 10-04-90 GJF New-style function declarator. Also, rewrote expr. +* to avoid using casts as lvalues. +* 10-26-90 GJF Added ulscount to avoid overflows. Ugly, temporary +* hack (whole function needs to be revised for ANSI +* conformance). +* 01-22-91 GJF ANSI naming. +* 03-24-93 GJF Propagated changes from 16-bit tree. Modified to +* expose _mkgmtime() routine. +* 07-15-93 GJF Replaced _tzset() call with __tzset() call. +* +*******************************************************************************/ + +#include +#include +#include +#include +#include + +/* + * ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed + */ +#define ChkAdd(dest, src1, src2) ( ((src1 >= 0L) && (src2 >= 0L) \ + && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) ) + +/* + * ChkMul evaluates to TRUE if dest = src1 * src2 has overflowed + */ +#define ChkMul(dest, src1, src2) ( src1 ? (dest/src1 != src2) : 0 ) + + +/* + * Core function for both mktime() and _mkgmtime() + */ +static time_t _CRTAPI3 _make_time_t( struct tm *, int); + + +/*** +*time_t mktime(tb) - Normalize user time block structure +* +*Purpose: +* Mktime converts a time structure, passed in as an argument, into a +* calendar time value in internal format (time_t). It also completes +* and updates the fields the of the passed in structure with 'normalized' +* values. There are three practical uses for this routine: +* +* (1) Convert broken-down time to internal time format (time_t). +* (2) To have mktime fill in the tm_wday, tm_yday, or tm_isdst fields. +* (3) To pass in a time structure with 'out of range' values for some +* fields and have mktime "normalize" them (e.g., pass in 1/35/87 and +* get back 2/4/87). +*Entry: +* struct tm *tb - pointer to a tm time structure to convert and +* normalize +* +*Exit: +* If successful, mktime returns the specified calender time encoded as +* a time_t value. Otherwise, (time_t)(-1) is returned to indicate an +* error. +* +*Exceptions: +* None. +* +*******************************************************************************/ + + +time_t _CRTAPI1 mktime ( + struct tm *tb + ) +{ + return( _make_time_t(tb, 1) ); +} + + +/*** +*time_t _mkgmtime(tb) - Convert broken down UTC time to time_t +* +*Purpose: +* Convert a tm structure, passed in as an argument, containing a UTC +* time value to internal format (time_t). It also completes and updates +* the fields the of the passed in structure with 'normalized' values. + +*Entry: +* struct tm *tb - pointer to a tm time structure to convert and +* normalize +* +*Exit: +* If successful, _mkgmtime returns the calender time encoded as time_t +* Otherwise, (time_t)(-1) is returned to indicate an error. +* +*Exceptions: +* None. +* +*******************************************************************************/ + +time_t _CRTAPI1 _mkgmtime ( + struct tm *tb + ) +{ + return( _make_time_t(tb, 0) ); +} + + +/*** +*static time_t make_time_t(tb, ultflag) - +* +*Purpose: +* Converts a struct tm value to a time_t value, then updates the struct +* tm value. Either local time or UTC is supported, based on ultflag. +* This is the routine that actually does the work for both mktime() and +* _mkgmtime(). +* +*Entry: +* struct tm *tb - pointer to a tm time structure to convert and +* normalize +* int ultflag - use local time flag. the tb structure is assumed +* to represent a local date/time if ultflag > 0. +* otherwise, UTC is assumed. +* +*Exit: +* If successful, mktime returns the specified calender time encoded as +* a time_t value. Otherwise, (time_t)(-1) is returned to indicate an +* error. +* +*Exceptions: +* None. +* +*******************************************************************************/ + +static time_t _CRTAPI3 _make_time_t ( + struct tm *tb, + int ultflag + ) +{ + long tmptm1, tmptm2, tmptm3; + struct tm *tbtemp; + + /* + * First, make sure tm_year is reasonably close to being in range. + */ + if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + + 1) ) + goto err_mktime; + + + /* + * Adjust month value so it is in the range 0 - 11. This is because + * we don't know how many days are in months 12, 13, 14, etc. + */ + + if ( (tmptm2 = tb->tm_mon/12) != 0L ) { + /* + * no danger of overflow because the range check above. + */ + tmptm1 += tmptm2; + + if ( (tb->tm_mon %= 12) < 0 ) { + tb->tm_mon += 12; + tmptm1--; + } + + /* + * Make sure year count is still in range. + */ + if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1) ) + goto err_mktime; + } + + /***** HERE: tmptm1 holds number of elapsed years *****/ + + /* + * Calculate days elapsed minus one, in the given year, to the given + * month. Check for leap year and adjust if necessary. + */ + tmptm2 = _days[tb->tm_mon]; + if ( !(tmptm1 & 3) && (tb->tm_mon > 1) ) + tmptm2++; + + /* + * Calculate elapsed days since base date (midnight, 1/1/70, UTC) + * + * + * 365 days for each elapsed year since 1970, plus one more day for + * each elapsed leap year. no danger of overflow because of the range + * check (above) on tmptm1. + */ + tmptm3 = (tmptm1 - _BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2) + - _LEAP_YEAR_ADJUST; + + /* + * elapsed days to current month (still no possible overflow) + */ + tmptm3 += tmptm2; + + /* + * elapsed days to current date. overflow is now possible. + */ + tmptm1 = tmptm3 + (tmptm2 = (long)(tb->tm_mday)); + if ( ChkAdd(tmptm1, tmptm3, tmptm2) ) + goto err_mktime; + + /***** HERE: tmptm1 holds number of elapsed days *****/ + + /* + * Calculate elapsed hours since base date + */ + tmptm2 = tmptm1 * 24L; + if ( ChkMul(tmptm2, tmptm1, 24L) ) + goto err_mktime; + + tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_hour); + if ( ChkAdd(tmptm1, tmptm2, tmptm3) ) + goto err_mktime; + + /***** HERE: tmptm1 holds number of elapsed hours *****/ + + /* + * Calculate elapsed minutes since base date + */ + + tmptm2 = tmptm1 * 60L; + if ( ChkMul(tmptm2, tmptm1, 60L) ) + goto err_mktime; + + tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_min); + if ( ChkAdd(tmptm1, tmptm2, tmptm3) ) + goto err_mktime; + + /***** HERE: tmptm1 holds number of elapsed minutes *****/ + + /* + * Calculate elapsed seconds since base date + */ + + tmptm2 = tmptm1 * 60L; + if ( ChkMul(tmptm2, tmptm1, 60L) ) + goto err_mktime; + + tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_sec); + if ( ChkAdd(tmptm1, tmptm2, tmptm3) ) + goto err_mktime; + + /***** HERE: tmptm1 holds number of elapsed seconds *****/ + + if ( ultflag ) { + /* + * Adjust for timezone. No need to check for overflow since + * localtime() will check its arg value + */ + +#ifdef _POSIX_ + tzset(); +#else + __tzset(); +#endif + tmptm1 += _timezone; + + /* + * Convert this second count back into a time block structure. + * If localtime returns NULL, return an error. + */ + if ( (tbtemp = localtime(&tmptm1)) == NULL ) + goto err_mktime; + + /* + * Now must compensate for DST. The ANSI rules are to use the + * passed-in tm_isdst flag if it is non-negative. Otherwise, + * compute if DST applies. Recall that tbtemp has the time without + * DST compensation, but has set tm_isdst correctly. + */ + if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) && + (tbtemp->tm_isdst > 0)) ) { +#ifdef _POSIX_ + tmptm1 -= _timezone; + tmptm1 += _dstoffset; +#else + tmptm1 -= 3600L; +#endif + tbtemp = localtime(&tmptm1); /* reconvert, can't get NULL */ + } + } + else { + if ( (tbtemp = gmtime(&tmptm1)) == NULL ) + goto err_mktime; + } + + /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/ + /***** for local time if requested *****/ + + *tb = *tbtemp; + return (time_t)tmptm1; + +err_mktime: + /* + * All errors come to here + */ + return (time_t)(-1); +} diff --git a/private/crt32/time/ppc/cinitclk.s b/private/crt32/time/ppc/cinitclk.s new file mode 100644 index 000000000..72f68c49c --- /dev/null +++ b/private/crt32/time/ppc/cinitclk.s @@ -0,0 +1,49 @@ +// *** +// cinitclk.asm - WIN32 C Run-Time Initialization for the clock() function +// +// Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved. +// +// Purpose: +// Initialization entry for the clock() function +// +// Notes: +// The variable _itimeb, used in clock.c, is declared in this module +// to force the inclusion of the initializer entry if clock() is +// referenced. +// +// This file declares a structure of type timeb. +// +// The include file "timeb.inc" must be kept in synch with sys/timeb.h +// and depends on the alignment behavior of the Intel 386. +// +// Revision History: +// 03-19-92 SKS Module created. +// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE) +// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs +// 08-06-92 SKS Revised to use new section names and macros +// 10-27-93 MDJ Wrote (this) ppc version based on code in i386 tree +// +// ***************************************************************************** + +#include "kxppc.h" + + .extern __inittime + + +beginSection(XIC) + + .long __inittime + +endSection(XIC) + + .globl __itimeb + + .data + .align 2 + +__itimeb: + .long 0 + .short 0 + .short 0 + .short 0 + .short 0 // struct timeb has four fields plus padding diff --git a/private/crt32/time/sources b/private/crt32/time/sources new file mode 100644 index 000000000..ee74a5740 --- /dev/null +++ b/private/crt32/time/sources @@ -0,0 +1,54 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + jeffrob 29-sep-1990, use crt32.def + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=crt +MINORCOMP=time + +TARGETNAME=time +TARGETPATH=..\obj +TARGETTYPE=LIBRARY +386_STDCALL=0 + +!INCLUDE ..\crt32.def + +SOURCES=asctime.c \ + clock.c \ + ctime.c \ + days.c \ + difftime.c \ + dtoxtime.c \ + ftime.c \ + gmtime.c \ + localtim.c \ + mktime.c \ + strftime.c \ + strdate.c \ + strtime.c \ + systime.c \ + time.c \ + timeset.c \ + tzset.c \ + utime.c \ + wcsftime.c diff --git a/private/crt32/time/strdate.c b/private/crt32/time/strdate.c new file mode 100644 index 000000000..ca106b12a --- /dev/null +++ b/private/crt32/time/strdate.c @@ -0,0 +1,99 @@ +/*** +*strdate.c - contains the function "_strdate()" for OS/2 +* +* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains the function _strdate() +* +*Revision History: +* 06-07-89 PHG Module created, base on asm version +* 03-20-90 GJF Made calling type _CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 07-25-90 SBM Removed '32' from API names +* 10-04-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include instead of +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 05-19-92 DJM ifndef for POSIX build. +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include +#include + +/*** +*char *_strdate(buffer) - return date in string form +* +*Purpose: +* _strdate() returns a string containing the date in "MM/DD/YY" form +* +*Entry: +* char *buffer = the address of a 9-byte user buffer +* +*Exit: +* returns buffer, which contains the date in "MM/DD/YY" form +* +*Exceptions: +* +*******************************************************************************/ + +char * _CALLTYPE1 _strdate ( + char *buffer + ) +{ + int month, day, year; + +#ifdef _CRUISER_ + DATETIME os2time; /* OS/2 time structure */ + + /* get time from OS/2, no error possible */ + DOSGETDATETIME(&os2time); + + month = os2time.month; + day = os2time.day; + year = os2time.year % 100; /* change year into 0-99 value */ + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + SYSTEMTIME dt; /* Win32 time structure */ + + GetLocalTime(&dt); + month = dt.wMonth; + day = dt.wDay; + year = dt.wYear % 100; /* change year into 0-99 value */ + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + /* store the components of the date into the string */ + /* store seperators */ + buffer[2] = buffer[5] = '/'; + /* store end of string */ + buffer[8] = '\0'; + /* store tens of month */ + buffer[0] = (char) (month / 10 + '0'); + /* store units of month */ + buffer[1] = (char) (month % 10 + '0'); + /* store tens of day */ + buffer[3] = (char) (day / 10 + '0'); + /* store units of day */ + buffer[4] = (char) (day % 10 + '0'); + /* store tens of year */ + buffer[6] = (char) (year / 10 + '0'); + /* store units of year */ + buffer[7] = (char) (year % 10 + '0'); + + return buffer; +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/strftime.c b/private/crt32/time/strftime.c new file mode 100644 index 000000000..516f0f88e --- /dev/null +++ b/private/crt32/time/strftime.c @@ -0,0 +1,891 @@ +/*** +*strftime.c - String Format Time +* +* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* 03-09-89 JCR Initial version. +* 03-15-89 JCR Changed day/month strings from all caps to leading cap +* 06-20-89 JCR Removed _LOAD_DGROUP code +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* , removed #include and +* removed some leftover 16-bit support. Also, fixed +* the copyright. +* 03-23-90 GJF Made static functions _CALLTYPE4. +* 07-23-90 SBM Compiles cleanly with -W3 (removed unreferenced +* variable) +* 08-13-90 SBM Compiles cleanly with -W3 with new build of compiler +* 10-04-90 GJF New-style function declarators. +* 01-22-91 GJF ANSI naming. +* 08-15-91 MRM Calls tzset() to set timezone info in case of %z. +* 08-16-91 MRM Put appropriate header file for tzset(). +* 10-10-91 ETC Locale support under _INTL switch. +* 12-18-91 ETC Use localized time strings structure. +* 02-10-93 CFW Ported to Cuda tree, change _CALLTYPE4 to _CRTAPI3. +* 02-16-93 CFW Massive changes: bug fixes & enhancements. +* 03-08-93 CFW Changed _expand to _expandtime. +* 03-09-93 CFW Handle string literals inside format strings. +* 03-09-93 CFW Alternate form cleanup. +* 03-17-93 CFW Change *count > 0, to *count != 0, *count is unsigned. +* 03-22-93 CFW Change "C" locale time format specifier to 24-hour. +* 03-30-93 GJF Call _tzset instead of __tzset (which no longer +* exists). +* 04-14-93 CFW Disable _alternate_form for 'X' specifier, fix count bug. +* 07-15-93 GJF Call __tzset() in place of _tzset(). +* +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#ifdef _INTL +#include +#include +#endif + +/* Prototypes for local routines */ +static void _CRTAPI3 _expandtime (char specifier, const struct tm *tmptr, char **out, size_t *count); +static void _CRTAPI3 _store_str (char *in, char **out, size_t *count); +static void _CRTAPI3 _store_num (int num, int digits, char **out, size_t *count); +#ifndef _INTL +static void _CRTAPI3 _store_time (const struct tm *tmptr, char **out, size_t *count); +static void _CRTAPI3 _store_date (const struct tm *tmptr, char **out, size_t *count); +#else /* _INTL */ +static void _CRTAPI3 _store_number (int num, char **out, size_t *count); +static void _CRTAPI3 _store_winword (const char *format, const struct tm *tmptr, char **out, size_t *count); +#endif + + +/* LC_TIME data for local "C" */ + +struct _lc_time_data _lc_time_c = { + + {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}, + + {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", }, + + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec"}, + + {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", + "November", "December"}, + + {"AM", "PM"} + +#ifdef _INTL + , { "M/d/yy" } + , { "dddd, MMMM dd, yyyy" } + , { "H:mm:ss" } +#endif + }; + + +/* Pointer to the current LC_TIME data structure. */ + +struct _lc_time_data *_lc_time_curr = &_lc_time_c; + +/* Flags */ +unsigned _alternate_form = 0; +#ifdef _INTL +unsigned _no_lead_zeros = 0; +#endif + + +/*** +*size_t strftime(string, maxsize, format, timeptr) - Format a time string +* +*Purpose: +* Place characters into the user's output buffer expanding time +* format directives as described in the user's control string. +* Use the supplied 'tm' structure for time data when expanding +* the format directives. +* [ANSI] +* +*Entry: +* char *string = pointer to output string +* size_t maxsize = max length of string +* const char *format = format control string +* const struct tm *timeptr = pointer to tb data structure +* +*Exit: +* !0 = If the total number of resulting characters including the +* terminating null is not more than 'maxsize', then return the +* number of chars placed in the 'string' array (not including the +* null terminator). +* +* 0 = Otherwise, return 0 and the contents of the string are +* indeterminate. +* +*Exceptions: +* +*******************************************************************************/ + +size_t _CRTAPI1 strftime ( + char *string, + size_t maxsize, + const char *format, + const struct tm *timeptr + ) +{ + + size_t left; /* space left in output string */ + + + /* Copy maxsize into temp. */ + left = maxsize; + + _mlock (_LC_TIME_LOCK); + + /* Copy the input string to the output string expanding the format + designations appropriately. Stop copying when one of the following + is true: (1) we hit a null char in the input stream, or (2) there's + no room left in the output stream. */ + + while (left > 0) + { + switch(*format) + { + + case('\0'): + + /* end of format input string */ + goto done; + + case('%'): + + /* Format directive. Take appropriate action based + on format control character. */ + + format++; /* skip over % char */ + +#ifdef _INTL + /* process flags */ + _alternate_form = 0; + if (*format == '#') + { + _alternate_form = 1; + format++; + } +#endif + _expandtime(*format, timeptr, &string, &left); + format++; /* skip format char */ + break; + + + default: + + /* store character, bump pointers, dec the char count */ +#ifdef _INTL + if (isleadbyte((int)(*format)) && left > 1) + { + *string++ = *format++; + left--; + } +#endif + *string++ = *format++; + left--; + break; + } + } + + + /* All done. See if we terminated because we hit a null char or because + we ran out of space */ + + done: + + _munlock (_LC_TIME_LOCK); + + if (left > 0) { + + /* Store a terminating null char and return the number of chars + we stored in the output string. */ + + *string = '\0'; + return(maxsize-left); + } + + else + return(0); + +} + + +/*** +*_expandtime() - Expand the conversion specifier +* +*Purpose: +* Expand the given strftime conversion specifier using the time struct +* and store it in the supplied buffer. +* +* The expansion is locale-dependent. +* +* *** For internal use with strftime() only *** +* +*Entry: +* char specifier = strftime conversion specifier to expand +* const struct tm *tmptr = pointer to time/date structure +* char **string = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +* +*Exceptions: +* +*******************************************************************************/ + +static void _CRTAPI3 _expandtime ( + char specifier, + const struct tm *timeptr, + char **string, + size_t *left + ) +{ + struct _lc_time_data *lc_time; /* lc_time data pointer */ + unsigned temp; /* temps */ + int wdaytemp; + + /* Get a copy of the current _lc_time_data pointer. This + should prevent the necessity of locking/unlocking in mthread + code (if we can guarantee that the various _lc_time data + structures are always in the same segment). */ + /* _INTL: contents of time strings structure can now change, + so thus we do use locking */ + + lc_time = _lc_time_curr; + + switch(specifier) { /* switch on specifier */ + + case('a'): /* abbreviated weekday name */ + _store_str((char *)(lc_time->wday_abbr[timeptr->tm_wday]), + string, left); + break; + + case('A'): /* full weekday name */ + _store_str((char *)(lc_time->wday[timeptr->tm_wday]), + string, left); + break; + + case('b'): /* abbreviated month name */ + _store_str((char *)(lc_time->month_abbr[timeptr->tm_mon]), + string, left); + break; + + case('B'): /* full month name */ + _store_str((char *)(lc_time->month[timeptr->tm_mon]), + string, left); + break; + + case('c'): /* date and time display */ +#ifdef _INTL + if (_alternate_form) + { + _alternate_form = FALSE; + _store_winword(lc_time->ww_ldatefmt, timeptr, string, left); + if (*left == 0) + return; + *(*string)++=' '; + (*left)--; + _store_winword(lc_time->ww_timefmt, timeptr, string, left); + } + else { + _store_winword(lc_time->ww_sdatefmt, timeptr, string, left); + if (*left == 0) + return; + *(*string)++=' '; + (*left)--; + _store_winword(lc_time->ww_timefmt, timeptr, string, left); + } +#else + if ((_DATE_LENGTH+_TIME_LENGTH+1) < *left) + { + _store_date(timeptr, string, left); + *(*string)++=' '; + (*left)--; + _store_time(timeptr, string, left); + } + else + *left=0; +#endif /* _INTL */ + break; + + case('d'): /* mday in decimal (01-31) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_mday, 2, string, left); + break; + + case('H'): /* 24-hour decimal (00-23) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_hour, 2, string, left); + break; + + case('I'): /* 12-hour decimal (01-12) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + if (!(temp = timeptr->tm_hour%12)) + temp=12; + _store_num(temp, 2, string, left); + break; + + case('j'): /* yday in decimal (001-366) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_yday+1, 3, string, left); + break; + + case('m'): /* month in decimal (01-12) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_mon+1, 2, string, left); + break; + + case('M'): /* minute in decimal (00-59) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_min, 2, string, left); + break; + + case('p'): /* AM/PM designation */ + if (timeptr->tm_hour <= 11) + _store_str((char *)(lc_time->ampm[0]), string, left); + else + _store_str((char *)(lc_time->ampm[1]), string, left); + break; + + case('S'): /* secs in decimal (00-59) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_sec, 2, string, left); + break; + + case('U'): /* sunday week number (00-53) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + wdaytemp = timeptr->tm_wday; + goto weeknum; /* join common code */ + + case('w'): /* week day in decimal (0-6) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + _store_num(timeptr->tm_wday, 1, string, left); + break; + + case('W'): /* monday week number (00-53) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + if (timeptr->tm_wday == 0) /* monday based */ + wdaytemp = 6; + else + wdaytemp = timeptr->tm_wday-1; + weeknum: + if (timeptr->tm_yday < wdaytemp) + temp=0; + else { + temp = timeptr->tm_yday/7; + if ((timeptr->tm_yday%7) >= wdaytemp) + temp++; + } + _store_num(temp, 2, string, left); + break; + + case('x'): /* date display */ +#ifdef _INTL + if (_alternate_form) + { + _alternate_form = FALSE; + _store_winword(lc_time->ww_ldatefmt, timeptr, string, left); + } + else + { + _store_winword(lc_time->ww_sdatefmt, timeptr, string, left); + } +#else + _store_date(timeptr, string, left); +#endif + break; + + case('X'): /* time display */ +#ifdef _INTL + _alternate_form = FALSE; + _store_winword(lc_time->ww_timefmt, timeptr, string, left); +#else + _store_time(timeptr, string, left); +#endif + break; + + case('y'): /* year w/o century (00-99) */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + temp = timeptr->tm_year%100; + _store_num(temp, 2, string, left); + break; + + case('Y'): /* year w/ century */ +#ifdef _INTL + _no_lead_zeros = _alternate_form; +#endif + temp = (((timeptr->tm_year/100)+19)*100) + + (timeptr->tm_year%100); + _store_num(temp, 4, string, left); + break; + + case('Z'): /* time zone name, if any */ + case('z'): /* time zone name, if any */ +#ifdef _POSIX_ + tzset(); /* Set time zone info */ + _store_str(tzname[((timeptr->tm_isdst)?1:0)], + string, left); +#else + __tzset(); /* Set time zone info */ + _store_str(_tzname[((timeptr->tm_isdst)?1:0)], + string, left); +#endif + break; + + case('%'): /* percent sign */ + *(*string)++ = '%'; + (*left)--; + break; + + default: /* unknown format directive */ + /* ignore the directive and continue */ + /* [ANSI: Behavior is undefined.] */ + break; + + } /* end % switch */ +} + + +/*** +*_store_str() - Copy a time string +* +*Purpose: +* Copy the supplied time string into the output string until +* (1) we hit a null in the time string, or (2) the given count +* goes to 0. +* +* *** For internal use with strftime() only *** +* +*Entry: +* char *in = pointer to null terminated time string +* char **out = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +*Exceptions: +* +*******************************************************************************/ + +static void _CRTAPI3 _store_str ( + char *in, + char **out, + size_t *count + ) +{ + +while ((*count != 0) && (*in != '\0')) { + *(*out)++ = *in++; + (*count)--; + } +} + + +/*** +*_store_num() - Convert a number to ascii and copy it +* +*Purpose: +* Convert the supplied number to decimal and store +* in the output buffer. Update both the count and +* buffer pointers. +* +* *** For internal use with strftime() only *** +* +*Entry: +* int num = pointer to integer value +* int digits = # of ascii digits to put into string +* char **out = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +*Exceptions: +* +*******************************************************************************/ + +static void _CRTAPI3 _store_num ( + int num, + int digits, + char **out, + size_t *count + ) +{ +int temp=0; + +#ifdef _INTL + if (_no_lead_zeros) { + _store_number (num, out, count); + return; + } +#endif + +if ((size_t)digits < *count) { + for (digits--; (digits+1); digits--) { + (*out)[digits] = (char)('0' + num % 10); + num /= 10; + temp++; + } + *out += temp; + *count -= temp; + } +else + *count = 0; +} + + +#ifndef _INTL + +/*** +*_store_time() - Store time in appropriate format +* +*Purpose: +* Format the time in the current locale's format +* and store it in the supplied buffer. +* +* [*** Currently, this routine assumes standard "C" +* locale. When full localization support is introduced, +* this functionality will have to be expanded.] +* +* Standard "C" locale time format: +* +* hh:mm:ss +* +* *** For internal use with strftime() only *** +* +*Entry: +* +* const struct tm *tmptr = pointer to time/date structure +* char **out = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +*Exceptions: +* +*******************************************************************************/ + +static void _CRTAPI3 _store_time ( + const struct tm *tmptr, + char **out, + size_t *count + ) +{ + +if (_TIME_LENGTH < *count) { + + _store_num(tmptr->tm_hour, 2, out, count); + *(*out)++ = ':'; + _store_num(tmptr->tm_min, 2, out, count); + *(*out)++ = ':'; + _store_num(tmptr->tm_sec, 2, out, count); + + *count -= 2; /* count the colons */ +} + +else + *count = 0; + +} + + +/*** +*_store_date() - Store date in appropriate format +* +*Purpose: +* Format the date in the current locale's format +* and store it in the supplied buffer. +* +* [*** Currently, this routine assumes standard "C" +* locale. When full localization support is introduced, +* this functionality will have to be expanded.] +* +* Standard "C" locale date format: +* +* mm/dd/yy +* +* *** For internal use with strftime() only *** +* +*Entry: +* +* const struct tm *tmptr = pointer to time/date structure +* char **out = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +*Exceptions: +* +*******************************************************************************/ + +static void _CRTAPI3 _store_date ( + const struct tm *tmptr, + char **out, + size_t *count + ) +{ + +if (_DATE_LENGTH < *count) { + + _store_num(tmptr->tm_mon+1, 2, out, count); + *(*out)++ = '/'; + _store_num(tmptr->tm_mday, 2, out, count); + *(*out)++ = '/'; + _store_num(tmptr->tm_year%100, 2, out, count); + + *count -= 2; /* count the backslashes */ + } + +else + *count = 0; + +} + +#else /* _INTL */ + +/*** +*_store_number() - Convert positive integer to string +* +*Purpose: +* Convert positive integer to a string and store it in the output +* buffer with no null terminator. Update both the count and +* buffer pointers. +* +* Differs from _store_num in that the precision is not specified, +* and no leading zeros are added. +* +* *** For internal use with strftime() only *** +* +* Created from xtoi.c +* +*Entry: +* int num = pointer to integer value +* char **out = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +* +*Exceptions: +* The buffer is filled until it is out of space. There is no +* way to tell beforehand (as in _store_num) if the buffer will +* run out of space. +* +*******************************************************************************/ + +static void _CRTAPI3 _store_number ( + int num, + char **out, + size_t *count + ) +{ + char *p; /* pointer to traverse string */ + char *firstdig; /* pointer to first digit */ + char temp; /* temp char */ + + p = *out; + + /* put the digits in the buffer in reverse order */ + if (*count > 1) + { + do { + *p++ = (char) (num % 10 + '0'); + (*count)--; + } while ((num/=10) > 0 && *count > 1); + } + + firstdig = *out; /* firstdig points to first digit */ + *out = p; /* return pointer to next space */ + p--; /* p points to last digit */ + + /* reverse the buffer */ + do { + temp = *p; + *p-- = *firstdig; + *firstdig++ = temp; /* swap *p and *firstdig */ + } while (firstdig < p); /* repeat until halfway */ +} + + +/*** +*_store_winword() - Store date/time in WinWord format +* +*Purpose: +* Format the date/time in the supplied WinWord format +* and store it in the supplied buffer. +* +* *** For internal use with strftime() only *** +* +* The WinWord format is converted token by token to +* strftime conversion specifiers. _expandtime is then called to +* do the work. The WinWord format is expected to be a +* character string (not wide-chars). +* +*Entry: +* const char **format = address of pointer to WinWord format +* const struct tm *tmptr = pointer to time/date structure +* char **out = address of pointer to output string +* size_t *count = address of char count (space in output area) +* +*Exit: +* none +* +*Exceptions: +* +*******************************************************************************/ + +static void _CRTAPI3 _store_winword ( + const char *format, + const struct tm *tmptr, + char **out, + size_t *count + ) +{ + char specifier; + const char *p; + int repeat; + + while (*format && *count != 0) + { + specifier = 0; /* indicate no match */ + _no_lead_zeros = 0; /* default is print leading zeros */ + + /* count the number of repetitions of this character */ + for (repeat=0, p=format; *p++ == *format; repeat++); + /* leave p pointing to the beginning of the next token */ + p--; + + /* switch on ascii format character and determine specifier */ + switch (*format) + { + case 'M': + switch (repeat) + { + case 1: _no_lead_zeros = 1; /* fall thru */ + case 2: specifier = 'm'; break; + case 3: specifier = 'b'; break; + case 4: specifier = 'B'; break; + } break; + case 'd': + switch (repeat) + { + case 1: _no_lead_zeros = 1; /* fall thru */ + case 2: specifier = 'd'; break; + case 3: specifier = 'a'; break; + case 4: specifier = 'A'; break; + } break; + case 'y': + switch (repeat) + { + case 2: specifier = 'y'; break; + case 4: specifier = 'Y'; break; + } break; + case 'h': + switch (repeat) + { + case 1: _no_lead_zeros = 1; /* fall thru */ + case 2: specifier = 'I'; break; + } break; + case 'H': + switch (repeat) + { + case 1: _no_lead_zeros = 1; /* fall thru */ + case 2: specifier = 'H'; break; + } break; + case 'm': + switch (repeat) + { + case 1: _no_lead_zeros = 1; /* fall thru */ + case 2: specifier = 'M'; break; + } break; + case 's': /* for compatibility; not strictly WinWord */ + switch (repeat) + { + case 1: _no_lead_zeros = 1; /* fall thru */ + case 2: specifier = 'S'; break; + } break; + case 'A': + case 'a': + if (!_stricmp(format, "am/pm")) + p = format + 5; + else if (!_stricmp(format, "a/p")) + p = format + 3; + specifier = 'p'; + break; + case '\'': /* literal string */ + if (repeat & 1) /* odd number */ + { + format += repeat; + while (*format && *count != 0) + { + if (*format == '\'') + { + format++; + break; + } + if (isleadbyte((int)*format)) + { + *(*out)++ = *format++; + (*count)--; + } + *(*out)++ = *format++; + (*count)--; + } + } + else { /* even number */ + format += repeat; + } + continue; + + default: /* non-control char, print it */ + break; + } /* switch */ + + /* expand specifier, or copy literal if specifier not found */ + if (specifier) + { + _expandtime(specifier, tmptr, out, count); + format = p; /* bump format up to the next token */ + } else { + if (isleadbyte((int)*format)) + { + *(*out)++ = *format++; + (*count)--; + } + *(*out)++ = *format++; + (*count)--; + } + } /* while */ +} + +#endif /* _INTL */ diff --git a/private/crt32/time/strtime.c b/private/crt32/time/strtime.c new file mode 100644 index 000000000..7525b672d --- /dev/null +++ b/private/crt32/time/strtime.c @@ -0,0 +1,98 @@ +/*** +*strtime.c - contains the function "_strtime()" for OS/2 +* +* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains the function _strtime() +* +*Revision History: +* 06-07-89 PHG Module created, based on asm version +* 03-20-90 GJF Made calling type _CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 07-25-90 SBM Removed '32' from API names +* 10-04-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include instead of +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 05-19-92 DJM ifndef for POSIX build. +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include +#include + +/*** +*char *_strtime(buffer) - return time in string form +* +*Purpose: +* _strtime() returns a string containing the time in "HH:MM:SS" form +* +*Entry: +* char *buffer = the address of a 9-byte user buffer +* +*Exit: +* returns buffer, which contains the time in "HH:MM:SS" form +* +*Exceptions: +* +*******************************************************************************/ + +char * _CALLTYPE1 _strtime ( + char *buffer + ) +{ + int hours, minutes, seconds; + +#ifdef _CRUISER_ + DATETIME os2time; /* OS/2 time structure */ + + /* ask OS/2 for the time, no error possible */ + DOSGETDATETIME(&os2time); + hours = os2time.hours; + minutes = os2time.minutes; + seconds = os2time.seconds; + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + SYSTEMTIME dt; /* Win32 time structure */ + + GetLocalTime(&dt); + hours = dt.wHour; + minutes = dt.wMinute; + seconds = dt.wSecond; + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + /* store the components of the time into the string */ + /* store separators */ + buffer[2] = buffer[5] = ':'; + /* store end of string */ + buffer[8] = '\0'; + /* store tens of hour */ + buffer[0] = (char) (hours / 10 + '0'); + /* store units of hour */ + buffer[1] = (char) (hours % 10 + '0'); + /* store tens of minute */ + buffer[3] = (char) (minutes / 10 + '0'); + /* store units of minute */ + buffer[4] = (char) (minutes % 10 + '0'); + /* store tens of second */ + buffer[6] = (char) (seconds / 10 + '0'); + /* store units of second */ + buffer[7] = (char) (seconds % 10 + '0'); + + return buffer; +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/systime.c b/private/crt32/time/systime.c new file mode 100644 index 000000000..cd7590cd0 --- /dev/null +++ b/private/crt32/time/systime.c @@ -0,0 +1,104 @@ +/*** +*systime.c - _getsystime and _setsystime +* +* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _getsystime() and _setsystime() +* +*Revision History: +* 08-22-91 BWM Wrote module. +* 05-19-92 DJM ifndef for POSIX build. +* 09-25-92 SKS Use SetLocalTime(), not SetSystemTime(). +* Fix bug: daylight flag must be initialized to -1. +* Replace C++ comments with C-style comments +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include +#include + +#if !defined(_WIN32_) +#error ERROR - ONLY WIN32 TARGET SUPPORTED! +#endif + +/*** +*unsigned _getsystime(timestruc, milliseconds) - Get current system time +* +*Purpose: +* +*Entry: + struct tm * ptm - time structure +* +*Exit: +* milliseconds of current time +* +*Exceptions: +* +*******************************************************************************/ + +unsigned _CALLTYPE1 _getsystime(struct tm * ptm) +{ + SYSTEMTIME st; + + GetLocalTime(&st); + + ptm->tm_isdst = -1; /* mktime() computes whether this is */ + /* during Standard or Daylight time. */ + ptm->tm_sec = (int)st.wSecond; + ptm->tm_min = (int)st.wMinute; + ptm->tm_hour = (int)st.wHour; + ptm->tm_mday = (int)st.wDay; + ptm->tm_mon = (int)st.wMonth - 1; + ptm->tm_year = (int)st.wYear - 1900; + ptm->tm_wday = (int)st.wDayOfWeek; + + /* Normalize uninitialized fields */ + mktime(ptm); + + return (st.wMilliseconds); +} + +/*** +*unsigned _setsystime(timestruc, milliseconds) - Set new system time +* +*Purpose: +* +*Entry: +* struct tm * ptm - time structure +* unsigned milliseconds - milliseconds of current time +* +*Exit: +* 0 if succeeds +* system error if fails +* +*Exceptions: +* +*******************************************************************************/ + +unsigned _CALLTYPE1 _setsystime(struct tm * ptm, unsigned uMilliseconds) +{ + SYSTEMTIME st; + + /* Normalize uninitialized fields */ + mktime(ptm); + + st.wYear = (WORD)(ptm->tm_year + 1900); + st.wMonth = (WORD)(ptm->tm_mon + 1); + st.wDay = (WORD)ptm->tm_mday; + st.wHour = (WORD)(ptm->tm_hour); + st.wMinute = (WORD)ptm->tm_min; + st.wSecond = (WORD)ptm->tm_sec; + st.wMilliseconds = (WORD)uMilliseconds; + + if (!SetLocalTime(&st)) { + return ((int)GetLastError()); + } + + return (0); +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/time.c b/private/crt32/time/time.c new file mode 100644 index 000000000..8a77b538e --- /dev/null +++ b/private/crt32/time/time.c @@ -0,0 +1,78 @@ +/*** +*time.c - get current system time +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines time() - gets the current system time and converts it to +* internal (time_t) format time. +* +*Revision History: +* 06-07-89 PHG Module created, based on asm version +* 03-20-90 GJF Made calling type _CALLTYPE1, added #include +* and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 07-25-90 SBM Removed '32' from API names +* 10-04-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include instead of +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 05-19-92 DJM ifndef for POSIX build. +* 03-30-93 GJF Replaced dtoxtime() reference by __gmtotime_t. Also +* purged Cruiser support. +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include +#include +#include +#include + +/*** +*time_t time(timeptr) - Get current system time and convert to time_t value. +* +*Purpose: +* Gets the current date and time and stores it in internal (time_t) +* format. The time is returned and stored via the pointer passed in +* timeptr. If timeptr == NULL, the time is only returned, not stored in +* *timeptr. The internal (time_t) format is the number of seconds since +* 00:00:00, Jan 1 1970 (UTC). +* +*Entry: +* time_t *timeptr - pointer to long to store time in. +* +*Exit: +* returns the current time. +* +*Exceptions: +* +*******************************************************************************/ + +time_t _CRTAPI1 time ( + time_t *timeptr + ) +{ + time_t tim; + + SYSTEMTIME dt; + + /* ask Win32 for the time, no error possible */ + + GetSystemTime(&dt); + + /* convert using our private routine */ + tim = __gmtotime_t((int)dt.wYear, + (int)dt.wMonth, + (int)dt.wDay, + (int)dt.wHour, + dt.wMinute, + dt.wSecond); + + if (timeptr) + *timeptr = tim; /* store time if requested */ + + return tim; +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/timeset.c b/private/crt32/time/timeset.c new file mode 100644 index 000000000..86a9f3cd1 --- /dev/null +++ b/private/crt32/time/timeset.c @@ -0,0 +1,92 @@ +/*** +*timeset.c - contains defaults for timezone setting +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Contains the timezone values for default timezone. +* Also contains month and day name three letter abbreviations. +* +*Revision History: +* 12-03-86 JMB added Japanese defaults and module header +* 09-22-87 SKS fixed declarations, include +* 02-21-88 SKS Clean up ifdef-ing, change IBMC20 to IBMC2 +* 07-05-89 PHG Remove _NEAR_ for 386 +* 08-15-89 GJF Fixed copyright, indents. Got rid of _NEAR. +* 03-20-90 GJF Added #include and fixed the copyright. +* 05-18-90 GJF Added _VARTYPE1 to publics to match declaration in +* time.h (picky 6.0 front-end!). +* 01-21-91 GJF ANSI naming. +* 08-10-92 PBS Posix support(TZ stuff). +* 06-08-93 KRS Tie JAPAN switch to _KANJI switch. +* +*******************************************************************************/ + +#include +#include +#include +#include + +#ifndef _POSIX_ + +#ifdef _KANJI +#define JAPAN +#endif + +#ifdef JAPAN +static char tzstd[11] = { "JST" }; +static char tzdst[11] = { "\0\0\0" }; +#else +static char tzstd[11] = { "PST" }; +static char tzdst[11] = { "PDT" }; +#endif + + +#ifdef JAPAN + +long _timezone = (-9)*3600L; /* Japanese Time */ +int _daylight = 0; /* no Daylight Savings Time */ + +#else /* JAPAN */ +#ifdef IBMC2 + +long _timezone = 5*3600L; /* Eastern Time */ +int _daylight = 1; /* Daylight Savings Time */ + /* when appropriate */ +#else /* IBMC2 */ + +long _timezone = 8*3600L; /* Pacific Time */ +int _daylight = 1; /* Daylight Savings Time */ + /* when appropriate */ +#endif /* IBMC2 */ +#endif /* JAPAN */ + +char * _tzname[2] = {tzstd, tzdst }; + +#else /* _POSIX_ */ + +long _timezone = 8*3600L; /* Pacific Time */ +int _daylight = 1; /* Daylight Savings Time */ + /* when appropriate */ + +static char tzstd[11] = { "PST" }; +static char tzdst[11] = { "PDT" }; + +char * tzname[2] = {tzstd, tzdst }; + +char *_rule; +long _dstoffset = 3600L; + +#endif /* _POSIX_ */ + +/* Day names must be Three character abbreviations strung together */ + +char __dnames[] = { + "SunMonTueWedThuFriSat" +}; + +/* Month names must be Three character abbreviations strung together */ + +char __mnames[] = { + "JanFebMarAprMayJunJulAugSepOctNovDec" +}; diff --git a/private/crt32/time/tzset.c b/private/crt32/time/tzset.c new file mode 100644 index 000000000..d5b5c711e --- /dev/null +++ b/private/crt32/time/tzset.c @@ -0,0 +1,927 @@ +/*** +*tzset.c - set timezone information and see if we're in daylight time +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _tzset() - set timezone and daylight saving time vars +* +*Revision History: +* 03-??-84 RLB initial version +* 03-26-86 TC added minus capability to time difference w.r.t GMT +* 03-27-86 TC fixed daylight davings time calculation, off by a day +* error +* 12-03-86 SKS daylight savings time is different starting april 1987 +* Fixed off-by-1 errors when either Apr 30 or Oct 31 is +* Sat. Simplified leap year check: this works for +* 1970-2099 only! +* 11-19-87 SKS Add __tzset() which calls tzset only the first time +* Made _isindst() a near procedure +* 11-25-87 WAJ Added calls to _lock and _unlock +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 01-27-88 SKS Made _isindst() and _dtoxtime() are no longer near (for +* QC) +* 05-24-88 PHG Merged DLL and normal versions +* 03-20-90 GJF Made calling type _CALLTYPE1, added #include +* , removed #include , removed +* some leftover 16-bit support and fixed the copyright. +* Also, cleaned up the formatting a bit. +* 03-23-90 GJF Made static functions _CALLTYPE4. +* 07-30-90 SBM Added void to empty function arg lists to create +* prototypes +* 10-04-90 GJF New-style function declarators. +* 01-21-91 GJF ANSI naming. +* 08-10-92 PBS Posix Support (TZ stuff). +* 03-30-93 GJF Ported C8-16 version to Win32. +* 06-28-93 GJF Limited support for system's notion of time zone +* in Windows NT. +* 07-15-93 GJF Resurrected __tzset(). +* +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#ifdef _POSIX_ +#include +#else +#include +#include +#endif +#include + +#ifndef _POSIX_ +/* + * Pointer to a saved copy of the TZ value obtained in the previous call + * to tzset() set (if any). + */ +static char * lastTZ = NULL; +#endif + + +/*** +*void tzset() - sets timezone information and calc if in daylight time +* +*Purpose: +* Sets the timezone information from the TZ environment variable +* and then sets _timezone, _daylight, and _tzname. If we're in daylight +* time is automatically calculated. +* +*Entry: +* None, reads TZ environment variable. +* +*Exit: +* sets _daylight, _timezone, and _tzname global vars, no return value +* +*Exceptions: +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#ifdef MTHREAD +static void _CRTAPI3 _tzset_lk(void); +#else +#define _tzset_lk _tzset +#endif + +void _CRTAPI1 __tzset(void) +{ + static int first_time; + + if ( !first_time ) { + + _mlock( _TIME_LOCK ); + + if ( !first_time ) { + _tzset_lk(); + first_time++; + } + + _munlock(_TIME_LOCK ); + + } +} + + +#ifdef MTHREAD /* multi-thread; define both tzset and _tzset_lk */ +void _CRTAPI1 _tzset ( + void + ) +{ + _mlock( _TIME_LOCK ); + + _tzset_lk(); + + _munlock( _TIME_LOCK ); +} + + +static void _CRTAPI3 _tzset_lk ( + +#else /* non multi-thread; only define tzset */ + +void _CRTAPI1 _tzset ( + +#endif /* rejoin common code */ + + void + ) +{ + REG1 char *TZ; + REG2 int negdiff = 0; + + _mlock(_ENV_LOCK); + + /* + * Fetch the value of the TZ environment variable. + */ + if ( (TZ = _getenv_lk("TZ")) == NULL ) { + /* + * If there is no TZ environment variable, try to use the + * time zone information from the system. + */ + TIME_ZONE_INFORMATION tzinfo; + + if ( GetTimeZoneInformation( &tzinfo ) != 0xffffffff ) { + /* + * Derive _timezone value from Bias and StandardBias fields. + */ + _timezone = tzinfo.Bias * 60L; + + if ( tzinfo.StandardDate.wMonth != 0 ) + _timezone += (tzinfo.StandardBias * 60L); + + /* + * Check to see if there is a daylight time bias. If so, we + * ASSUME it is USA daylight saving time (that is all we + * support for rev. one). + */ + if ( (tzinfo.DaylightDate.wMonth != 0) && + (tzinfo.DaylightBias != 0) ) + _daylight = 1; + else + _daylight = 0; + + /* + * Remove the default names, but don't try to determine + * suitable replacements (NT does not enforce any standard + * or convention for timezone naming). + */ + *_tzname[0] = '\0'; + *_tzname[1] = '\0'; + } + + /* + * Time zone information is unavailable, just return. + */ + _munlock(_ENV_LOCK); + return; + } + + + if ( (*TZ == '\0') || ((lastTZ != NULL) && (strcmp(TZ, lastTZ) == 0)) ) + { + /* + * Either TZ is NULL, pointing to '\0', or is the unchanged + * from a earlier call (to this function). In any case, there + * is no work to do, so just return + */ + _munlock(_ENV_LOCK); + return; + } + + /* + * Update lastTZ + */ + if (lastTZ != NULL) { + free(lastTZ); + } + lastTZ = strdup(TZ); + + _munlock(_ENV_LOCK); + + /* + * Process TZ value and update _tzname, _timezone and _daylight. + */ + + strncpy(_tzname[0], TZ, 3); + + /* + * time difference is of the form: + * + * [+|-]hh[:mm[:ss]] + * + * check minus sign first. + */ + if ( *(TZ += 3) == '-' ) { + negdiff++; + TZ++; + } + + /* + * process, then skip over, the hours + */ + _timezone = atol(TZ) * 3600L; + + while ( (*TZ == '+') || ((*TZ >= '0') && (*TZ <= '9')) ) TZ++; + + /* + * check if minutes were specified + */ + if ( *TZ == ':' ) { + /* + * process, then skip over, the minutes + */ + _timezone += atol(++TZ) * 60L; + while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++; + + /* + * check if seconds were specified + */ + if ( *TZ == ':' ) { + /* + * process, then skip over, the seconds + */ + _timezone += atol(++TZ); + while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++; + } + } + + if ( negdiff ) + _timezone = -_timezone; + + /* + * finally, check for a DST zone suffix + */ + if ( _daylight = *TZ ) + strncpy(_tzname[1], TZ, 3); + else + *_tzname[1] = '\0'; + +} + + +/*** +*int _isindst(tb) - determine if broken-down time falls in DST +* +*Purpose: +* Determine if the given broken-down time falls within DST. Only +* modern, summer-time DST is handled (USA, post 1967). +* +* This is the rule for years before 1987: +* a time is in DST iff it is on or after 02:00:00 on the last Sunday +* in April and before 01:00:00 on the last Sunday in October. +* This is the rule for years starting with 1987: +* a time is in DST iff it is on or after 02:00:00 on the first Sunday +* in April and before 01:00:00 on the last Sunday in October. +* +*Entry: +* struct tm *tb - structure holding broken-down time value +* +*Exit: +* 1, if time represented is in DST +* 0, otherwise +* +*******************************************************************************/ + +int _CRTAPI1 _isindst ( + REG1 struct tm *tb + ) +{ + int mdays; + REG2 int yr; + int critsun; + + /* + * Handle easy cases. + * + * Modern DST was put into effect by Congress in 1967. Also, if the + * month is before April or after October, it cannot be DST. + */ + if ( (tb->tm_year < 67) || (tb->tm_mon < 3) || (tb->tm_mon > 9) ) + return(0); + + /* + * If the month is after April and before October, it must be DST. + */ + if ( (tb->tm_mon > 3) && (tb->tm_mon < 9) ) + return(1); + + /* + * Now for the hard part. Month is April or October; see if date + * falls between appropriate Sundays. + */ + + /* + * The objective for years before 1987 (after 1986) is to determine + * if the day is on or after 2:00 am on the last (first) Sunday in + * April, or before 1:00 am on the last Sunday in October. + * + * We know the year-day (0..365) of the current time structure. We must + * determine the year-day of the last (first) Sunday in this month, + * April or October, and then do the comparison. + * + * To determine the year-day of the last Sunday, we do the following: + * 1. Get the year-day of the last day of the current month (Apr + * or Oct) + * 2. Determine the week-day number of #1, + * which is defined as 0 = Sun, 1 = Mon, ... 6 = Sat + * 3. Subtract #2 from #1 + * + * To determine the year-day of the first Sunday, we do the following: + * 1. Get the year-day of the 7th day of the current month + * (April) + * 2. Determine the week-day number of #1, + * which is defined as 0 = Sun, 1 = Mon, ... 6 = Sat + * 3. Subtract #2 from #1 + */ + + /* + * First we get #1. The year-days for each month are stored in _days[] + * they're all off by -1 + */ + if ( ((yr = tb->tm_year) > 86) && (tb->tm_mon == 3) ) + mdays = 7 + _days[tb->tm_mon]; + else + mdays = _days[tb->tm_mon+1]; + + /* + * if this is a leap-year, add an extra day + */ + if ( !(yr & 3) ) + mdays++; + + /* + * mdays now has #1 + */ + + /* Now get #2. We know the week-day number of January 1, 1970, which is + * defined as the constant _BASE_DOW. Add to this the number of elapsed + * days since then, take the result mod 7, and we have our day number. + * + * To obtain #3, we just subtract this from mdays. + */ + + critsun = mdays - ((mdays + 365 * (yr - 70) + ((yr - 1) >> 2) - + _LEAP_YEAR_ADJUST + _BASE_DOW) % 7); + + /* Now we know 1 and 3; we're golden: */ + + return ( (tb->tm_mon == 3) + ? ((tb->tm_yday > critsun) || + ((tb->tm_yday == critsun) && (tb->tm_hour >= 2))) + : ((tb->tm_yday < critsun) || + ((tb->tm_yday == critsun) && (tb->tm_hour < 1))) ); +} + + +#else /* _POSIX_ */ + +/* + * The following is an implementation of the TZ grammar specified in the + * document: + * + * 8.1.1 Extension to Time Functions + * IEEE Std 1003.1 - 1990 + * Page 152 - 153 + * + * The TZ grammar looks like: + * + * stdoffset[dst[offset][,start[/time],end[/time]]] + * + * Variables used in code: + * + * tzname[0] ==> std + * _timezone ==> offset(the one after 'std') + * tzname[1] ==> dst + * _dstoffset ==> offset(the one after 'dst') + * _startdate ==> start + * _starttime ==> time(the one after 'start') + * _enddate ==> end + * _endtime ==> time(the one after 'end') + * + */ + +/* + * Refer to the document for the detailed description of fields of _DSTDATE. + * Two of Jn, n, and Mm are -1, indicating the one(not -1) is a vaild value. + */ + +typedef struct _DSTDATE { + int Jn; /* -1 or [1, 365](year day and leap day shall not be counted) */ + int n; /* -1 or [0, 365](year day and leap day shall be counted) */ + int Mm; /* -1 or [1, 12](month) */ + int Mn; /* [1, 5] if Mm != -1 (week) */ + int Md; /* [0, 6] if Mm != -1 (weekday, Sunday == 0) */ +} DSTDATE, *PDSTDATE; + +#define SEC_PER_HOUR (60 * 60) +#define SEC_PER_DAY (SEC_PER_HOUR * 24) + + +/* + * The default TZ in tzset() should look like: + * + * TZ = "PST8PDT,M4.1.0/2:00,M10.5.0/2:00"; + */ + +/* Day light saving start/end date and default vaules */ +static DSTDATE _startdate = { -1, -1, 4, 1, 0}; +static DSTDATE _enddate = {-1, -1, 10, 5, 0}; + + +/* Seconds since midnight on _startdate/_enddate with default values. + * _endtime is 1am instead of 2am because the DST end time is 2am + * local time, which by default is 1am standard time. + */ +long _starttime = 7200L, _endtime = 7200L; + +/* + * If we are only interested in years between 1901 and 2099, we could use this: + * + * #define IS_LEAP_YEAR(y) (y % 4 == 0) + */ + +#define IS_LEAP_YEAR(y) ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) + + +/* + * ParsePosixStdOrDst - parse the std or dst element in TZ. + * + * ENTRY pch - beginning of the substring in TZ. + * + * RETURN pointer to one position after the std or dst element parsed, + * or NULL if failed. + */ + + +static char * _CRTAPI3 +ParsePosixStdOrDst( + REG1 char *pch + ) +{ +#define UNWANTED(x) (isdigit(x) || x=='\0' || x==',' || x=='-' || x=='+') + int i; + + /* + * Check against the rule. + */ + + if(*pch == ':' || UNWANTED(*pch)) { + return NULL; + } + + /* + * Get a valid std or dst(i.e. 3 <= lenth_of(std | dst) <= TZNAME_MAX). + */ + + for(i=1, ++pch; (i < TZNAME_MAX) && !UNWANTED(*pch); i++, pch++) { + ; + } + + /* + * pch now point to 1 position after the valid std or dst. + */ + + return (i >= 3) ? pch : NULL; +} + + +/* + * ParsePosixOffset - parse the offset element in TZ. The format of time is: + * + * [- | +]hh[:mm[:ss]] + * + * ENTRY pch - beginning of the substring in TZ. + * + * ptime - pointer to a variable(_timezone or _dstoffset) storing the + * time(in seconds) parsed. + * + * RETURN pointer to one position after the end of the offset element parsed. + */ + + +static char * _CRTAPI3 +ParsePosixOffset( + REG1 char *pch, + REG2 long *poffset + ) +{ + int fNegative; + long offset; + + if((fNegative = (*pch == '-')) || *pch == '+') { + pch++; + } + + offset = atol(pch)*3600L; /* hh */ + + while(*pch && isdigit(*pch)) { + pch++; + } + + if(*pch == ':') { + offset += atol(++pch)*60L; /* mm */ + while(*pch && isdigit(*pch)) { + pch++; + } + + if(*pch == ':') { + offset += atol(++pch); /* ss */ + while(*pch && isdigit(*pch)) { + pch++; + } + } + } + + *poffset = fNegative ? -offset : offset; + + return pch; +} + + + +/* + * ParsePosixDate - parse the date element in TZ. The format of date is one + * of following: + * + * Jn, n, and Mm.n.d + * + * ENTRY pch - beginning of the substring in TZ. + * + * pDstDate - pointer to _startdate or _enddate storing the result. + * + * RETURN pointer to one position after the end of the date element parsed, + * or NULL if failed. + */ + +static char * _CRTAPI3 +ParsePosixDate( + REG1 char *pch, + REG2 PDSTDATE pDstDate + ) +{ + pDstDate->Jn = -1; + pDstDate->n = -1; + pDstDate->Mn = -1; + + /* + * Two out of the three -1's will remain. + */ + + if(*pch == 'J') { /* Jn */ + pDstDate->Jn = atoi(++pch); + } else if(*pch != 'M') { /* n */ + pDstDate->n = atoi(pch); + } else { /* Mm.n.d */ + + pDstDate->Mm = atoi(++pch); + + if(*++pch != '.') { + pch++; + } + pDstDate->Mn = atoi(++pch); + + if(*++pch != '.') { + pch++; + } + pDstDate->Md = atoi(++pch); + } + + while(*pch && isdigit(*pch)) { + pch++; + } + +#define IN_RANGE(x, a, b) (x >= a && x <= b) + + return ((pDstDate->Jn != -1 && IN_RANGE(pDstDate->Jn, 1, 365)) || + (pDstDate->n != -1 && IN_RANGE(pDstDate->n, 0, 365)) || + (pDstDate->Mm != -1 && IN_RANGE(pDstDate->Mm, 1, 12) && + IN_RANGE(pDstDate->Mn, 1, 5) && IN_RANGE(pDstDate->Md, 0, 6))) + ? pch : NULL; +} + +/* + * ParsePosixTime - parse the time element in TZ. The format of time is: + * + * hh[:mm[:ss]] + * + * ENTRY pch - beginning of the substring in TZ. + * + * ptime - pointer to a variable(_starttime or _endtime) storing the + * time(in seconds) parsed. + * + * RETURN pointer to one position after the end of the time element parsed. + */ + +static char * _CRTAPI3 +ParsePosixTime( + REG1 char *pch, + REG2 long *ptime + ) +{ + long time; + + time = atol(pch)*SEC_PER_HOUR; /* hh */ + + while(*pch && isdigit(*pch)) { + pch++; + } + + if(*pch == ':') { + + time += atol(++pch)*60L; /* mm */ + while(*pch && isdigit(*pch)) { + pch++; + } + + if(*pch == ':') { + + time += atol(++pch); /* ss */ + while(*pch && isdigit(*pch)) { + pch++; + } + } + } + + *ptime = time; + + return pch; +} + +/* + * tzset - sets the timezone information from the TZ environment variable. + * Global tzname[], _timezone, _daylight, and _dstoffset will be + * set. Static _startdate, _enddate, _starttime, and _endtime will + * also be set. TZ string looks like: + * + * stdoffset[dst[offset][,start[/time],end[/time]]] + * + * In form of variables: tzname[0]_timezone[tzname[1][_dstoffset] + * [,_startdate[/_starttime],_enddate[/_endtime]]] + * + * ENTRY none. + * + * RETURN none. + */ + +void _CRTAPI1 tzset( + void + ) +{ + /* pch points to the beginning of an element to be parsed. */ + REG1 char *pch; + + /* pchCurr points to one position after the end of last element parsed. */ + REG2 char *pchCurr; + + char *TZ; + + _endtime = 7200L; + _starttime = 7200L; + + if (!(TZ = getenv("TZ")) || !*TZ) { + TZ = "PST8PDT7,M4.1.0/2:00,M10.5.0/2:00"; /* use default */ + } + + if((pchCurr = ParsePosixStdOrDst(pch=TZ)) == NULL) { + return; + } + + memcpy(tzname[0], pch, (int)(pchCurr-pch)); + tzname[0][(int)(pchCurr-pch)] = '\0'; + + if((pchCurr = ParsePosixOffset(pch=pchCurr, &_timezone)) == NULL) { + return; + } + + _daylight = (*pchCurr != '\0'); + + if(!_daylight) { + return; + } + + if((pchCurr = ParsePosixStdOrDst(pch=pchCurr)) == NULL) { + return; + } + + memcpy(tzname[1], pch, (int)(pchCurr-pch)); + tzname[1][(int)(pchCurr-pch)] = '\0'; + + if(isdigit(*pchCurr) || *pchCurr == '-' || *pchCurr == '+') { + if((pchCurr = ParsePosixOffset(pch=pchCurr, &_dstoffset)) == NULL) { + return; + } + } else { + /* default: 1 hour ahead of standard time */ + _dstoffset = _timezone - SEC_PER_HOUR; + } + + if(*pchCurr == ',') { /* ,start[/time],end[/time] */ + + if((pchCurr = ParsePosixDate(pchCurr+1, &_startdate)) == NULL) { + goto out; + } + + if(*pchCurr == '/') { + if(!(pchCurr = ParsePosixTime(pchCurr+1, &_starttime))) { + goto out; + } + } + + if(*pchCurr != ',') { + goto out; + } + + if ((pchCurr = ParsePosixDate(pchCurr+1, &_enddate)) == NULL) { + goto out; + } + + if (*pchCurr == '/') { + if(!(pchCurr = ParsePosixTime(pchCurr+1, &_endtime))) { + goto out; + } + } + } +out: + /* + * Adjust the _endtime to account for the fact that + * dst ends at _endtime local time, rather than + * standard time. + */ + + _endtime -= (_timezone - _dstoffset); +} + + +#define DAY1 (4) /* Jan 1 1970 was a Thursday */ + +/* + * GetDstStartOrEndYearDay - Converts day info from DSTDATE into 0-based + * year-day. + * + * ENTRY tm_year - the year concerned(tb->tm_year). + * + * pDstDate - pointer to either _startdate or _enddate. + * + * RETURN the year-day calculated. + */ + +static int _CRTAPI3 +GetDstStartOrEndYearDay( + REG1 int tm_year, + REG2 PDSTDATE pDstDate + ) +{ + REG1 int yday; /* year-day */ + REG2 int theyear; + + theyear = tm_year + 1900; + + if(pDstDate->Jn != -1) { + + /* + * Jn is in [1, 365] and leap day is not counted. + * Convert Jn to 0-based yday; Note: 60 is March 1. + */ + + + yday = (IS_LEAP_YEAR(theyear) && (pDstDate->Jn >= 60)) + ? pDstDate->Jn : pDstDate->Jn - 1; + + } else if(pDstDate->n != -1) { + + /* + * n is in [0, 365] and leap day is counted. + */ + + yday = pDstDate->n; + + } else { /* Mm.n.d */ + + int *ptrday; + int years; + int wday; + + /* + * We first need to calculate year-day(yday) and week-day + * (wday) of 1st day of month pDstDate->Mm. We then figure + * out year-day(yday) of Md day of week Mn of month Mm. + */ + + ptrday = IS_LEAP_YEAR(theyear) ? _lpdays : _days; + + yday = ptrday[pDstDate->Mm-1] + 1; /* ptrday[i] are all by -1 off */ + + years = tm_year - 70; + + /* + * Here constant Day1 is the week-day of Jan 1, 1970. + * (years+1)/4 is for correcting the leap years. + */ + + wday = (yday + 365*years + (years+1)/4 + DAY1) % 7; + + /* + * Calculate yday of Md day of week 1 of month Mm. + */ + + yday += pDstDate->Md - wday; + if(pDstDate->Md < wday) { + yday += 7; + } + + /* + * Calculate yday of Md day of week Mn of month Mm. + */ + + yday += (pDstDate->Mn-1)*7; + + /* + * Adjust if yday goes beyond the end of the month. + */ + + if(pDstDate->Md == 5 && yday >= ptrday[pDstDate->Mm] + 1) { + yday -= 7; + } + + } + + return yday; +} + +/* + * _isindst - Tells whether Xenix-type time value falls under DST. + * + * ENTRY tb - 'time' structure holding broken-down time value. + * + * RETURN 1 if time represented is in DST, else 0. + */ + +int _CRTAPI1 _isindst ( + REG1 struct tm *tb + ) +{ + int st_yday, end_yday; + int st_sec, end_sec; + + int check_time; + + /* + * We need start/end year-days of DST in syday/eyday which are converted + * from one of the format Jn, n, and Mm.n.d. We already have start/end + * time (in seconds) of DST in _starttime/_endtime. + */ + + st_yday = GetDstStartOrEndYearDay(tb->tm_year, &_startdate); + end_yday = GetDstStartOrEndYearDay(tb->tm_year, &_enddate); + + st_sec = st_yday * SEC_PER_DAY + _starttime; + end_sec = end_yday * SEC_PER_DAY + _endtime; + + check_time = tb->tm_yday * SEC_PER_DAY + tb->tm_hour * SEC_PER_HOUR + + tb->tm_min * 60 + tb->tm_sec; + + if (check_time >= st_sec && check_time < end_sec) + return 1; + + return 0; +} + +/* + * _isskiptime - Tells whether the given time is skipped at the + * dst change. For instance, we set our clocks forward one + * hour at 2am to 3am... This function returns true for + * the times between 1:59:59 and 3:00:00. + * + * ENTRY tb - 'time' structure holding broken-down time value. + * + * RETURN 1 if time represented is in the skipped period, 0 + * otherwise. + */ + +int _CRTAPI1 _isskiptime ( + REG1 struct tm *tb + ) +{ + int st_yday; + int st_sec; + int check_time; + + st_yday = GetDstStartOrEndYearDay(tb->tm_year, &_startdate); + st_sec = st_yday * SEC_PER_DAY + _starttime; + + check_time = tb->tm_yday * SEC_PER_DAY + tb->tm_hour * SEC_PER_HOUR + + tb->tm_min * 60 + tb->tm_sec; + + if (check_time >= st_sec && check_time < st_sec - _dstoffset) { + return 1; + } + return 0; +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/utime.c b/private/crt32/time/utime.c new file mode 100644 index 000000000..c30c77733 --- /dev/null +++ b/private/crt32/time/utime.c @@ -0,0 +1,202 @@ +/*** +*utime.c - set modification time for a file +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Sets the access/modification times for a file. +* +*Revision History: +* 03-??-84 RLB initial version +* 05-17-86 SKS ported to OS/2 +* 08-21-87 JCR error return if localtime() returns NULL. +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 10-03-88 JCR 386: Change DOS calls to SYS calls +* 10-04-88 JCR 386: Removed 'far' keyword +* 10-10-88 GJF Made API names match DOSCALLS.H +* 10-11-88 GJF Made API arg types match DOSCALLS.H +* 04-12-89 JCR New syscall interface +* 05-01-89 JCR Corrected OS/2 time/date interpretation +* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention +* 08-16-89 PHG moved date validation above open() so file isn't left +* open if the date is invalid +* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* , removed #include , removed +* some leftover 16-bit support and fixed the copyright. +* Also, cleaned up the formatting a bit. +* 07-25-90 SBM Compiles cleanly with -W3 (added include, removed +* unreferenced variable), removed '32' from API names +* 10-04-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include instead of +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-18-91 GJF ANSI naming. +* 02-14-91 SRW Fix Mips compile error (_WIN32_) +* 02-26-91 SRW Fix SetFileTime parameter ordering (_WIN32_) +* 08-21-91 BWM Add _futime to set time on open file +* 08-26-91 BWM Change _utime to call _futime +* 05-19-92 DJM ifndef for POSIX build. +* 08-18-92 SKS SystemTimeToFileTime now takes UTC/GMT, not local time. +* Remove _CRUISER_ conditional +* 04-02-93 GJF Changed interpretation of error on SetFileTime call. +* +*******************************************************************************/ + +#ifndef _POSIX_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/*** +*int _utime(pathname, time) - set modification time for file +* +*Purpose: +* Sets the modification time for the file specified by pathname. +* Only the modification time from the _utimbuf structure is used +* under MS-DOS. +* +*Entry: +* struct _utimbuf *time - new modification date +* +*Exit: +* returns 0 if successful +* returns -1 and sets errno if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _utime ( + char *fname, + struct _utimbuf *times + ) +{ + int fh; + int retval; + + /* open file, fname, since filedate system call needs a handle. Note + * _utime definition says you must have write permission for the file + * to change its time, so open file for write only. Also, must force + * it to open in binary mode so we dont remove ^Z's from binary files. + */ + + if ((fh = _open(fname, _O_RDWR | _O_BINARY)) < 0) + return(-1); + + retval = _futime(fh, times); + + _close(fh); + return(retval); +} + +/*** +*int _futime(fh, time) - set modification time for open file +* +*Purpose: +* Sets the modification time for the open file specified by fh. +* Only the modification time from the _utimbuf structure is used +* under MS-DOS. +* +*Entry: +* struct _utimbuf *time - new modification date +* +*Exit: +* returns 0 if successful +* returns -1 and sets errno if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _futime ( + int fh, + struct _utimbuf *times + ) +{ + REG1 struct tm *tmb; + +#ifndef _WIN32_ + +#error ERROR - ONLY WIN32 TARGET SUPPORTED! + +#else /* def _WIN32_ */ + + SYSTEMTIME SystemTime; + FILETIME LastWriteTime; + FILETIME LastAccessTime; + struct _utimbuf deftimes; + + if (times == NULL) { + time(&deftimes.modtime); + deftimes.actime = deftimes.modtime; + times = &deftimes; + } + + if ((tmb = gmtime(×->modtime)) == NULL) { + errno = EINVAL; + return(-1); + } + + SystemTime.wYear = (WORD)(tmb->tm_year + 1900); + SystemTime.wMonth = (WORD)(tmb->tm_mon + 1); + SystemTime.wDay = (WORD)(tmb->tm_mday); + SystemTime.wHour = (WORD)(tmb->tm_hour); + SystemTime.wMinute = (WORD)(tmb->tm_min); + SystemTime.wSecond = (WORD)(tmb->tm_sec); + SystemTime.wMilliseconds = 0; + if (!SystemTimeToFileTime( &SystemTime, &LastWriteTime )) { + errno = EINVAL; + return(-1); + } + + if ((tmb = gmtime(×->actime)) == NULL) { + errno = EINVAL; + return(-1); + } + + SystemTime.wYear = (WORD)(tmb->tm_year + 1900); + SystemTime.wMonth = (WORD)(tmb->tm_mon + 1); + SystemTime.wDay = (WORD)(tmb->tm_mday); + SystemTime.wHour = (WORD)(tmb->tm_hour); + SystemTime.wMinute = (WORD)(tmb->tm_min); + SystemTime.wSecond = (WORD)(tmb->tm_sec); + SystemTime.wMilliseconds = 0; + if (!SystemTimeToFileTime( &SystemTime, &LastAccessTime )) { + errno = EINVAL; + return(-1); + } + + /* set the date via the filedate system call and return. failing + * this call implies the new file times are not supported by the + * underlying file system. + */ + + if (!SetFileTime((HANDLE)_get_osfhandle(fh), + NULL, + &LastAccessTime, + &LastWriteTime + )) + { + errno = EINVAL; + return(-1); + } + +#endif /* _WIN32_ */ + + return(0); +} + +#endif /* _POSIX_ */ diff --git a/private/crt32/time/wcsftime.c b/private/crt32/time/wcsftime.c new file mode 100644 index 000000000..ab046af58 --- /dev/null +++ b/private/crt32/time/wcsftime.c @@ -0,0 +1,67 @@ +/*** +*wcsftime.c - String Format Time +* +* Copyright (c) 1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* 03-08-93 CFW Module Created. +* 03-10-93 CFW Fixed up properly. +* +*******************************************************************************/ + +#include +#include +#include +#include + + +/*** +*size_t wcsftime(wstring, maxsize, format, timeptr) - Format a time string +* +*Purpose: +* The wcsftime functions is equivalent to to the strftime function, except +* that the argument 'wstring' specifies an array of a wide string into +* which the generated output is to be placed. The wcsftime acts as if +* strftime were called and the result string converted by mbstowcs(). +* [ISO] +* +*Entry: +* wchar_t *wstring = pointer to output string +* size_t maxsize = max length of string +* const char *format = format control string +* const struct tm *timeptr = pointer to tb data structure +* +*Exit: +* !0 = If the total number of resulting characters including the +* terminating null is not more than 'maxsize', then return the +* number of wide chars placed in the 'wstring' array (not including the +* null terminator). +* +* 0 = Otherwise, return 0 and the contents of the string are +* indeterminate. +* +*Exceptions: +* +*******************************************************************************/ + +size_t _CALLTYPE1 wcsftime ( + wchar_t *wstring, + size_t maxsize, + const char *format, + const struct tm *timeptr + ) +{ + /* assumes no multi-byte strings returned from strftime */ + char *string = (char *)malloc(sizeof(char) * maxsize); + size_t retval = 0; + + if (strftime(string, maxsize, format, timeptr)) + { + if ((retval = mbstowcs(wstring, string, maxsize)) == -1) + retval = 0; + free(string); + } + return retval; +} -- cgit v1.2.3