[libc-commits] [libc] [libc] implement localtime (PR #110363)

Зишан Мирза via libc-commits libc-commits at lists.llvm.org
Sun Dec 22 20:03:41 PST 2024


https://github.com/zimirza updated https://github.com/llvm/llvm-project/pull/110363

>From 406379c7b0944e8984abcf1068dde9b6972f990b 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/35] [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 81aab96f3034b0157cef317f8d37006e357ac3ca 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/35] [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 dc97bbe25f28bd108d66baed62d091041865cedb 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/35] [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 720a2b7371ade40328c075a9c294745ea3f2324a 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/35] [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 09dd05d10b4926f19584547e1d9c3366072a3647 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/35] [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 30271b588da7d56a832623baef486db784b238db 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/35] [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 ad97588ea939434f03faed50028d12121148ebf6 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/35] [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 4e71c37bf916dac51d7fed81c460613edc2e021c 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/35] 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 b1a901b2d84fc6f3474b9fe75ba1c4f509730093 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/35] 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 02e4224322656980766af8793341f142a3f2f3eb 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/35] 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 8e1c7f7e8e129d05452b7b5eb0878fd7c43e8224 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/35] 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 c18b7de4859558e402ca8e59ecc150992efc919d 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/35] 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 57c96e3bbd3581714a00a9a0ad68cfaf928bc8ea 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/35] 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 2bfa8bb1746a3229c9681c746ab744c21b68c067 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/35] 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 b02596b0a6f2512faaeb781c4a14f59f35e43888 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/35] 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 ee49d0a8c776e35e5ff6b27964f2330246ab44a7 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/35] 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 a516da320fd86372d8946635013f4ad9ac02d4cb 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/35] 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 e97df510185f890e05ef5c7d6e6a5978a0bfd7db 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/35] 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 0a9e08bea8e70f00deb079a35f282985bc3ebcb0 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/35] 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 3f63e6f59fd7fe43bebbc067a117df5795c6465f 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/35] 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 a6832a61d11b75820cfa03292c483b34ae7db902 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/35] 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 f450da7760085b47d77cbd0d2875bb6c0c592a04 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/35] 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 37ae9c49cc730bdf42faac5e577d74154f3e536f 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/35] 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 cb9027f05b9d3ad6f8ac41b9cddbbcdf8688a4ae 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/35] 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 b35abe732e65b6bfe7aaa443345cc2b163a5e3b2 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/35] 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 6192dc49430a1ff0c3044b37655a9671651568f4 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/35] 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 2fdaf6ae42bc3878b42582a7b0263c2d6ff12a31 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/35] 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 e1f081cd6d049ad5b9a5d0490295da7540a38a4d 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/35] 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 8cbd30f711da62c84e907db6dbc5145b978819fc 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/35] 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 b8b0c17736062bff273e46f3e174bf64262de5af 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/35] 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 63a9e41e307935402aa9f444e5cd542e10fa0f15 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/35] 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 9ad6c5399c9ccc278b45eab73034d5095483139e 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/35] 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 59b3582bbe3b2fa608ae896542de7c7b5d4a14cb 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/35] 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 316e0a9ddde05659f7797ddaef7fc22cc6c2ab85 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/35] 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 6d57656672af55162b774451b613803d357191f3 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/35] 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,
-  ];
-}



More information about the libc-commits mailing list