summaryrefslogtreecommitdiffstats
path: root/private/crt32/time
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/time
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/crt32/time')
-rw-r--r--private/crt32/time/asctime.c194
-rw-r--r--private/crt32/time/clock.c169
-rw-r--r--private/crt32/time/ctime.c56
-rw-r--r--private/crt32/time/days.c26
-rw-r--r--private/crt32/time/difftime.c53
-rw-r--r--private/crt32/time/dtoxtime.c113
-rw-r--r--private/crt32/time/ftime.c107
-rw-r--r--private/crt32/time/gmtime.c185
-rw-r--r--private/crt32/time/i386/_initclk.asm17
-rw-r--r--private/crt32/time/i386/cinitclk.asm93
-rw-r--r--private/crt32/time/localtim.c252
-rw-r--r--private/crt32/time/makefile6
-rw-r--r--private/crt32/time/mktime.c315
-rw-r--r--private/crt32/time/ppc/cinitclk.s49
-rw-r--r--private/crt32/time/sources54
-rw-r--r--private/crt32/time/strdate.c99
-rw-r--r--private/crt32/time/strftime.c891
-rw-r--r--private/crt32/time/strtime.c98
-rw-r--r--private/crt32/time/systime.c104
-rw-r--r--private/crt32/time/time.c78
-rw-r--r--private/crt32/time/timeset.c92
-rw-r--r--private/crt32/time/tzset.c927
-rw-r--r--private/crt32/time/utime.c202
-rw-r--r--private/crt32/time/wcsftime.c67
24 files changed, 4247 insertions, 0 deletions
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
+* <cruntime.h>, removed #include <register.h>, 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 <cruntime.h>
+#include <time.h>
+#include <internal.h>
+#include <os2dll.h>
+#ifdef MTHREAD
+#include <malloc.h>
+#include <stddef.h>
+#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
+* <cruntime.h> 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 <cruntime.h>
+#include <stdio.h>
+#include <time.h>
+
+#ifdef _POSIX_
+#include <posix/sys/times.h>
+#else
+#include <sys\timeb.h>
+#include <sys\types.h>
+#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
+* <cruntime.h> 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 <cruntime.h>
+#include <time.h>
+#include <stddef.h>
+
+/***
+*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 <internal.h>
+
+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
+* <cruntime.h> 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 <cruntime.h>
+#include <time.h>
+
+/***
+*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
+* <cruntime.h>, removed #include <register.h> 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 <cruntime.h>
+#include <time.h>
+#include <ctime.h>
+#include <internal.h>
+
+/***
+*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
+* <cruntime.h>, 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 <oscalls.h> instead of <doscalls.h>
+* 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 <cruntime.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <time.h>
+#include <dostypes.h>
+#include <msdos.h>
+#include <dos.h>
+#include <stdlib.h>
+#include <oscalls.h>
+#include <internal.h>
+
+/***
+*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
+* <cruntime.h>, removed #include <register.h> 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 <cruntime.h>
+#include <time.h>
+#include <ctime.h>
+#include <stddef.h>
+#include <internal.h>
+#include <os2dll.h>
+#ifdef MTHREAD
+#include <malloc.h>
+#include <stddef.h>
+#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
+* <cruntime.h>, removed #include <register.h> 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 <cruntime.h>
+#include <limits.h>
+#include <time.h>
+#include <stddef.h>
+#include <ctime.h>
+#include <internal.h>
+
+/***
+*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( &ltime );
+
+ /*
+ * Check and adjust for Daylight Saving Time.
+ */
+ if ( _daylight && _isindst( ptm ) ) {
+#ifdef _POSIX_
+ ltime -= _dstoffset - _timezone;
+#else
+ ltime += 3600L;
+#endif
+ ptm = gmtime( (time_t *)&ltime );
+ 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
+* <cruntime.h> 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 <cruntime.h>
+#include <stddef.h>
+#include <ctime.h>
+#include <time.h>
+#include <internal.h>
+
+/*
+ * 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
+* <cruntime.h> 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 <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-19-92 DJM ifndef for POSIX build.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+#include <oscalls.h>
+
+/***
+*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
+* <cruntime.h>, removed #include <register.h> 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 <cruntime.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <time.h>
+#include <locale.h>
+#include <setlocal.h>
+#ifdef _INTL
+#include <ctype.h>
+#include <string.h>
+#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
+* <cruntime.h> 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 <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-19-92 DJM ifndef for POSIX build.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+#include <oscalls.h>
+
+/***
+*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 <cruntime.h>
+#include <oscalls.h>
+#include <time.h>
+
+#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
+* <cruntime.h> 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 <oscalls.h> instead of <doscalls.h>
+* 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 <cruntime.h>
+#include <time.h>
+#include <oscalls.h>
+#include <internal.h>
+
+/***
+*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 <time.h>
+* 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 <cruntime.h> 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 <cruntime.h>
+#include <stdlib.h>
+#include <time.h>
+#include <internal.h>
+
+#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
+* <cruntime.h>, removed #include <register.h>, 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 <cruntime.h>
+#include <ctype.h>
+#include <ctime.h>
+#include <time.h>
+#include <stdlib.h>
+#include <internal.h>
+#ifdef _POSIX_
+#include <limits.h>
+#else
+#include <os2dll.h>
+#include <windows.h>
+#endif
+#include <string.h>
+
+#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
+* <cruntime.h>, removed #include <register.h>, 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 <oscalls.h> instead of <doscalls.h>
+* 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 <cruntime.h>
+#include <sys/types.h>
+#include <sys/utime.h>
+#include <msdos.h>
+#include <dostypes.h>
+#include <time.h>
+#include <fcntl.h>
+#include <io.h>
+#include <dos.h>
+#include <oscalls.h>
+#include <errno.h>
+#include <stddef.h>
+#include <internal.h>
+
+#include <stdio.h>
+
+/***
+*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(&times->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(&times->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 <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+/***
+*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;
+}