+++ /dev/null
-/**\r
- Definitions and Implementation for <time.h>.\r
-\r
- Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials are licensed and made available under\r
- the terms and conditions of the BSD License that accompanies this distribution.\r
- The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
- Portions derived from the NIH time zone package file, localtime.c,\r
- which contains the following notice:\r
-\r
- This file is in the public domain, so clarified as of\r
- 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).\r
-\r
- NetBSD: localtime.c,v 1.39 2006/03/22 14:01:30 christos Exp\r
-**/\r
-#include <Uefi.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/TimerLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-//#include <Library/UefiRuntimeLib.h>\r
-\r
-#include <LibConfig.h>\r
-\r
-#include <errno.h>\r
-#include <limits.h>\r
-#include <time.h>\r
-#include <reentrant.h>\r
-#include "tzfile.h"\r
-#include "TimeVals.h"\r
-#include <MainData.h>\r
-#include <extern.h> // Library/include/extern.h: Private to implementation\r
-\r
-#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */\r
-// Keep compiler quiet about casting from function to data pointers\r
-#pragma warning ( disable : 4054 )\r
-#endif /* defined(_MSC_VER) */\r
-\r
-/* ####################### Private Data ################################# */\r
-\r
-#if 0\r
-static EFI_TIME TimeBuffer;\r
-\r
- static UINT16 MonthOffs[12] = {\r
- 00,\r
- 31, 59, 90, 120,\r
- 151, 181, 212, 243,\r
- 273, 304, 334\r
- };\r
- static clock_t y2kOffs = 730485;\r
-#endif\r
-\r
-const int mon_lengths[2][MONSPERYEAR] = {\r
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\r
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }\r
-};\r
-\r
-const int year_lengths[2] = {\r
- DAYSPERNYEAR, DAYSPERLYEAR\r
-};\r
-\r
-\r
-static const char *wday_name[7] = {\r
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"\r
-};\r
-\r
-static const char *mon_name[12] = {\r
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"\r
-};\r
-\r
-static int gmt_is_set;\r
-\r
-/* ############### Implementation Functions ############################ */\r
-// Forward reference\r
-static void\r
-localsub(const time_t * const timep, const long offset, struct tm * const tmp);\r
-\r
-clock_t\r
-__getCPS(void)\r
-{\r
- return gMD->ClocksPerSecond;\r
-}\r
-\r
-static void\r
-timesub(\r
- const time_t * const timep,\r
- const long offset,\r
- const struct state * const sp,\r
- struct tm * const tmp\r
- )\r
-{\r
- const struct lsinfo * lp;\r
- time_t /*INTN*/ days;\r
- time_t /*INTN*/ rem;\r
- time_t /*INTN*/ y;\r
- int yleap;\r
- const int * ip;\r
- time_t /*INTN*/ corr;\r
- int hit;\r
- int i;\r
-\r
- corr = 0;\r
- hit = 0;\r
-#ifdef ALL_STATE\r
- i = (sp == NULL) ? 0 : sp->leapcnt;\r
-#endif /* defined ALL_STATE */\r
-#ifndef ALL_STATE\r
- i = sp->leapcnt;\r
-#endif /* State Farm */\r
- while (--i >= 0) {\r
- lp = &sp->lsis[i];\r
- if (*timep >= lp->ls_trans) {\r
- if (*timep == lp->ls_trans) {\r
- hit = ((i == 0 && lp->ls_corr > 0) ||\r
- lp->ls_corr > sp->lsis[i - 1].ls_corr);\r
- if (hit)\r
- while (i > 0 &&\r
- sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 &&\r
- sp->lsis[i].ls_corr == sp->lsis[i - 1].ls_corr + 1 )\r
- {\r
- ++hit;\r
- --i;\r
- }\r
- }\r
- corr = lp->ls_corr;\r
- break;\r
- }\r
- }\r
- days = *timep / SECSPERDAY;\r
- rem = *timep % SECSPERDAY;\r
- rem += (offset - corr);\r
- while (rem < 0) {\r
- rem += SECSPERDAY;\r
- --days;\r
- }\r
- while (rem >= SECSPERDAY) {\r
- rem -= SECSPERDAY;\r
- ++days;\r
- }\r
- tmp->tm_hour = (int) (rem / SECSPERHOUR);\r
- rem = rem % SECSPERHOUR;\r
- tmp->tm_min = (int) (rem / SECSPERMIN);\r
- /*\r
- ** A positive leap second requires a special\r
- ** representation. This uses "... ??:59:60" et seq.\r
- */\r
- tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;\r
- tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);\r
- if (tmp->tm_wday < 0)\r
- tmp->tm_wday += DAYSPERWEEK;\r
- y = EPOCH_YEAR;\r
- while (days < 0 || days >= (LONG32) year_lengths[yleap = isleap(y)]) {\r
- time_t /*INTN*/ newy;\r
-\r
- newy = (y + days / DAYSPERNYEAR);\r
- if (days < 0)\r
- --newy;\r
- days -= (newy - y) * DAYSPERNYEAR +\r
- LEAPS_THRU_END_OF(newy - 1) -\r
- LEAPS_THRU_END_OF(y - 1);\r
- y = newy;\r
- }\r
- tmp->tm_year = (int)(y - TM_YEAR_BASE);\r
- tmp->tm_yday = (int) days;\r
- ip = mon_lengths[yleap];\r
- for (tmp->tm_mon = 0; days >= (LONG32) ip[tmp->tm_mon]; ++(tmp->tm_mon))\r
- days = days - (LONG32) ip[tmp->tm_mon];\r
- tmp->tm_mday = (int) (days + 1);\r
- tmp->tm_isdst = 0;\r
-#ifdef TM_GMTOFF\r
- tmp->TM_GMTOFF = offset;\r
-#endif /* defined TM_GMTOFF */\r
-}\r
-\r
-/* ############### Time Manipulation Functions ########################## */\r
-\r
-/**\r
-**/\r
-double\r
-difftime(time_t time1, time_t time0)\r
-{\r
- return (double)(time1 - time0);\r
-}\r
-\r
-/*\r
-** Adapted from code provided by Robert Elz, who writes:\r
-** The "best" way to do mktime I think is based on an idea of Bob\r
-** Kridle's (so its said...) from a long time ago.\r
-** [kridle@xinet.com as of 1996-01-16.]\r
-** It does a binary search of the time_t space. Since time_t's are\r
-** just 32 bits, its a max of 32 iterations (even at 64 bits it\r
-** would still be very reasonable).\r
-*/\r
-\r
-#ifndef WRONG\r
-#define WRONG (-1)\r
-#endif /* !defined WRONG */\r
-\r
-/*\r
-** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).\r
-*/\r
-\r
-static int\r
-increment_overflow(int * number, int delta)\r
-{\r
- int number0;\r
-\r
- number0 = *number;\r
- *number += delta;\r
- return (*number < number0) != (delta < 0);\r
-}\r
-\r
-static int\r
-normalize_overflow(int * const tensptr, int * const unitsptr, const int base)\r
-{\r
- register int tensdelta;\r
-\r
- tensdelta = (*unitsptr >= 0) ?\r
- (*unitsptr / base) : (-1 - (-1 - *unitsptr) / base);\r
- *unitsptr -= tensdelta * base;\r
- return increment_overflow(tensptr, tensdelta);\r
-}\r
-\r
-static int\r
-tmcomp(const struct tm * const atmp, const struct tm * const btmp)\r
-{\r
- register int result;\r
-\r
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&\r
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&\r
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&\r
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&\r
- (result = (atmp->tm_min - btmp->tm_min)) == 0)\r
- result = atmp->tm_sec - btmp->tm_sec;\r
- return result;\r
-}\r
-\r
-static time_t\r
-time2sub(\r
- struct tm * const tmp,\r
- void (* const funcp)(const time_t*, long, struct tm*),\r
- const long offset,\r
- int * const okayp,\r
- const int do_norm_secs\r
- )\r
-{\r
- register const struct state * sp;\r
- register int dir;\r
- register int bits;\r
- register int i, j ;\r
- register int saved_seconds;\r
- time_t newt;\r
- time_t t;\r
- struct tm yourtm, mytm;\r
-\r
- *okayp = FALSE;\r
- yourtm = *tmp; // Create a copy of tmp\r
- if (do_norm_secs) {\r
- if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,\r
- SECSPERMIN))\r
- return WRONG;\r
- }\r
- if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))\r
- return WRONG;\r
- if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))\r
- return WRONG;\r
- if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))\r
- return WRONG;\r
- /*\r
- ** Turn yourtm.tm_year into an actual year number for now.\r
- ** It is converted back to an offset from TM_YEAR_BASE later.\r
- */\r
- if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))\r
- return WRONG;\r
- while (yourtm.tm_mday <= 0) {\r
- if (increment_overflow(&yourtm.tm_year, -1))\r
- return WRONG;\r
- i = yourtm.tm_year + (1 < yourtm.tm_mon);\r
- yourtm.tm_mday += year_lengths[isleap(i)];\r
- }\r
- while (yourtm.tm_mday > DAYSPERLYEAR) {\r
- i = yourtm.tm_year + (1 < yourtm.tm_mon);\r
- yourtm.tm_mday -= year_lengths[isleap(i)];\r
- if (increment_overflow(&yourtm.tm_year, 1))\r
- return WRONG;\r
- }\r
- for ( ; ; ) {\r
- i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];\r
- if (yourtm.tm_mday <= i)\r
- break;\r
- yourtm.tm_mday -= i;\r
- if (++yourtm.tm_mon >= MONSPERYEAR) {\r
- yourtm.tm_mon = 0;\r
- if (increment_overflow(&yourtm.tm_year, 1))\r
- return WRONG;\r
- }\r
- }\r
- if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))\r
- return WRONG;\r
- if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)\r
- saved_seconds = 0;\r
- else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {\r
- /*\r
- ** We can't set tm_sec to 0, because that might push the\r
- ** time below the minimum representable time.\r
- ** Set tm_sec to 59 instead.\r
- ** This assumes that the minimum representable time is\r
- ** not in the same minute that a leap second was deleted from,\r
- ** which is a safer assumption than using 58 would be.\r
- */\r
- if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))\r
- return WRONG;\r
- saved_seconds = yourtm.tm_sec;\r
- yourtm.tm_sec = SECSPERMIN - 1;\r
- } else {\r
- saved_seconds = yourtm.tm_sec;\r
- yourtm.tm_sec = 0;\r
- }\r
- /*\r
- ** Divide the search space in half\r
- ** (this works whether time_t is signed or unsigned).\r
- */\r
- bits = TYPE_BIT(time_t) - 1;\r
- /*\r
- ** Set t to the midpoint of our binary search.\r
- **\r
- ** If time_t is signed, then 0 is just above the median,\r
- ** assuming two's complement arithmetic.\r
- ** If time_t is unsigned, then (1 << bits) is just above the median.\r
- */\r
- t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);\r
- for ( ; ; ) {\r
- (*funcp)(&t, offset, &mytm); // Convert t to broken-down time in mytm\r
- dir = tmcomp(&mytm, &yourtm); // Is mytm larger, equal, or less than yourtm?\r
- if (dir != 0) { // If mytm != yourtm...\r
- if (bits-- < 0) // If we have exhausted all the bits..\r
- return WRONG; // Return that we failed\r
- if (bits < 0) // If on the last bit...\r
- --t; /* may be needed if new t is minimal */\r
- else if (dir > 0) // else if mytm > yourtm...\r
- t -= ((time_t) 1) << bits; // subtract half the remaining time-space\r
- else t += ((time_t) 1) << bits; // otherwise add half the remaining time-space\r
- continue; // Repeat for the next half\r
- }\r
- if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)\r
- break;\r
- /*\r
- ** Right time, wrong type.\r
- ** Hunt for right time, right type.\r
- ** It's okay to guess wrong since the guess\r
- ** gets checked.\r
- */\r
- /*\r
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.\r
- */\r
- sp = (const struct state *)\r
- (((void *) funcp == (void *) localsub) ?\r
- lclptr : gmtptr);\r
-#ifdef ALL_STATE\r
- if (sp == NULL)\r
- return WRONG;\r
-#endif /* defined ALL_STATE */\r
- for (i = sp->typecnt - 1; i >= 0; --i) {\r
- if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)\r
- continue;\r
- for (j = sp->typecnt - 1; j >= 0; --j) {\r
- if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)\r
- continue;\r
- newt = t + sp->ttis[j].tt_gmtoff -\r
- sp->ttis[i].tt_gmtoff;\r
- (*funcp)(&newt, offset, &mytm);\r
- if (tmcomp(&mytm, &yourtm) != 0)\r
- continue;\r
- if (mytm.tm_isdst != yourtm.tm_isdst)\r
- continue;\r
- /*\r
- ** We have a match.\r
- */\r
- t = newt;\r
- goto label;\r
- }\r
- }\r
- return WRONG;\r
- }\r
- label:\r
- newt = t + saved_seconds;\r
- if ((newt < t) != (saved_seconds < 0))\r
- return WRONG;\r
- t = newt;\r
- (*funcp)(&t, offset, tmp);\r
- *okayp = TRUE;\r
- return t;\r
-}\r
-\r
-time_t\r
-time2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),\r
- const long offset, int * const okayp)\r
-{\r
- time_t t;\r
-\r
- /*\r
- ** First try without normalization of seconds\r
- ** (in case tm_sec contains a value associated with a leap second).\r
- ** If that fails, try with normalization of seconds.\r
- */\r
- t = time2sub(tmp, funcp, offset, okayp, FALSE);\r
- return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);\r
-}\r
-\r
-static time_t\r
-time1(\r
- struct tm * const tmp,\r
- void (* const funcp)(const time_t *, long, struct tm *),\r
- const long offset\r
- )\r
-{\r
- register time_t t;\r
- register const struct state * sp;\r
- register int samei, otheri;\r
- register int sameind, otherind;\r
- register int i;\r
- register int nseen;\r
- int seen[TZ_MAX_TYPES];\r
- int types[TZ_MAX_TYPES];\r
- int okay;\r
-\r
- if (tmp->tm_isdst > 1)\r
- tmp->tm_isdst = 1;\r
- t = time2(tmp, funcp, offset, &okay);\r
-#ifdef PCTS\r
- /*\r
- ** PCTS code courtesy Grant Sullivan (grant@osf.org).\r
- */\r
- if (okay)\r
- return t;\r
- if (tmp->tm_isdst < 0)\r
- tmp->tm_isdst = 0; /* reset to std and try again */\r
-#endif /* defined PCTS */\r
-#ifndef PCTS\r
- if (okay || tmp->tm_isdst < 0)\r
- return t;\r
-#endif /* !defined PCTS */\r
- /*\r
- ** We're supposed to assume that somebody took a time of one type\r
- ** and did some math on it that yielded a "struct tm" that's bad.\r
- ** We try to divine the type they started from and adjust to the\r
- ** type they need.\r
- */\r
- /*\r
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.\r
- */\r
- sp = (const struct state *) (((void *) funcp == (void *) localsub) ?\r
- lclptr : gmtptr);\r
-#ifdef ALL_STATE\r
- if (sp == NULL)\r
- return WRONG;\r
-#endif /* defined ALL_STATE */\r
- for (i = 0; i < sp->typecnt; ++i)\r
- seen[i] = FALSE;\r
- nseen = 0;\r
- for (i = sp->timecnt - 1; i >= 0; --i)\r
- if (!seen[sp->types[i]]) {\r
- seen[sp->types[i]] = TRUE;\r
- types[nseen++] = sp->types[i];\r
- }\r
- for (sameind = 0; sameind < nseen; ++sameind) {\r
- samei = types[sameind];\r
- if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)\r
- continue;\r
- for (otherind = 0; otherind < nseen; ++otherind) {\r
- otheri = types[otherind];\r
- if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)\r
- continue;\r
- tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -\r
- sp->ttis[samei].tt_gmtoff);\r
- tmp->tm_isdst = !tmp->tm_isdst;\r
- t = time2(tmp, funcp, offset, &okay);\r
- if (okay)\r
- return t;\r
- tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -\r
- sp->ttis[samei].tt_gmtoff);\r
- tmp->tm_isdst = !tmp->tm_isdst;\r
- }\r
- }\r
- return WRONG;\r
-}\r
-\r
-/** The mktime function converts the broken-down time, expressed as local time,\r
- in the structure pointed to by timeptr into a calendar time value with the\r
- same encoding as that of the values returned by the time function. The\r
- original values of the tm_wday and tm_yday components of the structure are\r
- ignored, and the original values of the other components are not restricted\r
- to the ranges indicated above. Thus, a positive or zero value for tm_isdst\r
- causes the mktime function to presume initially that Daylight Saving Time,\r
- respectively, is or is not in effect for the specified time. A negative\r
- value causes it to attempt to determine whether Daylight Saving Time is in\r
- effect for the specified time. On successful completion, the values of the\r
- tm_wday and tm_yday components of the structure are set appropriately, and\r
- the other components are set to represent the specified calendar time, but\r
- with their values forced to the ranges indicated above; the final value of\r
- tm_mday is not set until tm_mon and tm_year are determined.\r
-\r
- @return The mktime function returns the specified calendar time encoded\r
- as a value of type time_t. If the calendar time cannot be\r
- represented, the function returns the value (time_t)(-1).\r
-**/\r
-time_t\r
-mktime(struct tm *timeptr)\r
-{\r
- /* From NetBSD */\r
- time_t result;\r
-\r
- rwlock_wrlock(&lcl_lock);\r
- tzset();\r
- result = time1(timeptr, &localsub, 0L);\r
- rwlock_unlock(&lcl_lock);\r
- return (result);\r
-}\r
-\r
-/** The time function determines the current calendar time. The encoding of\r
- the value is unspecified.\r
-\r
- @return The time function returns the implementation's best approximation\r
- to the current calendar time. The value (time_t)(-1) is returned\r
- if the calendar time is not available. If timer is not a null\r
- pointer, the return value is also assigned to the object it\r
- points to.\r
-**/\r
-time_t\r
-time(time_t *timer)\r
-{\r
- time_t CalTime;\r
- EFI_STATUS Status;\r
- EFI_TIME *ET;\r
- struct tm *BT;\r
-\r
- ET = &gMD->TimeBuffer;\r
- BT = &gMD->BDTime;\r
-\r
- // Get EFI Time\r
- Status = gRT->GetTime( ET, NULL);\r
-// Status = EfiGetTime( ET, NULL);\r
- EFIerrno = Status;\r
- if( Status != RETURN_SUCCESS) {\r
- return (time_t)-1;\r
- }\r
-\r
- // Convert EFI time to broken-down time.\r
- Efi2Tm( ET, BT);\r
-\r
- // Convert to time_t\r
- CalTime = mktime(&gMD->BDTime);\r
-\r
- if( timer != NULL) {\r
- *timer = CalTime;\r
- }\r
- return CalTime; // Return calendar time in microseconds\r
-}\r
-\r
-/** The clock function determines the processor time used.\r
-\r
- @return The clock function returns the implementation's best\r
- approximation to the processor time used by the program since the\r
- beginning of an implementation-defined era related only to the\r
- program invocation. To determine the time in seconds, the value\r
- returned by the clock function should be divided by the value of\r
- the macro CLOCKS_PER_SEC. If the processor time used is not\r
- available or its value cannot be represented, the function\r
- returns the value (clock_t)(-1).\r
-**/\r
-clock_t\r
-clock(void)\r
-{\r
- clock_t retval;\r
- time_t temp;\r
-\r
- temp = time(NULL);\r
- retval = ((clock_t)((UINT32)temp)) - gMD->AppStartTime;\r
- return retval;\r
-}\r
-\r
-/* ################# Time Conversion Functions ########################## */\r
-/*\r
- Except for the strftime function, these functions each return a pointer to\r
- one of two types of static objects: a broken-down time structure or an\r
- array of char. Execution of any of the functions that return a pointer to\r
- one of these object types may overwrite the information in any object of\r
- the same type pointed to by the value returned from any previous call to\r
- any of them. The implementation shall behave as if no other library\r
- functions call these functions.\r
-*/\r
-\r
-/** The asctime function converts the broken-down time in the structure pointed\r
- to by timeptr into a string in the form\r
- Sun Sep 16 01:03:52 1973\n\0\r
- using the equivalent of the following algorithm.\r
-\r
- char *asctime(const struct tm *timeptr)\r
- {\r
- static const char wday_name[7][3] = {\r
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"\r
- };\r
- static const char mon_name[12][3] = {\r
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"\r
- };\r
- static char result[26];\r
- sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",\r
- wday_name[timeptr->tm_wday],\r
- mon_name[timeptr->tm_mon],\r
- timeptr->tm_mday, timeptr->tm_hour,\r
- timeptr->tm_min, timeptr->tm_sec,\r
- 1900 + timeptr->tm_year);\r
- return result;\r
- }\r
- @return The asctime function returns a pointer to the string.\r
-**/\r
-char *\r
-asctime(const struct tm *timeptr)\r
-{\r
- register const char * wn;\r
- register const char * mn;\r
-\r
- if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)\r
- wn = "???";\r
- else wn = wday_name[timeptr->tm_wday];\r
- if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)\r
- mn = "???";\r
- else mn = mon_name[timeptr->tm_mon];\r
- /*\r
- ** The X3J11-suggested format is\r
- ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"\r
- ** Since the .2 in 02.2d is ignored, we drop it.\r
- */\r
- (void)snprintf(gMD->ASasctime,\r
- sizeof (char[ASCTIME_BUFLEN]),\r
- "%.3s %.3s%3d %02d:%02d:%02d %d\r\n", // explicit CRLF for EFI\r
- wn, mn,\r
- timeptr->tm_mday, timeptr->tm_hour,\r
- timeptr->tm_min, timeptr->tm_sec,\r
- TM_YEAR_BASE + timeptr->tm_year);\r
- return gMD->ASasctime;\r
-}\r
-\r
-/**\r
-**/\r
-char *\r
-ctime(const time_t *timer)\r
-{\r
- return asctime(localtime(timer));\r
-}\r
-\r
-/*\r
-** gmtsub is to gmtime as localsub is to localtime.\r
-*/\r
-void\r
-gmtsub(\r
- const time_t * const timep,\r
- const long offset,\r
- struct tm * const tmp\r
- )\r
-{\r
-#ifdef _REENTRANT\r
- static mutex_t gmt_mutex = MUTEX_INITIALIZER;\r
-#endif\r
-\r
- mutex_lock(&gmt_mutex);\r
- if (!gmt_is_set) {\r
- gmt_is_set = TRUE;\r
-#ifdef ALL_STATE\r
- gmtptr = (struct state *) malloc(sizeof *gmtptr);\r
- if (gmtptr != NULL)\r
-#endif /* defined ALL_STATE */\r
- gmtload(gmtptr);\r
- }\r
- mutex_unlock(&gmt_mutex);\r
- timesub(timep, offset, gmtptr, tmp);\r
-#ifdef TM_ZONE\r
- /*\r
- ** Could get fancy here and deliver something such as\r
- ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,\r
- ** but this is no time for a treasure hunt.\r
- */\r
- if (offset != 0)\r
- tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr);\r
- else {\r
-#ifdef ALL_STATE\r
- if (gmtptr == NULL)\r
- tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt);\r
- else tmp->TM_ZONE = gmtptr->chars;\r
-#endif /* defined ALL_STATE */\r
-#ifndef ALL_STATE\r
- tmp->TM_ZONE = gmtptr->chars;\r
-#endif /* State Farm */\r
- }\r
-#endif /* defined TM_ZONE */\r
-}\r
-\r
-/**\r
-**/\r
-struct tm *\r
-gmtime(const time_t *timer)\r
-{\r
- gmtsub(timer, 0L, &gMD->BDTime);\r
- return &gMD->BDTime;\r
-}\r
-\r
-static void\r
-localsub(const time_t * const timep, const long offset, struct tm * const tmp)\r
-{\r
- register struct state * sp;\r
- register const struct ttinfo * ttisp;\r
- register int i;\r
- const time_t t = *timep;\r
-\r
- sp = lclptr;\r
-#ifdef ALL_STATE\r
- if (sp == NULL) {\r
- gmtsub(timep, offset, tmp);\r
- return;\r
- }\r
-#endif /* defined ALL_STATE */\r
- if (sp->timecnt == 0 || t < sp->ats[0]) {\r
- i = 0;\r
- while (sp->ttis[i].tt_isdst)\r
- if (++i >= sp->typecnt) {\r
- i = 0;\r
- break;\r
- }\r
- } else {\r
- for (i = 1; i < sp->timecnt; ++i)\r
- if (t < sp->ats[i])\r
- break;\r
- i = sp->types[i - 1];\r
- }\r
- ttisp = &sp->ttis[i];\r
- /*\r
- ** To get (wrong) behavior that's compatible with System V Release 2.0\r
- ** you'd replace the statement below with\r
- ** t += ttisp->tt_gmtoff;\r
- ** timesub(&t, 0L, sp, tmp);\r
- */\r
- timesub(&t, ttisp->tt_gmtoff, sp, tmp);\r
- tmp->tm_isdst = ttisp->tt_isdst;\r
- tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];\r
-#ifdef TM_ZONE\r
- tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];\r
-#endif /* defined TM_ZONE */\r
-}\r
-\r
-/**\r
-**/\r
-struct tm *\r
-localtime(const time_t *timer)\r
-{\r
- tzset();\r
- localsub(timer, 0L, &gMD->BDTime);\r
- return &gMD->BDTime;\r
-}\r