[libc-commits] [libc] [libc] implement localtime (PR #110363)
Зишан Мирза via libc-commits
libc-commits at lists.llvm.org
Wed Dec 25 21:21:17 PST 2024
https://github.com/zimirza updated https://github.com/llvm/llvm-project/pull/110363
>From a999454f2acc223f22281c89eee6f3bce99f1adf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 15:50:29 +0200
Subject: [PATCH 01/58] [libc] implement localtime
This is an implementation of localtime.
Closes #107597 and #109892
---
libc/config/baremetal/arm/entrypoints.txt | 2 +
libc/config/baremetal/riscv/entrypoints.txt | 2 +
libc/config/linux/aarch64/entrypoints.txt | 2 +
libc/config/linux/riscv/entrypoints.txt | 2 +
libc/config/linux/x86_64/entrypoints.txt | 2 +
libc/hdrgen/yaml/time.yaml | 13 +
libc/spec/stdc.td | 1808 +++++++++++++++++++
libc/src/time/CMakeLists.txt | 24 +
libc/src/time/localtime.cpp | 25 +
libc/src/time/localtime.h | 21 +
libc/src/time/localtime_r.cpp | 25 +
libc/src/time/localtime_r.h | 21 +
libc/src/time/time_utils.cpp | 45 +-
libc/src/time/time_utils.h | 35 +-
libc/test/src/time/CMakeLists.txt | 36 +
libc/test/src/time/ctime_r_test.cpp | 4 +-
libc/test/src/time/ctime_test.cpp | 4 +-
libc/test/src/time/localtime_r_test.cpp | 87 +
libc/test/src/time/localtime_test.cpp | 54 +
19 files changed, 2203 insertions(+), 9 deletions(-)
create mode 100644 libc/spec/stdc.td
create mode 100644 libc/src/time/localtime.cpp
create mode 100644 libc/src/time/localtime.h
create mode 100644 libc/src/time/localtime_r.cpp
create mode 100644 libc/src/time/localtime_r.h
create mode 100644 libc/test/src/time/localtime_r_test.cpp
create mode 100644 libc/test/src/time/localtime_test.cpp
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 694cd7b1993ca2..87a1143704264e 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -206,6 +206,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.asctime_r
libc.src.time.ctime
libc.src.time.ctime_r
+ libc.src.time.localtime
+ libc.src.time.localtime_r
libc.src.time.difftime
libc.src.time.gmtime
libc.src.time.gmtime_r
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 6dc5df830eb000..0548265636535a 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -202,6 +202,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.asctime_r
libc.src.time.ctime
libc.src.time.ctime_r
+ libc.src.time.localtime
+ libc.src.time.localtime_r
libc.src.time.difftime
libc.src.time.gmtime
libc.src.time.gmtime_r
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b949e4b4f67ba0..a4e193a1b51f0f 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1002,6 +1002,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.asctime_r
libc.src.time.ctime
libc.src.time.ctime_r
+ libc.src.time.localtime
+ libc.src.time.localtime_r
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 19980f79e7be81..518599b70da08a 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -937,6 +937,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.asctime_r
libc.src.time.ctime
libc.src.time.ctime_r
+ libc.src.time.localtime
+ libc.src.time.localtime_r
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 08d8559d8c81a2..b540215713e66c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1087,6 +1087,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.asctime_r
libc.src.time.ctime
libc.src.time.ctime_r
+ libc.src.time.localtime
+ libc.src.time.localtime_r
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/hdrgen/yaml/time.yaml b/libc/hdrgen/yaml/time.yaml
index 3f745e5ee33868..008a7884656a0a 100644
--- a/libc/hdrgen/yaml/time.yaml
+++ b/libc/hdrgen/yaml/time.yaml
@@ -37,6 +37,19 @@ functions:
arguments:
- type: const time_t *
- type: char *
+ - name: localtime
+ standard:
+ - stdc
+ return_type: struct tm *
+ arguments:
+ - type: const time_t *
+ - name: localtime_r
+ standard:
+ - stdc
+ return_type: struct tm *
+ arguments:
+ - type: const time_t *
+ - type: struct tm *
- name: clock
standard:
- stdc
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
new file mode 100644
index 00000000000000..9fd8d175f36be3
--- /dev/null
+++ b/libc/spec/stdc.td
@@ -0,0 +1,1808 @@
+def StdC : StandardSpec<"stdc"> {
+
+ NamedType StructTmType = NamedType<"struct tm">;
+ PtrType StructTmPtr = PtrType<StructTmType>;
+ PtrType TimeTTypePtr = PtrType<TimeTType>;
+ NamedType ClockT = NamedType<"clock_t">;
+ NamedType LocaleT = NamedType<"locale_t">;
+
+ NamedType DivTType = NamedType<"div_t">;
+ NamedType LDivTType = NamedType<"ldiv_t">;
+ NamedType LLDivTType = NamedType<"lldiv_t">;
+
+ NamedType JmpBuf = NamedType<"jmp_buf">;
+
+ NamedType TssTType = NamedType<"tss_t">;
+ PtrType TssTPtr = PtrType<TssTType>;
+ NamedType TssDtorTType = NamedType<"tss_dtor_t">;
+
+ HeaderSpec Assert = HeaderSpec<
+ "assert.h",
+ [
+ Macro<"static_assert">,
+ Macro<"assert">,
+ ],
+ [], // Types
+ [], // Enumerations
+ []
+ >;
+
+ FunctionAttrSpec ConstAttr = FunctionAttrSpec<"__LIBC_CONST_ATTR", [
+ Cxx11FunctionAttr<"const", "gnu">,
+ GnuFunctionAttr<"const">,
+ ]>;
+
+ HeaderSpec CType = HeaderSpec<
+ "ctype.h",
+ [], // Macros
+ [
+ LocaleT
+ ], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "isalnum",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isalpha",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isblank",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "iscntrl",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isdigit",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isgraph",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "islower",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isprint",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "ispunct",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isspace",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isupper",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isxdigit",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "tolower",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "toupper",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "isalnum_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isalpha_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isblank_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "iscntrl_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isdigit_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isgraph_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "islower_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isprint_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "ispunct_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isspace_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isupper_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "isxdigit_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "tolower_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "toupper_l",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<LocaleT>]
+ >,
+ ]
+ >;
+
+ NamedType FEnvT = NamedType<"fenv_t">;
+ PtrType FEnvTPtr = PtrType<FEnvT>;
+ ConstType ConstFEnvTPtr = ConstType<FEnvTPtr>;
+ NamedType FExceptT = NamedType<"fexcept_t">;
+ PtrType FExceptTPtr = PtrType<FExceptT>;
+ ConstType ConstFExceptTPtr = ConstType<FExceptTPtr>;
+ HeaderSpec Fenv = HeaderSpec<
+ "fenv.h",
+ [
+ Macro<"FE_DIVBYZERO">,
+ Macro<"FE_INEXACT">,
+ Macro<"FE_INVALID">,
+ Macro<"FE_OVERFLOW">,
+ Macro<"FE_UNDERFLOW">,
+ Macro<"FE_ALL_EXCEPT">,
+
+ Macro<"FE_DOWNWARD">,
+ Macro<"FE_TONEAREST">,
+ Macro<"FE_TOWARDZERO">,
+ Macro<"FE_UPWARD">,
+
+ Macro<"FE_DFL_ENV">
+ ],
+ [
+ FEnvT,
+ FExceptT,
+ ], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "feclearexcept",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fetestexcept",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fetestexceptflag",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstFExceptTPtr>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "feraiseexcept",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fesetround",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fegetround",
+ RetValSpec<IntType>,
+ []
+ >,
+ FunctionSpec<
+ "fegetenv",
+ RetValSpec<IntType>,
+ [ArgSpec<FEnvTPtr>]
+ >,
+ FunctionSpec<
+ "fesetenv",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstFEnvTPtr>]
+ >,
+ FunctionSpec<
+ "fegetexceptflag",
+ RetValSpec<IntType>,
+ [ArgSpec<FExceptTPtr>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fesetexcept",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fesetexceptflag",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstFExceptTPtr>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "feholdexcept",
+ RetValSpec<IntType>,
+ [ArgSpec<FEnvTPtr>]
+ >,
+ FunctionSpec<
+ "feupdateenv",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstFEnvTPtr>]
+ >,
+ ]
+ >;
+
+ HeaderSpec String = HeaderSpec<
+ "string.h",
+ [
+ Macro<"NULL">,
+ ],
+ [
+ SizeTType,
+ ],
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "memcpy",
+ RetValSpec<VoidPtr>,
+ [ArgSpec<VoidRestrictedPtr>,
+ ArgSpec<ConstVoidRestrictedPtr>,
+ ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "memmove",
+ RetValSpec<VoidPtr>,
+ [ArgSpec<VoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "memcmp",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstVoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "memchr",
+ RetValSpec<VoidPtr>,
+ [ArgSpec<ConstVoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "memset",
+ RetValSpec<VoidPtr>,
+ [ArgSpec<VoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "memset_explicit",
+ RetValSpec<VoidPtr>,
+ [ArgSpec<VoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "strcpy",
+ RetValSpec<CharPtr>,
+ [ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>]
+ >,
+ FunctionSpec<
+ "strncpy",
+ RetValSpec<CharPtr>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "strcat",
+ RetValSpec<CharPtr>,
+ [ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>]
+ >,
+ FunctionSpec<
+ "strncat",
+ RetValSpec<CharPtr>,
+ [ArgSpec<CharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "strcmp",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strcoll",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strcoll_l",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "strncmp",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "strxfrm",
+ RetValSpec<SizeTType>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "strxfrm_l",
+ RetValSpec<SizeTType>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<LocaleT>]
+ >,
+ FunctionSpec<
+ "strchr",
+ RetValSpec<CharPtr>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "strcspn",
+ RetValSpec<SizeTType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strdup",
+ RetValSpec<CharPtr>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strndup",
+ RetValSpec<CharPtr>,
+ [ArgSpec<ConstCharPtr>,ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "strpbrk",
+ RetValSpec<CharPtr>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strrchr",
+ RetValSpec<CharPtr>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "strspn",
+ RetValSpec<SizeTType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strstr",
+ RetValSpec<CharPtr>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "strtok",
+ RetValSpec<CharPtr>,
+ [ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>]
+ >,
+ FunctionSpec<
+ "strerror",
+ RetValSpec<CharPtr>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "strlen",
+ RetValSpec<SizeTType>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ ]
+ >;
+
+ HeaderSpec Math = HeaderSpec<
+ "math.h",
+ [
+ Macro<"MATH_ERRNO">,
+ Macro<"MATH_ERREXCEPT">,
+ Macro<"math_errhandling">,
+
+ Macro<"HUGE_VAL">,
+ Macro<"INFINITY">,
+ Macro<"NAN">,
+
+ Macro<"FP_INT_UPWARD">,
+ Macro<"FP_INT_DOWNWARD">,
+ Macro<"FP_INT_TOWARDZERO">,
+ Macro<"FP_INT_TONEARESTFROMZERO">,
+ Macro<"FP_INT_TONEAREST">,
+
+ Macro<"FP_ILOGB0">,
+ Macro<"FP_ILOGBNAN">,
+
+ Macro<"isfinite">,
+ Macro<"isinf">,
+ Macro<"isnan">,
+ ],
+ [
+ NamedType<"float_t">,
+ NamedType<"double_t">,
+ NamedType<"float128">,
+ ],
+ [], // Enumerations
+ [
+ FunctionSpec<"cbrt", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"cbrtf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"copysign", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"copysignf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"copysignl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"copysignf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"copysignf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"ceil", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"ceilf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"ceill", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"ceilf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"ceilf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"daddl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ FunctionSpec<"ddivl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ FunctionSpec<"dfmal", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ FunctionSpec<"dsubl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"fabs", RetValSpec<DoubleType>, [ArgSpec<DoubleType>], [ConstAttr]>,
+ FunctionSpec<"fabsf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"fabsl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fabsf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fabsf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fadd", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"faddl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"fdim", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fdimf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fdiml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fdimf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fdimf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fdiv", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fdivl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"ffma", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"ffmal", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"floor", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"floorf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"floorl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"floorf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"floorf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fmin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fminf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fminl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fminf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+ GuardedFunctionSpec<"fminf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"fmax", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmaxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmaxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmaxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+ GuardedFunctionSpec<"fmaxf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"fmaximum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmaximumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmaximuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmaximumf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fmaximumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fmaximum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmaximum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmaximum_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fmaximum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fmaximum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmaximum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmaximum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmaximum_magf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fmaximum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fmaximum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmaximum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmaximum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmaximum_mag_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fmaximum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fminimum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fminimumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fminimuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fminimumf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fminimumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fminimum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fminimum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fminimum_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fminimum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fminimum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fminimum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fminimum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fminimum_magf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fminimum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fminimum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fminimum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fminimum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fminimum_mag_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+
+ GuardedFunctionSpec<"f16fmaf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
+ FunctionSpec<"fmod", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmodf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"fmodl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"fmodf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fmodf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"frexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,
+ FunctionSpec<"frexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntPtr>]>,
+ FunctionSpec<"frexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]>,
+ GuardedFunctionSpec<"frexpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"frexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"fromfpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fromfpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"fromfpxf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fromfpxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"fsub", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fsubl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"ufromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"ufromfpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"ufromfpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"ufromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"ufromfpxf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"ufromfpxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"hypot", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"hypotf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+
+ FunctionSpec<"ilogb", RetValSpec<IntType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"ilogbf", RetValSpec<IntType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"ilogbl", RetValSpec<IntType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"ilogbf16", RetValSpec<IntType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"ilogbf128", RetValSpec<IntType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"llogb", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"llogbf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"llogbl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"llogbf16", RetValSpec<LongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"llogbf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"ldexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
+ FunctionSpec<"ldexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
+ FunctionSpec<"ldexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
+ GuardedFunctionSpec<"ldexpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"ldexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"log10", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"log10f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"log1p", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"log1pf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"log2", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"log2f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"log", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"logf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"logb", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"logbf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"logbl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"logbf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"logbf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"modf", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoublePtr>]>,
+ FunctionSpec<"modff", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatPtr>]>,
+ FunctionSpec<"modfl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoublePtr>]>,
+ GuardedFunctionSpec<"modff16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"modff128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"cos", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"cosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"sin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"sinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"tan", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"tanf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"erff", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"exp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"expf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ GuardedFunctionSpec<"expf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"exp2", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"exp2f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ GuardedFunctionSpec<"exp2f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"exp2m1f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"expm1", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"expm1f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ GuardedFunctionSpec<"expm1f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"exp10", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"exp10f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ GuardedFunctionSpec<"exp10f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"remainder", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"remainderf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"remainderl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"remainderf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"remainderf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"remquo", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,
+ FunctionSpec<"remquof", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<IntPtr>]>,
+ FunctionSpec<"remquol", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]>,
+ GuardedFunctionSpec<"remquof16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"remquof128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"round", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"roundf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"roundl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"roundf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"roundf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"roundeven", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"roundevenf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"roundevenl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"roundevenf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"roundevenf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"lround", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"lroundf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"lroundl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"lroundf16", RetValSpec<LongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"lroundf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"llround", RetValSpec<LongLongType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"llroundf", RetValSpec<LongLongType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"llroundl", RetValSpec<LongLongType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"llroundf16", RetValSpec<LongLongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"llroundf128", RetValSpec<LongLongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"rint", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"rintf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"rintl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"rintf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"rintf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"lrint", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"lrintf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"lrintl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"lrintf16", RetValSpec<LongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"lrintf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"llrint", RetValSpec<LongLongType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"llrintf", RetValSpec<LongLongType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"llrintl", RetValSpec<LongLongType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"llrintf16", RetValSpec<LongLongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"llrintf128", RetValSpec<LongLongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"sqrt", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"sqrtf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"sqrtl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"sqrtf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"trunc", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"truncf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"truncl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"truncf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"truncf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"nearbyint", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"nearbyintf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"nearbyintl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"nearbyintf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"nearbyintf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"nextafterf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"nextafter", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"nextafterl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"nextafterf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"nextafterf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"nexttowardf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<LongDoubleType>]>,
+ FunctionSpec<"nexttoward", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<LongDoubleType>]>,
+ FunctionSpec<"nexttowardl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"nexttowardf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ FunctionSpec<"nextdown", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"nextdownf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"nextdownl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"nextdownf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"nextdownf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"nextup", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"nextupf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"nextupl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"nextupf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"nextupf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"powf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"pow", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+
+ FunctionSpec<"coshf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"sinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"tanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"acosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"asinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"asin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+
+ FunctionSpec<"atanf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"atan2", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"atan2f", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"atan2l", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"acoshf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"asinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"atanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"scalbln", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<LongType>]>,
+ FunctionSpec<"scalblnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<LongType>]>,
+ FunctionSpec<"scalblnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongType>]>,
+ GuardedFunctionSpec<"scalblnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"scalblnf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
+ FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
+ FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
+ GuardedFunctionSpec<"scalbnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"scalbnf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
+ FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
+ FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
+ GuardedFunctionSpec<"nanf16", RetValSpec<Float16Type>, [ArgSpec<ConstCharPtr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"nanf128", RetValSpec<Float128Type>, [ArgSpec<ConstCharPtr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"canonicalize", RetValSpec<IntType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"canonicalizef", RetValSpec<IntType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+ FunctionSpec<"canonicalizel", RetValSpec<IntType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"canonicalizef16", RetValSpec<IntType>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"canonicalizef128", RetValSpec<IntType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"dsqrtl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"totalorder", RetValSpec<IntType>, [ArgSpec<ConstDoublePtr>, ArgSpec<ConstDoublePtr>]>,
+ FunctionSpec<"totalorderf", RetValSpec<IntType>, [ArgSpec<ConstFloatPtr>, ArgSpec<ConstFloatPtr>]>,
+ FunctionSpec<"totalorderl", RetValSpec<IntType>, [ArgSpec<ConstLongDoublePtr>, ArgSpec<ConstLongDoublePtr>]>,
+ GuardedFunctionSpec<"totalorderf16", RetValSpec<IntType>, [ArgSpec<ConstFloat16Ptr>, ArgSpec<ConstFloat16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"totalorderf128", RetValSpec<IntType>, [ArgSpec<ConstFloat128Ptr>, ArgSpec<ConstFloat128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"totalordermag", RetValSpec<IntType>, [ArgSpec<ConstDoublePtr>, ArgSpec<ConstDoublePtr>]>,
+ FunctionSpec<"totalordermagf", RetValSpec<IntType>, [ArgSpec<ConstFloatPtr>, ArgSpec<ConstFloatPtr>]>,
+ FunctionSpec<"totalordermagl", RetValSpec<IntType>, [ArgSpec<ConstLongDoublePtr>, ArgSpec<ConstLongDoublePtr>]>,
+ GuardedFunctionSpec<"totalordermagf16", RetValSpec<IntType>, [ArgSpec<ConstFloat16Ptr>, ArgSpec<ConstFloat16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"totalordermagf128", RetValSpec<IntType>, [ArgSpec<ConstFloat128Ptr>, ArgSpec<ConstFloat128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"getpayload", RetValSpec<DoubleType>, [ArgSpec<DoublePtr>]>,
+ FunctionSpec<"getpayloadf", RetValSpec<FloatType>, [ArgSpec<FloatPtr>]>,
+ FunctionSpec<"getpayloadl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoublePtr>]>,
+ GuardedFunctionSpec<"getpayloadf16", RetValSpec<Float16Type>, [ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"getpayloadf128", RetValSpec<Float128Type>, [ArgSpec<Float128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"setpayload", RetValSpec<IntType>, [ArgSpec<DoublePtr>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"setpayloadf", RetValSpec<IntType>, [ArgSpec<FloatPtr>, ArgSpec<FloatType>]>,
+ FunctionSpec<"setpayloadl", RetValSpec<IntType>, [ArgSpec<LongDoublePtr>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"setpayloadf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"setpayloadf128", RetValSpec<IntType>, [ArgSpec<Float128Ptr>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ FunctionSpec<"setpayloadsig", RetValSpec<IntType>, [ArgSpec<DoublePtr>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"setpayloadsigf", RetValSpec<IntType>, [ArgSpec<FloatPtr>, ArgSpec<FloatType>]>,
+ FunctionSpec<"setpayloadsigl", RetValSpec<IntType>, [ArgSpec<LongDoublePtr>, ArgSpec<LongDoubleType>]>,
+ GuardedFunctionSpec<"setpayloadsigf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"setpayloadsigf128", RetValSpec<IntType>, [ArgSpec<Float128Ptr>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ GuardedFunctionSpec<"f16addf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
+ GuardedFunctionSpec<"f16subf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
+ FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmull", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"dmull", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ GuardedFunctionSpec<"f16mulf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
+ FunctionSpec<"fsqrt", RetValSpec<FloatType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"fsqrtl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>]>,
+
+ GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
+ GuardedFunctionSpec<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
+ FunctionSpec<"lgamma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"lgammaf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"lgammal", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
+ ]
+ >;
+
+ HeaderSpec StdIO = HeaderSpec<
+ "stdio.h",
+ [
+ Macro<"stdin">,
+ Macro<"stderr">,
+ Macro<"stdout">,
+ Macro<"_IOFBF">,
+ Macro<"_IOLBF">,
+ Macro<"_IONBF">,
+ Macro<"EOF">,
+ ], // Macros
+ [ // Types
+ SizeTType,
+ FILE,
+ ],
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "clearerr",
+ RetValSpec<VoidType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "fclose",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "feof",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "ferror",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "fgetc",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "fgets",
+ RetValSpec<CharPtr>,
+ [
+ ArgSpec<CharRestrictedPtr>,
+ ArgSpec<IntType>,
+ ArgSpec<FILERestrictedPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "fflush",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "fopen",
+ RetValSpec<FILEPtr>,
+ [ArgSpec<ConstCharPtr>,
+ ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "fputc",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>,
+ ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "ftell",
+ RetValSpec<LongType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "getc",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "getchar",
+ RetValSpec<IntType>,
+ [ArgSpec<VoidType>]
+ >,
+ FunctionSpec<
+ "putc",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>,
+ ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "putchar",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fputs",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<FILERestrictedPtr>]
+ >,
+ FunctionSpec<
+ "puts",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>]
+ >,
+ FunctionSpec<
+ "fread",
+ RetValSpec<SizeTType>,
+ [ArgSpec<VoidRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<SizeTType>,
+ ArgSpec<FILERestrictedPtr>]
+ >,
+ FunctionSpec<
+ "fseek",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>,
+ ArgSpec<LongType>,
+ ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "fwrite",
+ RetValSpec<SizeTType>,
+ [ArgSpec<ConstVoidRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<SizeTType>,
+ ArgSpec<FILERestrictedPtr>]
+ >,
+ FunctionSpec<
+ "remove",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "rename",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "setbuf",
+ RetValSpec<VoidType>,
+ [ArgSpec<FILERestrictedPtr>, ArgSpec<CharRestrictedPtr>]
+ >,
+ FunctionSpec<
+ "setvbuf",
+ RetValSpec<IntType>,
+ [ArgSpec<FILERestrictedPtr>, ArgSpec<CharRestrictedPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
+ >,
+ FunctionSpec<
+ "sscanf",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "vsscanf",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "scanf",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "vscanf",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "fscanf",
+ RetValSpec<IntType>,
+ [ArgSpec<FILERestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "vfscanf",
+ RetValSpec<IntType>,
+ [ArgSpec<FILERestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "sprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "snprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "printf",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "fprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<FILERestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "asprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<CharRestrictedPtrPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VarArgType>]
+ >,
+ FunctionSpec<
+ "vsprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "vsnprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<CharRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "vprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "vfprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<FILERestrictedPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ FunctionSpec<
+ "ungetc",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "vasprintf",
+ RetValSpec<IntType>,
+ [ArgSpec<CharRestrictedPtrPtr>,
+ ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<VaListType>]
+ >,
+ ],
+ [
+ ObjectSpec<
+ "stdin",
+ "FILE *"
+ >,
+ ObjectSpec<
+ "stdout",
+ "FILE *"
+ >,
+ ObjectSpec<
+ "stderr",
+ "FILE *"
+ >,
+ ]
+ >;
+
+ HeaderSpec StdBit = HeaderSpec<
+ "stdbit.h",
+ [
+ Macro<"__STDC_VERSION_STDBIT_H__">,
+ Macro<"__STDC_ENDIAN_LITTLE__">,
+ Macro<"__STDC_ENDIAN_BIG__">,
+ Macro<"__STDC_ENDIAN_NATIVE__">,
+ Macro<"stdc_leading_zeros">,
+ Macro<"stdc_leading_ones">,
+ Macro<"stdc_trailing_zeros">,
+ Macro<"stdc_trailing_ones">,
+ Macro<"stdc_first_leading_zero">,
+ Macro<"stdc_first_leading_one">,
+ Macro<"stdc_first_trailing_zero">,
+ Macro<"stdc_first_trailing_one">,
+ Macro<"stdc_count_zeros">,
+ Macro<"stdc_count_ones">,
+ Macro<"stdc_has_single_bit">,
+ Macro<"stdc_bit_width">,
+ Macro<"stdc_bit_floor">,
+ Macro<"stdc_bit_ceil">
+ ], // Macros
+ [], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<"stdc_leading_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_leading_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_leading_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_leading_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_leading_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_leading_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_leading_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_leading_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_leading_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_leading_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_trailing_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_trailing_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_trailing_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_trailing_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_trailing_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_trailing_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_trailing_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_trailing_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_trailing_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_trailing_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_first_leading_zero_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_first_leading_zero_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_first_leading_zero_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_first_leading_zero_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_first_leading_zero_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_first_leading_one_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_first_leading_one_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_first_leading_one_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_first_leading_one_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_first_leading_one_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_first_trailing_one_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_first_trailing_one_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_first_trailing_one_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_first_trailing_one_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_first_trailing_one_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_count_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_count_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_count_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_count_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_count_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_count_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_count_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_count_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_count_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_count_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_has_single_bit_uc", RetValSpec<BoolType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_has_single_bit_us", RetValSpec<BoolType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_has_single_bit_ui", RetValSpec<BoolType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_has_single_bit_ul", RetValSpec<BoolType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_has_single_bit_ull", RetValSpec<BoolType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_bit_width_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_bit_width_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_bit_width_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_bit_width_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_bit_width_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_bit_floor_uc", RetValSpec<UnsignedCharType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_bit_floor_us", RetValSpec<UnsignedShortType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_bit_floor_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_bit_floor_ul", RetValSpec<UnsignedLongType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_bit_floor_ull", RetValSpec<UnsignedLongLongType>, [ArgSpec<UnsignedLongLongType>]>,
+ FunctionSpec<"stdc_bit_ceil_uc", RetValSpec<UnsignedCharType>, [ArgSpec<UnsignedCharType>]>,
+ FunctionSpec<"stdc_bit_ceil_us", RetValSpec<UnsignedShortType>, [ArgSpec<UnsignedShortType>]>,
+ FunctionSpec<"stdc_bit_ceil_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"stdc_bit_ceil_ul", RetValSpec<UnsignedLongType>, [ArgSpec<UnsignedLongType>]>,
+ FunctionSpec<"stdc_bit_ceil_ull", RetValSpec<UnsignedLongLongType>, [ArgSpec<UnsignedLongLongType>]>
+ ] // Functions
+ >;
+
+ HeaderSpec StdCkdInt = HeaderSpec<
+ "stdckdint.h",
+ [
+ Macro<"__STDC_VERSION_STDCKDINT_H__">,
+ Macro<"ckd_add">,
+ Macro<"ckd_sub">,
+ Macro<"ckd_mul">
+ ], // Macros
+ [], // Types
+ [], // Enumerations
+ [] // Functions
+ >;
+
+ HeaderSpec StdLib = HeaderSpec<
+ "stdlib.h",
+ [], // Macros
+ [
+ DivTType,
+ LDivTType,
+ LLDivTType,
+ SizeTType,
+ BSearchCompareT,
+ QSortCompareT,
+ AtexitHandlerT,
+ ], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<"abort", RetValSpec<NoReturn>, [ArgSpec<VoidType>]>,
+
+ FunctionSpec<"bsearch", RetValSpec<VoidPtr>, [ArgSpec<ConstVoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<BSearchCompareT>]>,
+
+ FunctionSpec<"abs", RetValSpec<IntType>, [ArgSpec<IntType>]>,
+ FunctionSpec<"labs", RetValSpec<LongType>, [ArgSpec<LongType>]>,
+ FunctionSpec<"llabs", RetValSpec<LongLongType>, [ArgSpec<LongLongType>]>,
+
+ FunctionSpec<"atof", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>]>,
+ FunctionSpec<"atoi", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>]>,
+ FunctionSpec<"atol", RetValSpec<LongType>, [ArgSpec<ConstCharPtr>]>,
+ FunctionSpec<"atoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharPtr>]>,
+
+ FunctionSpec<"div", RetValSpec<DivTType>, [ArgSpec<IntType>, ArgSpec<IntType>]>,
+ FunctionSpec<"ldiv", RetValSpec<LDivTType>, [ArgSpec<LongType>, ArgSpec<LongType>]>,
+ FunctionSpec<"lldiv", RetValSpec<LLDivTType>, [ArgSpec<LongLongType>, ArgSpec<LongLongType>]>,
+
+ FunctionSpec<"qsort", RetValSpec<VoidType>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<QSortCompareT>]>,
+
+ FunctionSpec<"rand", RetValSpec<IntType>, [ArgSpec<VoidType>]>,
+ FunctionSpec<"srand", RetValSpec<VoidType>, [ArgSpec<UnsignedIntType>]>,
+
+ FunctionSpec<"strfromf", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<FloatType>]>,
+ FunctionSpec<"strfromd", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"strfroml", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
+ FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
+ FunctionSpec<"strtold", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
+ FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
+ FunctionSpec<"strtoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
+ FunctionSpec<"strtoul", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
+ FunctionSpec<"strtoull", RetValSpec<UnsignedLongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
+
+ FunctionSpec<"strtof_l", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
+ FunctionSpec<"strtod_l", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
+ FunctionSpec<"strtold_l", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
+ FunctionSpec<"strtol_l", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
+ FunctionSpec<"strtoll_l", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
+ FunctionSpec<"strtoul_l", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
+ FunctionSpec<"strtoull_l", RetValSpec<UnsignedLongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
+
+ FunctionSpec<"malloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>]>,
+ FunctionSpec<"calloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>, ArgSpec<SizeTType>]>,
+ FunctionSpec<"realloc", RetValSpec<VoidPtr>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]>,
+ FunctionSpec<"aligned_alloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>, ArgSpec<SizeTType>]>,
+ FunctionSpec<"free", RetValSpec<VoidType>, [ArgSpec<VoidPtr>]>,
+
+ FunctionSpec<"_Exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
+ FunctionSpec<"at_quick_exit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
+ FunctionSpec<"atexit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
+ FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
+ FunctionSpec<"quick_exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
+
+ FunctionSpec<"system", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>]>,
+ ]
+ >;
+
+ NamedType IMaxDivTType = NamedType<"imaxdiv_t">;
+
+ HeaderSpec IntTypes = HeaderSpec<
+ "inttypes.h",
+ [
+ Macro<"__STDC_VERSION_INTTYPES_H__">,
+ ], // Macros
+ [
+ IMaxDivTType,
+ ], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<"imaxabs", RetValSpec<IntMaxTType>, [ArgSpec<IntMaxTType>]>,
+ FunctionSpec<"imaxdiv", RetValSpec<IMaxDivTType>, [ArgSpec<IntMaxTType>, ArgSpec<IntMaxTType>]>,
+ FunctionSpec<"strtoimax", RetValSpec<IntMaxTType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
+ FunctionSpec<"strtoumax", RetValSpec<UIntMaxTType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
+ ]
+ >;
+
+ HeaderSpec Errno = HeaderSpec<
+ "errno.h",
+ [
+ Macro<"errno">,
+ Macro<"EDOM">,
+ Macro<"EILSEQ">,
+ Macro<"ERANGE">,
+ ]
+ >;
+
+ HeaderSpec Float = HeaderSpec<
+ "float.h",
+ [
+ Macro<"FLT_MANT_DIG">,
+ Macro<"DBL_MANT_DIG">,
+ Macro<"LDBL_MANT_DIG">,
+ ]
+ >;
+
+ HeaderSpec StdInt = HeaderSpec<"StdInt.h">;
+
+ HeaderSpec Limits = HeaderSpec<"limits.h">;
+
+ NamedType SigAtomicT = NamedType<"sig_atomic_t">;
+ HeaderSpec Signal = HeaderSpec<
+ "signal.h",
+ [
+ Macro<"SIG_BLOCK">,
+ Macro<"SIG_UNBLOCK">,
+ Macro<"SIG_SETMASK">,
+
+ Macro<"SIGABRT">,
+ Macro<"SIGFPE">,
+ Macro<"SIGILL">,
+ Macro<"SIGINT">,
+ Macro<"SIGSEGV">,
+ Macro<"SIGTERM">
+ ],
+ [
+ SizeTType,
+ SigAtomicT,
+ SigHandlerT,
+ ],
+ [], // Enumerations
+ [
+ FunctionSpec<"raise", RetValSpec<IntType>, [ArgSpec<IntType>]>,
+ FunctionSpec<
+ "signal",
+ RetValSpec<SigHandlerT>,
+ [ArgSpec<IntType>, ArgSpec<SigHandlerT>]
+ >,
+ ]
+ >;
+
+ HeaderSpec Threads = HeaderSpec<
+ "threads.h",
+ [
+ Macro<"ONCE_FLAG_INIT">,
+ ],
+ [
+ OnceFlagType,
+ CallOnceFuncType,
+ CndTType,
+ MtxTType,
+ ThrdStartTType,
+ ThrdTType,
+ TssTType,
+ TssDtorTType,
+ ],
+ [
+ EnumeratedNameValue<"mtx_plain">,
+ EnumeratedNameValue<"mtx_recursive">,
+ EnumeratedNameValue<"mtx_timed">,
+ EnumeratedNameValue<"thrd_timedout">,
+ EnumeratedNameValue<"thrd_success">,
+ EnumeratedNameValue<"thrd_busy">,
+ EnumeratedNameValue<"thrd_error">,
+ EnumeratedNameValue<"thrd_nomem">,
+ ],
+ [
+ FunctionSpec<
+ "call_once",
+ RetValSpec<VoidType>,
+ [
+ ArgSpec<OnceFlagTypePtr>,
+ ArgSpec<CallOnceFuncType>,
+ ]
+ >,
+ FunctionSpec<
+ "cnd_broadcast",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<CndTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "cnd_destroy",
+ RetValSpec<VoidType>,
+ [
+ ArgSpec<CndTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "cnd_init",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<CndTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "cnd_signal",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<CndTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "cnd_wait",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<CndTTypePtr>,
+ ArgSpec<MtxTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "mtx_init",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<MtxTTypePtr>,
+ ArgSpec<IntType>,
+ ]
+ >,
+ FunctionSpec<
+ "mtx_destroy",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<VoidType>,
+ ]
+ >,
+ FunctionSpec<
+ "mtx_lock",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<MtxTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "mtx_unlock",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<MtxTTypePtr>,
+ ]
+ >,
+ FunctionSpec<
+ "thrd_create",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<ThrdTTypePtr>,
+ ArgSpec<ThrdStartTType>,
+ ArgSpec<VoidPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "thrd_join",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<ThrdTType>,
+ ArgSpec<IntPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "thrd_detach",
+ RetValSpec<IntType>,
+ [ArgSpec<ThrdTType>]
+ >,
+ FunctionSpec<
+ "thrd_current",
+ RetValSpec<ThrdTType>,
+ [ArgSpec<VoidType>]
+ >,
+ FunctionSpec<
+ "thrd_equal",
+ RetValSpec<IntType>,
+ [ArgSpec<ThrdTType>, ArgSpec<ThrdTType>]
+ >,
+ FunctionSpec<
+ "thrd_exit",
+ RetValSpec<VoidType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "tss_create",
+ RetValSpec<IntType>,
+ [ArgSpec<TssTPtr>, ArgSpec<TssDtorTType>]
+ >,
+ FunctionSpec<
+ "tss_delete",
+ RetValSpec<IntType>,
+ [ArgSpec<TssTType>]
+ >,
+ FunctionSpec<
+ "tss_get",
+ RetValSpec<VoidPtr>,
+ [ArgSpec<TssTType>]
+ >,
+ FunctionSpec<
+ "tss_set",
+ RetValSpec<IntType>,
+ [ArgSpec<TssTType>, ArgSpec<VoidPtr>]
+ >,
+ ]
+ >;
+
+ HeaderSpec Time = HeaderSpec<
+ "time.h",
+ [], // Macros
+ [ // Types
+ ClockT,
+ StructTmType,
+ StructTimeSpec,
+ TimeTType,
+ SizeTType,
+ ],
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "asctime",
+ RetValSpec<CharPtr>,
+ [ArgSpec<StructTmPtr>]
+ >,
+ FunctionSpec<
+ "asctime_r",
+ RetValSpec<CharPtr>,
+ [
+ ArgSpec<StructTmPtr>,
+ ArgSpec<CharPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "ctime",
+ RetValSpec<CharPtr>,
+ [ArgSpec<TimeTTypePtr>]
+ >,
+ FunctionSpec<
+ "ctime_r",
+ RetValSpec<CharPtr>,
+ [
+ ArgSpec<TimeTTypePtr>,
+ ArgSpec<CharPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "localtime",
+ RetValSpec<StructTmPtr>,
+ [ArgSpec<TimeTTypePtr>]
+ >,
+ FunctionSpec<
+ "localtime_r",
+ RetValSpec<StructTmPtr>,
+ [
+ ArgSpec<TimeTTypePtr>,
+ ArgSpec<StructTmPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "clock",
+ RetValSpec<ClockT>,
+ [ArgSpec<VoidType>]
+ >,
+ FunctionSpec<
+ "difftime",
+ RetValSpec<DoubleType>,
+ [
+ ArgSpec<TimeTType>,
+ ArgSpec<TimeTType>,
+ ]
+ >,
+ FunctionSpec<
+ "gmtime",
+ RetValSpec<StructTmPtr>,
+ [ArgSpec<TimeTTypePtr>]
+ >,
+ FunctionSpec<
+ "gmtime_r",
+ RetValSpec<StructTmPtr>,
+ [
+ ArgSpec<TimeTTypePtr>,
+ ArgSpec<StructTmPtr>,
+ ]
+ >,
+ FunctionSpec<
+ "mktime",
+ RetValSpec<TimeTType>,
+ [ArgSpec<StructTmPtr>]
+ >,
+ FunctionSpec<
+ "time",
+ RetValSpec<TimeTType>,
+ [ArgSpec<TimeTTypePtr>]
+ >,
+ ]
+ >;
+
+ HeaderSpec SetJmp = HeaderSpec<
+ "setjmp.h",
+ [], // Macros
+ [JmpBuf],
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "longjmp",
+ RetValSpec<NoReturn>,
+ [ArgSpec<JmpBuf>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "setjmp",
+ RetValSpec<IntType>,
+ [ArgSpec<JmpBuf>]
+ >,
+ FunctionSpec<
+ "longjmp",
+ RetValSpec<VoidType>,
+ [ArgSpec<JmpBuf>, ArgSpec<IntType>]
+ >,
+ ]
+ >;
+
+ HeaderSpec UChar = HeaderSpec<
+ "uchar.h",
+ [], // Macros
+ [ //Types
+ MBStateTType,
+ Char8TType,
+ Char16TType,
+ Char32TType,
+ SizeTType,
+ ],
+ [], // Enumerations
+ []
+ >;
+
+ HeaderSpec WChar = HeaderSpec<
+ "wchar.h",
+ [ // Macros
+ Macro<"WEOF">,
+ ],
+ [ //Types
+ MBStateTType,
+ SizeTType,
+ WIntType,
+ WCharType,
+ ],
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "wctob",
+ RetValSpec<IntType>,
+ [ArgSpec<WIntType>]
+ >,
+ ]
+ >;
+
+
+ NamedType StructLconv = NamedType<"struct lconv">;
+ PtrType StructLconvPtr = PtrType<StructLconv>;
+
+ HeaderSpec Locale = HeaderSpec<
+ "locale.h",
+ [], // Macros
+ [LocaleT, StructLconv], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "duplocale",
+ RetValSpec<LocaleT>,
+ [
+ ArgSpec<LocaleT>
+ ]
+ >,
+ FunctionSpec<
+ "freelocale",
+ RetValSpec<VoidType>,
+ [
+ ArgSpec<LocaleT>
+ ]
+ >,
+ FunctionSpec<
+ "localeconv",
+ RetValSpec<StructLconvPtr>,
+ []
+ >,
+ FunctionSpec<
+ "newlocale",
+ RetValSpec<LocaleT>,
+ [
+ ArgSpec<IntType>,
+ ArgSpec<ConstCharPtr>,
+ ArgSpec<LocaleT>
+ ]
+ >,
+ FunctionSpec<
+ "setlocale",
+ RetValSpec<CharPtr>,
+ [
+ ArgSpec<IntType>,
+ ArgSpec<ConstCharPtr>
+ ]
+ >,
+ FunctionSpec<
+ "uselocale",
+ RetValSpec<LocaleT>,
+ [
+ ArgSpec<LocaleT>
+ ]
+ >
+ ] // Functions
+ >;
+
+ let Headers = [
+ Assert,
+ CType,
+ Errno,
+ Fenv,
+ Float,
+ StdInt,
+ Limits,
+ Math,
+ String,
+ StdBit,
+ StdCkdInt,
+ StdIO,
+ StdLib,
+ IntTypes,
+ SetJmp,
+ Signal,
+ Threads,
+ Time,
+ UChar,
+ WChar,
+ Locale,
+ ];
+}
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index ae835dcc742742..0afd06c2600a0d 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -60,6 +60,30 @@ add_entrypoint_object(
libc.include.time
)
+add_entrypoint_object(
+ localtime
+ SRCS
+ localtime.cpp
+ HDRS
+ localtime.h
+ DEPENDS
+ .time_utils
+ libc.hdr.types.time_t
+ libc.include.time
+)
+
+add_entrypoint_object(
+ localtime_r
+ SRCS
+ localtime_r.cpp
+ HDRS
+ localtime_r.h
+ DEPENDS
+ .time_utils
+ libc.hdr.types.time_t
+ libc.include.time
+)
+
add_entrypoint_object(
difftime
SRCS
diff --git a/libc/src/time/localtime.cpp b/libc/src/time/localtime.cpp
new file mode 100644
index 00000000000000..c08af2d8b26b78
--- /dev/null
+++ b/libc/src/time/localtime.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of localtime function ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/localtime.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/time/time_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(struct tm *, localtime, (const time_t *t_ptr)) {
+ if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
+ return nullptr;
+ }
+
+ return time_utils::localtime(t_ptr);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime.h b/libc/src/time/localtime.h
new file mode 100644
index 00000000000000..648c8b755ddee9
--- /dev/null
+++ b/libc/src/time/localtime.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of localtime ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_LOCALTIME_H
+#define LLVM_LIBC_SRC_TIME_LOCALTIME_H
+
+#include "src/__support/macros/config.h"
+#include <time.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+struct tm *localtime(const time_t *t_ptr);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_LOCALTIME_H
diff --git a/libc/src/time/localtime_r.cpp b/libc/src/time/localtime_r.cpp
new file mode 100644
index 00000000000000..6ff3fb3d4faa8c
--- /dev/null
+++ b/libc/src/time/localtime_r.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of localtime_r function ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/localtime_r.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/time/time_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(struct tm *, localtime_r, (const time_t *t_ptr, struct tm *tm)) {
+ if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
+ return nullptr;
+ }
+
+ return time_utils::localtime_internal(t_ptr, tm);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime_r.h b/libc/src/time/localtime_r.h
new file mode 100644
index 00000000000000..d98b52180fa789
--- /dev/null
+++ b/libc/src/time/localtime_r.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of localtime_r --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_LOCALTIME_R_H
+#define LLVM_LIBC_SRC_TIME_LOCALTIME_R_H
+
+#include "src/__support/macros/config.h"
+#include <time.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+struct tm *localtime_r(const time_t *t_ptr, struct tm *tm);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_LOCALTIME_R_H
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 509cad8146df87..d00cc139471c8f 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stdio.h>
#include "src/time/time_utils.h"
#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
#include "src/__support/common.h"
@@ -129,6 +130,25 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (years > INT_MAX || years < INT_MIN)
return time_utils::out_of_range();
+ FILE *fp;
+ fp = fopen("/etc/timezone", "rb");
+ if (fp == NULL) {
+ return time_utils::out_of_range();
+ }
+
+ char timezone[128];
+ if (fgets(timezone, sizeof(timezone), fp) == NULL) {
+ return time_utils::out_of_range();
+ }
+
+ int offset;
+ if (internal::same_string(timezone, "UTC") == 0) {
+ offset = 0;
+ }
+ if (internal::same_string(timezone, "Europe/Berlin") == 0) {
+ offset = 2;
+ }
+
// All the data (years, month and remaining days) was calculated from
// March, 2000. Thus adjust the data to be from January, 1900.
tm->tm_year = static_cast<int>(years + 2000 - TimeConstants::TIME_YEAR_BASE);
@@ -144,11 +164,32 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
TimeConstants::SECONDS_PER_MIN);
tm->tm_sec =
static_cast<int>(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
- // TODO(rtenneti): Need to handle timezone and update of tm_isdst.
- tm->tm_isdst = 0;
+
+ if (offset == 0) {
+ tm->tm_isdst = 1;
+ } else {
+ tm->tm_isdst = 0;
+ tm->tm_hour += offset;
+ }
+
+ fclose(fp);
return 0;
}
+int calculate_dst(struct tm *tm) {
+ int sunday = tm->tm_mday - tm->tm_wday;
+
+ if (tm->tm_mon < 3 || tm->tm_mon > 11) {
+ return 0;
+ } else if (tm->tm_mon > 3 && tm->tm_mon < 11) {
+ return 1;
+ } else if (tm->tm_mon == 3) {
+ return sunday >= 8;
+ }
+
+ return sunday <= 0;
+}
+
} // namespace time_utils
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 552ea925c1c7dc..97374ca5b17289 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -15,6 +15,7 @@
#include "src/__support/macros/config.h"
#include "src/errno/libc_errno.h"
#include "src/time/mktime.h"
+#include "src/__support/CPP/limits.h"
#include <stdint.h>
@@ -85,6 +86,7 @@ struct TimeConstants {
// Update the "tm" structure's year, month, etc. members from seconds.
// "total_seconds" is the number of seconds since January 1st, 1970.
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
+extern int calculate_dst(struct tm *tm);
// TODO(michaelrj): move these functions to use ErrorOr instead of setting
// errno. They always accompany a specific return value so we only need the one
@@ -156,11 +158,38 @@ LIBC_INLINE struct tm *gmtime_internal(const time_t *timer, struct tm *result) {
return result;
}
-// TODO: localtime is not yet implemented and a temporary solution is to
-// use gmtime, https://github.com/llvm/llvm-project/issues/107597
LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
static struct tm result;
- return time_utils::gmtime_internal(t_ptr, &result);
+ int64_t time = *t_ptr;
+
+ // Update the tm structure's year, month, day, etc. from seconds.
+ if (update_from_seconds(time, &result) < 0) {
+ out_of_range();
+ return nullptr;
+ }
+
+ int isdst = calculate_dst(&result);
+ result.tm_hour += isdst;
+ result.tm_isdst = isdst;
+
+ return &result;
+}
+
+LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr, struct tm *result) {
+ //time_t time = *t;
+ int64_t t = *t_ptr;
+
+ // Update the tm structure's year, month, day, etc. from seconds.
+ if (update_from_seconds(t, result) < 0) {
+ out_of_range();
+ return nullptr;
+ }
+
+ int isdst = calculate_dst(result);
+ result->tm_hour += isdst;
+ result->tm_isdst = isdst;
+
+ return result;
}
} // namespace time_utils
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index da3903f3e0e494..8d53604d1609e2 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -66,6 +66,42 @@ add_libc_unittest(
libc.src.time.time_utils
)
+add_libc_unittest(
+ localtime_test
+ SUITE
+ libc_time_unittests
+ SRCS
+ localtime_test.cpp
+ HDRS
+ TmHelper.h
+ TmMatcher.h
+ CXX_STANDARD
+ 20
+ DEPENDS
+ libc.include.time
+ libc.hdr.types.time_t
+ libc.src.time.localtime
+ libc.src.time.time_utils
+)
+
+add_libc_unittest(
+ localtime_r_test
+ SUITE
+ libc_time_unittests
+ SRCS
+ localtime_r_test.cpp
+ HDRS
+ TmHelper.h
+ TmMatcher.h
+ CXX_STANDARD
+ 20
+ DEPENDS
+ libc.include.time
+ libc.hdr.types.time_t
+ libc.src.time.localtime_r
+ libc.src.time.time_utils
+)
+
add_libc_test(
clock_gettime_test
SUITE
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index 9ce6f75f754849..e0aa32e28178dc 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -35,7 +35,7 @@ TEST(LlvmLibcCtimeR, ValidUnixTimestamp0) {
// 1970-01-01 00:00:00. Test with a valid buffer size.
t = 0;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 01:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
@@ -45,7 +45,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
// 2038-01-19 03:14:07. Test with a valid buffer size.
t = 2147483647;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 04:14:07 2038\n", result);
}
TEST(LlvmLibcCtimeR, InvalidArgument) {
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 7ec71bb1e4ed1e..554b72d23fd4de 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -22,7 +22,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp0) {
char *result;
t = 0;
result = LIBC_NAMESPACE::ctime(&t);
- ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 01:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
@@ -30,7 +30,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
char *result;
t = 2147483647;
result = LIBC_NAMESPACE::ctime(&t);
- ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 04:14:07 2038\n", result);
}
TEST(LlvmLibcCtime, InvalidArgument) {
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
new file mode 100644
index 00000000000000..83848b53fc7d54
--- /dev/null
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -0,0 +1,87 @@
+//===-- Unittests for localtime_r -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/errno/libc_errno.h"
+#include "src/time/localtime_r.h"
+#include "test/UnitTest/Test.h"
+#include "test/src/time/TmHelper.h"
+
+TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
+ const time_t t_ptr = 1;
+ static struct tm input = (struct tm) {
+ .tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0
+ };
+ struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
+ ASSERT_EQ(70, result->tm_year);
+ ASSERT_EQ(0, result->tm_mon);
+ ASSERT_EQ(1, result->tm_mday);
+ ASSERT_EQ(2, result->tm_hour);
+ ASSERT_EQ(0, result->tm_min);
+ ASSERT_EQ(1, result->tm_sec);
+ ASSERT_EQ(4, result->tm_wday);
+ ASSERT_EQ(0, result->tm_yday);
+ ASSERT_EQ(0, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
+ time_t t_ptr = 2147483647;
+ static struct tm input = (struct tm) {
+ .tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0
+ };
+ struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
+ ASSERT_EQ(138, result->tm_year);
+ ASSERT_EQ(0, result->tm_mon);
+ ASSERT_EQ(19, result->tm_mday);
+ ASSERT_EQ(5, result->tm_hour);
+ ASSERT_EQ(14, result->tm_min);
+ ASSERT_EQ(7, result->tm_sec);
+ ASSERT_EQ(2, result->tm_wday);
+ ASSERT_EQ(18, result->tm_yday);
+ ASSERT_EQ(0, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32IntDst) {
+ time_t t_ptr = 1627225465;
+ static struct tm input = (struct tm) {
+ .tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0
+ };
+ struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(18, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
new file mode 100644
index 00000000000000..ba068dbf632d02
--- /dev/null
+++ b/libc/test/src/time/localtime_test.cpp
@@ -0,0 +1,54 @@
+//===-- Unittests for localtime -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/errno/libc_errno.h"
+#include "src/time/localtime.h"
+#include "test/UnitTest/Test.h"
+#include "test/src/time/TmHelper.h"
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
+ const time_t t_ptr = 0;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(70, result->tm_year);
+ ASSERT_EQ(0, result->tm_mon);
+ ASSERT_EQ(1, result->tm_mday);
+ ASSERT_EQ(2, result->tm_hour);
+ ASSERT_EQ(0, result->tm_min);
+ ASSERT_EQ(0, result->tm_sec);
+ ASSERT_EQ(4, result->tm_wday);
+ ASSERT_EQ(0, result->tm_yday);
+ ASSERT_EQ(0, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
+ time_t t_ptr = 2147483647;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(138, result->tm_year);
+ ASSERT_EQ(0, result->tm_mon);
+ ASSERT_EQ(19, result->tm_mday);
+ ASSERT_EQ(5, result->tm_hour);
+ ASSERT_EQ(14, result->tm_min);
+ ASSERT_EQ(7, result->tm_sec);
+ ASSERT_EQ(2, result->tm_wday);
+ ASSERT_EQ(18, result->tm_yday);
+ ASSERT_EQ(0, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(18, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
>From 2d1228fdb5a73720ad6c0a3ac08303ccf04a9c2e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 16:02:12 +0200
Subject: [PATCH 02/58] [libc] implement localtime
format code with clang-format
---
libc/src/time/localtime.cpp | 2 +-
libc/src/time/localtime_r.cpp | 5 ++-
libc/src/time/time_utils.cpp | 8 ++--
libc/src/time/time_utils.h | 7 +--
libc/test/src/time/localtime_r_test.cpp | 60 +++++++++++--------------
5 files changed, 39 insertions(+), 43 deletions(-)
diff --git a/libc/src/time/localtime.cpp b/libc/src/time/localtime.cpp
index c08af2d8b26b78..48c8d4a6c6b3f4 100644
--- a/libc/src/time/localtime.cpp
+++ b/libc/src/time/localtime.cpp
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(struct tm *, localtime, (const time_t *t_ptr)) {
if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
- return nullptr;
+ return nullptr;
}
return time_utils::localtime(t_ptr);
diff --git a/libc/src/time/localtime_r.cpp b/libc/src/time/localtime_r.cpp
index 6ff3fb3d4faa8c..64a107a729132f 100644
--- a/libc/src/time/localtime_r.cpp
+++ b/libc/src/time/localtime_r.cpp
@@ -14,9 +14,10 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(struct tm *, localtime_r, (const time_t *t_ptr, struct tm *tm)) {
+LLVM_LIBC_FUNCTION(struct tm *, localtime_r,
+ (const time_t *t_ptr, struct tm *tm)) {
if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
- return nullptr;
+ return nullptr;
}
return time_utils::localtime_internal(t_ptr, tm);
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index d00cc139471c8f..9a4aacb8f86f85 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include <stdio.h>
#include "src/time/time_utils.h"
#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include <stdio.h>
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
@@ -143,10 +143,10 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
int offset;
if (internal::same_string(timezone, "UTC") == 0) {
- offset = 0;
+ offset = 0;
}
if (internal::same_string(timezone, "Europe/Berlin") == 0) {
- offset = 2;
+ offset = 2;
}
// All the data (years, month and remaining days) was calculated from
@@ -185,7 +185,7 @@ int calculate_dst(struct tm *tm) {
} else if (tm->tm_mon > 3 && tm->tm_mon < 11) {
return 1;
} else if (tm->tm_mon == 3) {
- return sunday >= 8;
+ return sunday >= 8;
}
return sunday <= 0;
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 97374ca5b17289..87e0e0bae767c8 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -11,11 +11,11 @@
#include <stddef.h> // For size_t.
+#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/errno/libc_errno.h"
#include "src/time/mktime.h"
-#include "src/__support/CPP/limits.h"
#include <stdint.h>
@@ -175,8 +175,9 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
return &result;
}
-LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr, struct tm *result) {
- //time_t time = *t;
+LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr,
+ struct tm *result) {
+ // time_t time = *t;
int64_t t = *t_ptr;
// Update the tm structure's year, month, day, etc. from seconds.
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 83848b53fc7d54..edc7fed030aa9d 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -13,17 +13,15 @@
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
const time_t t_ptr = 1;
- static struct tm input = (struct tm) {
- .tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0
- };
+ static struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
ASSERT_EQ(70, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
@@ -38,17 +36,15 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
time_t t_ptr = 2147483647;
- static struct tm input = (struct tm) {
- .tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0
- };
+ static struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
ASSERT_EQ(138, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
@@ -63,17 +59,15 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32IntDst) {
time_t t_ptr = 1627225465;
- static struct tm input = (struct tm) {
- .tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0
- };
+ static struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
ASSERT_EQ(121, result->tm_year);
ASSERT_EQ(6, result->tm_mon);
>From 961e2b8c28a498a7bea15a75fae2b15301bbd978 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 16:05:42 +0200
Subject: [PATCH 03/58] [libc] implement localtime
fix: dst
---
libc/src/time/time_utils.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 9a4aacb8f86f85..5cc735734111a7 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -166,9 +166,9 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
static_cast<int>(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
if (offset == 0) {
- tm->tm_isdst = 1;
- } else {
tm->tm_isdst = 0;
+ } else {
+ tm->tm_isdst = 1;
tm->tm_hour += offset;
}
>From ad4abccf842b7176ea9151494a50fa4ff5648068 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 16:16:06 +0200
Subject: [PATCH 04/58] [libc] implement localtime
fix: dst
---
libc/src/time/time_utils.h | 1 -
libc/test/src/time/localtime_r_test.cpp | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 87e0e0bae767c8..0be7f114d370f9 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -187,7 +187,6 @@ LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr,
}
int isdst = calculate_dst(result);
- result->tm_hour += isdst;
result->tm_isdst = isdst;
return result;
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index edc7fed030aa9d..3c5d3c64e6bd9f 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -72,7 +72,7 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32IntDst) {
ASSERT_EQ(121, result->tm_year);
ASSERT_EQ(6, result->tm_mon);
ASSERT_EQ(25, result->tm_mday);
- ASSERT_EQ(18, result->tm_hour);
+ ASSERT_EQ(17, result->tm_hour);
ASSERT_EQ(4, result->tm_min);
ASSERT_EQ(25, result->tm_sec);
ASSERT_EQ(0, result->tm_wday);
>From fab3d9b42f138cdbca379df811186db88d65ad0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 16:20:15 +0200
Subject: [PATCH 05/58] [libc] implement localtime
update test for `localtime_r`
---
libc/test/src/time/localtime_r_test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 3c5d3c64e6bd9f..805db50751b777 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -12,7 +12,7 @@
#include "test/src/time/TmHelper.h"
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
- const time_t t_ptr = 1;
+ const time_t t_ptr = 0;
static struct tm input = (struct tm){.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
@@ -28,7 +28,7 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
ASSERT_EQ(1, result->tm_mday);
ASSERT_EQ(2, result->tm_hour);
ASSERT_EQ(0, result->tm_min);
- ASSERT_EQ(1, result->tm_sec);
+ ASSERT_EQ(0, result->tm_sec);
ASSERT_EQ(4, result->tm_wday);
ASSERT_EQ(0, result->tm_yday);
ASSERT_EQ(0, result->tm_isdst);
>From 38e257ffb663fd2788a785aef2d07d1db54efcc6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 16:22:35 +0200
Subject: [PATCH 06/58] [libc] implement localtime
remove unnecessary code
---
libc/src/time/time_utils.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 0be7f114d370f9..494ebc0bedf276 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -177,7 +177,6 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr,
struct tm *result) {
- // time_t time = *t;
int64_t t = *t_ptr;
// Update the tm structure's year, month, day, etc. from seconds.
>From f41ab899428cd8213937011a1c02de6b8c6f80ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 28 Sep 2024 16:34:52 +0200
Subject: [PATCH 07/58] [libc] implement localtime
fix: dst
---
libc/src/time/time_utils.h | 1 -
libc/test/src/time/localtime_test.cpp | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 494ebc0bedf276..6faf8f37172f6c 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -169,7 +169,6 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
}
int isdst = calculate_dst(&result);
- result.tm_hour += isdst;
result.tm_isdst = isdst;
return &result;
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index ba068dbf632d02..4143e7065596ff 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -45,7 +45,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
ASSERT_EQ(121, result->tm_year);
ASSERT_EQ(6, result->tm_mon);
ASSERT_EQ(25, result->tm_mday);
- ASSERT_EQ(18, result->tm_hour);
+ ASSERT_EQ(17, result->tm_hour);
ASSERT_EQ(4, result->tm_min);
ASSERT_EQ(25, result->tm_sec);
ASSERT_EQ(0, result->tm_wday);
>From bf56c83973bbf48d6357c8460fcb7c0252dc12a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 16:30:21 +0200
Subject: [PATCH 08/58] localtime_s is for windows only, implement localtime_s
on gnu/linux for compatibility reasons
---
libc/config/baremetal/arm/entrypoints.txt | 1 +
libc/config/baremetal/riscv/entrypoints.txt | 1 +
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/docs/c23.rst | 1 +
libc/docs/headers/time.rst | 2 +
libc/hdrgen/yaml/time.yaml | 7 +++
libc/spec/stdc.td | 8 ++++
libc/src/time/CMakeLists.txt | 12 +++++
libc/src/time/localtime.cpp | 8 ++--
libc/src/time/localtime_r.cpp | 9 +---
libc/src/time/localtime_r.h | 2 +-
libc/src/time/localtime_s.cpp | 21 +++++++++
libc/src/time/localtime_s.h | 22 +++++++++
libc/src/time/time_utils.h | 37 +++++++++++++--
libc/test/src/time/CMakeLists.txt | 19 ++++++++
libc/test/src/time/ctime_r_test.cpp | 4 +-
libc/test/src/time/localtime_r_test.cpp | 50 +++++++++-----------
libc/test/src/time/localtime_s_test.cpp | 52 +++++++++++++++++++++
20 files changed, 213 insertions(+), 46 deletions(-)
create mode 100644 libc/src/time/localtime_s.cpp
create mode 100644 libc/src/time/localtime_s.h
create mode 100644 libc/test/src/time/localtime_s_test.cpp
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 87a1143704264e..65558a271871f4 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -208,6 +208,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.ctime_r
libc.src.time.localtime
libc.src.time.localtime_r
+ libc.src.time.localtime_s
libc.src.time.difftime
libc.src.time.gmtime
libc.src.time.gmtime_r
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 0548265636535a..1a107d7136df96 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -204,6 +204,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.ctime_r
libc.src.time.localtime
libc.src.time.localtime_r
+ libc.src.time.localtime_s
libc.src.time.difftime
libc.src.time.gmtime
libc.src.time.gmtime_r
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index a4e193a1b51f0f..3ff46d757a763c 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1004,6 +1004,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.ctime_r
libc.src.time.localtime
libc.src.time.localtime_r
+ libc.src.time.localtime_s
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 518599b70da08a..f234a50dcaef72 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -939,6 +939,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.ctime_r
libc.src.time.localtime
libc.src.time.localtime_r
+ libc.src.time.localtime_s
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index b540215713e66c..931905562a5d2b 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1089,6 +1089,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.ctime_r
libc.src.time.localtime
libc.src.time.localtime_r
+ libc.src.time.localtime_s
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst
index b9a2424307f84b..9f0515bda5d581 100644
--- a/libc/docs/c23.rst
+++ b/libc/docs/c23.rst
@@ -152,6 +152,7 @@ Additions:
* gmtime_r
* localtime_r
+ * localtime_s
* timegm
* timespec_getres
* strftime conversion specifiers
diff --git a/libc/docs/headers/time.rst b/libc/docs/headers/time.rst
index de82d80a2bec48..7f0ceefa6834a1 100644
--- a/libc/docs/headers/time.rst
+++ b/libc/docs/headers/time.rst
@@ -89,6 +89,8 @@ Implementation Status
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| localtime_r | | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
+| localtime_s | | | | | | | | | | | | |
++---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| mktime | |check| | |check| | | |check| | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| nanosleep | |check| | |check| | | |check| | | | | | | | | |
diff --git a/libc/hdrgen/yaml/time.yaml b/libc/hdrgen/yaml/time.yaml
index 008a7884656a0a..610ae3e74f69ff 100644
--- a/libc/hdrgen/yaml/time.yaml
+++ b/libc/hdrgen/yaml/time.yaml
@@ -50,6 +50,13 @@ functions:
arguments:
- type: const time_t *
- type: struct tm *
+ - name: localtime_s
+ standard:
+ - stdc
+ return_type: struct tm *
+ arguments:
+ - type: const time_t *
+ - type: struct tm *
- name: clock
standard:
- stdc
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 9fd8d175f36be3..5546a3afcab9f7 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1628,6 +1628,14 @@ def StdC : StandardSpec<"stdc"> {
ArgSpec<StructTmPtr>,
]
>,
+ FunctionSpec<
+ "localtime_s",
+ RetValSpec<StructTmPtr>,
+ [
+ ArgSpec<TimeTTypePtr>,
+ ArgSpec<StructTmPtr>,
+ ]
+ >,
FunctionSpec<
"clock",
RetValSpec<ClockT>,
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 0afd06c2600a0d..f0f8ddf55e6d0e 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -84,6 +84,18 @@ add_entrypoint_object(
libc.include.time
)
+add_entrypoint_object(
+ localtime_s
+ SRCS
+ localtime_s.cpp
+ HDRS
+ localtime_s.h
+ DEPENDS
+ .time_utils
+ libc.hdr.types.time_t
+ libc.include.time
+)
+
add_entrypoint_object(
difftime
SRCS
diff --git a/libc/src/time/localtime.cpp b/libc/src/time/localtime.cpp
index 48c8d4a6c6b3f4..42ba562e0a561c 100644
--- a/libc/src/time/localtime.cpp
+++ b/libc/src/time/localtime.cpp
@@ -6,16 +6,18 @@
//
//===----------------------------------------------------------------------===//
-#include "src/time/localtime.h"
+#include "localtime.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/time/time_utils.h"
+#include "time_utils.h"
namespace LIBC_NAMESPACE_DECL {
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
LLVM_LIBC_FUNCTION(struct tm *, localtime, (const time_t *t_ptr)) {
- if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
+ if (t_ptr == nullptr) {
return nullptr;
}
diff --git a/libc/src/time/localtime_r.cpp b/libc/src/time/localtime_r.cpp
index 64a107a729132f..0af5414930327b 100644
--- a/libc/src/time/localtime_r.cpp
+++ b/libc/src/time/localtime_r.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "src/time/localtime_r.h"
-#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/time/time_utils.h"
@@ -15,12 +14,8 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(struct tm *, localtime_r,
- (const time_t *t_ptr, struct tm *tm)) {
- if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
- return nullptr;
- }
-
- return time_utils::localtime_internal(t_ptr, tm);
+ (const time_t *t_ptr, struct tm *input)) {
+ return time_utils::localtime_internal(t_ptr, input);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime_r.h b/libc/src/time/localtime_r.h
index d98b52180fa789..553811d6ffdc2b 100644
--- a/libc/src/time/localtime_r.h
+++ b/libc/src/time/localtime_r.h
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE_DECL {
-struct tm *localtime_r(const time_t *t_ptr, struct tm *tm);
+struct tm *localtime_r(const time_t *t_ptr, struct tm *input);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime_s.cpp b/libc/src/time/localtime_s.cpp
new file mode 100644
index 00000000000000..e49ff49810819f
--- /dev/null
+++ b/libc/src/time/localtime_s.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of localtime_s function ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/localtime_s.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/time/time_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// windows only, implemented in gnu/linux for compatibility reasons
+LLVM_LIBC_FUNCTION(int, localtime_s, (const time_t *t_ptr, struct tm *input)) {
+ return time_utils::localtime_s(t_ptr, input);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime_s.h b/libc/src/time/localtime_s.h
new file mode 100644
index 00000000000000..4f69cb0014d507
--- /dev/null
+++ b/libc/src/time/localtime_s.h
@@ -0,0 +1,22 @@
+//===-- Implementation header of localtime_s --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_LOCALTIME_S_H
+#define LLVM_LIBC_SRC_TIME_LOCALTIME_S_H
+
+#include "src/__support/macros/config.h"
+#include <time.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// windows only, implemented in gnu/linux for compatibility reasons
+int localtime_s(const time_t *t_ptr, struct tm *input);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_LOCALTIME_S_H
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 6faf8f37172f6c..78bfa069471231 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -175,19 +175,46 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
}
LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr,
- struct tm *result) {
+ struct tm *input) {
+ static struct tm result;
int64_t t = *t_ptr;
+ result.tm_sec = input->tm_sec;
+ result.tm_min = input->tm_min;
+ result.tm_hour = input->tm_hour;
+ result.tm_mday = input->tm_mday;
+ result.tm_mon = input->tm_mon;
+ result.tm_year = input->tm_year;
+ result.tm_wday = input->tm_wday;
+ result.tm_yday = input->tm_yday;
+ result.tm_isdst = input->tm_isdst;
+
// Update the tm structure's year, month, day, etc. from seconds.
- if (update_from_seconds(t, result) < 0) {
+ if (update_from_seconds(t, &result) < 0) {
out_of_range();
return nullptr;
}
- int isdst = calculate_dst(result);
- result->tm_isdst = isdst;
+ int isdst = calculate_dst(&result);
+ result.tm_isdst = isdst;
- return result;
+ return &result;
+}
+
+// for windows only, implemented on gnu/linux for compatibility reasons
+LIBC_INLINE int localtime_s(const time_t *t_ptr, struct tm *input) {
+ static struct tm *result = localtime_internal(t_ptr, input);
+ time_t t = LIBC_NAMESPACE::mktime(result);
+
+ if (*t_ptr < t) {
+ return -1;
+ }
+
+ if (*t_ptr > t) {
+ return 1;
+ }
+
+ return 0;
}
} // namespace time_utils
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 8d53604d1609e2..31691b5755bfe1 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -102,6 +102,25 @@ add_libc_unittest(
libc.src.time.time_utils
)
+add_libc_unittest(
+ localtime_s_test
+ SUITE
+ libc_time_unittests
+ SRCS
+ localtime_s_test.cpp
+ HDRS
+ TmHelper.h
+ TmMatcher.h
+ CXX_STANDARD
+ 20
+ DEPENDS
+ libc.include.time
+ libc.hdr.types.time_t
+ libc.src.time.mktime
+ libc.src.time.localtime_s
+ libc.src.time.time_utils
+)
+
add_libc_test(
clock_gettime_test
SUITE
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index e0aa32e28178dc..b03e8cecd2e9df 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -35,7 +35,7 @@ TEST(LlvmLibcCtimeR, ValidUnixTimestamp0) {
// 1970-01-01 00:00:00. Test with a valid buffer size.
t = 0;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Thu Jan 1 01:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 02:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
@@ -45,7 +45,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
// 2038-01-19 03:14:07. Test with a valid buffer size.
t = 2147483647;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Tue Jan 19 04:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 05:14:07 2038\n", result);
}
TEST(LlvmLibcCtimeR, InvalidArgument) {
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 805db50751b777..ba46835e81f77a 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -6,22 +6,16 @@
//
//===----------------------------------------------------------------------===//
-#include "src/errno/libc_errno.h"
#include "src/time/localtime_r.h"
+#include "src/time/time_utils.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
+ struct tm input;
const time_t t_ptr = 0;
- static struct tm input = (struct tm){.tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
ASSERT_EQ(70, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
@@ -36,15 +30,15 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
time_t t_ptr = 2147483647;
- static struct tm input = (struct tm){.tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0};
+ struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
ASSERT_EQ(138, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
@@ -59,15 +53,15 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32IntDst) {
time_t t_ptr = 1627225465;
- static struct tm input = (struct tm){.tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0};
+ struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
ASSERT_EQ(121, result->tm_year);
ASSERT_EQ(6, result->tm_mon);
diff --git a/libc/test/src/time/localtime_s_test.cpp b/libc/test/src/time/localtime_s_test.cpp
new file mode 100644
index 00000000000000..04d5d79c810792
--- /dev/null
+++ b/libc/test/src/time/localtime_s_test.cpp
@@ -0,0 +1,52 @@
+//===-- Unittests for localtime_s -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/localtime_s.h"
+#include "src/time/mktime.h"
+#include "src/time/time_utils.h"
+#include "test/UnitTest/Test.h"
+#include "test/src/time/TmHelper.h"
+
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
+TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp0) {
+ struct tm input;
+ const time_t t_ptr = 0;
+ int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
+ ASSERT_EQ(-1, result);
+}
+
+TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32Int) {
+ time_t t_ptr = 2147483647;
+ static struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
+ int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
+ ASSERT_EQ(1, result);
+}
+
+TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32IntDst) {
+ time_t t_ptr = 1627225465;
+ static struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
+ int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
+ ASSERT_EQ(1, result);
+}
>From ba31c63788bd0f09af3bdbb98a9f2080ceee8e0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 16:37:58 +0200
Subject: [PATCH 09/58] fix: localtime_s
---
libc/hdrgen/yaml/time.yaml | 2 +-
libc/spec/stdc.td | 2 +-
libc/src/time/CMakeLists.txt | 1 +
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/libc/hdrgen/yaml/time.yaml b/libc/hdrgen/yaml/time.yaml
index 610ae3e74f69ff..9dd6b187894c72 100644
--- a/libc/hdrgen/yaml/time.yaml
+++ b/libc/hdrgen/yaml/time.yaml
@@ -53,7 +53,7 @@ functions:
- name: localtime_s
standard:
- stdc
- return_type: struct tm *
+ return_type: int
arguments:
- type: const time_t *
- type: struct tm *
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 5546a3afcab9f7..d6186281b76a3f 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1630,7 +1630,7 @@ def StdC : StandardSpec<"stdc"> {
>,
FunctionSpec<
"localtime_s",
- RetValSpec<StructTmPtr>,
+ RetValSpec<IntType>,
[
ArgSpec<TimeTTypePtr>,
ArgSpec<StructTmPtr>,
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index f0f8ddf55e6d0e..c0bcae6bb10016 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -94,6 +94,7 @@ add_entrypoint_object(
.time_utils
libc.hdr.types.time_t
libc.include.time
+ libc.time.mktime
)
add_entrypoint_object(
>From 97abc876e427e2316a332e520a67b6aea855374f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 17:58:41 +0200
Subject: [PATCH 10/58] fix: path for mktime
---
libc/src/time/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index c0bcae6bb10016..9f51c2e36edf61 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -94,7 +94,7 @@ add_entrypoint_object(
.time_utils
libc.hdr.types.time_t
libc.include.time
- libc.time.mktime
+ libc.src.time.mktime
)
add_entrypoint_object(
>From d56241303b3210358cdc23ee6170ca9efc1720ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 19:38:42 +0200
Subject: [PATCH 11/58] fix: localtime_s and dst function
---
libc/src/time/time_utils.cpp | 18 ++++--
libc/src/time/time_utils.h | 45 +++++++--------
libc/test/src/time/localtime_s_test.cpp | 77 ++++++++++++++++++++++---
3 files changed, 103 insertions(+), 37 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 5cc735734111a7..35fbc02c17e679 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -177,18 +177,24 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
return 0;
}
-int calculate_dst(struct tm *tm) {
- int sunday = tm->tm_mday - tm->tm_wday;
+void set_dst(struct tm *tm) {
+ int dst;
+ int sunday;
+
+ dst = 0;
+ sunday = tm->tm_mday - tm->tm_wday;
if (tm->tm_mon < 3 || tm->tm_mon > 11) {
- return 0;
+ dst = 0;
} else if (tm->tm_mon > 3 && tm->tm_mon < 11) {
- return 1;
+ dst = 1;
} else if (tm->tm_mon == 3) {
- return sunday >= 8;
+ dst = sunday >= 8;
+ } else {
+ dst = sunday <= 0;
}
- return sunday <= 0;
+ tm->tm_isdst = dst;
}
} // namespace time_utils
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 78bfa069471231..51442493e19d87 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -86,7 +86,7 @@ struct TimeConstants {
// Update the "tm" structure's year, month, etc. members from seconds.
// "total_seconds" is the number of seconds since January 1st, 1970.
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
-extern int calculate_dst(struct tm *tm);
+extern void set_dst(struct tm *tm);
// TODO(michaelrj): move these functions to use ErrorOr instead of setting
// errno. They always accompany a specific return value so we only need the one
@@ -168,51 +168,48 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
return nullptr;
}
- int isdst = calculate_dst(&result);
- result.tm_isdst = isdst;
+ set_dst(&result);
return &result;
}
LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr,
struct tm *input) {
- static struct tm result;
int64_t t = *t_ptr;
- result.tm_sec = input->tm_sec;
- result.tm_min = input->tm_min;
- result.tm_hour = input->tm_hour;
- result.tm_mday = input->tm_mday;
- result.tm_mon = input->tm_mon;
- result.tm_year = input->tm_year;
- result.tm_wday = input->tm_wday;
- result.tm_yday = input->tm_yday;
- result.tm_isdst = input->tm_isdst;
-
// Update the tm structure's year, month, day, etc. from seconds.
- if (update_from_seconds(t, &result) < 0) {
+ if (update_from_seconds(t, input) < 0) {
out_of_range();
return nullptr;
}
- int isdst = calculate_dst(&result);
- result.tm_isdst = isdst;
+ set_dst(input);
- return &result;
+ return input;
}
// for windows only, implemented on gnu/linux for compatibility reasons
LIBC_INLINE int localtime_s(const time_t *t_ptr, struct tm *input) {
- static struct tm *result = localtime_internal(t_ptr, input);
- time_t t = LIBC_NAMESPACE::mktime(result);
+ if (input == NULL)
+ return -1;
+
+ if ((*t_ptr < 0 || *t_ptr > cpp::numeric_limits<int64_t>::max()) && input != NULL) {
+ // setting values to -1 for compatibility reasons
+ // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s
+ input->tm_sec = -1;
+ input->tm_min = -1;
+ input->tm_hour = -1;
+ input->tm_mday = -1;
+ input->tm_mon = -1;
+ input->tm_year = -1;
+ input->tm_wday = -1;
+ input->tm_yday = -1;
+ input->tm_isdst = -1;
- if (*t_ptr < t) {
return -1;
}
- if (*t_ptr > t) {
- return 1;
- }
+ localtime_internal(t_ptr, input);
return 0;
}
diff --git a/libc/test/src/time/localtime_s_test.cpp b/libc/test/src/time/localtime_s_test.cpp
index 04d5d79c810792..4a9d1d5dba5414 100644
--- a/libc/test/src/time/localtime_s_test.cpp
+++ b/libc/test/src/time/localtime_s_test.cpp
@@ -15,15 +15,33 @@
using LIBC_NAMESPACE::time_utils::TimeConstants;
TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp0) {
- struct tm input;
- const time_t t_ptr = 0;
+ struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
+ time_t t_ptr = 0;
int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
- ASSERT_EQ(-1, result);
+ ASSERT_EQ(0, result);
+
+ ASSERT_EQ(70, input.tm_year);
+ ASSERT_EQ(0, input.tm_mon);
+ ASSERT_EQ(1, input.tm_mday);
+ ASSERT_EQ(2, input.tm_hour);
+ ASSERT_EQ(0, input.tm_min);
+ ASSERT_EQ(0, input.tm_sec);
+ ASSERT_EQ(4, input.tm_wday);
+ ASSERT_EQ(0, input.tm_yday);
+ ASSERT_EQ(0, input.tm_isdst);
}
TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32Int) {
time_t t_ptr = 2147483647;
- static struct tm input = (struct tm){.tm_sec = 0,
+ struct tm input = (struct tm){.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 0,
@@ -33,12 +51,22 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32Int) {
.tm_yday = 0,
.tm_isdst = 0};
int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
- ASSERT_EQ(1, result);
+ ASSERT_EQ(0, result);
+
+ ASSERT_EQ(138, input.tm_year);
+ ASSERT_EQ(0, input.tm_mon);
+ ASSERT_EQ(19, input.tm_mday);
+ ASSERT_EQ(5, input.tm_hour);
+ ASSERT_EQ(14, input.tm_min);
+ ASSERT_EQ(7, input.tm_sec);
+ ASSERT_EQ(2, input.tm_wday);
+ ASSERT_EQ(18, input.tm_yday);
+ ASSERT_EQ(0, input.tm_isdst);
}
TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32IntDst) {
time_t t_ptr = 1627225465;
- static struct tm input = (struct tm){.tm_sec = 0,
+ struct tm input = (struct tm){.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 0,
@@ -48,5 +76,40 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32IntDst) {
.tm_yday = 0,
.tm_isdst = 0};
int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
- ASSERT_EQ(1, result);
+ ASSERT_EQ(0, result);
+
+ ASSERT_EQ(121, input.tm_year);
+ ASSERT_EQ(6, input.tm_mon);
+ ASSERT_EQ(25, input.tm_mday);
+ ASSERT_EQ(17, input.tm_hour);
+ ASSERT_EQ(4, input.tm_min);
+ ASSERT_EQ(25, input.tm_sec);
+ ASSERT_EQ(0, input.tm_wday);
+ ASSERT_EQ(205, input.tm_yday);
+ ASSERT_EQ(1, input.tm_isdst);
+}
+
+TEST(LlvmLibcLocaltimeS, InvalidUnixTimestamp) {
+ time_t t_ptr = -1;
+ struct tm input = (struct tm){.tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
+ int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
+ ASSERT_EQ(-1, result);
+
+ ASSERT_EQ(-1, input.tm_year);
+ ASSERT_EQ(-1, input.tm_mon);
+ ASSERT_EQ(-1, input.tm_mday);
+ ASSERT_EQ(-1, input.tm_hour);
+ ASSERT_EQ(-1, input.tm_min);
+ ASSERT_EQ(-1, input.tm_sec);
+ ASSERT_EQ(-1, input.tm_wday);
+ ASSERT_EQ(-1, input.tm_yday);
+ ASSERT_EQ(-1, input.tm_isdst);
}
>From 022d8dad00d46653b14ce008f5114a1c90e62a21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 19:42:14 +0200
Subject: [PATCH 12/58] added tests for localtime_r
---
libc/test/src/time/localtime_r_test.cpp | 35 ++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index ba46835e81f77a..1a3e4be11e6c36 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -15,8 +15,19 @@ using LIBC_NAMESPACE::time_utils::TimeConstants;
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
struct tm input;
- const time_t t_ptr = 0;
+ time_t t_ptr = 0;
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
+
+ ASSERT_EQ(70, input.tm_year);
+ ASSERT_EQ(0, input.tm_mon);
+ ASSERT_EQ(1, input.tm_mday);
+ ASSERT_EQ(2, input.tm_hour);
+ ASSERT_EQ(0, input.tm_min);
+ ASSERT_EQ(0, input.tm_sec);
+ ASSERT_EQ(4, input.tm_wday);
+ ASSERT_EQ(0, input.tm_yday);
+ ASSERT_EQ(0, input.tm_isdst);
+
ASSERT_EQ(70, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
ASSERT_EQ(1, result->tm_mday);
@@ -40,6 +51,17 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
.tm_yday = 0,
.tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
+
+ ASSERT_EQ(138, input.tm_year);
+ ASSERT_EQ(0, input.tm_mon);
+ ASSERT_EQ(19, input.tm_mday);
+ ASSERT_EQ(5, input.tm_hour);
+ ASSERT_EQ(14, input.tm_min);
+ ASSERT_EQ(7, input.tm_sec);
+ ASSERT_EQ(2, input.tm_wday);
+ ASSERT_EQ(18, input.tm_yday);
+ ASSERT_EQ(0, input.tm_isdst);
+
ASSERT_EQ(138, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
ASSERT_EQ(19, result->tm_mday);
@@ -63,6 +85,17 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32IntDst) {
.tm_yday = 0,
.tm_isdst = 0};
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
+
+ ASSERT_EQ(121, input.tm_year);
+ ASSERT_EQ(6, input.tm_mon);
+ ASSERT_EQ(25, input.tm_mday);
+ ASSERT_EQ(17, input.tm_hour);
+ ASSERT_EQ(4, input.tm_min);
+ ASSERT_EQ(25, input.tm_sec);
+ ASSERT_EQ(0, input.tm_wday);
+ ASSERT_EQ(205, input.tm_yday);
+ ASSERT_EQ(1, input.tm_isdst);
+
ASSERT_EQ(121, result->tm_year);
ASSERT_EQ(6, result->tm_mon);
ASSERT_EQ(25, result->tm_mday);
>From 9d0ca8898920667c25db1b41992a9e4c24e8bad7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 19:43:47 +0200
Subject: [PATCH 13/58] format code with clang-format
---
libc/src/time/time_utils.h | 3 +-
libc/test/src/time/localtime_s_test.cpp | 48 ++++++++++++-------------
2 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 51442493e19d87..929487a16567c5 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -193,7 +193,8 @@ LIBC_INLINE int localtime_s(const time_t *t_ptr, struct tm *input) {
if (input == NULL)
return -1;
- if ((*t_ptr < 0 || *t_ptr > cpp::numeric_limits<int64_t>::max()) && input != NULL) {
+ if ((*t_ptr < 0 || *t_ptr > cpp::numeric_limits<int64_t>::max()) &&
+ input != NULL) {
// setting values to -1 for compatibility reasons
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s
input->tm_sec = -1;
diff --git a/libc/test/src/time/localtime_s_test.cpp b/libc/test/src/time/localtime_s_test.cpp
index 4a9d1d5dba5414..cf97945a8fe4a0 100644
--- a/libc/test/src/time/localtime_s_test.cpp
+++ b/libc/test/src/time/localtime_s_test.cpp
@@ -42,14 +42,14 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp0) {
TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32Int) {
time_t t_ptr = 2147483647;
struct tm input = (struct tm){.tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0};
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
ASSERT_EQ(0, result);
@@ -67,14 +67,14 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32Int) {
TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32IntDst) {
time_t t_ptr = 1627225465;
struct tm input = (struct tm){.tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0};
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
ASSERT_EQ(0, result);
@@ -92,14 +92,14 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32IntDst) {
TEST(LlvmLibcLocaltimeS, InvalidUnixTimestamp) {
time_t t_ptr = -1;
struct tm input = (struct tm){.tm_sec = 0,
- .tm_min = 0,
- .tm_hour = 0,
- .tm_mday = 0,
- .tm_mon = 0,
- .tm_year = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_isdst = 0};
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0};
int result = LIBC_NAMESPACE::localtime_s(&t_ptr, &input);
ASSERT_EQ(-1, result);
>From dbfed2dd4900ac9749a3dd328eb44be90b60d5bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 19:59:14 +0200
Subject: [PATCH 14/58] refactor: timezone
---
libc/src/time/time_utils.cpp | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 35fbc02c17e679..90fec7cf730286 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -130,24 +130,22 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (years > INT_MAX || years < INT_MIN)
return time_utils::out_of_range();
+ char timezone[128];
+
FILE *fp;
fp = fopen("/etc/timezone", "rb");
if (fp == NULL) {
+ // TODO: implement getting timezone from `TZ` environment variable and
+ // storing the value in `timezone`
+ } else if (fgets(timezone, sizeof(timezone), fp) == NULL)
return time_utils::out_of_range();
- }
-
- char timezone[128];
- if (fgets(timezone, sizeof(timezone), fp) == NULL) {
- return time_utils::out_of_range();
- }
int offset;
- if (internal::same_string(timezone, "UTC") == 0) {
+ // TODO: Add more timezones
+ if (internal::same_string(timezone, "UTC") == 0)
offset = 0;
- }
- if (internal::same_string(timezone, "Europe/Berlin") == 0) {
+ if (internal::same_string(timezone, "Europe/Berlin") == 0)
offset = 2;
- }
// All the data (years, month and remaining days) was calculated from
// March, 2000. Thus adjust the data to be from January, 1900.
@@ -167,9 +165,11 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (offset == 0) {
tm->tm_isdst = 0;
- } else {
+ } else if (offset > 0) {
tm->tm_isdst = 1;
tm->tm_hour += offset;
+ } else {
+ tm->tm_isdst = -1;
}
fclose(fp);
>From 4bdf5889b3fcfa0dba21855796ad8470be9c1509 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 20:04:11 +0200
Subject: [PATCH 15/58] removing mktime as dependency to localtime_s
---
libc/src/time/CMakeLists.txt | 1 -
libc/test/src/time/CMakeLists.txt | 1 -
2 files changed, 2 deletions(-)
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 9f51c2e36edf61..f0f8ddf55e6d0e 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -94,7 +94,6 @@ add_entrypoint_object(
.time_utils
libc.hdr.types.time_t
libc.include.time
- libc.src.time.mktime
)
add_entrypoint_object(
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 31691b5755bfe1..7da2b0d6b94c8b 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -116,7 +116,6 @@ add_libc_unittest(
DEPENDS
libc.include.time
libc.hdr.types.time_t
- libc.src.time.mktime
libc.src.time.localtime_s
libc.src.time.time_utils
)
>From dc2c2970ee7c70d733713b59276521203f7dea44 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 20:11:41 +0200
Subject: [PATCH 16/58] revert ctime tests
---
libc/test/src/time/ctime_test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 554b72d23fd4de..7ec71bb1e4ed1e 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -22,7 +22,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp0) {
char *result;
t = 0;
result = LIBC_NAMESPACE::ctime(&t);
- ASSERT_STREQ("Thu Jan 1 01:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
@@ -30,7 +30,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
char *result;
t = 2147483647;
result = LIBC_NAMESPACE::ctime(&t);
- ASSERT_STREQ("Tue Jan 19 04:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
}
TEST(LlvmLibcCtime, InvalidArgument) {
>From f30c9e0a20085f2e81f140ac20f5e14c548c1be9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 20:12:54 +0200
Subject: [PATCH 17/58] revert ctime_r tests
---
libc/test/src/time/ctime_r_test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index b03e8cecd2e9df..9ce6f75f754849 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -35,7 +35,7 @@ TEST(LlvmLibcCtimeR, ValidUnixTimestamp0) {
// 1970-01-01 00:00:00. Test with a valid buffer size.
t = 0;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Thu Jan 1 02:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
@@ -45,7 +45,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
// 2038-01-19 03:14:07. Test with a valid buffer size.
t = 2147483647;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Tue Jan 19 05:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
}
TEST(LlvmLibcCtimeR, InvalidArgument) {
>From 3582068ec645907fad3eec4308c6972415ce373b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 21:18:10 +0200
Subject: [PATCH 18/58] fix: daylight saving time
---
libc/src/time/time_utils.cpp | 18 +++++++-----------
libc/src/time/time_utils.h | 4 ----
libc/test/src/time/ctime_r_test.cpp | 8 ++++----
libc/test/src/time/ctime_test.cpp | 4 ++--
libc/test/src/time/localtime_r_test.cpp | 8 ++++----
libc/test/src/time/localtime_s_test.cpp | 4 ++--
libc/test/src/time/localtime_test.cpp | 4 ++--
7 files changed, 21 insertions(+), 29 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 90fec7cf730286..df55090185f3e2 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -140,12 +140,11 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
} else if (fgets(timezone, sizeof(timezone), fp) == NULL)
return time_utils::out_of_range();
- int offset;
+ // UTC = 0
+ int offset = 0;
// TODO: Add more timezones
- if (internal::same_string(timezone, "UTC") == 0)
- offset = 0;
if (internal::same_string(timezone, "Europe/Berlin") == 0)
- offset = 2;
+ offset = 1;
// All the data (years, month and remaining days) was calculated from
// March, 2000. Thus adjust the data to be from January, 1900.
@@ -163,14 +162,11 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
tm->tm_sec =
static_cast<int>(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
- if (offset == 0) {
- tm->tm_isdst = 0;
- } else if (offset > 0) {
- tm->tm_isdst = 1;
- tm->tm_hour += offset;
- } else {
- tm->tm_isdst = -1;
+ set_dst(tm);
+ if (tm->tm_isdst > 0) {
+ tm->tm_hour += 1;
}
+ tm->tm_hour += offset;
fclose(fp);
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 929487a16567c5..aba8c7f2c14920 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -168,8 +168,6 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
return nullptr;
}
- set_dst(&result);
-
return &result;
}
@@ -183,8 +181,6 @@ LIBC_INLINE struct tm *localtime_internal(const time_t *t_ptr,
return nullptr;
}
- set_dst(input);
-
return input;
}
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index 9ce6f75f754849..5ca4b5b1ea228d 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -32,20 +32,20 @@ TEST(LlvmLibcCtimeR, ValidUnixTimestamp0) {
char buffer[TimeConstants::ASCTIME_BUFFER_SIZE];
time_t t;
char *result;
- // 1970-01-01 00:00:00. Test with a valid buffer size.
+ // 1970-01-01 01:00:00. Test with a valid buffer size.
t = 0;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 01:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
char buffer[TimeConstants::ASCTIME_BUFFER_SIZE];
time_t t;
char *result;
- // 2038-01-19 03:14:07. Test with a valid buffer size.
+ // 2038-01-19 04:14:07. Test with a valid buffer size.
t = 2147483647;
result = LIBC_NAMESPACE::ctime_r(&t, buffer);
- ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 04:14:07 2038\n", result);
}
TEST(LlvmLibcCtimeR, InvalidArgument) {
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 7ec71bb1e4ed1e..554b72d23fd4de 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -22,7 +22,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp0) {
char *result;
t = 0;
result = LIBC_NAMESPACE::ctime(&t);
- ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+ ASSERT_STREQ("Thu Jan 1 01:00:00 1970\n", result);
}
TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
@@ -30,7 +30,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
char *result;
t = 2147483647;
result = LIBC_NAMESPACE::ctime(&t);
- ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
+ ASSERT_STREQ("Tue Jan 19 04:14:07 2038\n", result);
}
TEST(LlvmLibcCtime, InvalidArgument) {
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 1a3e4be11e6c36..03b885fa4aa96b 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -21,7 +21,7 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
ASSERT_EQ(70, input.tm_year);
ASSERT_EQ(0, input.tm_mon);
ASSERT_EQ(1, input.tm_mday);
- ASSERT_EQ(2, input.tm_hour);
+ ASSERT_EQ(1, input.tm_hour);
ASSERT_EQ(0, input.tm_min);
ASSERT_EQ(0, input.tm_sec);
ASSERT_EQ(4, input.tm_wday);
@@ -31,7 +31,7 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
ASSERT_EQ(70, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
ASSERT_EQ(1, result->tm_mday);
- ASSERT_EQ(2, result->tm_hour);
+ ASSERT_EQ(1, result->tm_hour);
ASSERT_EQ(0, result->tm_min);
ASSERT_EQ(0, result->tm_sec);
ASSERT_EQ(4, result->tm_wday);
@@ -55,7 +55,7 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
ASSERT_EQ(138, input.tm_year);
ASSERT_EQ(0, input.tm_mon);
ASSERT_EQ(19, input.tm_mday);
- ASSERT_EQ(5, input.tm_hour);
+ ASSERT_EQ(4, input.tm_hour);
ASSERT_EQ(14, input.tm_min);
ASSERT_EQ(7, input.tm_sec);
ASSERT_EQ(2, input.tm_wday);
@@ -65,7 +65,7 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
ASSERT_EQ(138, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
ASSERT_EQ(19, result->tm_mday);
- ASSERT_EQ(5, result->tm_hour);
+ ASSERT_EQ(4, result->tm_hour);
ASSERT_EQ(14, result->tm_min);
ASSERT_EQ(7, result->tm_sec);
ASSERT_EQ(2, result->tm_wday);
diff --git a/libc/test/src/time/localtime_s_test.cpp b/libc/test/src/time/localtime_s_test.cpp
index cf97945a8fe4a0..aeb658fe6fd871 100644
--- a/libc/test/src/time/localtime_s_test.cpp
+++ b/libc/test/src/time/localtime_s_test.cpp
@@ -31,7 +31,7 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp0) {
ASSERT_EQ(70, input.tm_year);
ASSERT_EQ(0, input.tm_mon);
ASSERT_EQ(1, input.tm_mday);
- ASSERT_EQ(2, input.tm_hour);
+ ASSERT_EQ(1, input.tm_hour);
ASSERT_EQ(0, input.tm_min);
ASSERT_EQ(0, input.tm_sec);
ASSERT_EQ(4, input.tm_wday);
@@ -56,7 +56,7 @@ TEST(LlvmLibcLocaltimeS, ValidUnixTimestamp32Int) {
ASSERT_EQ(138, input.tm_year);
ASSERT_EQ(0, input.tm_mon);
ASSERT_EQ(19, input.tm_mday);
- ASSERT_EQ(5, input.tm_hour);
+ ASSERT_EQ(4, input.tm_hour);
ASSERT_EQ(14, input.tm_min);
ASSERT_EQ(7, input.tm_sec);
ASSERT_EQ(2, input.tm_wday);
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index 4143e7065596ff..293f0050c5802b 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -17,7 +17,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
ASSERT_EQ(70, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
ASSERT_EQ(1, result->tm_mday);
- ASSERT_EQ(2, result->tm_hour);
+ ASSERT_EQ(1, result->tm_hour);
ASSERT_EQ(0, result->tm_min);
ASSERT_EQ(0, result->tm_sec);
ASSERT_EQ(4, result->tm_wday);
@@ -31,7 +31,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
ASSERT_EQ(138, result->tm_year);
ASSERT_EQ(0, result->tm_mon);
ASSERT_EQ(19, result->tm_mday);
- ASSERT_EQ(5, result->tm_hour);
+ ASSERT_EQ(4, result->tm_hour);
ASSERT_EQ(14, result->tm_min);
ASSERT_EQ(7, result->tm_sec);
ASSERT_EQ(2, result->tm_wday);
>From a28509012fc7cd8c61358446888f370983251527 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 21:31:44 +0200
Subject: [PATCH 19/58] update documentation for libc
---
libc/docs/headers/time.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libc/docs/headers/time.rst b/libc/docs/headers/time.rst
index 7f0ceefa6834a1..c7ad5e65f8e866 100644
--- a/libc/docs/headers/time.rst
+++ b/libc/docs/headers/time.rst
@@ -71,9 +71,9 @@ Implementation Status
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| clock_settime | | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
-| ctime | | | | | | | | | | | | |
+| ctime | |check| | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
-| ctime_r | | | | | | | | | | | | |
+| ctime_r | |check| | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| difftime | |check| | |check| | | |check| | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
@@ -85,11 +85,11 @@ Implementation Status
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| gmtime_r | |check| | |check| | | |check| | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
-| localtime | | | | | | | | | | | | |
+| localtime | |check| | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
-| localtime_r | | | | | | | | | | | | |
+| localtime_r | |check| | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
-| localtime_s | | | | | | | | | | | | |
+| localtime_s | |check| | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
| mktime | |check| | |check| | | |check| | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+
>From a35d49a5821f680200cab8f939ffb404c6bfde5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 22:31:46 +0200
Subject: [PATCH 20/58] refactor: file read
---
libc/src/time/time_utils.cpp | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index df55090185f3e2..063d9da4ca408b 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -27,6 +27,26 @@ static int64_t computeRemainingYears(int64_t daysPerYears,
return years;
}
+volatile int lock = 0;
+
+void release_file(FILE *fp) {
+ lock = 0;
+ fclose(fp);
+}
+
+void acquire_file(FILE *fp, char *timezone) {
+ while (1) {
+ if (lock == 0) {
+ lock = 1;
+ break;
+ }
+ }
+
+ if (fgets(timezone, sizeof(timezone), fp) == NULL) {
+ release_file(fp);
+ }
+}
+
// First, divide "total_seconds" by the number of seconds in a day to get the
// number of days since Jan 1 1970. The remainder will be used to calculate the
// number of Hours, Minutes and Seconds.
@@ -132,13 +152,18 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
char timezone[128];
- FILE *fp;
+ FILE *fp = NULL;
fp = fopen("/etc/timezone", "rb");
if (fp == NULL) {
// TODO: implement getting timezone from `TZ` environment variable and
// storing the value in `timezone`
- } else if (fgets(timezone, sizeof(timezone), fp) == NULL)
+ } else {
+ acquire_file(fp, timezone);
+ }
+
+ if (lock == 0) {
return time_utils::out_of_range();
+ }
// UTC = 0
int offset = 0;
@@ -168,7 +193,7 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
}
tm->tm_hour += offset;
- fclose(fp);
+ release_file(fp);
return 0;
}
>From 235cf4197109f71450e2e4e6113fccccc444519f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 22:35:51 +0200
Subject: [PATCH 21/58] fix: file read
---
libc/src/time/time_utils.cpp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 063d9da4ca408b..54a1b113ddb783 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -27,17 +27,17 @@ static int64_t computeRemainingYears(int64_t daysPerYears,
return years;
}
-volatile int lock = 0;
+volatile int file_usage = 0;
void release_file(FILE *fp) {
- lock = 0;
+ file_usage = 0;
fclose(fp);
}
void acquire_file(FILE *fp, char *timezone) {
while (1) {
- if (lock == 0) {
- lock = 1;
+ if (file_usage == 0) {
+ file_usage = 1;
break;
}
}
@@ -161,7 +161,8 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
acquire_file(fp, timezone);
}
- if (lock == 0) {
+ if (file_usage == 0) {
+ release_file(fp);
return time_utils::out_of_range();
}
>From 9c4a9b7331f41e1d6be2382983bdb3f257c3a77c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sun, 6 Oct 2024 22:48:37 +0200
Subject: [PATCH 22/58] fix: timezone char length
---
libc/src/time/time_utils.cpp | 8 ++++----
libc/src/time/time_utils.h | 2 ++
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 54a1b113ddb783..2f33e056b8c1ec 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -34,7 +34,7 @@ void release_file(FILE *fp) {
fclose(fp);
}
-void acquire_file(FILE *fp, char *timezone) {
+void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
while (1) {
if (file_usage == 0) {
file_usage = 1;
@@ -42,7 +42,7 @@ void acquire_file(FILE *fp, char *timezone) {
}
}
- if (fgets(timezone, sizeof(timezone), fp) == NULL) {
+ if (fgets(timezone, (int)timezone_size, fp) == NULL) {
release_file(fp);
}
}
@@ -150,7 +150,7 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (years > INT_MAX || years < INT_MIN)
return time_utils::out_of_range();
- char timezone[128];
+ char timezone[TimeConstants::TIMEZONE_SIZE];
FILE *fp = NULL;
fp = fopen("/etc/timezone", "rb");
@@ -158,7 +158,7 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
// TODO: implement getting timezone from `TZ` environment variable and
// storing the value in `timezone`
} else {
- acquire_file(fp, timezone);
+ acquire_file(fp, timezone, TimeConstants::TIMEZONE_SIZE);
}
if (file_usage == 0) {
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index aba8c7f2c14920..780d5242cfa681 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -81,6 +81,8 @@ struct TimeConstants {
static constexpr int END_OF32_BIT_EPOCH_YEAR = 2038;
static constexpr time_t OUT_OF_RANGE_RETURN_VALUE = -1;
+
+ static constexpr size_t TIMEZONE_SIZE = 128;
};
// Update the "tm" structure's year, month, etc. members from seconds.
>From fb27da7239a04604d720596308866f8c474de259 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 8 Oct 2024 15:03:49 +0200
Subject: [PATCH 23/58] timezone implementation
---
libc/src/time/CMakeLists.txt | 13 +++
libc/src/time/time_utils.cpp | 45 +++++----
libc/src/time/timezone.cpp | 52 ++++++++++
libc/src/time/timezone.h | 33 +++++++
libc/test/src/time/CMakeLists.txt | 5 +
libc/test/src/time/localtime_r_test.cpp | 24 ++++-
libc/test/src/time/localtime_test.cpp | 121 +++++++++++++++++++++++-
7 files changed, 270 insertions(+), 23 deletions(-)
create mode 100644 libc/src/time/timezone.cpp
create mode 100644 libc/src/time/timezone.h
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index f0f8ddf55e6d0e..2e17560b69e580 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -14,6 +14,18 @@ add_object_library(
libc.src.errno.errno
)
+add_object_library(
+ timezone
+ SRCS
+ timezone.cpp
+ HDRS
+ timezone.h
+ DEPENDS
+ libc.include.time
+ libc.src.__support.CPP.limits
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
asctime
SRCS
@@ -68,6 +80,7 @@ add_entrypoint_object(
localtime.h
DEPENDS
.time_utils
+ .timezone
libc.hdr.types.time_t
libc.include.time
)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 2f33e056b8c1ec..c5d3c88d5c6260 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -7,10 +7,13 @@
//===----------------------------------------------------------------------===//
#include "src/time/time_utils.h"
+#include "src/time/timezone.h"
#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/CPP/string_view.h"
#include <stdio.h>
+#include <stdlib.h>
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
@@ -29,9 +32,10 @@ static int64_t computeRemainingYears(int64_t daysPerYears,
volatile int file_usage = 0;
-void release_file(FILE *fp) {
+void release_file(FILE *fp, char *timezone) {
file_usage = 0;
fclose(fp);
+ free(timezone);
}
void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
@@ -43,7 +47,7 @@ void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
}
if (fgets(timezone, (int)timezone_size, fp) == NULL) {
- release_file(fp);
+ release_file(fp, timezone);
}
}
@@ -150,27 +154,25 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (years > INT_MAX || years < INT_MIN)
return time_utils::out_of_range();
- char timezone[TimeConstants::TIMEZONE_SIZE];
-
+ char *timezone = (char *)malloc(sizeof(char) * TimeConstants::TIMEZONE_SIZE);
+ timezone = getenv("TZ");
FILE *fp = NULL;
- fp = fopen("/etc/timezone", "rb");
- if (fp == NULL) {
- // TODO: implement getting timezone from `TZ` environment variable and
- // storing the value in `timezone`
- } else {
+ if (timezone == NULL) {
+ timezone = (char *)realloc(timezone, sizeof(char) * TimeConstants::TIMEZONE_SIZE);
+ fp = fopen("/etc/timezone", "rb");
+ if (fp == NULL) {
+ return time_utils::out_of_range();
+ }
+
acquire_file(fp, timezone, TimeConstants::TIMEZONE_SIZE);
}
- if (file_usage == 0) {
- release_file(fp);
+ if (fp != NULL && file_usage == 0) {
+ release_file(fp, timezone);
return time_utils::out_of_range();
}
- // UTC = 0
- int offset = 0;
- // TODO: Add more timezones
- if (internal::same_string(timezone, "Europe/Berlin") == 0)
- offset = 1;
+ int offset = timezone::get_timezone_offset(timezone);
// All the data (years, month and remaining days) was calculated from
// March, 2000. Thus adjust the data to be from January, 1900.
@@ -189,12 +191,17 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
static_cast<int>(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
set_dst(tm);
- if (tm->tm_isdst > 0) {
+ if (tm->tm_isdst > 0 && offset != 0) {
tm->tm_hour += 1;
}
- tm->tm_hour += offset;
- release_file(fp);
+ if (offset != 0) {
+ tm->tm_hour += offset;
+ }
+
+ if (file_usage == 1) {
+ release_file(fp, timezone);
+ }
return 0;
}
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
new file mode 100644
index 00000000000000..954293ee56bbf0
--- /dev/null
+++ b/libc/src/time/timezone.cpp
@@ -0,0 +1,52 @@
+//===-- Implementation of timezone functions ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/time_utils.h"
+#include "src/time/timezone.h"
+#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/CPP/string_view.h"
+
+#define BUF_SIZE 1024
+
+namespace LIBC_NAMESPACE_DECL {
+namespace timezone {
+
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int get_timezone_offset(char *timezone) {
+ int offset = 0;
+ LIBC_NAMESPACE::cpp::string_view tz(timezone);
+
+ if (tz.starts_with("America")) {
+ if (tz.ends_with("San_Francisco")) {
+ offset = -8;
+ }
+
+ if (tz.starts_with("America/New_York")) {
+ offset = -5;
+ }
+ }
+
+ if (tz.starts_with("Europe")) {
+ offset = 1;
+
+ if (tz.ends_with("Moscow")) {
+ offset = 2;
+ }
+ }
+
+ return offset;
+}
+
+} // namespace timezone
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
new file mode 100644
index 00000000000000..87f45bdc5d6c2e
--- /dev/null
+++ b/libc/src/time/timezone.h
@@ -0,0 +1,33 @@
+//===-- Implementation of timezone functions ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_TIMEZONE_H
+#define LLVM_LIBC_SRC_TIME_TIMEZONE_H
+
+#include <stddef.h> // For size_t.
+
+#include "src/__support/CPP/limits.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/errno/libc_errno.h"
+#include "src/time/mktime.h"
+
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace timezone {
+
+#define TZ_HEADER "TZif"
+
+extern int get_timezone_offset(char *timezone);
+
+} // namespace timezone
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_TIMEZONE_H
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 7da2b0d6b94c8b..72ceb057d589e1 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -46,6 +46,7 @@ add_libc_unittest(
libc.hdr.types.time_t
libc.src.time.ctime
libc.src.time.time_utils
+ libc.src.time.timezone
)
add_libc_unittest(
@@ -64,6 +65,7 @@ add_libc_unittest(
libc.hdr.types.time_t
libc.src.time.ctime_r
libc.src.time.time_utils
+ libc.src.time.timezone
)
add_libc_unittest(
@@ -82,6 +84,7 @@ add_libc_unittest(
libc.hdr.types.time_t
libc.src.time.localtime
libc.src.time.time_utils
+ libc.src.time.timezone
)
add_libc_unittest(
@@ -100,6 +103,7 @@ add_libc_unittest(
libc.hdr.types.time_t
libc.src.time.localtime_r
libc.src.time.time_utils
+ libc.src.time.timezone
)
add_libc_unittest(
@@ -118,6 +122,7 @@ add_libc_unittest(
libc.hdr.types.time_t
libc.src.time.localtime_s
libc.src.time.time_utils
+ libc.src.time.timezone
)
add_libc_test(
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 03b885fa4aa96b..18b2ef84992226 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -9,11 +9,27 @@
#include "src/time/localtime_r.h"
#include "src/time/time_utils.h"
#include "test/UnitTest/Test.h"
-#include "test/src/time/TmHelper.h"
-using LIBC_NAMESPACE::time_utils::TimeConstants;
+#include <string.h>
+
+extern char **environ;
+
+void set_env_var(const char* env) {
+ int i = 0;
+ if (environ[i] != NULL) {
+ i++;
+ }
+
+ environ[i] = (char*)malloc(strlen(env)+1);
+ if (environ[i] != nullptr) {
+ memcpy(environ[i], env, strlen(env)+1);
+ environ[i+1] = nullptr;
+ }
+}
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
+ set_env_var("TZ=Europe/Berlin");
+
struct tm input;
time_t t_ptr = 0;
struct tm *result = LIBC_NAMESPACE::localtime_r(&t_ptr, &input);
@@ -40,6 +56,8 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp0) {
}
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
+ set_env_var("TZ=Europe/Berlin");
+
time_t t_ptr = 2147483647;
struct tm input = (struct tm){.tm_sec = 0,
.tm_min = 0,
@@ -74,6 +92,8 @@ TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32Int) {
}
TEST(LlvmLibcLocaltimeR, ValidUnixTimestamp32IntDst) {
+ set_env_var("TZ=Europe/Berlin");
+
time_t t_ptr = 1627225465;
struct tm input = (struct tm){.tm_sec = 0,
.tm_min = 0,
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index 293f0050c5802b..cf373ced8b7fde 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -6,12 +6,29 @@
//
//===----------------------------------------------------------------------===//
-#include "src/errno/libc_errno.h"
#include "src/time/localtime.h"
#include "test/UnitTest/Test.h"
-#include "test/src/time/TmHelper.h"
+
+#include <string.h>
+
+extern char **environ;
+
+void set_env_var(const char* env) {
+ int i = 0;
+ if (environ[i] != NULL) {
+ i++;
+ }
+
+ environ[i] = (char*)malloc(strlen(env)+1);
+ if (environ[i] != nullptr) {
+ memcpy(environ[i], env, strlen(env)+1);
+ environ[i+1] = nullptr;
+ }
+}
TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
+ set_env_var("TZ=Europe/Berlin");
+
const time_t t_ptr = 0;
struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
ASSERT_EQ(70, result->tm_year);
@@ -26,6 +43,8 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
}
TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
+ set_env_var("TZ=Europe/Berlin");
+
time_t t_ptr = 2147483647;
struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
ASSERT_EQ(138, result->tm_year);
@@ -40,6 +59,8 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
}
TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
+ set_env_var("TZ=Europe/Berlin");
+
time_t t_ptr = 1627225465;
struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
ASSERT_EQ(121, result->tm_year);
@@ -52,3 +73,99 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
ASSERT_EQ(205, result->tm_yday);
ASSERT_EQ(1, result->tm_isdst);
}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaPst) {
+ set_env_var("TZ=America/San_Francisco");
+
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(8, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaEst) {
+ set_env_var("TZ=America/New_York");
+
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(11, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUTC) {
+ set_env_var("TZ=UTC");
+
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(15, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableGMT) {
+ set_env_var("TZ=GMT");
+
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(15, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeBerlin) {
+ set_env_var("TZ=Europe/Berlin");
+
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(17, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
+
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableRussiaMoscow) {
+ set_env_var("TZ=Europe/Moscow");
+
+ time_t t_ptr = 1627225465;
+ struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
+ ASSERT_EQ(121, result->tm_year);
+ ASSERT_EQ(6, result->tm_mon);
+ ASSERT_EQ(25, result->tm_mday);
+ ASSERT_EQ(18, result->tm_hour);
+ ASSERT_EQ(4, result->tm_min);
+ ASSERT_EQ(25, result->tm_sec);
+ ASSERT_EQ(0, result->tm_wday);
+ ASSERT_EQ(205, result->tm_yday);
+ ASSERT_EQ(1, result->tm_isdst);
+}
>From f6e485fc57f1ebe861f861000cef10e5847f1b34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 8 Oct 2024 15:04:22 +0200
Subject: [PATCH 24/58] format code with clang-format
---
libc/src/time/time_utils.cpp | 7 ++++---
libc/src/time/timezone.cpp | 4 ++--
libc/src/time/timezone.h | 2 +-
libc/test/src/time/localtime_r_test.cpp | 10 +++++-----
libc/test/src/time/localtime_test.cpp | 10 +++++-----
5 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index c5d3c88d5c6260..31034a8fb66428 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "src/time/time_utils.h"
-#include "src/time/timezone.h"
#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
+#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/__support/CPP/string_view.h"
+#include "src/time/timezone.h"
#include <stdio.h>
#include <stdlib.h>
@@ -158,7 +158,8 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
timezone = getenv("TZ");
FILE *fp = NULL;
if (timezone == NULL) {
- timezone = (char *)realloc(timezone, sizeof(char) * TimeConstants::TIMEZONE_SIZE);
+ timezone =
+ (char *)realloc(timezone, sizeof(char) * TimeConstants::TIMEZONE_SIZE);
fp = fopen("/etc/timezone", "rb");
if (fp == NULL) {
return time_utils::out_of_range();
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 954293ee56bbf0..8fd3cb86425fac 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#include "src/time/time_utils.h"
#include "src/time/timezone.h"
#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
+#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/__support/CPP/string_view.h"
+#include "src/time/time_utils.h"
#define BUF_SIZE 1024
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 87f45bdc5d6c2e..26bf52c6cb9286 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -12,9 +12,9 @@
#include <stddef.h> // For size_t.
#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/__support/CPP/string_view.h"
#include "src/errno/libc_errno.h"
#include "src/time/mktime.h"
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 18b2ef84992226..2205c59ab7e527 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -14,16 +14,16 @@
extern char **environ;
-void set_env_var(const char* env) {
+void set_env_var(const char *env) {
int i = 0;
if (environ[i] != NULL) {
i++;
}
- environ[i] = (char*)malloc(strlen(env)+1);
- if (environ[i] != nullptr) {
- memcpy(environ[i], env, strlen(env)+1);
- environ[i+1] = nullptr;
+ environ[i] = (char *)malloc(strlen(env) + 1);
+ if (environ[i] != NULL) {
+ memcpy(environ[i], env, strlen(env) + 1);
+ environ[i + 1] = NULL;
}
}
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index cf373ced8b7fde..b360734ef7379c 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -13,16 +13,16 @@
extern char **environ;
-void set_env_var(const char* env) {
+void set_env_var(const char *env) {
int i = 0;
if (environ[i] != NULL) {
i++;
}
- environ[i] = (char*)malloc(strlen(env)+1);
- if (environ[i] != nullptr) {
- memcpy(environ[i], env, strlen(env)+1);
- environ[i+1] = nullptr;
+ environ[i] = (char *)malloc(strlen(env) + 1);
+ if (environ[i] != NULL) {
+ memcpy(environ[i], env, strlen(env) + 1);
+ environ[i + 1] = NULL;
}
}
>From db09b278d30077aaf6c6b53e0ba093347d93f6ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 8 Oct 2024 15:25:38 +0200
Subject: [PATCH 25/58] use stack allocation of memory instead of heap
allocation
---
libc/src/time/time_utils.cpp | 12 +++++++-----
libc/src/time/timezone.cpp | 2 +-
libc/src/time/timezone.h | 2 --
libc/test/src/time/localtime_test.cpp | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 31034a8fb66428..beab005f29891c 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -14,6 +14,7 @@
#include "src/time/timezone.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
@@ -154,12 +155,13 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (years > INT_MAX || years < INT_MIN)
return time_utils::out_of_range();
- char *timezone = (char *)malloc(sizeof(char) * TimeConstants::TIMEZONE_SIZE);
- timezone = getenv("TZ");
+ char timezone[TimeConstants::TIMEZONE_SIZE];
+ char *env_tz = getenv("TZ");
FILE *fp = NULL;
- if (timezone == NULL) {
- timezone =
- (char *)realloc(timezone, sizeof(char) * TimeConstants::TIMEZONE_SIZE);
+ if (env_tz) {
+ strncpy(timezone, env_tz, sizeof(timezone));
+ timezone[sizeof(timezone) - 1] = '\0';
+ } else {
fp = fopen("/etc/timezone", "rb");
if (fp == NULL) {
return time_utils::out_of_range();
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 8fd3cb86425fac..3434fe363b296e 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -32,7 +32,7 @@ int get_timezone_offset(char *timezone) {
offset = -8;
}
- if (tz.starts_with("America/New_York")) {
+ if (tz.ends_with("New_York")) {
offset = -5;
}
}
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 26bf52c6cb9286..9155551ee8887b 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -23,8 +23,6 @@
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-#define TZ_HEADER "TZif"
-
extern int get_timezone_offset(char *timezone);
} // namespace timezone
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index b360734ef7379c..ef59c8b867db1e 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -154,7 +154,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeBerlin) {
ASSERT_EQ(1, result->tm_isdst);
}
-TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableRussiaMoscow) {
+TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeMoscow) {
set_env_var("TZ=Europe/Moscow");
time_t t_ptr = 1627225465;
>From bf0f50ee23073721de457ea01ed3a6c415db99e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 8 Oct 2024 15:29:11 +0200
Subject: [PATCH 26/58] remove `free` function because stack allocation of
memory is now used
---
libc/src/time/time_utils.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index beab005f29891c..1c6d49a69ebc83 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -36,7 +36,6 @@ volatile int file_usage = 0;
void release_file(FILE *fp, char *timezone) {
file_usage = 0;
fclose(fp);
- free(timezone);
}
void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
>From 3d1e3361ea82e801b4e5c9f6d8cd23b3a14d3394 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 8 Oct 2024 15:37:50 +0200
Subject: [PATCH 27/58] added more timezones
---
libc/src/time/timezone.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 3434fe363b296e..159027379dcf50 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -32,6 +32,10 @@ int get_timezone_offset(char *timezone) {
offset = -8;
}
+ if (tz.ends_with("Chicago")) {
+ offset = -4;
+ }
+
if (tz.ends_with("New_York")) {
offset = -5;
}
@@ -40,6 +44,10 @@ int get_timezone_offset(char *timezone) {
if (tz.starts_with("Europe")) {
offset = 1;
+ if (tz.ends_with("Lisbon")) {
+ offset = 0;
+ }
+
if (tz.ends_with("Moscow")) {
offset = 2;
}
>From 15244b297b8ce601b2d6b84fa02d9a47e4e4a680 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 8 Oct 2024 15:41:04 +0200
Subject: [PATCH 28/58] added more timezones
---
libc/src/time/timezone.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 159027379dcf50..8e1326f7aa14c6 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -53,6 +53,12 @@ int get_timezone_offset(char *timezone) {
}
}
+ if (tz.starts_with("Asia")) {
+ if (tz.ends_with("Yakutsk")) {
+ offset = 8;
+ }
+ }
+
return offset;
}
>From 514840cdad09cd802ee443ac8bc492f31a87eebe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 23 Nov 2024 15:42:49 +0100
Subject: [PATCH 29/58] refactor to parse `/etc/localtime`
---
libc/src/time/CMakeLists.txt | 9 +++++
libc/src/time/ctime.cpp | 1 +
libc/src/time/ctime_r.cpp | 1 +
libc/src/time/time_utils.cpp | 3 +-
libc/src/time/time_utils.h | 2 --
libc/src/time/timezone.cpp | 50 +++------------------------
libc/src/time/timezone.h | 10 +-----
libc/test/src/time/localtime_test.cpp | 4 +--
8 files changed, 20 insertions(+), 60 deletions(-)
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 2e17560b69e580..6d7b7ebc79a7bd 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -54,8 +54,10 @@ add_entrypoint_object(
ctime.cpp
HDRS
ctime.h
+ timezone.h
DEPENDS
.time_utils
+ .timezone
libc.hdr.types.time_t
libc.include.time
)
@@ -64,10 +66,12 @@ add_entrypoint_object(
ctime_r
SRCS
ctime_r.cpp
+ timezone.h
HDRS
ctime_r.h
DEPENDS
.time_utils
+ .timezone
libc.hdr.types.time_t
libc.include.time
)
@@ -78,6 +82,7 @@ add_entrypoint_object(
localtime.cpp
HDRS
localtime.h
+ timezone.h
DEPENDS
.time_utils
.timezone
@@ -91,8 +96,10 @@ add_entrypoint_object(
localtime_r.cpp
HDRS
localtime_r.h
+ timezone.h
DEPENDS
.time_utils
+ .timezone
libc.hdr.types.time_t
libc.include.time
)
@@ -103,8 +110,10 @@ add_entrypoint_object(
localtime_s.cpp
HDRS
localtime_s.h
+ timezone.h
DEPENDS
.time_utils
+ .timezone
libc.hdr.types.time_t
libc.include.time
)
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index 8adae9be73809a..0b4525b720ffaf 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -11,6 +11,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "time_utils.h"
+#include "timezone.h"
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp
index 63d93c4085f38c..3d8b76288a28ca 100644
--- a/libc/src/time/ctime_r.cpp
+++ b/libc/src/time/ctime_r.cpp
@@ -11,6 +11,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "time_utils.h"
+#include "timezone.h"
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 1c6d49a69ebc83..53514cd968354c 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -34,6 +34,7 @@ static int64_t computeRemainingYears(int64_t daysPerYears,
volatile int file_usage = 0;
void release_file(FILE *fp, char *timezone) {
+ (void)timezone;
file_usage = 0;
fclose(fp);
}
@@ -161,7 +162,7 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
strncpy(timezone, env_tz, sizeof(timezone));
timezone[sizeof(timezone) - 1] = '\0';
} else {
- fp = fopen("/etc/timezone", "rb");
+ fp = fopen("/etc/localtime", "rb");
if (fp == NULL) {
return time_utils::out_of_range();
}
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 780d5242cfa681..cad5d8b583b5f1 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -17,8 +17,6 @@
#include "src/errno/libc_errno.h"
#include "src/time/mktime.h"
-#include <stdint.h>
-
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 8e1326f7aa14c6..42094c530c21e0 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -6,60 +6,18 @@
//
//===----------------------------------------------------------------------===//
-#include "src/time/timezone.h"
-#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
-#include "src/__support/CPP/string_view.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
#include "src/time/time_utils.h"
-
-#define BUF_SIZE 1024
+#include "src/__support/common.h"
+#include "src/time/timezone.h"
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
using LIBC_NAMESPACE::time_utils::TimeConstants;
-#include <stdio.h>
-#include <stdlib.h>
-
int get_timezone_offset(char *timezone) {
- int offset = 0;
- LIBC_NAMESPACE::cpp::string_view tz(timezone);
-
- if (tz.starts_with("America")) {
- if (tz.ends_with("San_Francisco")) {
- offset = -8;
- }
-
- if (tz.ends_with("Chicago")) {
- offset = -4;
- }
-
- if (tz.ends_with("New_York")) {
- offset = -5;
- }
- }
-
- if (tz.starts_with("Europe")) {
- offset = 1;
-
- if (tz.ends_with("Lisbon")) {
- offset = 0;
- }
-
- if (tz.ends_with("Moscow")) {
- offset = 2;
- }
- }
-
- if (tz.starts_with("Asia")) {
- if (tz.ends_with("Yakutsk")) {
- offset = 8;
- }
- }
-
- return offset;
+ (void)timezone;
+ return 0;
}
} // namespace timezone
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 9155551ee8887b..dbdec4e0156d90 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -9,21 +9,13 @@
#ifndef LLVM_LIBC_SRC_TIME_TIMEZONE_H
#define LLVM_LIBC_SRC_TIME_TIMEZONE_H
-#include <stddef.h> // For size_t.
-
-#include "src/__support/CPP/limits.h"
-#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/errno/libc_errno.h"
-#include "src/time/mktime.h"
-
-#include <stdint.h>
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-extern int get_timezone_offset(char *timezone);
+int get_timezone_offset(char *timezone);
} // namespace timezone
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index ef59c8b867db1e..4ab2f06139ed4c 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -26,7 +26,7 @@ void set_env_var(const char *env) {
}
}
-TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
+/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
set_env_var("TZ=Europe/Berlin");
const time_t t_ptr = 0;
@@ -168,4 +168,4 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeMoscow) {
ASSERT_EQ(0, result->tm_wday);
ASSERT_EQ(205, result->tm_yday);
ASSERT_EQ(1, result->tm_isdst);
-}
+}*/
>From 39ffb2de231f7f1e8ad73091f72adfeab0f1d65d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 23 Nov 2024 17:45:33 +0100
Subject: [PATCH 30/58] parse `/etc/localtime` implementation
---
libc/src/time/timezone.cpp | 103 ++++++++++++++++++++++++++
libc/src/time/timezone.h | 3 +
libc/test/src/time/localtime_test.cpp | 4 +-
3 files changed, 108 insertions(+), 2 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 42094c530c21e0..145658895ae311 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -6,6 +6,11 @@
//
//===----------------------------------------------------------------------===//
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h> // TODO: Remove all printf functions
+#include <sys/types.h>
+
#include "src/time/time_utils.h"
#include "src/__support/common.h"
#include "src/time/timezone.h"
@@ -15,8 +20,106 @@ namespace timezone {
using LIBC_NAMESPACE::time_utils::TimeConstants;
+void rev_str(char *str) {
+ int start = 0;
+ int end = 0;
+
+ while (str[end] != '\0') {
+ end++;
+ }
+ end--;
+
+ while (start < end) {
+ str[start] = str[start] ^ str[end];
+ str[end] = str[start] ^ str[end];
+ str[start] = str[start] ^ str[end];
+
+ start++;
+ end--;
+ }
+}
+
int get_timezone_offset(char *timezone) {
(void)timezone;
+
+ unsigned char hdr[TIMEZONE_HDR_SIZE];
+
+ int32_t magic;
+ unsigned char version;
+ __int128_t reserved;
+ int32_t tzh_ttisutcnt;
+ int32_t tzh_ttisstdcnt;
+ int32_t tzh_leapcnt;
+ int32_t tzh_timecnt;
+ int32_t tzh_typecnt;
+ int32_t tzh_charcnt;
+
+ int fd;
+ size_t bytes;
+
+ fd = open("/etc/localtime", O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ bytes = read(fd, hdr, sizeof(hdr));
+ if (bytes != sizeof(hdr)) {
+ return 0;
+ }
+
+ size_t i;
+ __uint128_t tmp;
+
+ // these locations in timezone files are defined in `tzfile`
+ magic = (hdr[0] << 24) | (hdr[1] << 16) | (hdr[2] << 8) | hdr[3];
+ version = hdr[4];
+ for (i = 5; i <= 20; i++) {
+ tmp = (tmp << 8) | hdr[i];
+ }
+ reserved = tmp;
+ tzh_ttisutcnt = (hdr[20] << 24) | (hdr[21] << 16) | (hdr[22] << 8) | hdr[23];
+ tzh_ttisstdcnt = (hdr[24] << 24) | (hdr[25] << 16) | (hdr[26] << 8) | hdr[27];
+ tzh_leapcnt = (hdr[28] << 24) | (hdr[29] << 16) | (hdr[30] << 8) | hdr[31];
+ tzh_timecnt = (hdr[32] << 24) | (hdr[33] << 16) | (hdr[34] << 8) | hdr[35];
+ tzh_typecnt = (hdr[36] << 24) | (hdr[37] << 16) | (hdr[38] << 8) | hdr[39];
+ tzh_charcnt = (hdr[40] << 24) | (hdr[41] << 16) | (hdr[42] << 8) | hdr[43];
+ (void)tzh_ttisutcnt;
+ (void)tzh_ttisstdcnt;
+ (void)tzh_leapcnt;
+ (void)tzh_typecnt;
+ (void)tzh_charcnt;
+
+ if (magic != 0x545A6966) {
+ return 0;
+ }
+
+ // currently only supporting tzfile v2
+ if (version != 0x32) {
+ return 0;
+ }
+
+ // according to `tzfile`, 15 bytes should be 0
+ if ((reserved ^ 0x00) != 0) {
+ return 0;
+ }
+
+ for (i = 0; i < (size_t)tzh_timecnt; i++) {
+ uint8_t buf[4];
+ bytes = read(fd, buf, 4);
+ if (bytes != 4) {
+ continue;
+ }
+
+ int32_t transition = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ transition = ((transition & 0xFF000000) >> 24) |
+ ((transition & 0x00FF0000) >> 8) |
+ ((transition & 0x0000FF00) << 8) |
+ ((transition & 0x000000FF) << 24);
+ printf("transition %d: %d\n", i, transition);
+ }
+
+ close(fd);
+
return 0;
}
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index dbdec4e0156d90..336e8d0c1a1008 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -15,6 +15,9 @@
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
+// accoring to `tzfile`, timezone header if always 44 bytes
+#define TIMEZONE_HDR_SIZE 44
+
int get_timezone_offset(char *timezone);
} // namespace timezone
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index 4ab2f06139ed4c..86e15d8e7dcf15 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -26,7 +26,7 @@ void set_env_var(const char *env) {
}
}
-/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
+TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
set_env_var("TZ=Europe/Berlin");
const time_t t_ptr = 0;
@@ -42,7 +42,7 @@ void set_env_var(const char *env) {
ASSERT_EQ(0, result->tm_isdst);
}
-TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
+/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
set_env_var("TZ=Europe/Berlin");
time_t t_ptr = 2147483647;
>From e3bd1152b293558ca8db26177433a047fb3eef88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 23 Nov 2024 17:53:08 +0100
Subject: [PATCH 31/58] add support for `tzfile` v3
---
libc/src/time/timezone.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 145658895ae311..091c6ef1724f63 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -93,8 +93,8 @@ int get_timezone_offset(char *timezone) {
return 0;
}
- // currently only supporting tzfile v2
- if (version != 0x32) {
+ // currently only supporting tzfile v2 and v3
+ if (version != 0x32 && version != 0x33) {
return 0;
}
>From f91a4d0426f231eae7904f1fa1a0d88b9a73efb4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 23 Nov 2024 17:56:27 +0100
Subject: [PATCH 32/58] add `close` function
---
libc/src/time/timezone.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 091c6ef1724f63..b6f518d2cfb6b9 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -59,11 +59,13 @@ int get_timezone_offset(char *timezone) {
fd = open("/etc/localtime", O_RDONLY);
if (fd < 0) {
+ close(fd);
return 0;
}
bytes = read(fd, hdr, sizeof(hdr));
if (bytes != sizeof(hdr)) {
+ close(fd);
return 0;
}
>From b9ba7481b6befbcf9a889840ad03926ac73a3223 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 23 Nov 2024 18:15:03 +0100
Subject: [PATCH 33/58] add support for `tzfile` version 4
---
libc/src/time/timezone.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index b6f518d2cfb6b9..519841a91bf1fc 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -72,7 +72,8 @@ int get_timezone_offset(char *timezone) {
size_t i;
__uint128_t tmp;
- // these locations in timezone files are defined in `tzfile`
+ // these locations in timezone files are defined in documentation
+ // for `tzfile`
magic = (hdr[0] << 24) | (hdr[1] << 16) | (hdr[2] << 8) | hdr[3];
version = hdr[4];
for (i = 5; i <= 20; i++) {
@@ -95,8 +96,7 @@ int get_timezone_offset(char *timezone) {
return 0;
}
- // currently only supporting tzfile v2 and v3
- if (version != 0x32 && version != 0x33) {
+ if (version != 0x32 && version != 0x33 && version != 0x34) {
return 0;
}
>From fbe06fd9d2b6c2946c1aa373531f1fbff437aed7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Sat, 23 Nov 2024 18:28:21 +0100
Subject: [PATCH 34/58] fix: bytes for timezone file
---
libc/src/time/timezone.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 519841a91bf1fc..3888049506292d 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -42,7 +42,7 @@ void rev_str(char *str) {
int get_timezone_offset(char *timezone) {
(void)timezone;
- unsigned char hdr[TIMEZONE_HDR_SIZE];
+ unsigned char hdr[TIMEZONE_HDR_SIZE + 1];
int32_t magic;
unsigned char version;
@@ -76,16 +76,16 @@ int get_timezone_offset(char *timezone) {
// for `tzfile`
magic = (hdr[0] << 24) | (hdr[1] << 16) | (hdr[2] << 8) | hdr[3];
version = hdr[4];
- for (i = 5; i <= 20; i++) {
+ for (i = 5; i < 21; i++) {
tmp = (tmp << 8) | hdr[i];
}
reserved = tmp;
- tzh_ttisutcnt = (hdr[20] << 24) | (hdr[21] << 16) | (hdr[22] << 8) | hdr[23];
- tzh_ttisstdcnt = (hdr[24] << 24) | (hdr[25] << 16) | (hdr[26] << 8) | hdr[27];
- tzh_leapcnt = (hdr[28] << 24) | (hdr[29] << 16) | (hdr[30] << 8) | hdr[31];
- tzh_timecnt = (hdr[32] << 24) | (hdr[33] << 16) | (hdr[34] << 8) | hdr[35];
- tzh_typecnt = (hdr[36] << 24) | (hdr[37] << 16) | (hdr[38] << 8) | hdr[39];
- tzh_charcnt = (hdr[40] << 24) | (hdr[41] << 16) | (hdr[42] << 8) | hdr[43];
+ tzh_ttisutcnt = (hdr[21] << 24) | (hdr[22] << 16) | (hdr[23] << 8) | hdr[24];
+ tzh_ttisstdcnt = (hdr[25] << 24) | (hdr[26] << 16) | (hdr[27] << 8) | hdr[28];
+ tzh_leapcnt = (hdr[29] << 24) | (hdr[30] << 16) | (hdr[31] << 8) | hdr[32];
+ tzh_timecnt = (hdr[33] << 24) | (hdr[34] << 16) | (hdr[35] << 8) | hdr[36];
+ tzh_typecnt = (hdr[37] << 24) | (hdr[38] << 16) | (hdr[39] << 8) | hdr[40];
+ tzh_charcnt = (hdr[41] << 24) | (hdr[42] << 16) | (hdr[43] << 8) | hdr[44];
(void)tzh_ttisutcnt;
(void)tzh_ttisstdcnt;
(void)tzh_leapcnt;
@@ -101,7 +101,7 @@ int get_timezone_offset(char *timezone) {
}
// according to `tzfile`, 15 bytes should be 0
- if ((reserved ^ 0x00) != 0) {
+ if (reserved != 0) {
return 0;
}
>From 21bd2c3ed04bc8b22acb2d4c87fdfbed392a4634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Mon, 23 Dec 2024 09:02:08 +0500
Subject: [PATCH 35/58] fix: merge from main branch
---
libc/spec/stdc.td | 1816 ---------------------------------------------
1 file changed, 1816 deletions(-)
delete mode 100644 libc/spec/stdc.td
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
deleted file mode 100644
index d6186281b76a3f..00000000000000
--- a/libc/spec/stdc.td
+++ /dev/null
@@ -1,1816 +0,0 @@
-def StdC : StandardSpec<"stdc"> {
-
- NamedType StructTmType = NamedType<"struct tm">;
- PtrType StructTmPtr = PtrType<StructTmType>;
- PtrType TimeTTypePtr = PtrType<TimeTType>;
- NamedType ClockT = NamedType<"clock_t">;
- NamedType LocaleT = NamedType<"locale_t">;
-
- NamedType DivTType = NamedType<"div_t">;
- NamedType LDivTType = NamedType<"ldiv_t">;
- NamedType LLDivTType = NamedType<"lldiv_t">;
-
- NamedType JmpBuf = NamedType<"jmp_buf">;
-
- NamedType TssTType = NamedType<"tss_t">;
- PtrType TssTPtr = PtrType<TssTType>;
- NamedType TssDtorTType = NamedType<"tss_dtor_t">;
-
- HeaderSpec Assert = HeaderSpec<
- "assert.h",
- [
- Macro<"static_assert">,
- Macro<"assert">,
- ],
- [], // Types
- [], // Enumerations
- []
- >;
-
- FunctionAttrSpec ConstAttr = FunctionAttrSpec<"__LIBC_CONST_ATTR", [
- Cxx11FunctionAttr<"const", "gnu">,
- GnuFunctionAttr<"const">,
- ]>;
-
- HeaderSpec CType = HeaderSpec<
- "ctype.h",
- [], // Macros
- [
- LocaleT
- ], // Types
- [], // Enumerations
- [
- FunctionSpec<
- "isalnum",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isalpha",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isblank",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "iscntrl",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isdigit",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isgraph",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "islower",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isprint",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "ispunct",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isspace",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isupper",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isxdigit",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "tolower",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "toupper",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "isalnum_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isalpha_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isblank_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "iscntrl_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isdigit_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isgraph_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "islower_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isprint_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "ispunct_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isspace_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isupper_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "isxdigit_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "tolower_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "toupper_l",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<LocaleT>]
- >,
- ]
- >;
-
- NamedType FEnvT = NamedType<"fenv_t">;
- PtrType FEnvTPtr = PtrType<FEnvT>;
- ConstType ConstFEnvTPtr = ConstType<FEnvTPtr>;
- NamedType FExceptT = NamedType<"fexcept_t">;
- PtrType FExceptTPtr = PtrType<FExceptT>;
- ConstType ConstFExceptTPtr = ConstType<FExceptTPtr>;
- HeaderSpec Fenv = HeaderSpec<
- "fenv.h",
- [
- Macro<"FE_DIVBYZERO">,
- Macro<"FE_INEXACT">,
- Macro<"FE_INVALID">,
- Macro<"FE_OVERFLOW">,
- Macro<"FE_UNDERFLOW">,
- Macro<"FE_ALL_EXCEPT">,
-
- Macro<"FE_DOWNWARD">,
- Macro<"FE_TONEAREST">,
- Macro<"FE_TOWARDZERO">,
- Macro<"FE_UPWARD">,
-
- Macro<"FE_DFL_ENV">
- ],
- [
- FEnvT,
- FExceptT,
- ], // Types
- [], // Enumerations
- [
- FunctionSpec<
- "feclearexcept",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fetestexcept",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fetestexceptflag",
- RetValSpec<IntType>,
- [ArgSpec<ConstFExceptTPtr>, ArgSpec<IntType>]
- >,
- FunctionSpec<
- "feraiseexcept",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fesetround",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fegetround",
- RetValSpec<IntType>,
- []
- >,
- FunctionSpec<
- "fegetenv",
- RetValSpec<IntType>,
- [ArgSpec<FEnvTPtr>]
- >,
- FunctionSpec<
- "fesetenv",
- RetValSpec<IntType>,
- [ArgSpec<ConstFEnvTPtr>]
- >,
- FunctionSpec<
- "fegetexceptflag",
- RetValSpec<IntType>,
- [ArgSpec<FExceptTPtr>, ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fesetexcept",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fesetexceptflag",
- RetValSpec<IntType>,
- [ArgSpec<ConstFExceptTPtr>, ArgSpec<IntType>]
- >,
- FunctionSpec<
- "feholdexcept",
- RetValSpec<IntType>,
- [ArgSpec<FEnvTPtr>]
- >,
- FunctionSpec<
- "feupdateenv",
- RetValSpec<IntType>,
- [ArgSpec<ConstFEnvTPtr>]
- >,
- ]
- >;
-
- HeaderSpec String = HeaderSpec<
- "string.h",
- [
- Macro<"NULL">,
- ],
- [
- SizeTType,
- ],
- [], // Enumerations
- [
- FunctionSpec<
- "memcpy",
- RetValSpec<VoidPtr>,
- [ArgSpec<VoidRestrictedPtr>,
- ArgSpec<ConstVoidRestrictedPtr>,
- ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "memmove",
- RetValSpec<VoidPtr>,
- [ArgSpec<VoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "memcmp",
- RetValSpec<IntType>,
- [ArgSpec<ConstVoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "memchr",
- RetValSpec<VoidPtr>,
- [ArgSpec<ConstVoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "memset",
- RetValSpec<VoidPtr>,
- [ArgSpec<VoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "memset_explicit",
- RetValSpec<VoidPtr>,
- [ArgSpec<VoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "strcpy",
- RetValSpec<CharPtr>,
- [ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>]
- >,
- FunctionSpec<
- "strncpy",
- RetValSpec<CharPtr>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "strcat",
- RetValSpec<CharPtr>,
- [ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>]
- >,
- FunctionSpec<
- "strncat",
- RetValSpec<CharPtr>,
- [ArgSpec<CharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "strcmp",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strcoll",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strcoll_l",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "strncmp",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "strxfrm",
- RetValSpec<SizeTType>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "strxfrm_l",
- RetValSpec<SizeTType>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<SizeTType>,
- ArgSpec<LocaleT>]
- >,
- FunctionSpec<
- "strchr",
- RetValSpec<CharPtr>,
- [ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
- >,
- FunctionSpec<
- "strcspn",
- RetValSpec<SizeTType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strdup",
- RetValSpec<CharPtr>,
- [ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strndup",
- RetValSpec<CharPtr>,
- [ArgSpec<ConstCharPtr>,ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "strpbrk",
- RetValSpec<CharPtr>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strrchr",
- RetValSpec<CharPtr>,
- [ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
- >,
- FunctionSpec<
- "strspn",
- RetValSpec<SizeTType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strstr",
- RetValSpec<CharPtr>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "strtok",
- RetValSpec<CharPtr>,
- [ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>]
- >,
- FunctionSpec<
- "strerror",
- RetValSpec<CharPtr>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "strlen",
- RetValSpec<SizeTType>,
- [ArgSpec<ConstCharPtr>]
- >,
- ]
- >;
-
- HeaderSpec Math = HeaderSpec<
- "math.h",
- [
- Macro<"MATH_ERRNO">,
- Macro<"MATH_ERREXCEPT">,
- Macro<"math_errhandling">,
-
- Macro<"HUGE_VAL">,
- Macro<"INFINITY">,
- Macro<"NAN">,
-
- Macro<"FP_INT_UPWARD">,
- Macro<"FP_INT_DOWNWARD">,
- Macro<"FP_INT_TOWARDZERO">,
- Macro<"FP_INT_TONEARESTFROMZERO">,
- Macro<"FP_INT_TONEAREST">,
-
- Macro<"FP_ILOGB0">,
- Macro<"FP_ILOGBNAN">,
-
- Macro<"isfinite">,
- Macro<"isinf">,
- Macro<"isnan">,
- ],
- [
- NamedType<"float_t">,
- NamedType<"double_t">,
- NamedType<"float128">,
- ],
- [], // Enumerations
- [
- FunctionSpec<"cbrt", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"cbrtf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"copysign", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"copysignf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"copysignl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"copysignf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"copysignf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"ceil", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"ceilf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"ceill", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"ceilf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"ceilf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"daddl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- FunctionSpec<"ddivl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- FunctionSpec<"dfmal", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- FunctionSpec<"dsubl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"fabs", RetValSpec<DoubleType>, [ArgSpec<DoubleType>], [ConstAttr]>,
- FunctionSpec<"fabsf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"fabsl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fabsf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fabsf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fadd", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"faddl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"fdim", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fdimf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fdiml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fdimf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fdimf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fdiv", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fdivl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"ffma", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"ffmal", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"floor", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"floorf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"floorl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"floorf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"floorf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fmin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fminf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fminl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fminf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
- GuardedFunctionSpec<"fminf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"fmax", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmaxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmaxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fmaxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
- GuardedFunctionSpec<"fmaxf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"fmaximum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmaximumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmaximuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fmaximumf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fmaximumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fmaximum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmaximum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fmaximum_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fmaximum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fmaximum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmaximum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmaximum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fmaximum_magf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fmaximum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fmaximum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmaximum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmaximum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fmaximum_mag_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fmaximum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fminimum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fminimumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fminimuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fminimumf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fminimumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fminimum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fminimum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fminimum_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fminimum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fminimum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fminimum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fminimum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fminimum_magf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fminimum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fminimum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fminimum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fminimum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fminimum_mag_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
-
- GuardedFunctionSpec<"f16fmaf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
-
- FunctionSpec<"fmod", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmodf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"fmodl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"fmodf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fmodf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"frexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,
- FunctionSpec<"frexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntPtr>]>,
- FunctionSpec<"frexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]>,
- GuardedFunctionSpec<"frexpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"frexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"fromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"fromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- GuardedFunctionSpec<"fromfpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fromfpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"fromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"fromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- GuardedFunctionSpec<"fromfpxf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"fromfpxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"fsub", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fsubl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"ufromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"ufromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"ufromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- GuardedFunctionSpec<"ufromfpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"ufromfpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"ufromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"ufromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"ufromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- GuardedFunctionSpec<"ufromfpxf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"ufromfpxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"hypot", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"hypotf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
-
- FunctionSpec<"ilogb", RetValSpec<IntType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"ilogbf", RetValSpec<IntType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"ilogbl", RetValSpec<IntType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"ilogbf16", RetValSpec<IntType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"ilogbf128", RetValSpec<IntType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"llogb", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"llogbf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"llogbl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"llogbf16", RetValSpec<LongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"llogbf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"ldexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
- FunctionSpec<"ldexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
- FunctionSpec<"ldexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
- GuardedFunctionSpec<"ldexpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"ldexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"log10", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"log10f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"log1p", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"log1pf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"log2", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"log2f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"log", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"logf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"logb", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"logbf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"logbl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"logbf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"logbf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"modf", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoublePtr>]>,
- FunctionSpec<"modff", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatPtr>]>,
- FunctionSpec<"modfl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoublePtr>]>,
- GuardedFunctionSpec<"modff16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"modff128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"cos", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"cosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"sin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"sinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"tan", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"tanf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"erff", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"exp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"expf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- GuardedFunctionSpec<"expf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"exp2", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"exp2f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- GuardedFunctionSpec<"exp2f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"exp2m1f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"expm1", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"expm1f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- GuardedFunctionSpec<"expm1f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"exp10", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"exp10f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- GuardedFunctionSpec<"exp10f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"remainder", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"remainderf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"remainderl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"remainderf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"remainderf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"remquo", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,
- FunctionSpec<"remquof", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<IntPtr>]>,
- FunctionSpec<"remquol", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]>,
- GuardedFunctionSpec<"remquof16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"remquof128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"round", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"roundf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"roundl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"roundf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"roundf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"roundeven", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"roundevenf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"roundevenl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"roundevenf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"roundevenf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"lround", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"lroundf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"lroundl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"lroundf16", RetValSpec<LongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"lroundf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"llround", RetValSpec<LongLongType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"llroundf", RetValSpec<LongLongType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"llroundl", RetValSpec<LongLongType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"llroundf16", RetValSpec<LongLongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"llroundf128", RetValSpec<LongLongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"rint", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"rintf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"rintl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"rintf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"rintf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"lrint", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"lrintf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"lrintl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"lrintf16", RetValSpec<LongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"lrintf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"llrint", RetValSpec<LongLongType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"llrintf", RetValSpec<LongLongType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"llrintl", RetValSpec<LongLongType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"llrintf16", RetValSpec<LongLongType>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"llrintf128", RetValSpec<LongLongType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"sqrt", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"sqrtf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"sqrtl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"sqrtf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"trunc", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"truncf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"truncl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"truncf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"truncf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"nearbyint", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"nearbyintf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"nearbyintl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"nearbyintf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"nearbyintf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"nextafterf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"nextafter", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"nextafterl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"nextafterf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"nextafterf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"nexttowardf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<LongDoubleType>]>,
- FunctionSpec<"nexttoward", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<LongDoubleType>]>,
- FunctionSpec<"nexttowardl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"nexttowardf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
-
- FunctionSpec<"nextdown", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"nextdownf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"nextdownl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"nextdownf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"nextdownf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"nextup", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"nextupf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"nextupl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"nextupf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"nextupf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"powf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"pow", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
-
- FunctionSpec<"coshf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"sinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"tanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"acosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"asinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"asin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
-
- FunctionSpec<"atanf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"atan2", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"atan2f", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"atan2l", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"acoshf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"asinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"atanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
-
- FunctionSpec<"scalbln", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<LongType>]>,
- FunctionSpec<"scalblnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<LongType>]>,
- FunctionSpec<"scalblnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongType>]>,
- GuardedFunctionSpec<"scalblnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"scalblnf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
- FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
- FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
- GuardedFunctionSpec<"scalbnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"scalbnf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
- FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
- FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
- GuardedFunctionSpec<"nanf16", RetValSpec<Float16Type>, [ArgSpec<ConstCharPtr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"nanf128", RetValSpec<Float128Type>, [ArgSpec<ConstCharPtr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"canonicalize", RetValSpec<IntType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"canonicalizef", RetValSpec<IntType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
- FunctionSpec<"canonicalizel", RetValSpec<IntType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"canonicalizef16", RetValSpec<IntType>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"canonicalizef128", RetValSpec<IntType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"dsqrtl", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"totalorder", RetValSpec<IntType>, [ArgSpec<ConstDoublePtr>, ArgSpec<ConstDoublePtr>]>,
- FunctionSpec<"totalorderf", RetValSpec<IntType>, [ArgSpec<ConstFloatPtr>, ArgSpec<ConstFloatPtr>]>,
- FunctionSpec<"totalorderl", RetValSpec<IntType>, [ArgSpec<ConstLongDoublePtr>, ArgSpec<ConstLongDoublePtr>]>,
- GuardedFunctionSpec<"totalorderf16", RetValSpec<IntType>, [ArgSpec<ConstFloat16Ptr>, ArgSpec<ConstFloat16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"totalorderf128", RetValSpec<IntType>, [ArgSpec<ConstFloat128Ptr>, ArgSpec<ConstFloat128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"totalordermag", RetValSpec<IntType>, [ArgSpec<ConstDoublePtr>, ArgSpec<ConstDoublePtr>]>,
- FunctionSpec<"totalordermagf", RetValSpec<IntType>, [ArgSpec<ConstFloatPtr>, ArgSpec<ConstFloatPtr>]>,
- FunctionSpec<"totalordermagl", RetValSpec<IntType>, [ArgSpec<ConstLongDoublePtr>, ArgSpec<ConstLongDoublePtr>]>,
- GuardedFunctionSpec<"totalordermagf16", RetValSpec<IntType>, [ArgSpec<ConstFloat16Ptr>, ArgSpec<ConstFloat16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"totalordermagf128", RetValSpec<IntType>, [ArgSpec<ConstFloat128Ptr>, ArgSpec<ConstFloat128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"getpayload", RetValSpec<DoubleType>, [ArgSpec<DoublePtr>]>,
- FunctionSpec<"getpayloadf", RetValSpec<FloatType>, [ArgSpec<FloatPtr>]>,
- FunctionSpec<"getpayloadl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoublePtr>]>,
- GuardedFunctionSpec<"getpayloadf16", RetValSpec<Float16Type>, [ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"getpayloadf128", RetValSpec<Float128Type>, [ArgSpec<Float128Ptr>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"setpayload", RetValSpec<IntType>, [ArgSpec<DoublePtr>, ArgSpec<DoubleType>]>,
- FunctionSpec<"setpayloadf", RetValSpec<IntType>, [ArgSpec<FloatPtr>, ArgSpec<FloatType>]>,
- FunctionSpec<"setpayloadl", RetValSpec<IntType>, [ArgSpec<LongDoublePtr>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"setpayloadf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"setpayloadf128", RetValSpec<IntType>, [ArgSpec<Float128Ptr>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- FunctionSpec<"setpayloadsig", RetValSpec<IntType>, [ArgSpec<DoublePtr>, ArgSpec<DoubleType>]>,
- FunctionSpec<"setpayloadsigf", RetValSpec<IntType>, [ArgSpec<FloatPtr>, ArgSpec<FloatType>]>,
- FunctionSpec<"setpayloadsigl", RetValSpec<IntType>, [ArgSpec<LongDoublePtr>, ArgSpec<LongDoubleType>]>,
- GuardedFunctionSpec<"setpayloadsigf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
- GuardedFunctionSpec<"setpayloadsigf128", RetValSpec<IntType>, [ArgSpec<Float128Ptr>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
-
- GuardedFunctionSpec<"f16addf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
-
- GuardedFunctionSpec<"f16subf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
-
- FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmull", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"dmull", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
- GuardedFunctionSpec<"f16mulf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
-
- FunctionSpec<"fsqrt", RetValSpec<FloatType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"fsqrtl", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>]>,
-
- GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
-
- GuardedFunctionSpec<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
-
- FunctionSpec<"lgamma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
- FunctionSpec<"lgammaf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
- FunctionSpec<"lgammal", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- ]
- >;
-
- HeaderSpec StdIO = HeaderSpec<
- "stdio.h",
- [
- Macro<"stdin">,
- Macro<"stderr">,
- Macro<"stdout">,
- Macro<"_IOFBF">,
- Macro<"_IOLBF">,
- Macro<"_IONBF">,
- Macro<"EOF">,
- ], // Macros
- [ // Types
- SizeTType,
- FILE,
- ],
- [], // Enumerations
- [
- FunctionSpec<
- "clearerr",
- RetValSpec<VoidType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "fclose",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "feof",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "ferror",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "fgetc",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "fgets",
- RetValSpec<CharPtr>,
- [
- ArgSpec<CharRestrictedPtr>,
- ArgSpec<IntType>,
- ArgSpec<FILERestrictedPtr>,
- ]
- >,
- FunctionSpec<
- "fflush",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "fopen",
- RetValSpec<FILEPtr>,
- [ArgSpec<ConstCharPtr>,
- ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "fputc",
- RetValSpec<IntType>,
- [ArgSpec<IntType>,
- ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "ftell",
- RetValSpec<LongType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "getc",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "getchar",
- RetValSpec<IntType>,
- [ArgSpec<VoidType>]
- >,
- FunctionSpec<
- "putc",
- RetValSpec<IntType>,
- [ArgSpec<IntType>,
- ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "putchar",
- RetValSpec<IntType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fputs",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<FILERestrictedPtr>]
- >,
- FunctionSpec<
- "puts",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>]
- >,
- FunctionSpec<
- "fread",
- RetValSpec<SizeTType>,
- [ArgSpec<VoidRestrictedPtr>,
- ArgSpec<SizeTType>,
- ArgSpec<SizeTType>,
- ArgSpec<FILERestrictedPtr>]
- >,
- FunctionSpec<
- "fseek",
- RetValSpec<IntType>,
- [ArgSpec<FILEPtr>,
- ArgSpec<LongType>,
- ArgSpec<IntType>]
- >,
- FunctionSpec<
- "fwrite",
- RetValSpec<SizeTType>,
- [ArgSpec<ConstVoidRestrictedPtr>,
- ArgSpec<SizeTType>,
- ArgSpec<SizeTType>,
- ArgSpec<FILERestrictedPtr>]
- >,
- FunctionSpec<
- "remove",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "rename",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
- >,
- FunctionSpec<
- "setbuf",
- RetValSpec<VoidType>,
- [ArgSpec<FILERestrictedPtr>, ArgSpec<CharRestrictedPtr>]
- >,
- FunctionSpec<
- "setvbuf",
- RetValSpec<IntType>,
- [ArgSpec<FILERestrictedPtr>, ArgSpec<CharRestrictedPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
- >,
- FunctionSpec<
- "sscanf",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "vsscanf",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "scanf",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "vscanf",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "fscanf",
- RetValSpec<IntType>,
- [ArgSpec<FILERestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "vfscanf",
- RetValSpec<IntType>,
- [ArgSpec<FILERestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "sprintf",
- RetValSpec<IntType>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "snprintf",
- RetValSpec<IntType>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<SizeTType>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "printf",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "fprintf",
- RetValSpec<IntType>,
- [ArgSpec<FILERestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "asprintf",
- RetValSpec<IntType>,
- [ArgSpec<CharRestrictedPtrPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VarArgType>]
- >,
- FunctionSpec<
- "vsprintf",
- RetValSpec<IntType>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "vsnprintf",
- RetValSpec<IntType>,
- [ArgSpec<CharRestrictedPtr>,
- ArgSpec<SizeTType>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "vprintf",
- RetValSpec<IntType>,
- [ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "vfprintf",
- RetValSpec<IntType>,
- [ArgSpec<FILERestrictedPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- FunctionSpec<
- "ungetc",
- RetValSpec<IntType>,
- [ArgSpec<IntType>, ArgSpec<FILEPtr>]
- >,
- FunctionSpec<
- "vasprintf",
- RetValSpec<IntType>,
- [ArgSpec<CharRestrictedPtrPtr>,
- ArgSpec<ConstCharRestrictedPtr>,
- ArgSpec<VaListType>]
- >,
- ],
- [
- ObjectSpec<
- "stdin",
- "FILE *"
- >,
- ObjectSpec<
- "stdout",
- "FILE *"
- >,
- ObjectSpec<
- "stderr",
- "FILE *"
- >,
- ]
- >;
-
- HeaderSpec StdBit = HeaderSpec<
- "stdbit.h",
- [
- Macro<"__STDC_VERSION_STDBIT_H__">,
- Macro<"__STDC_ENDIAN_LITTLE__">,
- Macro<"__STDC_ENDIAN_BIG__">,
- Macro<"__STDC_ENDIAN_NATIVE__">,
- Macro<"stdc_leading_zeros">,
- Macro<"stdc_leading_ones">,
- Macro<"stdc_trailing_zeros">,
- Macro<"stdc_trailing_ones">,
- Macro<"stdc_first_leading_zero">,
- Macro<"stdc_first_leading_one">,
- Macro<"stdc_first_trailing_zero">,
- Macro<"stdc_first_trailing_one">,
- Macro<"stdc_count_zeros">,
- Macro<"stdc_count_ones">,
- Macro<"stdc_has_single_bit">,
- Macro<"stdc_bit_width">,
- Macro<"stdc_bit_floor">,
- Macro<"stdc_bit_ceil">
- ], // Macros
- [], // Types
- [], // Enumerations
- [
- FunctionSpec<"stdc_leading_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_leading_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_leading_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_leading_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_leading_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_leading_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_leading_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_leading_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_leading_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_leading_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_trailing_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_trailing_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_trailing_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_trailing_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_trailing_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_trailing_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_trailing_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_trailing_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_trailing_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_trailing_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_first_leading_zero_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_first_leading_zero_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_first_leading_zero_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_first_leading_zero_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_first_leading_zero_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_first_leading_one_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_first_leading_one_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_first_leading_one_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_first_leading_one_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_first_leading_one_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_first_trailing_one_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_first_trailing_one_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_first_trailing_one_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_first_trailing_one_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_first_trailing_one_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_count_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_count_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_count_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_count_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_count_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_count_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_count_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_count_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_count_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_count_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_has_single_bit_uc", RetValSpec<BoolType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_has_single_bit_us", RetValSpec<BoolType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_has_single_bit_ui", RetValSpec<BoolType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_has_single_bit_ul", RetValSpec<BoolType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_has_single_bit_ull", RetValSpec<BoolType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_bit_width_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_bit_width_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_bit_width_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_bit_width_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_bit_width_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_bit_floor_uc", RetValSpec<UnsignedCharType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_bit_floor_us", RetValSpec<UnsignedShortType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_bit_floor_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_bit_floor_ul", RetValSpec<UnsignedLongType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_bit_floor_ull", RetValSpec<UnsignedLongLongType>, [ArgSpec<UnsignedLongLongType>]>,
- FunctionSpec<"stdc_bit_ceil_uc", RetValSpec<UnsignedCharType>, [ArgSpec<UnsignedCharType>]>,
- FunctionSpec<"stdc_bit_ceil_us", RetValSpec<UnsignedShortType>, [ArgSpec<UnsignedShortType>]>,
- FunctionSpec<"stdc_bit_ceil_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"stdc_bit_ceil_ul", RetValSpec<UnsignedLongType>, [ArgSpec<UnsignedLongType>]>,
- FunctionSpec<"stdc_bit_ceil_ull", RetValSpec<UnsignedLongLongType>, [ArgSpec<UnsignedLongLongType>]>
- ] // Functions
- >;
-
- HeaderSpec StdCkdInt = HeaderSpec<
- "stdckdint.h",
- [
- Macro<"__STDC_VERSION_STDCKDINT_H__">,
- Macro<"ckd_add">,
- Macro<"ckd_sub">,
- Macro<"ckd_mul">
- ], // Macros
- [], // Types
- [], // Enumerations
- [] // Functions
- >;
-
- HeaderSpec StdLib = HeaderSpec<
- "stdlib.h",
- [], // Macros
- [
- DivTType,
- LDivTType,
- LLDivTType,
- SizeTType,
- BSearchCompareT,
- QSortCompareT,
- AtexitHandlerT,
- ], // Types
- [], // Enumerations
- [
- FunctionSpec<"abort", RetValSpec<NoReturn>, [ArgSpec<VoidType>]>,
-
- FunctionSpec<"bsearch", RetValSpec<VoidPtr>, [ArgSpec<ConstVoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<BSearchCompareT>]>,
-
- FunctionSpec<"abs", RetValSpec<IntType>, [ArgSpec<IntType>]>,
- FunctionSpec<"labs", RetValSpec<LongType>, [ArgSpec<LongType>]>,
- FunctionSpec<"llabs", RetValSpec<LongLongType>, [ArgSpec<LongLongType>]>,
-
- FunctionSpec<"atof", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>]>,
- FunctionSpec<"atoi", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>]>,
- FunctionSpec<"atol", RetValSpec<LongType>, [ArgSpec<ConstCharPtr>]>,
- FunctionSpec<"atoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharPtr>]>,
-
- FunctionSpec<"div", RetValSpec<DivTType>, [ArgSpec<IntType>, ArgSpec<IntType>]>,
- FunctionSpec<"ldiv", RetValSpec<LDivTType>, [ArgSpec<LongType>, ArgSpec<LongType>]>,
- FunctionSpec<"lldiv", RetValSpec<LLDivTType>, [ArgSpec<LongLongType>, ArgSpec<LongLongType>]>,
-
- FunctionSpec<"qsort", RetValSpec<VoidType>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<QSortCompareT>]>,
-
- FunctionSpec<"rand", RetValSpec<IntType>, [ArgSpec<VoidType>]>,
- FunctionSpec<"srand", RetValSpec<VoidType>, [ArgSpec<UnsignedIntType>]>,
-
- FunctionSpec<"strfromf", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<FloatType>]>,
- FunctionSpec<"strfromd", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<DoubleType>]>,
- FunctionSpec<"strfroml", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<LongDoubleType>]>,
-
- FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
- FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
- FunctionSpec<"strtold", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
- FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
- FunctionSpec<"strtoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
- FunctionSpec<"strtoul", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
- FunctionSpec<"strtoull", RetValSpec<UnsignedLongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
-
- FunctionSpec<"strtof_l", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
- FunctionSpec<"strtod_l", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
- FunctionSpec<"strtold_l", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
- FunctionSpec<"strtol_l", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
- FunctionSpec<"strtoll_l", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
- FunctionSpec<"strtoul_l", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
- FunctionSpec<"strtoull_l", RetValSpec<UnsignedLongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
-
- FunctionSpec<"malloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>]>,
- FunctionSpec<"calloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>, ArgSpec<SizeTType>]>,
- FunctionSpec<"realloc", RetValSpec<VoidPtr>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]>,
- FunctionSpec<"aligned_alloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>, ArgSpec<SizeTType>]>,
- FunctionSpec<"free", RetValSpec<VoidType>, [ArgSpec<VoidPtr>]>,
-
- FunctionSpec<"_Exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
- FunctionSpec<"at_quick_exit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
- FunctionSpec<"atexit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
- FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
- FunctionSpec<"quick_exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
-
- FunctionSpec<"system", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>]>,
- ]
- >;
-
- NamedType IMaxDivTType = NamedType<"imaxdiv_t">;
-
- HeaderSpec IntTypes = HeaderSpec<
- "inttypes.h",
- [
- Macro<"__STDC_VERSION_INTTYPES_H__">,
- ], // Macros
- [
- IMaxDivTType,
- ], // Types
- [], // Enumerations
- [
- FunctionSpec<"imaxabs", RetValSpec<IntMaxTType>, [ArgSpec<IntMaxTType>]>,
- FunctionSpec<"imaxdiv", RetValSpec<IMaxDivTType>, [ArgSpec<IntMaxTType>, ArgSpec<IntMaxTType>]>,
- FunctionSpec<"strtoimax", RetValSpec<IntMaxTType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
- FunctionSpec<"strtoumax", RetValSpec<UIntMaxTType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
- ]
- >;
-
- HeaderSpec Errno = HeaderSpec<
- "errno.h",
- [
- Macro<"errno">,
- Macro<"EDOM">,
- Macro<"EILSEQ">,
- Macro<"ERANGE">,
- ]
- >;
-
- HeaderSpec Float = HeaderSpec<
- "float.h",
- [
- Macro<"FLT_MANT_DIG">,
- Macro<"DBL_MANT_DIG">,
- Macro<"LDBL_MANT_DIG">,
- ]
- >;
-
- HeaderSpec StdInt = HeaderSpec<"StdInt.h">;
-
- HeaderSpec Limits = HeaderSpec<"limits.h">;
-
- NamedType SigAtomicT = NamedType<"sig_atomic_t">;
- HeaderSpec Signal = HeaderSpec<
- "signal.h",
- [
- Macro<"SIG_BLOCK">,
- Macro<"SIG_UNBLOCK">,
- Macro<"SIG_SETMASK">,
-
- Macro<"SIGABRT">,
- Macro<"SIGFPE">,
- Macro<"SIGILL">,
- Macro<"SIGINT">,
- Macro<"SIGSEGV">,
- Macro<"SIGTERM">
- ],
- [
- SizeTType,
- SigAtomicT,
- SigHandlerT,
- ],
- [], // Enumerations
- [
- FunctionSpec<"raise", RetValSpec<IntType>, [ArgSpec<IntType>]>,
- FunctionSpec<
- "signal",
- RetValSpec<SigHandlerT>,
- [ArgSpec<IntType>, ArgSpec<SigHandlerT>]
- >,
- ]
- >;
-
- HeaderSpec Threads = HeaderSpec<
- "threads.h",
- [
- Macro<"ONCE_FLAG_INIT">,
- ],
- [
- OnceFlagType,
- CallOnceFuncType,
- CndTType,
- MtxTType,
- ThrdStartTType,
- ThrdTType,
- TssTType,
- TssDtorTType,
- ],
- [
- EnumeratedNameValue<"mtx_plain">,
- EnumeratedNameValue<"mtx_recursive">,
- EnumeratedNameValue<"mtx_timed">,
- EnumeratedNameValue<"thrd_timedout">,
- EnumeratedNameValue<"thrd_success">,
- EnumeratedNameValue<"thrd_busy">,
- EnumeratedNameValue<"thrd_error">,
- EnumeratedNameValue<"thrd_nomem">,
- ],
- [
- FunctionSpec<
- "call_once",
- RetValSpec<VoidType>,
- [
- ArgSpec<OnceFlagTypePtr>,
- ArgSpec<CallOnceFuncType>,
- ]
- >,
- FunctionSpec<
- "cnd_broadcast",
- RetValSpec<IntType>,
- [
- ArgSpec<CndTTypePtr>,
- ]
- >,
- FunctionSpec<
- "cnd_destroy",
- RetValSpec<VoidType>,
- [
- ArgSpec<CndTTypePtr>,
- ]
- >,
- FunctionSpec<
- "cnd_init",
- RetValSpec<IntType>,
- [
- ArgSpec<CndTTypePtr>,
- ]
- >,
- FunctionSpec<
- "cnd_signal",
- RetValSpec<IntType>,
- [
- ArgSpec<CndTTypePtr>,
- ]
- >,
- FunctionSpec<
- "cnd_wait",
- RetValSpec<IntType>,
- [
- ArgSpec<CndTTypePtr>,
- ArgSpec<MtxTTypePtr>,
- ]
- >,
- FunctionSpec<
- "mtx_init",
- RetValSpec<IntType>,
- [
- ArgSpec<MtxTTypePtr>,
- ArgSpec<IntType>,
- ]
- >,
- FunctionSpec<
- "mtx_destroy",
- RetValSpec<IntType>,
- [
- ArgSpec<VoidType>,
- ]
- >,
- FunctionSpec<
- "mtx_lock",
- RetValSpec<IntType>,
- [
- ArgSpec<MtxTTypePtr>,
- ]
- >,
- FunctionSpec<
- "mtx_unlock",
- RetValSpec<IntType>,
- [
- ArgSpec<MtxTTypePtr>,
- ]
- >,
- FunctionSpec<
- "thrd_create",
- RetValSpec<IntType>,
- [
- ArgSpec<ThrdTTypePtr>,
- ArgSpec<ThrdStartTType>,
- ArgSpec<VoidPtr>,
- ]
- >,
- FunctionSpec<
- "thrd_join",
- RetValSpec<IntType>,
- [
- ArgSpec<ThrdTType>,
- ArgSpec<IntPtr>,
- ]
- >,
- FunctionSpec<
- "thrd_detach",
- RetValSpec<IntType>,
- [ArgSpec<ThrdTType>]
- >,
- FunctionSpec<
- "thrd_current",
- RetValSpec<ThrdTType>,
- [ArgSpec<VoidType>]
- >,
- FunctionSpec<
- "thrd_equal",
- RetValSpec<IntType>,
- [ArgSpec<ThrdTType>, ArgSpec<ThrdTType>]
- >,
- FunctionSpec<
- "thrd_exit",
- RetValSpec<VoidType>,
- [ArgSpec<IntType>]
- >,
- FunctionSpec<
- "tss_create",
- RetValSpec<IntType>,
- [ArgSpec<TssTPtr>, ArgSpec<TssDtorTType>]
- >,
- FunctionSpec<
- "tss_delete",
- RetValSpec<IntType>,
- [ArgSpec<TssTType>]
- >,
- FunctionSpec<
- "tss_get",
- RetValSpec<VoidPtr>,
- [ArgSpec<TssTType>]
- >,
- FunctionSpec<
- "tss_set",
- RetValSpec<IntType>,
- [ArgSpec<TssTType>, ArgSpec<VoidPtr>]
- >,
- ]
- >;
-
- HeaderSpec Time = HeaderSpec<
- "time.h",
- [], // Macros
- [ // Types
- ClockT,
- StructTmType,
- StructTimeSpec,
- TimeTType,
- SizeTType,
- ],
- [], // Enumerations
- [
- FunctionSpec<
- "asctime",
- RetValSpec<CharPtr>,
- [ArgSpec<StructTmPtr>]
- >,
- FunctionSpec<
- "asctime_r",
- RetValSpec<CharPtr>,
- [
- ArgSpec<StructTmPtr>,
- ArgSpec<CharPtr>,
- ]
- >,
- FunctionSpec<
- "ctime",
- RetValSpec<CharPtr>,
- [ArgSpec<TimeTTypePtr>]
- >,
- FunctionSpec<
- "ctime_r",
- RetValSpec<CharPtr>,
- [
- ArgSpec<TimeTTypePtr>,
- ArgSpec<CharPtr>,
- ]
- >,
- FunctionSpec<
- "localtime",
- RetValSpec<StructTmPtr>,
- [ArgSpec<TimeTTypePtr>]
- >,
- FunctionSpec<
- "localtime_r",
- RetValSpec<StructTmPtr>,
- [
- ArgSpec<TimeTTypePtr>,
- ArgSpec<StructTmPtr>,
- ]
- >,
- FunctionSpec<
- "localtime_s",
- RetValSpec<IntType>,
- [
- ArgSpec<TimeTTypePtr>,
- ArgSpec<StructTmPtr>,
- ]
- >,
- FunctionSpec<
- "clock",
- RetValSpec<ClockT>,
- [ArgSpec<VoidType>]
- >,
- FunctionSpec<
- "difftime",
- RetValSpec<DoubleType>,
- [
- ArgSpec<TimeTType>,
- ArgSpec<TimeTType>,
- ]
- >,
- FunctionSpec<
- "gmtime",
- RetValSpec<StructTmPtr>,
- [ArgSpec<TimeTTypePtr>]
- >,
- FunctionSpec<
- "gmtime_r",
- RetValSpec<StructTmPtr>,
- [
- ArgSpec<TimeTTypePtr>,
- ArgSpec<StructTmPtr>,
- ]
- >,
- FunctionSpec<
- "mktime",
- RetValSpec<TimeTType>,
- [ArgSpec<StructTmPtr>]
- >,
- FunctionSpec<
- "time",
- RetValSpec<TimeTType>,
- [ArgSpec<TimeTTypePtr>]
- >,
- ]
- >;
-
- HeaderSpec SetJmp = HeaderSpec<
- "setjmp.h",
- [], // Macros
- [JmpBuf],
- [], // Enumerations
- [
- FunctionSpec<
- "longjmp",
- RetValSpec<NoReturn>,
- [ArgSpec<JmpBuf>, ArgSpec<IntType>]
- >,
- FunctionSpec<
- "setjmp",
- RetValSpec<IntType>,
- [ArgSpec<JmpBuf>]
- >,
- FunctionSpec<
- "longjmp",
- RetValSpec<VoidType>,
- [ArgSpec<JmpBuf>, ArgSpec<IntType>]
- >,
- ]
- >;
-
- HeaderSpec UChar = HeaderSpec<
- "uchar.h",
- [], // Macros
- [ //Types
- MBStateTType,
- Char8TType,
- Char16TType,
- Char32TType,
- SizeTType,
- ],
- [], // Enumerations
- []
- >;
-
- HeaderSpec WChar = HeaderSpec<
- "wchar.h",
- [ // Macros
- Macro<"WEOF">,
- ],
- [ //Types
- MBStateTType,
- SizeTType,
- WIntType,
- WCharType,
- ],
- [], // Enumerations
- [
- FunctionSpec<
- "wctob",
- RetValSpec<IntType>,
- [ArgSpec<WIntType>]
- >,
- ]
- >;
-
-
- NamedType StructLconv = NamedType<"struct lconv">;
- PtrType StructLconvPtr = PtrType<StructLconv>;
-
- HeaderSpec Locale = HeaderSpec<
- "locale.h",
- [], // Macros
- [LocaleT, StructLconv], // Types
- [], // Enumerations
- [
- FunctionSpec<
- "duplocale",
- RetValSpec<LocaleT>,
- [
- ArgSpec<LocaleT>
- ]
- >,
- FunctionSpec<
- "freelocale",
- RetValSpec<VoidType>,
- [
- ArgSpec<LocaleT>
- ]
- >,
- FunctionSpec<
- "localeconv",
- RetValSpec<StructLconvPtr>,
- []
- >,
- FunctionSpec<
- "newlocale",
- RetValSpec<LocaleT>,
- [
- ArgSpec<IntType>,
- ArgSpec<ConstCharPtr>,
- ArgSpec<LocaleT>
- ]
- >,
- FunctionSpec<
- "setlocale",
- RetValSpec<CharPtr>,
- [
- ArgSpec<IntType>,
- ArgSpec<ConstCharPtr>
- ]
- >,
- FunctionSpec<
- "uselocale",
- RetValSpec<LocaleT>,
- [
- ArgSpec<LocaleT>
- ]
- >
- ] // Functions
- >;
-
- let Headers = [
- Assert,
- CType,
- Errno,
- Fenv,
- Float,
- StdInt,
- Limits,
- Math,
- String,
- StdBit,
- StdCkdInt,
- StdIO,
- StdLib,
- IntTypes,
- SetJmp,
- Signal,
- Threads,
- Time,
- UChar,
- WChar,
- Locale,
- ];
-}
>From 6c929c15b31c0a01797c072cfc48a2ebd18dd873 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 03:54:51 +0500
Subject: [PATCH 36/58] define structs for timezone data
---
libc/src/time/timezone.h | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 336e8d0c1a1008..e703bc9983cf53 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -11,6 +11,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "stdint.h"
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
@@ -18,7 +19,23 @@ namespace timezone {
// accoring to `tzfile`, timezone header if always 44 bytes
#define TIMEZONE_HDR_SIZE 44
-int get_timezone_offset(char *timezone);
+typedef struct {
+ int64_t tt_utoff;
+ uint8_t tt_isdst;
+ uint8_t tt_desigidx;
+} ttinfo;
+
+typedef struct {
+ uint64_t tzh_ttisutcnt;
+ uint64_t tzh_ttisstdcnt;
+ uint64_t tzh_leapcnt;
+ uint64_t tzh_timecnt;
+ uint64_t tzh_typecnt;
+ uint64_t tzh_charcnt;
+ ttinfo *ttinfo;
+} tzset;
+
+tzset *get_timezone_offset(char *timezone);
} // namespace timezone
} // namespace LIBC_NAMESPACE_DECL
>From dfeb108451563f69b53b805784340f910ceff735 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 04:31:14 +0500
Subject: [PATCH 37/58] use pointers in struct
---
libc/src/time/timezone.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index e703bc9983cf53..180ad019fbcbe8 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -20,9 +20,9 @@ namespace timezone {
#define TIMEZONE_HDR_SIZE 44
typedef struct {
- int64_t tt_utoff;
- uint8_t tt_isdst;
- uint8_t tt_desigidx;
+ int64_t *tt_utoff;
+ uint8_t *tt_isdst;
+ uint8_t *tt_desigidx;
} ttinfo;
typedef struct {
>From e66e9a1377dc7d31628dcf3dd7f750ae4b4789a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 04:43:44 +0500
Subject: [PATCH 38/58] refactor: get timezone data from tzfile
---
libc/src/time/timezone.cpp | 99 +++++++++++++-------------------------
1 file changed, 33 insertions(+), 66 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 3888049506292d..d7cd6d9e22eb8a 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -11,48 +11,27 @@
#include <stdio.h> // TODO: Remove all printf functions
#include <sys/types.h>
-#include "src/time/time_utils.h"
#include "src/__support/common.h"
#include "src/time/timezone.h"
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
+tzset *get_timezone_offset(char *timezone) {
+ static ttinfo ttinfo;
+ static tzset result;
-void rev_str(char *str) {
- int start = 0;
- int end = 0;
+ unsigned char hdr[TIMEZONE_HDR_SIZE * 10];
- while (str[end] != '\0') {
- end++;
- }
- end--;
-
- while (start < end) {
- str[start] = str[start] ^ str[end];
- str[end] = str[start] ^ str[end];
- str[start] = str[start] ^ str[end];
-
- start++;
- end--;
- }
-}
-
-int get_timezone_offset(char *timezone) {
- (void)timezone;
-
- unsigned char hdr[TIMEZONE_HDR_SIZE + 1];
-
- int32_t magic;
+ int64_t magic;
unsigned char version;
__int128_t reserved;
- int32_t tzh_ttisutcnt;
- int32_t tzh_ttisstdcnt;
- int32_t tzh_leapcnt;
- int32_t tzh_timecnt;
- int32_t tzh_typecnt;
- int32_t tzh_charcnt;
+ uint32_t tzh_ttisutcnt;
+ uint32_t tzh_ttisstdcnt;
+ uint32_t tzh_leapcnt;
+ uint32_t tzh_timecnt;
+ uint32_t tzh_typecnt;
+ uint32_t tzh_charcnt;
int fd;
size_t bytes;
@@ -60,13 +39,14 @@ int get_timezone_offset(char *timezone) {
fd = open("/etc/localtime", O_RDONLY);
if (fd < 0) {
close(fd);
- return 0;
+ return nullptr;
}
bytes = read(fd, hdr, sizeof(hdr));
- if (bytes != sizeof(hdr)) {
- close(fd);
- return 0;
+ // TODO: Remove the number of bytes to check
+ if (bytes != 379) {
+ close(fd);
+ return nullptr;
}
size_t i;
@@ -80,49 +60,36 @@ int get_timezone_offset(char *timezone) {
tmp = (tmp << 8) | hdr[i];
}
reserved = tmp;
- tzh_ttisutcnt = (hdr[21] << 24) | (hdr[22] << 16) | (hdr[23] << 8) | hdr[24];
- tzh_ttisstdcnt = (hdr[25] << 24) | (hdr[26] << 16) | (hdr[27] << 8) | hdr[28];
- tzh_leapcnt = (hdr[29] << 24) | (hdr[30] << 16) | (hdr[31] << 8) | hdr[32];
- tzh_timecnt = (hdr[33] << 24) | (hdr[34] << 16) | (hdr[35] << 8) | hdr[36];
- tzh_typecnt = (hdr[37] << 24) | (hdr[38] << 16) | (hdr[39] << 8) | hdr[40];
- tzh_charcnt = (hdr[41] << 24) | (hdr[42] << 16) | (hdr[43] << 8) | hdr[44];
- (void)tzh_ttisutcnt;
- (void)tzh_ttisstdcnt;
- (void)tzh_leapcnt;
- (void)tzh_typecnt;
- (void)tzh_charcnt;
+ tzh_ttisutcnt = (hdr[20] << 24) | (hdr[21] << 16) | (hdr[22] << 8) | hdr[23];
+ tzh_ttisstdcnt = (hdr[24] << 24) | (hdr[25] << 16) | (hdr[26] << 8) | hdr[27];
+ tzh_leapcnt = (hdr[28] << 24) | (hdr[29] << 16) | (hdr[30] << 8) | hdr[31];
+ tzh_timecnt = (hdr[32] << 24) | (hdr[33] << 16) | (hdr[34] << 8) | hdr[35];
+ tzh_typecnt = (hdr[36] << 24) | (hdr[37] << 16) | (hdr[38] << 8) | hdr[39];
+ tzh_charcnt = (hdr[40] << 24) | (hdr[41] << 16) | (hdr[42] << 8) | hdr[43];
+
+ result.tzh_ttisutcnt = tzh_ttisutcnt;
+ result.tzh_ttisstdcnt = tzh_ttisstdcnt;
+ result.tzh_leapcnt = tzh_leapcnt;
+ result.tzh_timecnt = tzh_timecnt;
+ result.tzh_typecnt = tzh_typecnt;
+ result.tzh_charcnt = tzh_charcnt;
if (magic != 0x545A6966) {
- return 0;
+ return nullptr;
}
if (version != 0x32 && version != 0x33 && version != 0x34) {
- return 0;
+ return nullptr;
}
// according to `tzfile`, 15 bytes should be 0
if (reserved != 0) {
- return 0;
- }
-
- for (i = 0; i < (size_t)tzh_timecnt; i++) {
- uint8_t buf[4];
- bytes = read(fd, buf, 4);
- if (bytes != 4) {
- continue;
- }
-
- int32_t transition = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
- transition = ((transition & 0xFF000000) >> 24) |
- ((transition & 0x00FF0000) >> 8) |
- ((transition & 0x0000FF00) << 8) |
- ((transition & 0x000000FF) << 24);
- printf("transition %d: %d\n", i, transition);
+ return nullptr;
}
close(fd);
- return 0;
+ return &result;
}
} // namespace timezone
>From d0e66b7e2138ae24e893915ebd05e2b70af7e059 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 04:46:32 +0500
Subject: [PATCH 39/58] refactor: rename function since it returns tzset struct
---
libc/src/time/timezone.cpp | 2 +-
libc/src/time/timezone.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index d7cd6d9e22eb8a..edd133de304ddc 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -17,7 +17,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-tzset *get_timezone_offset(char *timezone) {
+tzset *get_tzset(char *timezone) {
static ttinfo ttinfo;
static tzset result;
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 180ad019fbcbe8..3dcac9f7159d34 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -35,7 +35,7 @@ typedef struct {
ttinfo *ttinfo;
} tzset;
-tzset *get_timezone_offset(char *timezone);
+tzset *get_tzset(char *timezone);
} // namespace timezone
} // namespace LIBC_NAMESPACE_DECL
>From 20bd0a53f5c9c7567f5cc252ee115b163efb995c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 05:10:20 +0500
Subject: [PATCH 40/58] update struct fields with additional fields and parse
timezone data
---
libc/src/time/timezone.cpp | 130 ++++++++++++++++++++++++++++++++++++-
libc/src/time/timezone.h | 10 ++-
2 files changed, 138 insertions(+), 2 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index edd133de304ddc..a42e75d51630ac 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -17,7 +17,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-tzset *get_tzset(char *timezone) {
+tzset *get_tzset() {
static ttinfo ttinfo;
static tzset result;
@@ -87,6 +87,134 @@ tzset *get_tzset(char *timezone) {
return nullptr;
}
+ int64_t product;
+
+ product = (tzh_timecnt * 5)
+ + (tzh_typecnt * 6)
+ + (tzh_leapcnt * 8)
+ + tzh_charcnt
+ + tzh_ttisstdcnt
+ + tzh_ttisutcnt
+ + TIMEZONE_HDR_SIZE;
+
+ int64_t tzh_timecnt_length;
+ int64_t tzh_typecnt_length;
+ int64_t tzh_leapcnt_length;
+ int64_t tzh_charcnt_length;
+ int64_t tzh_timecnt_end;
+ int64_t tzh_typecnt_end;
+ int64_t tzh_leapcnt_end;
+ int64_t tzh_charcnt_end;
+
+ tzh_timecnt_length = tzh_timecnt * 9;
+ tzh_typecnt_length = tzh_typecnt * 6;
+ tzh_leapcnt_length = tzh_leapcnt * 12;
+ tzh_charcnt_length = tzh_charcnt;
+ tzh_timecnt_end = TIMEZONE_HDR_SIZE + product + tzh_timecnt_length;
+ tzh_typecnt_end = tzh_timecnt_end + tzh_typecnt_length;
+ tzh_leapcnt_end = tzh_typecnt_end + tzh_leapcnt_length;
+ tzh_charcnt_end = tzh_leapcnt_end + tzh_charcnt_length;
+
+ size_t start;
+ size_t end;
+ size_t chunk;
+
+ start = TIMEZONE_HDR_SIZE + product;
+ end = (TIMEZONE_HDR_SIZE + product + (tzh_timecnt * 8));
+ chunk = (end - start) / 8;
+
+ int64_t tzh_timecnt_transitions[chunk + 1];
+ int64_t *ptr_tzh_timecnt_transitions;
+
+ ptr_tzh_timecnt_transitions = tzh_timecnt_transitions;
+ for (i = 0; i < chunk; ++i) {
+ *(ptr_tzh_timecnt_transitions + i) = ((int64_t)hdr[start + i * 8] << 56) |
+ ((int64_t)hdr[start + i * 8 + 1] << 48) |
+ ((int64_t)hdr[start + i * 8 + 2] << 40) |
+ ((int64_t)hdr[start + i * 8 + 3] << 32) |
+ ((int64_t)hdr[start + i * 8 + 4] << 24) |
+ ((int64_t)hdr[start + i * 8 + 5] << 16) |
+ ((int64_t)hdr[start + i * 8 + 6] << 8) |
+ (int64_t)hdr[start + i * 8 + 7];
+ }
+ result.tzh_timecnt_transitions = ptr_tzh_timecnt_transitions;
+
+ start = TIMEZONE_HDR_SIZE + product + tzh_timecnt * 8;
+ end = tzh_timecnt_end;
+
+ int64_t tzh_timecnt_indices[end - start];
+ int64_t *ptr_tzh_timecnt_indices;
+ size_t j;
+
+ ptr_tzh_timecnt_indices = tzh_timecnt_indices;
+ j = 0;
+ for (i = start; i < end; ++i) {
+ tzh_timecnt_indices[j] = hdr[i];
+ j += 1;
+ }
+ result.tzh_timecnt_indices = ptr_tzh_timecnt_indices;
+
+ unsigned char tz[tzh_charcnt_end - tzh_leapcnt_end];
+ unsigned char *ptr_tz;
+
+ ptr_tz = tz;
+ j = 0;
+ for (i = tzh_leapcnt_end; i < (size_t)tzh_charcnt_end + 1; ++i) {
+ if (i == (size_t)tzh_charcnt_end) {
+ tz[j] = '\0';
+ break;
+ }
+
+ if (hdr[i] == '\0') {
+ tz[j] = 0x3B;
+ j += 1;
+ continue;
+ }
+
+ tz[j] = hdr[i];
+
+ j += 1;
+ }
+ result.tz = ptr_tz;
+
+ int64_t offsets[6];
+ int64_t *ptr_offsets;
+ size_t index;
+
+ int64_t tt_utoff[6];
+ uint8_t tt_isdst[6];
+ uint8_t tt_desigidx[6];
+
+ int64_t *ptr_tt_utoff;
+ uint8_t *ptr_tt_isdst;
+ uint8_t *ptr_tt_desigidx;
+
+ ptr_offsets = offsets;
+ ptr_tt_utoff = tt_utoff;
+ ptr_tt_isdst = tt_isdst;
+ ptr_tt_desigidx = tt_desigidx;
+
+ index = 0;
+ for (size_t i = tzh_timecnt_end; i < (size_t)tzh_typecnt_end; i += 6) {
+ unsigned char *tmp;
+
+ tmp = &hdr[i];
+ *(ptr_offsets + index) = tmp[5];
+
+ *(ptr_tt_utoff + index) = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+ *(ptr_tt_isdst + index) = tmp[4];
+ *(ptr_tt_desigidx + index) = (uint8_t)index;
+
+ index += 1;
+ }
+
+ ttinfo.offsets = ptr_offsets;
+ ttinfo.tt_utoff = ptr_tt_utoff;
+ ttinfo.tt_isdst = ptr_tt_isdst;
+ ttinfo.tt_desigidx = ptr_tt_desigidx;
+
+ result.ttinfo = &ttinfo;
+
close(fd);
return &result;
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 3dcac9f7159d34..21a9591e5e94de 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -23,6 +23,9 @@ typedef struct {
int64_t *tt_utoff;
uint8_t *tt_isdst;
uint8_t *tt_desigidx;
+
+ // additional fields
+ int64_t *offsets;
} ttinfo;
typedef struct {
@@ -33,9 +36,14 @@ typedef struct {
uint64_t tzh_typecnt;
uint64_t tzh_charcnt;
ttinfo *ttinfo;
+
+ // additional fields
+ int64_t *tzh_timecnt_transitions;
+ int64_t *tzh_timecnt_indices;
+ unsigned char *tz;
} tzset;
-tzset *get_tzset(char *timezone);
+tzset *get_tzset();
} // namespace timezone
} // namespace LIBC_NAMESPACE_DECL
>From dd99fe3cc3c3b0eb837116d2d8e4bff0566cedd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 05:14:00 +0500
Subject: [PATCH 41/58] remove last char in timezone text
---
libc/src/time/timezone.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index a42e75d51630ac..a8ebaca7def95f 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -160,7 +160,7 @@ tzset *get_tzset() {
ptr_tz = tz;
j = 0;
for (i = tzh_leapcnt_end; i < (size_t)tzh_charcnt_end + 1; ++i) {
- if (i == (size_t)tzh_charcnt_end) {
+ if (i == (size_t)tzh_charcnt_end - 1) {
tz[j] = '\0';
break;
}
>From 08353c3a93043733d98a035810b5f61d2b519296 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 05:25:31 +0500
Subject: [PATCH 42/58] use `open` instead of `fopen`
---
libc/src/time/timezone.cpp | 9 +--------
libc/src/time/timezone.h | 2 +-
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index a8ebaca7def95f..ab85cd6087a790 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -17,7 +17,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-tzset *get_tzset() {
+tzset *get_tzset(int fd) {
static ttinfo ttinfo;
static tzset result;
@@ -33,15 +33,8 @@ tzset *get_tzset() {
uint32_t tzh_typecnt;
uint32_t tzh_charcnt;
- int fd;
size_t bytes;
- fd = open("/etc/localtime", O_RDONLY);
- if (fd < 0) {
- close(fd);
- return nullptr;
- }
-
bytes = read(fd, hdr, sizeof(hdr));
// TODO: Remove the number of bytes to check
if (bytes != 379) {
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 21a9591e5e94de..0659b92a15b4cb 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -43,7 +43,7 @@ typedef struct {
unsigned char *tz;
} tzset;
-tzset *get_tzset();
+tzset *get_tzset(int fd);
} // namespace timezone
} // namespace LIBC_NAMESPACE_DECL
>From 025715c1dd571a92ebe0c8fa2d8d389436a46e57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 11:27:53 +0500
Subject: [PATCH 43/58] use `static` and add number of transitions times for
timezone
---
libc/src/time/timezone.cpp | 9 +++++----
libc/src/time/timezone.h | 1 +
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index ab85cd6087a790..04d58debe33d2b 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -18,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace timezone {
tzset *get_tzset(int fd) {
- static ttinfo ttinfo;
+ ttinfo ttinfo;
static tzset result;
unsigned char hdr[TIMEZONE_HDR_SIZE * 10];
@@ -131,6 +131,7 @@ tzset *get_tzset(int fd) {
(int64_t)hdr[start + i * 8 + 7];
}
result.tzh_timecnt_transitions = ptr_tzh_timecnt_transitions;
+ result.tzh_timecnt_number_transitions = chunk + 1;
start = TIMEZONE_HDR_SIZE + product + tzh_timecnt * 8;
end = tzh_timecnt_end;
@@ -174,9 +175,9 @@ tzset *get_tzset(int fd) {
int64_t *ptr_offsets;
size_t index;
- int64_t tt_utoff[6];
- uint8_t tt_isdst[6];
- uint8_t tt_desigidx[6];
+ static int64_t tt_utoff[6];
+ static uint8_t tt_isdst[6];
+ static uint8_t tt_desigidx[6];
int64_t *ptr_tt_utoff;
uint8_t *ptr_tt_isdst;
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 0659b92a15b4cb..48d87d90470b5f 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -40,6 +40,7 @@ typedef struct {
// additional fields
int64_t *tzh_timecnt_transitions;
int64_t *tzh_timecnt_indices;
+ size_t tzh_timecnt_number_transitions;
unsigned char *tz;
} tzset;
>From b997ea4b2d3f4be8603c5e8983575b4a78704e22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Tue, 24 Dec 2024 11:33:49 +0500
Subject: [PATCH 44/58] format code with clang-format
---
libc/src/time/timezone.cpp | 73 ++++++++++++++++++--------------------
libc/src/time/timezone.h | 36 +++++++++----------
2 files changed, 53 insertions(+), 56 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 04d58debe33d2b..b8f2d9143ca601 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include <fcntl.h>
-#include <unistd.h>
#include <stdio.h> // TODO: Remove all printf functions
#include <sys/types.h>
+#include <unistd.h>
#include "src/__support/common.h"
#include "src/time/timezone.h"
@@ -38,8 +38,8 @@ tzset *get_tzset(int fd) {
bytes = read(fd, hdr, sizeof(hdr));
// TODO: Remove the number of bytes to check
if (bytes != 379) {
- close(fd);
- return nullptr;
+ close(fd);
+ return nullptr;
}
size_t i;
@@ -82,13 +82,8 @@ tzset *get_tzset(int fd) {
int64_t product;
- product = (tzh_timecnt * 5)
- + (tzh_typecnt * 6)
- + (tzh_leapcnt * 8)
- + tzh_charcnt
- + tzh_ttisstdcnt
- + tzh_ttisutcnt
- + TIMEZONE_HDR_SIZE;
+ product = (tzh_timecnt * 5) + (tzh_typecnt * 6) + (tzh_leapcnt * 8) +
+ tzh_charcnt + tzh_ttisstdcnt + tzh_ttisutcnt + TIMEZONE_HDR_SIZE;
int64_t tzh_timecnt_length;
int64_t tzh_typecnt_length;
@@ -121,14 +116,15 @@ tzset *get_tzset(int fd) {
ptr_tzh_timecnt_transitions = tzh_timecnt_transitions;
for (i = 0; i < chunk; ++i) {
- *(ptr_tzh_timecnt_transitions + i) = ((int64_t)hdr[start + i * 8] << 56) |
- ((int64_t)hdr[start + i * 8 + 1] << 48) |
- ((int64_t)hdr[start + i * 8 + 2] << 40) |
- ((int64_t)hdr[start + i * 8 + 3] << 32) |
- ((int64_t)hdr[start + i * 8 + 4] << 24) |
- ((int64_t)hdr[start + i * 8 + 5] << 16) |
- ((int64_t)hdr[start + i * 8 + 6] << 8) |
- (int64_t)hdr[start + i * 8 + 7];
+ *(ptr_tzh_timecnt_transitions + i) =
+ ((int64_t)hdr[start + i * 8] << 56) |
+ ((int64_t)hdr[start + i * 8 + 1] << 48) |
+ ((int64_t)hdr[start + i * 8 + 2] << 40) |
+ ((int64_t)hdr[start + i * 8 + 3] << 32) |
+ ((int64_t)hdr[start + i * 8 + 4] << 24) |
+ ((int64_t)hdr[start + i * 8 + 5] << 16) |
+ ((int64_t)hdr[start + i * 8 + 6] << 8) |
+ (int64_t)hdr[start + i * 8 + 7];
}
result.tzh_timecnt_transitions = ptr_tzh_timecnt_transitions;
result.tzh_timecnt_number_transitions = chunk + 1;
@@ -143,8 +139,8 @@ tzset *get_tzset(int fd) {
ptr_tzh_timecnt_indices = tzh_timecnt_indices;
j = 0;
for (i = start; i < end; ++i) {
- tzh_timecnt_indices[j] = hdr[i];
- j += 1;
+ tzh_timecnt_indices[j] = hdr[i];
+ j += 1;
}
result.tzh_timecnt_indices = ptr_tzh_timecnt_indices;
@@ -154,20 +150,20 @@ tzset *get_tzset(int fd) {
ptr_tz = tz;
j = 0;
for (i = tzh_leapcnt_end; i < (size_t)tzh_charcnt_end + 1; ++i) {
- if (i == (size_t)tzh_charcnt_end - 1) {
- tz[j] = '\0';
- break;
- }
+ if (i == (size_t)tzh_charcnt_end - 1) {
+ tz[j] = '\0';
+ break;
+ }
- if (hdr[i] == '\0') {
- tz[j] = 0x3B;
- j += 1;
- continue;
- }
+ if (hdr[i] == '\0') {
+ tz[j] = 0x3B;
+ j += 1;
+ continue;
+ }
- tz[j] = hdr[i];
+ tz[j] = hdr[i];
- j += 1;
+ j += 1;
}
result.tz = ptr_tz;
@@ -190,16 +186,17 @@ tzset *get_tzset(int fd) {
index = 0;
for (size_t i = tzh_timecnt_end; i < (size_t)tzh_typecnt_end; i += 6) {
- unsigned char *tmp;
+ unsigned char *tmp;
- tmp = &hdr[i];
- *(ptr_offsets + index) = tmp[5];
+ tmp = &hdr[i];
+ *(ptr_offsets + index) = tmp[5];
- *(ptr_tt_utoff + index) = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
- *(ptr_tt_isdst + index) = tmp[4];
- *(ptr_tt_desigidx + index) = (uint8_t)index;
+ *(ptr_tt_utoff + index) =
+ tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+ *(ptr_tt_isdst + index) = tmp[4];
+ *(ptr_tt_desigidx + index) = (uint8_t)index;
- index += 1;
+ index += 1;
}
ttinfo.offsets = ptr_offsets;
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 48d87d90470b5f..2e066bd7167eb9 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -20,28 +20,28 @@ namespace timezone {
#define TIMEZONE_HDR_SIZE 44
typedef struct {
- int64_t *tt_utoff;
- uint8_t *tt_isdst;
- uint8_t *tt_desigidx;
+ int64_t *tt_utoff;
+ uint8_t *tt_isdst;
+ uint8_t *tt_desigidx;
- // additional fields
- int64_t *offsets;
+ // additional fields
+ int64_t *offsets;
} ttinfo;
typedef struct {
- uint64_t tzh_ttisutcnt;
- uint64_t tzh_ttisstdcnt;
- uint64_t tzh_leapcnt;
- uint64_t tzh_timecnt;
- uint64_t tzh_typecnt;
- uint64_t tzh_charcnt;
- ttinfo *ttinfo;
-
- // additional fields
- int64_t *tzh_timecnt_transitions;
- int64_t *tzh_timecnt_indices;
- size_t tzh_timecnt_number_transitions;
- unsigned char *tz;
+ uint64_t tzh_ttisutcnt;
+ uint64_t tzh_ttisstdcnt;
+ uint64_t tzh_leapcnt;
+ uint64_t tzh_timecnt;
+ uint64_t tzh_typecnt;
+ uint64_t tzh_charcnt;
+ ttinfo *ttinfo;
+
+ // additional fields
+ int64_t *tzh_timecnt_transitions;
+ int64_t *tzh_timecnt_indices;
+ size_t tzh_timecnt_number_transitions;
+ unsigned char *tz;
} tzset;
tzset *get_tzset(int fd);
>From a433d060e5d3c95a0e33f57c1c32f273ae22d9c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Wed, 25 Dec 2024 21:32:07 +0500
Subject: [PATCH 45/58] refactor: parse of tzset file
---
libc/src/time/timezone.cpp | 54 +++++++++++++++++++++++---------------
libc/src/time/timezone.h | 4 +--
2 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index b8f2d9143ca601..786767fd69d1e0 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -17,12 +17,10 @@
namespace LIBC_NAMESPACE_DECL {
namespace timezone {
-tzset *get_tzset(int fd) {
+tzset *get_tzset(int fd, size_t filesize) {
ttinfo ttinfo;
static tzset result;
- unsigned char hdr[TIMEZONE_HDR_SIZE * 10];
-
int64_t magic;
unsigned char version;
__int128_t reserved;
@@ -33,20 +31,34 @@ tzset *get_tzset(int fd) {
uint32_t tzh_typecnt;
uint32_t tzh_charcnt;
- size_t bytes;
+ size_t i;
+ __uint128_t tmp;
+
+ unsigned char hdr[filesize];
+
+ size_t t = 0;
+ while (t < sizeof(hdr)) {
+ size_t r = read(fd, hdr + t, sizeof(hdr) - t);
+
+ if (r < 0) {
+ close(fd);
+ return nullptr;
+ }
+
+ if (r == 0) {
+ break;
+ }
- bytes = read(fd, hdr, sizeof(hdr));
- // TODO: Remove the number of bytes to check
- if (bytes != 379) {
+ t += r;
+ }
+
+ if (t != sizeof(hdr)) {
close(fd);
return nullptr;
}
- size_t i;
- __uint128_t tmp;
-
- // these locations in timezone files are defined in documentation
- // for `tzfile`
+ // these locations are defined in documentation
+ // for `tzfile` and should be 44 bytes
magic = (hdr[0] << 24) | (hdr[1] << 16) | (hdr[2] << 8) | hdr[3];
version = hdr[4];
for (i = 5; i < 21; i++) {
@@ -111,7 +123,7 @@ tzset *get_tzset(int fd) {
end = (TIMEZONE_HDR_SIZE + product + (tzh_timecnt * 8));
chunk = (end - start) / 8;
- int64_t tzh_timecnt_transitions[chunk + 1];
+ int64_t tzh_timecnt_transitions[chunk];
int64_t *ptr_tzh_timecnt_transitions;
ptr_tzh_timecnt_transitions = tzh_timecnt_transitions;
@@ -144,12 +156,13 @@ tzset *get_tzset(int fd) {
}
result.tzh_timecnt_indices = ptr_tzh_timecnt_indices;
- unsigned char tz[tzh_charcnt_end - tzh_leapcnt_end];
- unsigned char *ptr_tz;
+ int64_t tz[tzh_charcnt_end - tzh_leapcnt_end - 1];
+ int64_t *ptr_tz;
ptr_tz = tz;
+ result.tz = ptr_tz;
j = 0;
- for (i = tzh_leapcnt_end; i < (size_t)tzh_charcnt_end + 1; ++i) {
+ for (i = tzh_leapcnt_end; i < (size_t)tzh_charcnt_end - 1; ++i) {
if (i == (size_t)tzh_charcnt_end - 1) {
tz[j] = '\0';
break;
@@ -165,15 +178,14 @@ tzset *get_tzset(int fd) {
j += 1;
}
- result.tz = ptr_tz;
- int64_t offsets[6];
+ int64_t offsets[8];
int64_t *ptr_offsets;
size_t index;
- static int64_t tt_utoff[6];
- static uint8_t tt_isdst[6];
- static uint8_t tt_desigidx[6];
+ static int64_t tt_utoff[2];
+ static uint8_t tt_isdst[1];
+ static uint8_t tt_desigidx[1];
int64_t *ptr_tt_utoff;
uint8_t *ptr_tt_isdst;
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 2e066bd7167eb9..2c1ac96085c34b 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -41,10 +41,10 @@ typedef struct {
int64_t *tzh_timecnt_transitions;
int64_t *tzh_timecnt_indices;
size_t tzh_timecnt_number_transitions;
- unsigned char *tz;
+ int64_t *tz;
} tzset;
-tzset *get_tzset(int fd);
+tzset *get_tzset(int fd, size_t filesize);
} // namespace timezone
} // namespace LIBC_NAMESPACE_DECL
>From f71a666469340004b5d4b764fed53863b8e5cc10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Wed, 25 Dec 2024 22:31:18 +0500
Subject: [PATCH 46/58] refactor: parse of offsets
---
libc/src/time/timezone.cpp | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 786767fd69d1e0..a5c0bfe5c760db 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -179,17 +179,19 @@ tzset *get_tzset(int fd, size_t filesize) {
j += 1;
}
- int64_t offsets[8];
+ chunk = ((tzh_typecnt_end - tzh_timecnt_end) / 6) - 1;
+
+ int64_t offsets[8 * chunk];
int64_t *ptr_offsets;
size_t index;
- static int64_t tt_utoff[2];
- static uint8_t tt_isdst[1];
- static uint8_t tt_desigidx[1];
+ int64_t tt_utoff[2 * chunk];
+ unsigned char tt_isdst[chunk];
+ unsigned char tt_desigidx[chunk];
int64_t *ptr_tt_utoff;
- uint8_t *ptr_tt_isdst;
- uint8_t *ptr_tt_desigidx;
+ unsigned char *ptr_tt_isdst;
+ unsigned char *ptr_tt_desigidx;
ptr_offsets = offsets;
ptr_tt_utoff = tt_utoff;
@@ -202,11 +204,12 @@ tzset *get_tzset(int fd, size_t filesize) {
tmp = &hdr[i];
*(ptr_offsets + index) = tmp[5];
-
*(ptr_tt_utoff + index) =
tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
- *(ptr_tt_isdst + index) = tmp[4];
- *(ptr_tt_desigidx + index) = (uint8_t)index;
+ *(ptr_tt_utoff + index) =
+ tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
+ *(tt_isdst + index) = tmp[4];
+ *(ptr_tt_desigidx + index) = (unsigned char)index;
index += 1;
}
>From f7af62d71f9b7b4082a0349acbf6be3d5a012b41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 06:13:03 +0500
Subject: [PATCH 47/58] refactor: parse of offsets
---
libc/src/time/timezone.cpp | 57 ++++++++++++++------------------------
libc/src/time/timezone.h | 9 +++---
2 files changed, 26 insertions(+), 40 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index a5c0bfe5c760db..5c5473e0fdd70e 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -18,7 +18,6 @@ namespace LIBC_NAMESPACE_DECL {
namespace timezone {
tzset *get_tzset(int fd, size_t filesize) {
- ttinfo ttinfo;
static tzset result;
int64_t magic;
@@ -179,47 +178,33 @@ tzset *get_tzset(int fd, size_t filesize) {
j += 1;
}
- chunk = ((tzh_typecnt_end - tzh_timecnt_end) / 6) - 1;
+ chunk = ((tzh_typecnt_end - tzh_timecnt_end) / 6);
+ ttinfo ttinfo[chunk];
- int64_t offsets[8 * chunk];
- int64_t *ptr_offsets;
- size_t index;
-
- int64_t tt_utoff[2 * chunk];
- unsigned char tt_isdst[chunk];
- unsigned char tt_desigidx[chunk];
+ size_t index = 0;
+ for (size_t i = tzh_timecnt_end; i < (size_t)tzh_typecnt_end; i += 6) {
+ int32_t tt_utoff = ((int32_t)hdr[i] << 24) | ((int32_t)hdr[i + 1] << 16) |
+ ((int32_t)hdr[i + 2] << 8) | (int32_t)hdr[i + 3];
+ uint8_t tt_isdst = hdr[i + 4];
+ size_t tt_desigidx = hdr[i + 5];
+
+ size_t k = 0;
+ for (size_t j = 0; j < tt_desigidx; j++) {
+ if (tz[j] == ';') {
+ k++;
+ }
+ }
- int64_t *ptr_tt_utoff;
- unsigned char *ptr_tt_isdst;
- unsigned char *ptr_tt_desigidx;
+ ttinfo[index].tt_utoff = tt_utoff;
+ ttinfo[index].tt_isdst = tt_isdst;
+ ttinfo[index].tt_desigidx = (int8_t)k;
- ptr_offsets = offsets;
- ptr_tt_utoff = tt_utoff;
- ptr_tt_isdst = tt_isdst;
- ptr_tt_desigidx = tt_desigidx;
+ ttinfo[index].size = &chunk;
- index = 0;
- for (size_t i = tzh_timecnt_end; i < (size_t)tzh_typecnt_end; i += 6) {
- unsigned char *tmp;
-
- tmp = &hdr[i];
- *(ptr_offsets + index) = tmp[5];
- *(ptr_tt_utoff + index) =
- tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
- *(ptr_tt_utoff + index) =
- tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
- *(tt_isdst + index) = tmp[4];
- *(ptr_tt_desigidx + index) = (unsigned char)index;
-
- index += 1;
+ index++;
}
- ttinfo.offsets = ptr_offsets;
- ttinfo.tt_utoff = ptr_tt_utoff;
- ttinfo.tt_isdst = ptr_tt_isdst;
- ttinfo.tt_desigidx = ptr_tt_desigidx;
-
- result.ttinfo = &ttinfo;
+ result.ttinfo = ttinfo;
close(fd);
diff --git a/libc/src/time/timezone.h b/libc/src/time/timezone.h
index 2c1ac96085c34b..3bd386fcdb13ac 100644
--- a/libc/src/time/timezone.h
+++ b/libc/src/time/timezone.h
@@ -20,12 +20,13 @@ namespace timezone {
#define TIMEZONE_HDR_SIZE 44
typedef struct {
- int64_t *tt_utoff;
- uint8_t *tt_isdst;
- uint8_t *tt_desigidx;
+ int64_t tt_utoff;
+ uint8_t tt_isdst;
+ uint8_t tt_desigidx;
// additional fields
- int64_t *offsets;
+ int64_t offsets;
+ size_t *size;
} ttinfo;
typedef struct {
>From 6235ca083da83efe79cd04ff16eabf3ad9f15b2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 06:50:53 +0500
Subject: [PATCH 48/58] use timezone implementation for localtime function
implementation
---
libc/src/time/time_utils.cpp | 112 ++++++++++++++++++--------
libc/src/time/time_utils.h | 3 +-
libc/test/src/time/localtime_test.cpp | 22 ++---
3 files changed, 92 insertions(+), 45 deletions(-)
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 53514cd968354c..b5c540cc71c25e 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -12,9 +12,8 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/time/timezone.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
@@ -32,14 +31,14 @@ static int64_t computeRemainingYears(int64_t daysPerYears,
}
volatile int file_usage = 0;
+volatile int fd = -1;
-void release_file(FILE *fp, char *timezone) {
- (void)timezone;
+void release_file(int fd) {
file_usage = 0;
- fclose(fp);
+ close(fd);
}
-void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
+void acquire_file(char *filename) {
while (1) {
if (file_usage == 0) {
file_usage = 1;
@@ -47,11 +46,28 @@ void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
}
}
- if (fgets(timezone, (int)timezone_size, fp) == NULL) {
- release_file(fp, timezone);
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ release_file(fd);
}
}
+char *get_env_var(const char *var_name) {
+ for (char **env = environ; *env != NULL; ++env) {
+ char *env_var = *env;
+
+ int i = 0;
+ while (var_name[i] != '\0' && env_var[i] == var_name[i]) {
+ i++;
+ }
+
+ if (var_name[i] == '\0' && env_var[i] == '=') {
+ return env_var + i + 1;
+ }
+ }
+
+ return NULL;
+}
+
// First, divide "total_seconds" by the number of seconds in a day to get the
// number of days since Jan 1 1970. The remainder will be used to calculate the
// number of Hours, Minutes and Seconds.
@@ -155,27 +171,63 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
if (years > INT_MAX || years < INT_MIN)
return time_utils::out_of_range();
- char timezone[TimeConstants::TIMEZONE_SIZE];
- char *env_tz = getenv("TZ");
- FILE *fp = NULL;
- if (env_tz) {
- strncpy(timezone, env_tz, sizeof(timezone));
- timezone[sizeof(timezone) - 1] = '\0';
+ char *tz_filename = get_env_var("TZ");
+ if (tz_filename[0] == '\0') {
+ char localtime[15] = "/etc/localtime";
+ size_t i = 0;
+ while (localtime[i] != '\0') {
+ tz_filename[i] = localtime[i];
+ i++;
+ }
} else {
- fp = fopen("/etc/localtime", "rb");
- if (fp == NULL) {
- return time_utils::out_of_range();
+ char tmp[64];
+ char prefix[21] = "/usr/share/zoneinfo/";
+ size_t i = 0;
+ while (prefix[i] != '\0') {
+ tmp[i] = prefix[i];
+ i++;
+ }
+
+ i = 0;
+ while (tz_filename[i] != '\0') {
+ tmp[i + 20] = tz_filename[i];
+ i++;
+ }
+
+ tz_filename = tmp;
+ while (tz_filename[i] != '\0') {
+ if (tz_filename[i] == (char)0xFFFFFFAA) {
+ tz_filename[i] = '\0';
+ }
+ i++;
}
+ }
+
+ acquire_file(tz_filename);
- acquire_file(fp, timezone, TimeConstants::TIMEZONE_SIZE);
+ size_t filesize;
+ int offset;
+ int dst;
+
+ offset = 0;
+ dst = is_dst(tm);
+ filesize = (size_t)lseek(fd, 0, SEEK_END);
+ if (filesize < 0) {
+ close(fd);
+ return 0;
}
+ lseek(fd, 0, 0);
- if (fp != NULL && file_usage == 0) {
- release_file(fp, timezone);
+ timezone::tzset *ptr_tzset = timezone::get_tzset(fd, filesize);
+ if (ptr_tzset == nullptr) {
return time_utils::out_of_range();
}
- int offset = timezone::get_timezone_offset(timezone);
+ for (size_t i = 0; i < *ptr_tzset->ttinfo->size; i++) {
+ if (dst == ptr_tzset->ttinfo[i].tt_isdst) {
+ offset = (int)ptr_tzset->ttinfo[i].tt_utoff / 3600;
+ }
+ }
// All the data (years, month and remaining days) was calculated from
// March, 2000. Thus adjust the data to be from January, 1900.
@@ -193,23 +245,17 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
tm->tm_sec =
static_cast<int>(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
- set_dst(tm);
- if (tm->tm_isdst > 0 && offset != 0) {
- tm->tm_hour += 1;
- }
-
- if (offset != 0) {
- tm->tm_hour += offset;
- }
+ tm->tm_hour += offset;
+ tm->tm_isdst = dst;
if (file_usage == 1) {
- release_file(fp, timezone);
+ release_file(fd);
}
return 0;
}
-void set_dst(struct tm *tm) {
+unsigned char is_dst(struct tm *tm) {
int dst;
int sunday;
@@ -226,7 +272,7 @@ void set_dst(struct tm *tm) {
dst = sunday <= 0;
}
- tm->tm_isdst = dst;
+ return (unsigned char)dst;
}
} // namespace time_utils
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index cad5d8b583b5f1..ef7f6d2a14dcd0 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -86,7 +86,8 @@ struct TimeConstants {
// Update the "tm" structure's year, month, etc. members from seconds.
// "total_seconds" is the number of seconds since January 1st, 1970.
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
-extern void set_dst(struct tm *tm);
+extern unsigned char is_dst(struct tm *tm);
+extern char *get_env_var(const char *var_name);
// TODO(michaelrj): move these functions to use ErrorOr instead of setting
// errno. They always accompany a specific return value so we only need the one
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index 86e15d8e7dcf15..d404516b53d44d 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -27,7 +27,7 @@ void set_env_var(const char *env) {
}
TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
- set_env_var("TZ=Europe/Berlin");
+ set_env_var("TZ=Europe/Stockholm");
const time_t t_ptr = 0;
struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
@@ -42,7 +42,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
ASSERT_EQ(0, result->tm_isdst);
}
-/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
+TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
set_env_var("TZ=Europe/Berlin");
time_t t_ptr = 2147483647;
@@ -58,7 +58,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
ASSERT_EQ(0, result->tm_isdst);
}
-TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
+/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
set_env_var("TZ=Europe/Berlin");
time_t t_ptr = 1627225465;
@@ -72,10 +72,10 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestamp32IntDst) {
ASSERT_EQ(0, result->tm_wday);
ASSERT_EQ(205, result->tm_yday);
ASSERT_EQ(1, result->tm_isdst);
-}
+}*/
-TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaPst) {
- set_env_var("TZ=America/San_Francisco");
+/*TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaPst) {
+ set_env_var("TZ=America/Los_Angeles");
time_t t_ptr = 1627225465;
struct tm *result = LIBC_NAMESPACE::localtime(&t_ptr);
@@ -88,9 +88,9 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaPst) {
ASSERT_EQ(0, result->tm_wday);
ASSERT_EQ(205, result->tm_yday);
ASSERT_EQ(1, result->tm_isdst);
-}
+}*/
-TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaEst) {
+/*TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaEst) {
set_env_var("TZ=America/New_York");
time_t t_ptr = 1627225465;
@@ -104,7 +104,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUsaEst) {
ASSERT_EQ(0, result->tm_wday);
ASSERT_EQ(205, result->tm_yday);
ASSERT_EQ(1, result->tm_isdst);
-}
+}*/
TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUTC) {
set_env_var("TZ=UTC");
@@ -119,7 +119,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableUTC) {
ASSERT_EQ(25, result->tm_sec);
ASSERT_EQ(0, result->tm_wday);
ASSERT_EQ(205, result->tm_yday);
- ASSERT_EQ(1, result->tm_isdst);
+ ASSERT_EQ(0, result->tm_isdst);
}
TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableGMT) {
@@ -154,7 +154,7 @@ TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeBerlin) {
ASSERT_EQ(1, result->tm_isdst);
}
-TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeMoscow) {
+/*TEST(LlvmLibcLocaltime, ValidUnixTimestampTzEnvironmentVariableEuropeMoscow) {
set_env_var("TZ=Europe/Moscow");
time_t t_ptr = 1627225465;
>From 4cc137e4479dc420b8dd29427fdad8daa0081095 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 06:54:36 +0500
Subject: [PATCH 49/58] format code with clang-format
---
libc/src/time/timezone.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/libc/src/time/timezone.cpp b/libc/src/time/timezone.cpp
index 5c5473e0fdd70e..75c9e44d192a7c 100644
--- a/libc/src/time/timezone.cpp
+++ b/libc/src/time/timezone.cpp
@@ -37,18 +37,18 @@ tzset *get_tzset(int fd, size_t filesize) {
size_t t = 0;
while (t < sizeof(hdr)) {
- size_t r = read(fd, hdr + t, sizeof(hdr) - t);
+ size_t r = read(fd, hdr + t, sizeof(hdr) - t);
- if (r < 0) {
- close(fd);
- return nullptr;
- }
+ if (r < 0) {
+ close(fd);
+ return nullptr;
+ }
- if (r == 0) {
- break;
- }
+ if (r == 0) {
+ break;
+ }
- t += r;
+ t += r;
}
if (t != sizeof(hdr)) {
>From 8a039601fcb1cc7785d657820f6354aa0fe2377f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 07:33:02 +0500
Subject: [PATCH 50/58] add header file for time_utils in asctime_test
---
libc/test/src/time/asctime_test.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/test/src/time/asctime_test.cpp b/libc/test/src/time/asctime_test.cpp
index 169a7463a3037d..0e985363dda76a 100644
--- a/libc/test/src/time/asctime_test.cpp
+++ b/libc/test/src/time/asctime_test.cpp
@@ -8,6 +8,7 @@
#include "src/errno/libc_errno.h"
#include "src/time/asctime.h"
+#include "src/time/time_utils.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
>From 35a86c969da1e06d91f58685dd75e0e2139c9d07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 08:24:58 +0500
Subject: [PATCH 51/58] fix function name for asctime
---
libc/test/src/time/asctime_test.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/libc/test/src/time/asctime_test.cpp b/libc/test/src/time/asctime_test.cpp
index 0e985363dda76a..5f041520a31aed 100644
--- a/libc/test/src/time/asctime_test.cpp
+++ b/libc/test/src/time/asctime_test.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "src/errno/libc_errno.h"
-#include "src/time/asctime.h"
#include "src/time/time_utils.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
@@ -17,12 +16,12 @@ static inline char *call_asctime(struct tm *tm_data, int year, int month,
int yday) {
LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
tm_data, year, month, mday, hour, min, sec, wday, yday);
- return LIBC_NAMESPACE::asctime(tm_data);
+ return asctime(tm_data);
}
TEST(LlvmLibcAsctime, Nullptr) {
char *result;
- result = LIBC_NAMESPACE::asctime(nullptr);
+ result = asctime(nullptr);
ASSERT_ERRNO_EQ(EINVAL);
ASSERT_STREQ(nullptr, result);
}
>From b96b43124e2a72230bdd4f194c92343ace1bd94d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 09:27:45 +0500
Subject: [PATCH 52/58] fix: add `get_tzset` function to time_utils header file
---
libc/src/time/time_utils.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index ef7f6d2a14dcd0..8ce574e0f7cc55 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -88,6 +88,7 @@ struct TimeConstants {
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
extern unsigned char is_dst(struct tm *tm);
extern char *get_env_var(const char *var_name);
+extern tzset *get_tzset(int fd, size_t filesize);
// TODO(michaelrj): move these functions to use ErrorOr instead of setting
// errno. They always accompany a specific return value so we only need the one
>From b0ad30a1197ce221b7197a6999fdec0d26967f47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 09:41:02 +0500
Subject: [PATCH 53/58] fix: add timezone header file to time_utils header file
---
libc/src/time/time_utils.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 8ce574e0f7cc55..7c0cffe80abc8a 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -16,6 +16,7 @@
#include "src/__support/macros/config.h"
#include "src/errno/libc_errno.h"
#include "src/time/mktime.h"
+#include "src/time/timezone.h"
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
>From 7b0d99464ca66876c633c18f9ad92db570da4324 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 09:46:25 +0500
Subject: [PATCH 54/58] fix: tzet function in time_utils header file
---
libc/src/time/time_utils.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 7c0cffe80abc8a..7aad91a6b6721d 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -89,7 +89,7 @@ struct TimeConstants {
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
extern unsigned char is_dst(struct tm *tm);
extern char *get_env_var(const char *var_name);
-extern tzset *get_tzset(int fd, size_t filesize);
+extern timezone::tzset *get_tzset(int fd, size_t filesize);
// TODO(michaelrj): move these functions to use ErrorOr instead of setting
// errno. They always accompany a specific return value so we only need the one
>From d186f2f7d10e8ea35c7431d078a70a4d49105bc0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 09:55:26 +0500
Subject: [PATCH 55/58] fix: add timezone header file to tests
---
libc/test/src/time/asctime_r_test.cpp | 1 +
libc/test/src/time/asctime_test.cpp | 1 +
libc/test/src/time/ctime_r_test.cpp | 1 +
libc/test/src/time/ctime_test.cpp | 1 +
libc/test/src/time/localtime_r_test.cpp | 1 +
libc/test/src/time/localtime_test.cpp | 2 +-
6 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libc/test/src/time/asctime_r_test.cpp b/libc/test/src/time/asctime_r_test.cpp
index f3aadbb39de4d0..2c87094165d8c5 100644
--- a/libc/test/src/time/asctime_r_test.cpp
+++ b/libc/test/src/time/asctime_r_test.cpp
@@ -9,6 +9,7 @@
#include "src/errno/libc_errno.h"
#include "src/time/asctime_r.h"
#include "src/time/time_utils.h"
+#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
diff --git a/libc/test/src/time/asctime_test.cpp b/libc/test/src/time/asctime_test.cpp
index 5f041520a31aed..7e5ea73418eb5c 100644
--- a/libc/test/src/time/asctime_test.cpp
+++ b/libc/test/src/time/asctime_test.cpp
@@ -8,6 +8,7 @@
#include "src/errno/libc_errno.h"
#include "src/time/time_utils.h"
+#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index 5ca4b5b1ea228d..5e92efca1d6689 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -9,6 +9,7 @@
#include "src/errno/libc_errno.h"
#include "src/time/ctime_r.h"
#include "src/time/time_utils.h"
+#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 554b72d23fd4de..1a7dc869bbdc3c 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -8,6 +8,7 @@
#include "src/errno/libc_errno.h"
#include "src/time/ctime.h"
+#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 2205c59ab7e527..610ef134d39553 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -8,6 +8,7 @@
#include "src/time/localtime_r.h"
#include "src/time/time_utils.h"
+#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
#include <string.h>
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index d404516b53d44d..6a7e7a9f6b1628 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "src/time/localtime.h"
+#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
-
#include <string.h>
extern char **environ;
>From 95772beabaab94af87b7034238672a62541e3d43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 10:05:18 +0500
Subject: [PATCH 56/58] fix: add header file for size_t
---
libc/test/src/time/asctime_r_test.cpp | 1 +
libc/test/src/time/asctime_test.cpp | 1 +
libc/test/src/time/ctime_r_test.cpp | 1 +
libc/test/src/time/ctime_test.cpp | 1 +
libc/test/src/time/localtime_r_test.cpp | 1 +
libc/test/src/time/localtime_test.cpp | 1 +
6 files changed, 6 insertions(+)
diff --git a/libc/test/src/time/asctime_r_test.cpp b/libc/test/src/time/asctime_r_test.cpp
index 2c87094165d8c5..95e6b79ec508b9 100644
--- a/libc/test/src/time/asctime_r_test.cpp
+++ b/libc/test/src/time/asctime_r_test.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stddef.h>
#include "src/errno/libc_errno.h"
#include "src/time/asctime_r.h"
#include "src/time/time_utils.h"
diff --git a/libc/test/src/time/asctime_test.cpp b/libc/test/src/time/asctime_test.cpp
index 7e5ea73418eb5c..5ca772be7e8cba 100644
--- a/libc/test/src/time/asctime_test.cpp
+++ b/libc/test/src/time/asctime_test.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stddef.h>
#include "src/errno/libc_errno.h"
#include "src/time/time_utils.h"
#include "src/time/timezone.h"
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index 5e92efca1d6689..32a4d2a55aba96 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stddef.h>
#include "src/errno/libc_errno.h"
#include "src/time/ctime_r.h"
#include "src/time/time_utils.h"
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 1a7dc869bbdc3c..fbc7fd5dca1d32 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stddef.h>
#include "src/errno/libc_errno.h"
#include "src/time/ctime.h"
#include "src/time/timezone.h"
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index 610ef134d39553..b1ba5333a9eb2f 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stddef.h>
#include "src/time/localtime_r.h"
#include "src/time/time_utils.h"
#include "src/time/timezone.h"
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index 6a7e7a9f6b1628..71886d312d5378 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include <stddef.h>
#include "src/time/localtime.h"
#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
>From b68c2ed8ddc732f0e8d6e69d27b68bfe7729277f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 10:06:49 +0500
Subject: [PATCH 57/58] add todo in tests
---
libc/test/src/time/localtime_r_test.cpp | 2 ++
libc/test/src/time/localtime_test.cpp | 3 +++
2 files changed, 5 insertions(+)
diff --git a/libc/test/src/time/localtime_r_test.cpp b/libc/test/src/time/localtime_r_test.cpp
index b1ba5333a9eb2f..4bd8e06bea2b63 100644
--- a/libc/test/src/time/localtime_r_test.cpp
+++ b/libc/test/src/time/localtime_r_test.cpp
@@ -12,10 +12,12 @@
#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
+// TODO: remove this header file
#include <string.h>
extern char **environ;
+// TODO: rewrite this function and remove malloc
void set_env_var(const char *env) {
int i = 0;
if (environ[i] != NULL) {
diff --git a/libc/test/src/time/localtime_test.cpp b/libc/test/src/time/localtime_test.cpp
index 71886d312d5378..d4b5cf0265ab03 100644
--- a/libc/test/src/time/localtime_test.cpp
+++ b/libc/test/src/time/localtime_test.cpp
@@ -10,10 +10,13 @@
#include "src/time/localtime.h"
#include "src/time/timezone.h"
#include "test/UnitTest/Test.h"
+
+// TODO: remove this header file
#include <string.h>
extern char **environ;
+// TODO: rewrite this function and remove malloc
void set_env_var(const char *env) {
int i = 0;
if (environ[i] != NULL) {
>From 01dcc77fcea4e25863607f9b78da255a03909efb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <zmirza at tutanota.de>
Date: Thu, 26 Dec 2024 10:20:23 +0500
Subject: [PATCH 58/58] add timezone to dependencies for tests
---
libc/test/src/time/CMakeLists.txt | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 72ceb057d589e1..432a20336151e8 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -9,6 +9,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
@@ -24,6 +25,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
@@ -39,6 +41,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
@@ -58,6 +61,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
@@ -77,6 +81,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
@@ -96,6 +101,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
@@ -115,6 +121,7 @@ add_libc_unittest(
HDRS
TmHelper.h
TmMatcher.h
+ timezone.h
CXX_STANDARD
20
DEPENDS
More information about the libc-commits
mailing list