diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt index 44c4ab49e5c58..2c226ef176c08 100644 --- a/libc/config/baremetal/aarch64/entrypoints.txt +++ b/libc/config/baremetal/aarch64/entrypoints.txt @@ -248,6 +248,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.time.gmtime libc.src.time.gmtime_r libc.src.time.mktime + libc.src.time.strftime + libc.src.time.strftime_l libc.src.time.timespec_get # internal entrypoints diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 370b5462fe9e8..6fd1fce3ab245 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -248,6 +248,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.time.gmtime libc.src.time.gmtime_r libc.src.time.mktime + libc.src.time.strftime + libc.src.time.strftime_l libc.src.time.timespec_get # internal entrypoints diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 07311a60a17a2..5985c495bdaf2 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -244,6 +244,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.time.gmtime libc.src.time.gmtime_r libc.src.time.mktime + libc.src.time.strftime + libc.src.time.strftime_l libc.src.time.timespec_get # internal entrypoints diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index a4f6671a59789..2e3af00ec303d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -1128,6 +1128,7 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.time.mktime libc.src.time.nanosleep libc.src.time.strftime + libc.src.time.strftime_l libc.src.time.time libc.src.time.timespec_get diff --git a/libc/include/time.yaml b/libc/include/time.yaml index 37ee824678cda..7bb25dbe85ac4 100644 --- a/libc/include/time.yaml +++ b/libc/include/time.yaml @@ -9,6 +9,7 @@ types: - type_name: time_t - type_name: clock_t - type_name: size_t + - type_name: locale_t enums: [] objects: [] functions: @@ -100,6 +101,16 @@ functions: - type: size_t - type: const char *__restrict - type: const struct tm *__restrict + - name: strftime_l + standard: + - stdc + return_type: size_t + arguments: + - type: char *__restrict + - type: size_t + - type: const char *__restrict + - type: const struct tm *__restrict + - type: locale_t - name: time standard: - stdc diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt index 8332e8ab66f97..3b951df810011 100644 --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -150,6 +150,20 @@ add_entrypoint_object( libc.src.time.strftime_core.strftime_main ) +add_entrypoint_object( + strftime_l + SRCS + strftime_l.cpp + HDRS + strftime_l.h + DEPENDS + libc.hdr.types.locale_t + libc.hdr.types.size_t + libc.hdr.types.struct_tm + libc.src.stdio.printf_core.writer + libc.src.time.strftime_core.strftime_main +) + add_entrypoint_object( time SRCS diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp index 4b89bf2ea3a70..c19e58fbadf71 100644 --- a/libc/src/time/strftime.cpp +++ b/libc/src/time/strftime.cpp @@ -19,7 +19,6 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(size_t, strftime, (char *__restrict buffer, size_t buffsz, const char *__restrict format, const tm *timeptr)) { - printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); printf_core::Writer writer(&wb); int ret = strftime_core::strftime_main(&writer, format, timeptr); diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp new file mode 100644 index 0000000000000..4203136af4cba --- /dev/null +++ b/libc/src/time/strftime_l.cpp @@ -0,0 +1,33 @@ +//===-- Implementation of strftime_l 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/strftime_l.h" +#include "hdr/types/size_t.h" +#include "hdr/types/struct_tm.h" +#include "include/llvm-libc-types/locale_t.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/stdio/printf_core/writer.h" +#include "src/time/strftime_core/strftime_main.h" + +namespace LIBC_NAMESPACE_DECL { + +// TODO: Add support for locales. +LLVM_LIBC_FUNCTION(size_t, strftime_l, + (char *__restrict buffer, size_t count, + const char *__restrict format, + const struct tm *__restrict tp, locale_t)) { + printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); + printf_core::Writer writer(&wb); + int ret = strftime_core::strftime_main(&writer, format, timeptr); + if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer. + wb.buff[wb.buff_cur] = '\0'; + return (ret < 0 || static_cast(ret) > buffsz) ? 0 : ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/strftime_l.h b/libc/src/time/strftime_l.h new file mode 100644 index 0000000000000..158c4a63986b4 --- /dev/null +++ b/libc/src/time/strftime_l.h @@ -0,0 +1,25 @@ +//===-- Implementation header for strftime_l --------------------*- 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_STRFTIME_L_H +#define LLVM_LIBC_SRC_TIME_STRFTIME_L_H + +#include "hdr/types/size_t.h" +#include "hdr/types/struct_tm.h" +#include "include/llvm-libc-types/locale_t.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +size_t strftime_l(char *__restrict buffer, size_t count, + const char *__restrict format, const struct tm *__restrict tp, + locale_t); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_TIME_STRFTIME_L_H