From a028a54e529b86b04ba6a51ccbfcf1ddbc9f1e73 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 18 Aug 2022 15:24:03 -0400 Subject: [PATCH] libroot: Replace strftime/strptime/wcsftime implementations with musl's. Now that we have locale_t, we can use the musl versions of these functions. This also fixes a licensing issue: the strptime implementation had an advertising clause (although in upstream *BSD it was removed, so we likely could have managed to remove it anyway.) --- headers/private/libroot/time/timelocal.h | 9 - src/system/libroot/posix/locale/locale_t.cpp | 10 + src/system/libroot/posix/musl/Jamfile | 2 + .../libroot/posix/musl/internal/locale_impl.h | 15 + src/system/libroot/posix/musl/time/Jamfile | 18 + src/system/libroot/posix/musl/time/difftime.c | 6 + src/system/libroot/posix/musl/time/strftime.c | 285 +++++++++ src/system/libroot/posix/musl/time/strptime.c | 207 ++++++ .../libroot/posix/musl/time/time_impl.h | 11 + .../libroot/posix/musl/time/time_impl_haiku.h | 23 + src/system/libroot/posix/musl/time/wcsftime.c | 72 +++ src/system/libroot/posix/time/Jamfile | 8 +- src/system/libroot/posix/time/difftime.c | 16 - .../system/libroot/posix}/time/private.h | 0 src/system/libroot/posix/time/strftime.c | 589 ------------------ src/system/libroot/posix/time/strptime.c | 502 --------------- src/system/libroot/posix/time/timelocal.cpp | 40 -- .../system/libroot/posix}/time/tzfile.h | 0 src/system/libroot/posix/time/wcsftime.c | 112 ---- 19 files changed, 650 insertions(+), 1275 deletions(-) create mode 100644 src/system/libroot/posix/musl/internal/locale_impl.h create mode 100644 src/system/libroot/posix/musl/time/Jamfile create mode 100644 src/system/libroot/posix/musl/time/difftime.c create mode 100644 src/system/libroot/posix/musl/time/strftime.c create mode 100644 src/system/libroot/posix/musl/time/strptime.c create mode 100644 src/system/libroot/posix/musl/time/time_impl.h create mode 100644 src/system/libroot/posix/musl/time/time_impl_haiku.h create mode 100644 src/system/libroot/posix/musl/time/wcsftime.c delete mode 100644 src/system/libroot/posix/time/difftime.c rename {headers/private/libroot => src/system/libroot/posix}/time/private.h (100%) delete mode 100644 src/system/libroot/posix/time/strftime.c delete mode 100644 src/system/libroot/posix/time/strptime.c delete mode 100644 src/system/libroot/posix/time/timelocal.cpp rename {headers/private/libroot => src/system/libroot/posix}/time/tzfile.h (100%) delete mode 100644 src/system/libroot/posix/time/wcsftime.c diff --git a/headers/private/libroot/time/timelocal.h b/headers/private/libroot/time/timelocal.h index a75fb31f24..6d0c7526a4 100644 --- a/headers/private/libroot/time/timelocal.h +++ b/headers/private/libroot/time/timelocal.h @@ -33,10 +33,6 @@ #include -/* - * Private header file for the strftime and strptime localization - * stuff. - */ struct lc_time_t { const char* mon[12]; const char* month[12]; @@ -53,10 +49,5 @@ struct lc_time_t { const char* ampm_fmt; }; -__BEGIN_DECLS -const struct lc_time_t* __get_current_time_locale(void); -const struct lc_time_t* __get_time_locale(locale_t); -__END_DECLS - #endif /* !_TIMELOCAL_H_ */ diff --git a/src/system/libroot/posix/locale/locale_t.cpp b/src/system/libroot/posix/locale/locale_t.cpp index 673a3ad6ca..2337a6a2e8 100644 --- a/src/system/libroot/posix/locale/locale_t.cpp +++ b/src/system/libroot/posix/locale/locale_t.cpp @@ -260,3 +260,13 @@ uselocale(locale_t newLoc) return oldLoc; } + + +extern "C" locale_t +__current_locale_t() +{ + locale_t locale = (locale_t)GetCurrentLocaleInfo(); + if (locale == NULL) + locale = LC_GLOBAL_LOCALE; + return locale; +} diff --git a/src/system/libroot/posix/musl/Jamfile b/src/system/libroot/posix/musl/Jamfile index fb4bac8d67..5a0796b7ab 100644 --- a/src/system/libroot/posix/musl/Jamfile +++ b/src/system/libroot/posix/musl/Jamfile @@ -12,6 +12,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { <$(architecture)>posix_musl_regex.o <$(architecture)>posix_musl_search.o <$(architecture)>posix_musl_string.o + <$(architecture)>posix_musl_time.o ; } } @@ -25,3 +26,4 @@ HaikuSubInclude misc ; HaikuSubInclude regex ; HaikuSubInclude search ; HaikuSubInclude string ; +HaikuSubInclude time ; diff --git a/src/system/libroot/posix/musl/internal/locale_impl.h b/src/system/libroot/posix/musl/internal/locale_impl.h new file mode 100644 index 0000000000..a7cd0de87d --- /dev/null +++ b/src/system/libroot/posix/musl/internal/locale_impl.h @@ -0,0 +1,15 @@ +/* + * Copyright 2022, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _LOCALE_IMPL_H +#define _LOCALE_IMPL_H + +#include + +#define __nl_langinfo_l nl_langinfo_l + +locale_t __current_locale_t(); +#define CURRENT_LOCALE (__current_locale_t()) + +#endif diff --git a/src/system/libroot/posix/musl/time/Jamfile b/src/system/libroot/posix/musl/time/Jamfile new file mode 100644 index 0000000000..b8d967a4bc --- /dev/null +++ b/src/system/libroot/posix/musl/time/Jamfile @@ -0,0 +1,18 @@ +SubDir HAIKU_TOP src system libroot posix musl time ; + +SubDirSysHdrs [ FDirName $(SUBDIR) .. include ] ; +UseHeaders [ FDirName $(SUBDIR) .. internal ] ; + +local architectureObject ; +for architectureObject in [ MultiArchSubDirSetup ] { + on $(architectureObject) { + local architecture = $(TARGET_PACKAGING_ARCH) ; + + MergeObject <$(architecture)>posix_musl_time.o : + difftime.c + strftime.c + strptime.c + wcsftime.c + ; + } +} diff --git a/src/system/libroot/posix/musl/time/difftime.c b/src/system/libroot/posix/musl/time/difftime.c new file mode 100644 index 0000000000..80a18cc0bc --- /dev/null +++ b/src/system/libroot/posix/musl/time/difftime.c @@ -0,0 +1,6 @@ +#include + +double difftime(time_t t1, time_t t0) +{ + return t1-t0; +} diff --git a/src/system/libroot/posix/musl/time/strftime.c b/src/system/libroot/posix/musl/time/strftime.c new file mode 100644 index 0000000000..7f3987bcda --- /dev/null +++ b/src/system/libroot/posix/musl/time/strftime.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include +#include +#include +#include "locale_impl.h" +#include "time_impl.h" + +static int is_leap(int y) +{ + /* Avoid overflow */ + if (y>INT_MAX-1900) y -= 2000; + y += 1900; + return !(y%4) && ((y%100) || !(y%400)); +} + +static int week_num(const struct tm *tm) +{ + int val = (tm->tm_yday + 7U - (tm->tm_wday+6U)%7) / 7; + /* If 1 Jan is just 1-3 days past Monday, + * the previous week is also in this year. */ + if ((tm->tm_wday + 371U - tm->tm_yday - 2) % 7 <= 2) + val++; + if (!val) { + val = 52; + /* If 31 December of prev year a Thursday, + * or Friday of a leap year, then the + * prev year has 53 weeks. */ + { + int dec31 = (tm->tm_wday + 7U - tm->tm_yday - 1) % 7; + if (dec31 == 4 || (dec31 == 5 && is_leap(tm->tm_year%400-1))) + val++; + } + } else if (val == 53) { + /* If 1 January is not a Thursday, and not + * a Wednesday of a leap year, then this + * year has only 52 weeks. */ + int jan1 = (tm->tm_wday + 371U - tm->tm_yday) % 7; + if (jan1 != 4 && (jan1 != 3 || !is_leap(tm->tm_year))) + val = 1; + } + return val; +} + +const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc, int pad) +{ + nl_item item; + long long val; + const char *fmt = "-"; + int width = 2, def_pad = '0'; + + switch (f) { + case 'a': + if (tm->tm_wday > 6U) goto string; + item = ABDAY_1 + tm->tm_wday; + goto nl_strcat; + case 'A': + if (tm->tm_wday > 6U) goto string; + item = DAY_1 + tm->tm_wday; + goto nl_strcat; + case 'h': + case 'b': + if (tm->tm_mon > 11U) goto string; + item = ABMON_1 + tm->tm_mon; + goto nl_strcat; + case 'B': + if (tm->tm_mon > 11U) goto string; + item = MON_1 + tm->tm_mon; + goto nl_strcat; + case 'c': + item = D_T_FMT; + goto nl_strftime; + case 'C': + val = (1900LL+tm->tm_year) / 100; + goto number; + case 'e': + def_pad = '_'; + case 'd': + val = tm->tm_mday; + goto number; + case 'D': + fmt = "%m/%d/%y"; + goto recu_strftime; + case 'F': + fmt = "%Y-%m-%d"; + goto recu_strftime; + case 'g': + case 'G': + val = tm->tm_year + 1900LL; + if (tm->tm_yday < 3 && week_num(tm) != 1) val--; + else if (tm->tm_yday > 360 && week_num(tm) == 1) val++; + if (f=='g') val %= 100; + else width = 4; + goto number; + case 'H': + val = tm->tm_hour; + goto number; + case 'I': + val = tm->tm_hour; + if (!val) val = 12; + else if (val > 12) val -= 12; + goto number; + case 'j': + val = tm->tm_yday+1; + width = 3; + goto number; + case 'm': + val = tm->tm_mon+1; + goto number; + case 'M': + val = tm->tm_min; + goto number; + case 'n': + *l = 1; + return "\n"; + case 'p': + item = tm->tm_hour >= 12 ? PM_STR : AM_STR; + goto nl_strcat; + case 'r': + item = T_FMT_AMPM; + goto nl_strftime; + case 'R': + fmt = "%H:%M"; + goto recu_strftime; + case 's': + val = __tm_to_secs(tm) - tm->__tm_gmtoff; + width = 1; + goto number; + case 'S': + val = tm->tm_sec; + goto number; + case 't': + *l = 1; + return "\t"; + case 'T': + fmt = "%H:%M:%S"; + goto recu_strftime; + case 'u': + val = tm->tm_wday ? tm->tm_wday : 7; + width = 1; + goto number; + case 'U': + val = (tm->tm_yday + 7U - tm->tm_wday) / 7; + goto number; + case 'W': + val = (tm->tm_yday + 7U - (tm->tm_wday+6U)%7) / 7; + goto number; + case 'V': + val = week_num(tm); + goto number; + case 'w': + val = tm->tm_wday; + width = 1; + goto number; + case 'x': + item = D_FMT; + goto nl_strftime; + case 'X': + item = T_FMT; + goto nl_strftime; + case 'y': + val = (tm->tm_year + 1900LL) % 100; + if (val < 0) val = -val; + goto number; + case 'Y': + val = tm->tm_year + 1900LL; + if (val >= 10000) { + *l = snprintf(*s, sizeof *s, "+%lld", val); + return *s; + } + width = 4; + goto number; + case 'z': + if (tm->tm_isdst < 0) { + *l = 0; + return ""; + } + *l = snprintf(*s, sizeof *s, "%+.4ld", + tm->__tm_gmtoff/3600*100 + tm->__tm_gmtoff%3600/60); + return *s; + case 'Z': + if (tm->tm_isdst < 0) { + *l = 0; + return ""; + } + fmt = __tm_to_tzname(tm); + goto string; + case '%': + *l = 1; + return "%"; + default: + return 0; + } +number: + switch (pad ? pad : def_pad) { + case '-': *l = snprintf(*s, sizeof *s, "%lld", val); break; + case '_': *l = snprintf(*s, sizeof *s, "%*lld", width, val); break; + case '0': + default: *l = snprintf(*s, sizeof *s, "%0*lld", width, val); break; + } + return *s; +nl_strcat: + fmt = __nl_langinfo_l(item, loc); +string: + *l = strlen(fmt); + return fmt; +nl_strftime: + fmt = __nl_langinfo_l(item, loc); +recu_strftime: + *l = __strftime_l(*s, sizeof *s, fmt, tm, loc); + if (!*l) return 0; + return *s; +} + +size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc) +{ + size_t l, k; + char buf[100]; + char *p; + const char *t; + int pad, plus; + unsigned long width; + for (l=0; ltm_year < -1900) { + s[l++] = '-'; + width--; + } else if (plus && d+(width-k) >= (*p=='C'?3:5)) { + s[l++] = '+'; + width--; + } + for (; width > k && l < n; width--) + s[l++] = '0'; + } + } + if (k > n-l) k = n-l; + memcpy(s+l, t, k); + l += k; + } + if (n) { + if (l==n) l=n-1; + s[l] = 0; + } + return 0; +} + +size_t strftime(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm) +{ + return __strftime_l(s, n, f, tm, CURRENT_LOCALE); +} + +weak_alias(__strftime_l, strftime_l); diff --git a/src/system/libroot/posix/musl/time/strptime.c b/src/system/libroot/posix/musl/time/strptime.c new file mode 100644 index 0000000000..2e51619a61 --- /dev/null +++ b/src/system/libroot/posix/musl/time/strptime.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include +#include "time_impl.h" + +char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm) +{ + int i, w, neg, adj, min, range, *dest, dummy; + const char *ex; + size_t len; + int want_century = 0, century = 0, relyear = 0; + while (*f) { + if (*f != '%') { + if (isspace(*f)) for (; *s && isspace(*s); s++); + else if (*s != *f) return 0; + else s++; + f++; + continue; + } + f++; + if (*f == '+') f++; + if (isdigit(*f)) { + char *new_f; + w=strtoul(f, &new_f, 10); + f = new_f; + } else { + w=-1; + } + adj=0; + switch (*f++) { + case 'a': case 'A': + dest = &tm->tm_wday; + min = ABDAY_1; + range = 7; + goto symbolic_range; + case 'b': case 'B': case 'h': + dest = &tm->tm_mon; + min = ABMON_1; + range = 12; + goto symbolic_range; + case 'c': + s = strptime(s, nl_langinfo(D_T_FMT), tm); + if (!s) return 0; + break; + case 'C': + dest = ¢ury; + if (w<0) w=2; + want_century |= 2; + goto numeric_digits; + case 'd': case 'e': + dest = &tm->tm_mday; + min = 1; + range = 31; + goto numeric_range; + case 'D': + s = strptime(s, "%m/%d/%y", tm); + if (!s) return 0; + break; + case 'H': + dest = &tm->tm_hour; + min = 0; + range = 24; + goto numeric_range; + case 'I': + dest = &tm->tm_hour; + min = 1; + range = 12; + goto numeric_range; + case 'j': + dest = &tm->tm_yday; + min = 1; + range = 366; + adj = 1; + goto numeric_range; + case 'm': + dest = &tm->tm_mon; + min = 1; + range = 12; + adj = 1; + goto numeric_range; + case 'M': + dest = &tm->tm_min; + min = 0; + range = 60; + goto numeric_range; + case 'n': case 't': + for (; *s && isspace(*s); s++); + break; + case 'p': + ex = nl_langinfo(AM_STR); + len = strlen(ex); + if (!strncasecmp(s, ex, len)) { + tm->tm_hour %= 12; + s += len; + break; + } + ex = nl_langinfo(PM_STR); + len = strlen(ex); + if (!strncasecmp(s, ex, len)) { + tm->tm_hour %= 12; + tm->tm_hour += 12; + s += len; + break; + } + return 0; + case 'r': + s = strptime(s, nl_langinfo(T_FMT_AMPM), tm); + if (!s) return 0; + break; + case 'R': + s = strptime(s, "%H:%M", tm); + if (!s) return 0; + break; + case 'S': + dest = &tm->tm_sec; + min = 0; + range = 61; + goto numeric_range; + case 'T': + s = strptime(s, "%H:%M:%S", tm); + if (!s) return 0; + break; + case 'U': + case 'W': + /* Throw away result, for now. (FIXME?) */ + dest = &dummy; + min = 0; + range = 54; + goto numeric_range; + case 'w': + dest = &tm->tm_wday; + min = 0; + range = 7; + goto numeric_range; + case 'x': + s = strptime(s, nl_langinfo(D_FMT), tm); + if (!s) return 0; + break; + case 'X': + s = strptime(s, nl_langinfo(T_FMT), tm); + if (!s) return 0; + break; + case 'y': + dest = &relyear; + w = 2; + want_century |= 1; + goto numeric_digits; + case 'Y': + dest = &tm->tm_year; + if (w<0) w=4; + adj = 1900; + want_century = 0; + goto numeric_digits; + case '%': + if (*s++ != '%') return 0; + break; + default: + return 0; + numeric_range: + if (!isdigit(*s)) return 0; + *dest = 0; + for (i=1; i<=min+range && isdigit(*s); i*=10) + *dest = *dest * 10 + *s++ - '0'; + if (*dest - min >= (unsigned)range) return 0; + *dest -= adj; + switch((char *)dest - (char *)tm) { + case offsetof(struct tm, tm_yday): + ; + } + goto update; + numeric_digits: + neg = 0; + if (*s == '+') s++; + else if (*s == '-') neg=1, s++; + if (!isdigit(*s)) return 0; + for (*dest=i=0; i=0; i--) { + ex = nl_langinfo(min+i); + len = strlen(ex); + if (strncasecmp(s, ex, len)) continue; + s += len; + *dest = i % range; + break; + } + if (i<0) return 0; + goto update; + update: + //FIXME + ; + } + } + if (want_century) { + tm->tm_year = relyear; + if (want_century & 2) tm->tm_year += century * 100 - 1900; + else if (tm->tm_year <= 68) tm->tm_year += 100; + } + return (char *)s; +} diff --git a/src/system/libroot/posix/musl/time/time_impl.h b/src/system/libroot/posix/musl/time/time_impl.h new file mode 100644 index 0000000000..4acd3ea07c --- /dev/null +++ b/src/system/libroot/posix/musl/time/time_impl.h @@ -0,0 +1,11 @@ +#include +#include + +#if __GNUC__ < 4 +#define restrict +#endif + +hidden size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc); +hidden const char *__strftime_fmt_1(char (*)[100], size_t *, int, const struct tm *, locale_t, int); + +#include "time_impl_haiku.h" diff --git a/src/system/libroot/posix/musl/time/time_impl_haiku.h b/src/system/libroot/posix/musl/time/time_impl_haiku.h new file mode 100644 index 0000000000..19ba6070f7 --- /dev/null +++ b/src/system/libroot/posix/musl/time/time_impl_haiku.h @@ -0,0 +1,23 @@ +time_t timegm(struct tm *tm); + +static inline time_t +__tm_to_secs(const struct tm *tm) +{ + struct tm tmp = *tm; + return timegm(&tmp); +} + +static inline const char* +__tm_to_tzname(const struct tm *tm) +{ + const void *p = tm->tm_zone; + if (p) + return p; + if (tm->tm_isdst >= 0) + return tzname[tm->tm_isdst != 0]; + + return ""; +} + +#define __tm_gmtoff tm_gmtoff +#define __tm_zone tm_zone diff --git a/src/system/libroot/posix/musl/time/wcsftime.c b/src/system/libroot/posix/musl/time/wcsftime.c new file mode 100644 index 0000000000..ba46e45744 --- /dev/null +++ b/src/system/libroot/posix/musl/time/wcsftime.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include "locale_impl.h" +#include "time_impl.h" + +size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc) +{ + size_t l, k; + char buf[100]; + wchar_t wbuf[100]; + wchar_t *p; + const char *t_mb; + const wchar_t *t; + int pad, plus; + unsigned long width; + for (l=0; ltm_year >= 10000-1900) + s[l++] = '+'; + else if (tm->tm_year < -1900) + s[l++] = '-'; + else + width++; + for (; width > k && l < n; width--) + s[l++] = '0'; + } + if (k >= n-l) k = n-l; + wmemcpy(s+l, t, k); + l += k; + } + if (n) { + if (l==n) l=n-1; + s[l] = 0; + } + return 0; +} + +size_t wcsftime(wchar_t *restrict wcs, size_t n, const wchar_t *restrict f, const struct tm *restrict tm) +{ + return __wcsftime_l(wcs, n, f, tm, CURRENT_LOCALE); +} + +weak_alias(__wcsftime_l, wcsftime_l); diff --git a/src/system/libroot/posix/time/Jamfile b/src/system/libroot/posix/time/Jamfile index 71c72882d4..9b5e71d303 100644 --- a/src/system/libroot/posix/time/Jamfile +++ b/src/system/libroot/posix/time/Jamfile @@ -1,13 +1,12 @@ SubDir HAIKU_TOP src system libroot posix time ; # for localtime.c strftime.c -SubDirCcFlags -DNOID -DUSG_COMPAT -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone +SubDirCcFlags -DNOID -DUSG_COMPAT -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DPCTS=1 -DSTD_INSPIRED ; UsePrivateHeaders libroot [ FDirName libroot locale ] - [ FDirName libroot time ] shared ; @@ -23,18 +22,13 @@ for architectureObject in [ MultiArchSubDirSetup ] { clock.cpp clock_support.cpp ctime.c - difftime.c localtime_fading_out.c localtime.cpp nanosleep.c stime.c - strftime.c - strptime.c - timelocal.cpp time.c timer_support.cpp timespec_get.cpp - wcsftime.c ; } } diff --git a/src/system/libroot/posix/time/difftime.c b/src/system/libroot/posix/time/difftime.c deleted file mode 100644 index 4101238d79..0000000000 --- a/src/system/libroot/posix/time/difftime.c +++ /dev/null @@ -1,16 +0,0 @@ -/* -** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the MIT License. -*/ - - -#include -#include - - -double -difftime(time_t time1, time_t time2) -{ - return 1. * ((bigtime_t)time1 - (bigtime_t)time2); -} - diff --git a/headers/private/libroot/time/private.h b/src/system/libroot/posix/time/private.h similarity index 100% rename from headers/private/libroot/time/private.h rename to src/system/libroot/posix/time/private.h diff --git a/src/system/libroot/posix/time/strftime.c b/src/system/libroot/posix/time/strftime.c deleted file mode 100644 index 72550bbd8d..0000000000 --- a/src/system/libroot/posix/time/strftime.c +++ /dev/null @@ -1,589 +0,0 @@ -#ifndef lint -#ifndef NOID -static char elsieid[] = "@(#)strftime.c 8.1"; -/* -** Based on the UCB version with the ID appearing below. -** This is ANSIish only when "multibyte character == plain character". -*/ -#endif /* !defined NOID */ -#endif /* !defined lint */ - -#include "private.h" - -/* -** Copyright (c) 1989 The Regents of the University of California. -** All rights reserved. -** -** Redistribution and use in source and binary forms are permitted -** provided that the above copyright notice and this paragraph are -** duplicated in all such forms and that any documentation, -** advertising materials, and other materials related to such -** distribution and use acknowledge that the software was developed -** by the University of California, Berkeley. The name of the -** University may not be used to endorse or promote products derived -** from this software without specific prior written permission. -** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -*/ - -#ifndef LIBC_SCCS -#ifndef lint -static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89"; -#endif /* !defined lint */ -#endif /* !defined LIBC_SCCS */ - -#include "tzfile.h" -#include "fcntl.h" -#include "locale.h" -#include "timelocal.h" - -static char * _add P((const char *, char *, const char *)); -static char * _conv P((int, const char *, char *, const char *)); -static char * _fmt P((const char *, const struct tm *, char *, const char *, - int *, const struct lc_time_t*)); -static char * _yconv P((int, int, int, int, char *, const char *)); -static size_t __strftime(char * const, const size_t, const char * const, - const struct tm * const, const struct lc_time_t*); - -extern char * tzname[]; - -#ifndef YEAR_2000_NAME -#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS" -#endif /* !defined YEAR_2000_NAME */ - -#define IN_NONE 0 -#define IN_SOME 1 -#define IN_THIS 2 -#define IN_ALL 3 - -#define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU - -size_t -strftime(char* const s, const size_t maxsize, const char* const format, const struct tm* const t) -{ - return __strftime(s, maxsize, format, t, __get_current_time_locale()); -} - -size_t -strftime_l(char* const s, const size_t maxsize, const char* const format, const struct tm* const t, - locale_t locale) -{ - return __strftime(s, maxsize, format, t, __get_time_locale(locale)); -} - -static size_t -__strftime(s, maxsize, format, t, locale) -char * const s; -const size_t maxsize; -const char * const format; -const struct tm * const t; -const struct lc_time_t* locale; -{ - char * p; - int warn; - - tzset(); - warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, locale); -#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU - if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); - if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", - format); - (void) fprintf(stderr, "yields only two digits of years in "); - if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); - else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); - } -#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ - if (p == s + maxsize) - return 0; - *p = '\0'; - return p - s; -} - -static char * -_fmt(format, t, pt, ptlim, warnp, Locale) -const char * format; -const struct tm * const t; -char * pt; -const char * const ptlim; -int * warnp; -const struct lc_time_t* Locale; -{ - for ( ; *format; ++format) { - if (*format == '%') { -label: - switch (*++format) { - case '\0': - --format; - break; - case '0': - // ignore '0'-modifier supported by glibc for compatibility - goto label; - case 'A': - pt = _add((t->tm_wday < 0 || - t->tm_wday >= DAYSPERWEEK) ? - "?" : Locale->weekday[t->tm_wday], - pt, ptlim); - continue; - case 'a': - pt = _add((t->tm_wday < 0 || - t->tm_wday >= DAYSPERWEEK) ? - "?" : Locale->wday[t->tm_wday], - pt, ptlim); - continue; - case 'B': - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->month[t->tm_mon], - pt, ptlim); - continue; - case 'b': - case 'h': - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->mon[t->tm_mon], - pt, ptlim); - continue; - case 'C': - /* - ** %C used to do a... - ** _fmt("%a %b %e %X %Y", t); - ** ...whereas now POSIX 1003.2 calls for - ** something completely different. - ** (ado, 1993-05-24) - */ - pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0, - pt, ptlim); - continue; - case 'c': - { - int warn2 = IN_SOME; - - pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp, Locale); - if (warn2 > *warnp) - *warnp = warn2; - } - continue; - case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, Locale); - continue; - case 'd': - pt = _conv(t->tm_mday, "%02d", pt, ptlim); - continue; - case 'E': - case 'O': - /* - ** C99 locale modifiers. - ** The sequences - ** %Ec %EC %Ex %EX %Ey %EY - ** %Od %oe %OH %OI %Om %OM - ** %OS %Ou %OU %OV %Ow %OW %Oy - ** are supposed to provide alternate - ** representations. - */ - goto label; - case 'e': - pt = _conv(t->tm_mday, "%2d", pt, ptlim); - continue; - case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, Locale); - continue; - case 'H': - pt = _conv(t->tm_hour, "%02d", pt, ptlim); - continue; - case 'I': - pt = _conv((t->tm_hour % 12) ? - (t->tm_hour % 12) : 12, - "%02d", pt, ptlim); - continue; - case 'j': - pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim); - continue; - case 'k': - /* - ** This used to be... - ** _conv(t->tm_hour % 12 ? - ** t->tm_hour % 12 : 12, 2, ' '); - ** ...and has been changed to the below to - ** match SunOS 4.1.1 and Arnold Robbins' - ** strftime version 3.0. That is, "%k" and - ** "%l" have been swapped. - ** (ado, 1993-05-24) - */ - pt = _conv(t->tm_hour, "%2d", pt, ptlim); - continue; -#ifdef KITCHEN_SINK - case 'K': - /* - ** After all this time, still unclaimed! - */ - pt = _add("kitchen sink", pt, ptlim); - continue; -#endif /* defined KITCHEN_SINK */ - case 'l': - /* - ** This used to be... - ** _conv(t->tm_hour, 2, ' '); - ** ...and has been changed to the below to - ** match SunOS 4.1.1 and Arnold Robbin's - ** strftime version 3.0. That is, "%k" and - ** "%l" have been swapped. - ** (ado, 1993-05-24) - */ - pt = _conv((t->tm_hour % 12) ? - (t->tm_hour % 12) : 12, - "%2d", pt, ptlim); - continue; - case 'M': - pt = _conv(t->tm_min, "%02d", pt, ptlim); - continue; - case 'm': - pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim); - continue; - case 'n': - pt = _add("\n", pt, ptlim); - continue; - case 'p': - pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ? - Locale->pm : - Locale->am, - pt, ptlim); - continue; - case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp, Locale); - continue; - case 'r': - pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, Locale); - continue; - case 'S': - pt = _conv(t->tm_sec, "%02d", pt, ptlim); - continue; - case 's': - { - struct tm tm; - char buf[INT_STRLEN_MAXIMUM( - time_t) + 1]; - time_t mkt; - - tm = *t; - mkt = mktime(&tm); - if (TYPE_SIGNED(time_t)) - (void) sprintf(buf, "%ld", - (long) mkt); - else (void) sprintf(buf, "%lu", - (unsigned long) mkt); - pt = _add(buf, pt, ptlim); - } - continue; - case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, Locale); - continue; - case 't': - pt = _add("\t", pt, ptlim); - continue; - case 'U': - pt = _conv((t->tm_yday + DAYSPERWEEK - - t->tm_wday) / DAYSPERWEEK, - "%02d", pt, ptlim); - continue; - case 'u': - /* - ** From Arnold Robbins' strftime version 3.0: - ** "ISO 8601: Weekday as a decimal number - ** [1 (Monday) - 7]" - ** (ado, 1993-05-24) - */ - pt = _conv((t->tm_wday == 0) ? - DAYSPERWEEK : t->tm_wday, - "%d", pt, ptlim); - continue; - case 'V': /* ISO 8601 week number */ - case 'G': /* ISO 8601 year (four digits) */ - case 'g': /* ISO 8601 year (two digits) */ -/* -** From Arnold Robbins' strftime version 3.0: "the week number of the -** year (the first Monday as the first day of week 1) as a decimal number -** (01-53)." -** (ado, 1993-05-24) -** -** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn: -** "Week 01 of a year is per definition the first week which has the -** Thursday in this year, which is equivalent to the week which contains -** the fourth day of January. In other words, the first week of a new year -** is the week which has the majority of its days in the new year. Week 01 -** might also contain days from the previous year and the week before week -** 01 of a year is the last week (52 or 53) of the previous year even if -** it contains days from the new year. A week starts with Monday (day 1) -** and ends with Sunday (day 7). For example, the first week of the year -** 1997 lasts from 1996-12-30 to 1997-01-05..." -** (ado, 1996-01-02) -*/ - { - int year; - int base; - int yday; - int wday; - int w; - - year = t->tm_year; - base = TM_YEAR_BASE; - yday = t->tm_yday; - wday = t->tm_wday; - for ( ; ; ) { - int len; - int bot; - int top; - - len = isleap_sum(year, base) ? - DAYSPERLYEAR : - DAYSPERNYEAR; - /* - ** What yday (-3 ... 3) does - ** the ISO year begin on? - */ - bot = ((yday + 11 - wday) % - DAYSPERWEEK) - 3; - /* - ** What yday does the NEXT - ** ISO year begin on? - */ - top = bot - - (len % DAYSPERWEEK); - if (top < -3) - top += DAYSPERWEEK; - top += len; - if (yday >= top) { - ++base; - w = 1; - break; - } - if (yday >= bot) { - w = 1 + ((yday - bot) / - DAYSPERWEEK); - break; - } - --base; - yday += isleap_sum(year, base) ? - DAYSPERLYEAR : - DAYSPERNYEAR; - } -#ifdef XPG4_1994_04_09 - if ((w == 52 && - t->tm_mon == TM_JANUARY) || - (w == 1 && - t->tm_mon == TM_DECEMBER)) - w = 53; -#endif /* defined XPG4_1994_04_09 */ - if (*format == 'V') - pt = _conv(w, "%02d", - pt, ptlim); - else if (*format == 'g') { - *warnp = IN_ALL; - pt = _yconv(year, base, 0, 1, - pt, ptlim); - } else pt = _yconv(year, base, 1, 1, - pt, ptlim); - } - continue; - case 'v': - /* - ** From Arnold Robbins' strftime version 3.0: - ** "date as dd-bbb-YYYY" - ** (ado, 1993-05-24) - */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, Locale); - continue; - case 'W': - pt = _conv((t->tm_yday + DAYSPERWEEK - - (t->tm_wday ? - (t->tm_wday - 1) : - (DAYSPERWEEK - 1))) / DAYSPERWEEK, - "%02d", pt, ptlim); - continue; - case 'w': - pt = _conv(t->tm_wday, "%d", pt, ptlim); - continue; - case 'X': - pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp, Locale); - continue; - case 'x': - { - int warn2 = IN_SOME; - - pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2, Locale); - if (warn2 == IN_ALL) - warn2 = IN_THIS; - if (warn2 > *warnp) - *warnp = warn2; - } - continue; - case 'y': - *warnp = IN_ALL; - pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, - pt, ptlim); - continue; - case 'Y': - pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, - pt, ptlim); - continue; - case 'Z': -#ifdef TM_ZONE - if (t->TM_ZONE != NULL) - pt = _add(t->TM_ZONE, pt, ptlim); - else -#endif /* defined TM_ZONE */ - if (t->tm_isdst >= 0) - pt = _add(tzname[t->tm_isdst != 0], - pt, ptlim); - /* - ** C99 says that %Z must be replaced by the - ** empty string if the time zone is not - ** determinable. - */ - continue; - case 'z': - { - int diff; - char const * sign; - - if (t->tm_isdst < 0) - continue; -#ifdef TM_GMTOFF - diff = t->TM_GMTOFF; -#else /* !defined TM_GMTOFF */ - /* - ** C99 says that the UTC offset must - ** be computed by looking only at - ** tm_isdst. This requirement is - ** incorrect, since it means the code - ** must rely on magic (in this case - ** altzone and timezone), and the - ** magic might not have the correct - ** offset. Doing things correctly is - ** tricky and requires disobeying C99; - ** see GNU C strftime for details. - ** For now, punt and conform to the - ** standard, even though it's incorrect. - ** - ** C99 says that %z must be replaced by the - ** empty string if the time zone is not - ** determinable, so output nothing if the - ** appropriate variables are not available. - */ - if (t->tm_isdst == 0) -#ifdef USG_COMPAT - diff = -timezone; -#else /* !defined USG_COMPAT */ - continue; -#endif /* !defined USG_COMPAT */ - else -#ifdef ALTZONE - diff = -altzone; -#else /* !defined ALTZONE */ - continue; -#endif /* !defined ALTZONE */ -#endif /* !defined TM_GMTOFF */ - if (diff < 0) { - sign = "-"; - diff = -diff; - } else sign = "+"; - pt = _add(sign, pt, ptlim); - diff /= SECSPERMIN; - diff = (diff / MINSPERHOUR) * 100 + - (diff % MINSPERHOUR); - pt = _conv(diff, "%04d", pt, ptlim); - } - continue; - case '+': - pt = _fmt(Locale->date_fmt, t, pt, ptlim, - warnp, Locale); - continue; - case '%': - /* - ** X311J/88-090 (4.12.3.5): if conversion char is - ** undefined, behavior is undefined. Print out the - ** character itself as printf(3) also does. - */ - default: - break; - } - } - if (pt == ptlim) - break; - *pt++ = *format; - } - return pt; -} - -static char * -_conv(n, format, pt, ptlim) -const int n; -const char * const format; -char * const pt; -const char * const ptlim; -{ - char buf[INT_STRLEN_MAXIMUM(int) + 1]; - - (void) sprintf(buf, format, n); - return _add(buf, pt, ptlim); -} - -static char * -_add(str, pt, ptlim) -const char * str; -char * pt; -const char * const ptlim; -{ - while (pt < ptlim && (*pt = *str++) != '\0') - ++pt; - return pt; -} - -/* -** POSIX and the C Standard are unclear or inconsistent about -** what %C and %y do if the year is negative or exceeds 9999. -** Use the convention that %C concatenated with %y yields the -** same output as %Y, and that %Y contains at least 4 bytes, -** with more only if necessary. -*/ - -static char * -_yconv(a, b, convert_top, convert_yy, pt, ptlim) -const int a; -const int b; -const int convert_top; -const int convert_yy; -char * pt; -const char * const ptlim; -{ - register int lead; - register int trail; - -#define DIVISOR 100 - trail = a % DIVISOR + b % DIVISOR; - lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR; - trail %= DIVISOR; - if (trail < 0 && lead > 0) { - trail += DIVISOR; - --lead; - } else if (lead < 0 && trail > 0) { - trail -= DIVISOR; - ++lead; - } - if (convert_top) { - if (lead == 0 && trail < 0) - pt = _add("-0", pt, ptlim); - else pt = _conv(lead, "%02d", pt, ptlim); - } - if (convert_yy) - pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim); - return pt; -} diff --git a/src/system/libroot/posix/time/strptime.c b/src/system/libroot/posix/time/strptime.c deleted file mode 100644 index 2bacda41d7..0000000000 --- a/src/system/libroot/posix/time/strptime.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 1994 Powerdog Industries. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgement: - * This product includes software developed by Powerdog Industries. - * 4. The name of Powerdog Industries may not be used to endorse or - * promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include "timelocal.h" - -#include - -static char * _strptime(const char *, const char *, struct tm *, int *); - -#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) - -static char * -_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp) -{ - char c; - const char *ptr; - int i, - len; - int Ealternative, Oalternative; - struct lc_time_t *tptr = __get_current_time_locale(); - - ptr = fmt; - while (*ptr != 0) { - c = *ptr++; - - if (c != '%') { - if (isspace((unsigned char)c)) - while (*buf != 0 && isspace((unsigned char)*buf)) - buf++; - else if (c != *buf++) - return 0; - continue; - } - - Ealternative = 0; - Oalternative = 0; -label: - c = *ptr++; - switch (c) { - case '%': - if (*buf++ != '%') - return 0; - break; - - case '+': - buf = _strptime(buf, tptr->date_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'C': - if (!isdigit((unsigned char)*buf)) - return 0; - - /* XXX This will break for 3-digit centuries. */ - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (i < 19) - return 0; - - tm->tm_year = i * 100 - 1900; - break; - - case 'c': - buf = _strptime(buf, tptr->c_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'D': - buf = _strptime(buf, "%m/%d/%y", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'E': - if (Ealternative || Oalternative) - break; - Ealternative++; - goto label; - - case 'O': - if (Ealternative || Oalternative) - break; - Oalternative++; - goto label; - - case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'R': - buf = _strptime(buf, "%H:%M", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'T': - buf = _strptime(buf, "%H:%M:%S", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'X': - buf = _strptime(buf, tptr->X_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'x': - buf = _strptime(buf, tptr->x_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'j': - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 3; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (i < 1 || i > 366) - return 0; - - tm->tm_yday = i - 1; - break; - - case 'M': - case 'S': - if (*buf == 0 || isspace((unsigned char)*buf)) - break; - - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - - if (c == 'M') { - if (i > 59) - return 0; - tm->tm_min = i; - } else { - if (i > 60) - return 0; - tm->tm_sec = i; - } - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 'H': - case 'I': - case 'k': - case 'l': - /* - * Of these, %l is the only specifier explicitly - * documented as not being zero-padded. However, - * there is no harm in allowing zero-padding. - * - * XXX The %l specifier may gobble one too many - * digits if used incorrectly. - */ - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (c == 'H' || c == 'k') { - if (i > 23) - return 0; - } else if (i > 12) - return 0; - - tm->tm_hour = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 'p': - /* - * XXX This is bogus if parsed before hour-related - * specifiers. - */ - len = strlen(tptr->am); - if (strncasecmp(buf, tptr->am, len) == 0) { - if (tm->tm_hour > 12) - return 0; - if (tm->tm_hour == 12) - tm->tm_hour = 0; - buf += len; - break; - } - - len = strlen(tptr->pm); - if (strncasecmp(buf, tptr->pm, len) == 0) { - if (tm->tm_hour > 12) - return 0; - if (tm->tm_hour != 12) - tm->tm_hour += 12; - buf += len; - break; - } - - return 0; - - case 'A': - case 'a': - for (i = 0; i < asizeof(tptr->weekday); i++) { - len = strlen(tptr->weekday[i]); - if (strncasecmp(buf, tptr->weekday[i], - len) == 0) - break; - len = strlen(tptr->wday[i]); - if (strncasecmp(buf, tptr->wday[i], - len) == 0) - break; - } - if (i == asizeof(tptr->weekday)) - return 0; - - tm->tm_wday = i; - buf += len; - break; - - case 'U': - case 'W': - /* - * XXX This is bogus, as we can not assume any valid - * information present in the tm structure at this - * point to calculate a real value, so just check the - * range for now. - */ - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (i > 53) - return 0; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 'w': - if (!isdigit((unsigned char)*buf)) - return 0; - - i = *buf - '0'; - if (i > 6) - return 0; - - tm->tm_wday = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 'd': - case 'e': - /* - * The %e specifier is explicitly documented as not - * being zero-padded but there is no harm in allowing - * such padding. - * - * XXX The %e specifier may gobble one too many - * digits if used incorrectly. - */ - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (i > 31) - return 0; - - tm->tm_mday = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 'B': - case 'b': - case 'h': - for (i = 0; i < asizeof(tptr->month); i++) { - if (Oalternative) { - if (c == 'B') { - len = strlen(tptr->alt_month[i]); - if (strncasecmp(buf, - tptr->alt_month[i], - len) == 0) - break; - } - } else { - len = strlen(tptr->month[i]); - if (strncasecmp(buf, tptr->month[i], - len) == 0) - break; - len = strlen(tptr->mon[i]); - if (strncasecmp(buf, tptr->mon[i], - len) == 0) - break; - } - } - if (i == asizeof(tptr->month)) - return 0; - - tm->tm_mon = i; - buf += len; - break; - - case 'm': - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (i < 1 || i > 12) - return 0; - - tm->tm_mon = i - 1; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 's': - { - char *cp; - int sverrno; - long n; - time_t t; - - sverrno = errno; - __set_errno(0); - n = strtol(buf, &cp, 10); - if (errno == ERANGE || (long)(t = n) != n) { - __set_errno(sverrno); - return 0; - } - __set_errno(sverrno); - buf = cp; - gmtime_r(&t, tm); - *GMTp = 1; - } - break; - - case 'Y': - case 'y': - if (*buf == 0 || isspace((unsigned char)*buf)) - break; - - if (!isdigit((unsigned char)*buf)) - return 0; - - len = (c == 'Y') ? 4 : 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } - if (c == 'Y') - i -= 1900; - if (c == 'y' && i < 69) - i += 100; - - tm->tm_year = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ptr++; - break; - - case 'Z': - { - const char *cp; - char *zonestr; - - for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} - if (cp - buf) { - zonestr = alloca(cp - buf + 1); - strncpy(zonestr, buf, cp - buf); - zonestr[cp - buf] = '\0'; - tzset(); - if (0 == strcmp(zonestr, "GMT")) { - *GMTp = 1; - } else if (0 == strcmp(zonestr, tzname[0])) { - tm->tm_isdst = 0; - } else if (0 == strcmp(zonestr, tzname[1])) { - tm->tm_isdst = 1; - } else { - return 0; - } - buf += cp - buf; - } - } - break; - - default: - return 0; - } - } - return (char *)buf; -} - - -char * -strptime(const char * __restrict buf, const char * __restrict fmt, - struct tm * __restrict tm) -{ - char *ret; - int gmt; - - gmt = 0; - ret = _strptime(buf, fmt, tm, &gmt); - if (ret && gmt) { - time_t t = timegm(tm); - localtime_r(&t, tm); - } - - return (ret); -} diff --git a/src/system/libroot/posix/time/timelocal.cpp b/src/system/libroot/posix/time/timelocal.cpp deleted file mode 100644 index 0aa99af3cb..0000000000 --- a/src/system/libroot/posix/time/timelocal.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. - * Distributed under the terms of the MIT License. - */ - - -#include "timelocal.h" - -#include - -#include "LocaleBackend.h" -#include "PosixLCTimeInfo.h" - - -using BPrivate::Libroot::GetCurrentLocaleBackend; -using BPrivate::Libroot::LocaleBackend; -using BPrivate::Libroot::LocaleBackendData; - - -extern "C" const lc_time_t* -__get_current_time_locale(void) -{ - if (GetCurrentLocaleBackend() != NULL) - return GetCurrentLocaleBackend()->LCTimeInfo(); - - return &BPrivate::Libroot::gPosixLCTimeInfo; -} - - -extern "C" const lc_time_t* -__get_time_locale(locale_t l) -{ - LocaleBackendData* locale = (LocaleBackendData*)l; - LocaleBackend* backend = locale->backend; - - if (backend != NULL) - return backend->LCTimeInfo(); - - return &BPrivate::Libroot::gPosixLCTimeInfo; -} diff --git a/headers/private/libroot/time/tzfile.h b/src/system/libroot/posix/time/tzfile.h similarity index 100% rename from headers/private/libroot/time/tzfile.h rename to src/system/libroot/posix/time/tzfile.h diff --git a/src/system/libroot/posix/time/wcsftime.c b/src/system/libroot/posix/time/wcsftime.c deleted file mode 100644 index fea84cbb84..0000000000 --- a/src/system/libroot/posix/time/wcsftime.c +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * Copyright (c) 2002 Tim J. Robbins - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include -#include -#include -#include - -#include -#include - - -/* - * Convert date and time to a wide-character string. - * - * This is the wide-character counterpart of strftime(). So that we do not - * have to duplicate the code of strftime(), we convert the format string to - * multibyte, call strftime(), then convert the result back into wide - * characters. - * - * This technique loses in the presence of stateful multibyte encoding if any - * of the conversions in the format string change conversion state. When - * stateful encoding is implemented, we will need to reset the state between - * format specifications in the format string. - */ -size_t -wcsftime(wchar_t *wcs, size_t maxsize, const wchar_t *format, - const struct tm *timeptr) -{ - static const mbstate_t initial; - mbstate_t mbs; - char *dst, *sformat; - const char *dstp; - const wchar_t *formatp; - size_t n, sflen; - int sverrno; - - sformat = dst = NULL; - - /* - * Convert the supplied format string to a multibyte representation - * for strftime(), which only handles single-byte characters. - */ - mbs = initial; - formatp = format; - sflen = __wcsrtombs(NULL, &formatp, 0, &mbs); - if (sflen == (size_t)-1) - goto error; - if ((sformat = malloc(sflen + 1)) == NULL) - goto error; - mbs = initial; - __wcsrtombs(sformat, &formatp, sflen + 1, &mbs); - - /* - * Allocate memory for longest multibyte sequence that will fit - * into the caller's buffer and call strftime() to fill it. - * Then, copy and convert the result back into wide characters in - * the caller's buffer. - */ - if (SIZE_MAX / MB_CUR_MAX <= maxsize) { - /* maxsize is prepostorously large - avoid int. overflow. */ - __set_errno(EINVAL); - goto error; - } - if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL) - goto error; - if (strftime(dst, maxsize, sformat, timeptr) == 0) - goto error; - dstp = dst; - mbs = initial; - n = __mbsrtowcs(wcs, &dstp, maxsize, &mbs); - if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL) - goto error; - - free(sformat); - free(dst); - - return n; - -error: - sverrno = errno; - free(sformat); - free(dst); - __set_errno(sverrno); - - return 0; -}