From ae64d6a8be81aefb84837eff9ea0e51cfabc18c9 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Fri, 9 Aug 2024 11:00:00 -0500 Subject: [PATCH 1/2] [libc] Initial support for 'locale.h' in the LLVM libc Summary: This patch adds the macros and entrypoints associated with the `locale.h` entrypoints. These are mostly stubs, as we (for now and the forseeable future) only expect to support the C and maybe C.UTF-8 locales in the LLVM libc. --- libc/config/gpu/entrypoints.txt | 9 +++ libc/config/gpu/headers.txt | 1 + libc/config/linux/x86_64/entrypoints.txt | 9 +++ libc/config/linux/x86_64/headers.txt | 1 + libc/hdr/types/CMakeLists.txt | 9 +++ libc/hdr/types/locale_t.h | 22 ++++++ libc/include/CMakeLists.txt | 12 +++ libc/include/llvm-libc-macros/CMakeLists.txt | 6 ++ libc/include/llvm-libc-macros/locale-macros.h | 32 ++++++++ libc/include/llvm-libc-types/CMakeLists.txt | 2 + libc/include/llvm-libc-types/locale_t.h | 22 ++++++ libc/include/llvm-libc-types/struct_lconv.h | 39 ++++++++++ libc/include/locale.h.def | 20 +++++ libc/newhdrgen/yaml/locale.yaml | 41 ++++++++++ libc/spec/stdc.td | 57 ++++++++++++++ libc/src/CMakeLists.txt | 1 + libc/src/locale/CMakeLists.txt | 76 +++++++++++++++++++ libc/src/locale/duplocale.cpp | 21 +++++ libc/src/locale/duplocale.h | 22 ++++++ libc/src/locale/freelocale.cpp | 21 +++++ libc/src/locale/freelocale.h | 22 ++++++ libc/src/locale/locale.cpp | 21 +++++ libc/src/locale/locale.h | 36 +++++++++ libc/src/locale/localeconv.cpp | 49 ++++++++++++ libc/src/locale/localeconv.h | 22 ++++++ libc/src/locale/newlocale.cpp | 28 +++++++ libc/src/locale/newlocale.h | 22 ++++++ libc/src/locale/setlocale.cpp | 28 +++++++ libc/src/locale/setlocale.h | 22 ++++++ libc/src/locale/uselocale.cpp | 23 ++++++ libc/src/locale/uselocale.h | 22 ++++++ libc/test/src/CMakeLists.txt | 1 + libc/test/src/locale/CMakeLists.txt | 25 ++++++ libc/test/src/locale/locale_test.cpp | 27 +++++++ libc/test/src/locale/localeconv_test.cpp | 17 +++++ 35 files changed, 788 insertions(+) create mode 100644 libc/hdr/types/locale_t.h create mode 100644 libc/include/llvm-libc-macros/locale-macros.h create mode 100644 libc/include/llvm-libc-types/locale_t.h create mode 100644 libc/include/llvm-libc-types/struct_lconv.h create mode 100644 libc/include/locale.h.def create mode 100644 libc/newhdrgen/yaml/locale.yaml create mode 100644 libc/src/locale/CMakeLists.txt create mode 100644 libc/src/locale/duplocale.cpp create mode 100644 libc/src/locale/duplocale.h create mode 100644 libc/src/locale/freelocale.cpp create mode 100644 libc/src/locale/freelocale.h create mode 100644 libc/src/locale/locale.cpp create mode 100644 libc/src/locale/locale.h create mode 100644 libc/src/locale/localeconv.cpp create mode 100644 libc/src/locale/localeconv.h create mode 100644 libc/src/locale/newlocale.cpp create mode 100644 libc/src/locale/newlocale.h create mode 100644 libc/src/locale/setlocale.cpp create mode 100644 libc/src/locale/setlocale.h create mode 100644 libc/src/locale/uselocale.cpp create mode 100644 libc/src/locale/uselocale.h create mode 100644 libc/test/src/locale/CMakeLists.txt create mode 100644 libc/test/src/locale/locale_test.cpp create mode 100644 libc/test/src/locale/localeconv_test.cpp diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index b2644d2ebf386..592c8cdb7ae77 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -231,6 +231,15 @@ set(TARGET_LIBC_ENTRYPOINTS # wchar.h entrypoints libc.src.wchar.wctob + # locale.h entrypoints + libc.src.locale.localeconv + libc.src.locale.duplocale + libc.src.locale.freelocale + libc.src.locale.localeconv + libc.src.locale.newlocale + libc.src.locale.setlocale + libc.src.locale.uselocale + # gpu/rpc.h entrypoints libc.src.gpu.rpc_host_call ) diff --git a/libc/config/gpu/headers.txt b/libc/config/gpu/headers.txt index 99280b7563a80..fc952c40f4daa 100644 --- a/libc/config/gpu/headers.txt +++ b/libc/config/gpu/headers.txt @@ -16,6 +16,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.wchar libc.include.uchar libc.include.features + libc.include.locale # Header for RPC extensions libc.include.gpu_rpc diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 65c5757efe627..e7c3c7db64abe 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -982,6 +982,15 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.time.nanosleep libc.src.time.time + # locale.h entrypoints + libc.src.locale.localeconv + libc.src.locale.duplocale + libc.src.locale.freelocale + libc.src.locale.localeconv + libc.src.locale.newlocale + libc.src.locale.setlocale + libc.src.locale.uselocale + # unistd.h entrypoints libc.src.unistd.__llvm_libc_syscall libc.src.unistd._exit diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt index 77e454e64395d..881e149d9c40d 100644 --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -33,6 +33,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.unistd libc.include.wchar libc.include.uchar + libc.include.locale libc.include.arpa_inet diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index 4fc28fd82e68d..f41576c07d99b 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -162,3 +162,12 @@ add_proxy_header_library( libc.include.llvm-libc-types.cookie_io_functions_t libc.include.stdio ) + +add_proxy_header_library( + locale_t + HDRS + locale_t.h + FULL_BUILD_DEPENDS + libc.include.llvm-libc-types.locale_t + libc.include.locale +) diff --git a/libc/hdr/types/locale_t.h b/libc/hdr/types/locale_t.h new file mode 100644 index 0000000000000..485258b461696 --- /dev/null +++ b/libc/hdr/types/locale_t.h @@ -0,0 +1,22 @@ +//===-- Definition of macros from locale_t.h ------------------------------===// +// +// 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_HDR_LOCALE_T_H +#define LLVM_LIBC_HDR_LOCALE_T_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/locale_t.h" + +#else // overlay mode + +#error "type not available in overlay mode" + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_LOCALE_T_H diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 2b6eb61782a63..733582c182735 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -717,6 +717,18 @@ add_header_macro( .llvm-libc-types.wchar_t ) +add_header_macro( + locale + ../libc/newhdrgen/yaml/locale.yaml + locale.h.def + locale.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-macros.locale_macros + .llvm-libc-types.locale_t + .llvm-libc-types.struct_lconv +) + if(LIBC_TARGET_OS_IS_GPU) file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/gpu) diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index 60a8725f9ef63..7b980232ba042 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -295,3 +295,9 @@ add_macro_header( HDR elf-macros.h ) + +add_macro_header( + locale_macros + HDR + locale-macros.h +) diff --git a/libc/include/llvm-libc-macros/locale-macros.h b/libc/include/llvm-libc-macros/locale-macros.h new file mode 100644 index 0000000000000..892f8b69f3a77 --- /dev/null +++ b/libc/include/llvm-libc-macros/locale-macros.h @@ -0,0 +1,32 @@ +//===-- Definition of macros from locale.h --------------------------------===// +// +// 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_MACROS_LOCALE_MACROS_H +#define LLVM_LIBC_MACROS_LOCALE_MACROS_H + +#include "../llvm-libc-types/locale_t.h" + +#define LC_CTYPE 0 +#define LC_NUMERIC 1 +#define LC_TIME 2 +#define LC_COLLATE 3 +#define LC_MONETARY 4 +#define LC_MESSAGES 5 +#define LC_ALL 6 + +#define LC_GLOBAL_LOCALE ((locale_t)(-1)) + +#define LC_CTYPE_MASK (1 << LC_CTYPE) +#define LC_NUMERIC_MASK (1 << LC_NUMERIC) +#define LC_TIME_MASK (1 << LC_TIME) +#define LC_COLLATE_MASK (1 << LC_COLLATE) +#define LC_MONETARY_MASK (1 << LC_MONETARY) +#define LC_MESSAGES_MASK (1 << LC_MESSAGES) +#define LC_ALL_MASK 0x7fffffff + +#endif // LLVM_LIBC_MACROS_LOCALE_MACROS_H diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index 0fa86e0152f9b..583b84ccaae67 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -142,3 +142,5 @@ DEPENDS .fsblkcnt_t .fsfilcnt_t ) +add_header(locale_t HDR locale_t.h) +add_header(struct_lconv HDR struct_lconv.h) diff --git a/libc/include/llvm-libc-types/locale_t.h b/libc/include/llvm-libc-types/locale_t.h new file mode 100644 index 0000000000000..6d783001acf9f --- /dev/null +++ b/libc/include/llvm-libc-types/locale_t.h @@ -0,0 +1,22 @@ +//===-- Definition of type locale_t ---------------------------------------===// +// +// 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_TYPES_LOCALE_T_H +#define LLVM_LIBC_TYPES_LOCALE_T_H + +#define NUM_LOCALE_CATEGORIES 6 + +struct __locale_data; + +struct __locale_t { + struct __locale_data *data[NUM_LOCALE_CATEGORIES]; +}; + +typedef struct __locale_t *locale_t; + +#endif // LLVM_LIBC_TYPES_LOCALE_T_H diff --git a/libc/include/llvm-libc-types/struct_lconv.h b/libc/include/llvm-libc-types/struct_lconv.h new file mode 100644 index 0000000000000..9d69f055484da --- /dev/null +++ b/libc/include/llvm-libc-types/struct_lconv.h @@ -0,0 +1,39 @@ +//===-- Definition of type lconv ------------------------------------------===// +// +// 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_TYPES_LCONV_H +#define LLVM_LIBC_TYPES_LCONV_H + +struct lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char *currency_symbol; + char frac_digits; + char p_cs_precedes; + char n_cs_precedes; + char p_sep_by_space; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char *int_curr_symbol; + char int_frac_digits; + char int_p_cs_precedes; + char int_n_cs_precedes; + char int_p_sep_by_space; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + +#endif // LLVM_LIBC_TYPES_LCONV_H diff --git a/libc/include/locale.h.def b/libc/include/locale.h.def new file mode 100644 index 0000000000000..516c6e6275e68 --- /dev/null +++ b/libc/include/locale.h.def @@ -0,0 +1,20 @@ +//===-- C standard library header locale.h --------------------------------===// +// +// 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_LOCALE_H +#define LLVM_LIBC_LOCALE_H + +#include "__llvm-libc-common.h" + +#include "llvm-libc-macros/locale-macros.h" +#include "llvm-libc-types/locale_t.h" +#include "llvm-libc-types/struct_lconv.h" + +%%public_api() + +#endif // LLVM_LIBC_LOCALE_H diff --git a/libc/newhdrgen/yaml/locale.yaml b/libc/newhdrgen/yaml/locale.yaml new file mode 100644 index 0000000000000..7da7966ea730f --- /dev/null +++ b/libc/newhdrgen/yaml/locale.yaml @@ -0,0 +1,41 @@ +header: locale.h +functions: + - name: localeconv + standards: + - stdc + return_type: struct lconv * + arguments: + - type: void + - name: duplocale + standards: + - stdc + return_type: locale_t + arguments: + - type: locale_t + - name: freelocale + standards: + - stdc + return_type: void + arguments: + - type: locale_t + - name: newlocale + standards: + - stdc + return_type: locale_t + arguments: + - type: int + - type: const char * + - type: locale_t + - name: setlocale + standards: + - stdc + return_type: char * + arguments: + - type: int + - type: const char * + - name: uselocale + standards: + - stdc + return_type: locale_t + arguments: + - type: locale_t diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index e06a4f9b268e6..76a9ed123356a 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -4,6 +4,7 @@ def StdC : StandardSpec<"stdc"> { PtrType StructTmPtr = PtrType; PtrType TimeTTypePtr = PtrType; NamedType ClockT = NamedType<"clock_t">; + NamedType LocaleT = NamedType<"locale_t">; NamedType DivTType = NamedType<"div_t">; NamedType LDivTType = NamedType<"ldiv_t">; @@ -1588,6 +1589,61 @@ def StdC : StandardSpec<"stdc"> { ] >; + + NamedType StructLconv : NamedType<"struct lconv">; + PtrType StructLconvPtr : PtrType; + + HeaderSpec Locale = HeaderSpec< + "locale.h", + [], // Macros + [LocaleT, StructLconv], // Types + [], // Enumerations + [ + FunctionSpec< + "duplocale", + RetValSpec, + [ + ArgSpec + ] + >, + FunctionSpec< + "freelocale", + RetValSpec, + [ + ArgSpec + ] + >, + FunctionSpec< + "localeconv", + RetValSpec, + [] + >, + FunctionSpec< + "newlocale", + RetValSpec, + [ + ArgSpec, + ArgSpec, + ArgSpec + ] + >, + FunctionSpec< + "setlocale", + RetValSpec, + [ + ArgSpec, + ArgSpec + ] + >, + FunctionSpec< + "uselocale", + RetValSpec, + [ + ArgSpec + ] + > + ] // Functions + >; let Headers = [ Assert, @@ -1610,5 +1666,6 @@ def StdC : StandardSpec<"stdc"> { Time, UChar, WChar, + Locale, ]; } diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt index 9597e2380172b..d554c12fb1ec8 100644 --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -40,3 +40,4 @@ add_subdirectory(signal) add_subdirectory(spawn) add_subdirectory(threads) add_subdirectory(time) +add_subdirectory(locale) diff --git a/libc/src/locale/CMakeLists.txt b/libc/src/locale/CMakeLists.txt new file mode 100644 index 0000000000000..6aaeb2ac31488 --- /dev/null +++ b/libc/src/locale/CMakeLists.txt @@ -0,0 +1,76 @@ +add_object_library( + locale + SRCS + locale.cpp + HDRS + locale.h + DEPENDS + libc.include.locale +) + +add_entrypoint_object( + localeconv + SRCS + localeconv.cpp + HDRS + localeconv.h + DEPENDS + libc.include.locale + CXX_STANDARD + 20 # For designated initializers +) + +add_entrypoint_object( + newlocale + SRCS + newlocale.cpp + HDRS + newlocale.h + DEPENDS + libc.include.locale + .locale +) + +add_entrypoint_object( + duplocale + SRCS + duplocale.cpp + HDRS + duplocale.h + DEPENDS + libc.include.locale + .locale +) + +add_entrypoint_object( + setlocale + SRCS + setlocale.cpp + HDRS + setlocale.h + DEPENDS + libc.include.locale + .locale +) + +add_entrypoint_object( + uselocale + SRCS + uselocale.cpp + HDRS + uselocale.h + DEPENDS + libc.include.locale + .locale +) + +add_entrypoint_object( + freelocale + SRCS + freelocale.cpp + HDRS + freelocale.h + DEPENDS + libc.include.locale + .locale +) diff --git a/libc/src/locale/duplocale.cpp b/libc/src/locale/duplocale.cpp new file mode 100644 index 0000000000000..d1bd0835121fc --- /dev/null +++ b/libc/src/locale/duplocale.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of duplocale ---------------------------------------===// +// +// 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/locale/duplocale.h" +#include "include/llvm-libc-macros/locale-macros.h" +#include "src/locale/locale.h" + +#include "src/__support/CPP/string_view.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(locale_t, duplocale, (locale_t loc)) { return loc; } + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/duplocale.h b/libc/src/locale/duplocale.h new file mode 100644 index 0000000000000..a745383860d83 --- /dev/null +++ b/libc/src/locale/duplocale.h @@ -0,0 +1,22 @@ +//===-- Implementation header for duplocale ---------------------*- 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_LOCALE_DUPLOCALE_H +#define LLVM_LIBC_SRC_LOCALE_DUPLOCALE_H + +#include "src/__support/macros/config.h" + +#include "hdr/types/locale_t.h" + +namespace LIBC_NAMESPACE_DECL { + +locale_t duplocale(locale_t loc); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_DUPLOCALE_H diff --git a/libc/src/locale/freelocale.cpp b/libc/src/locale/freelocale.cpp new file mode 100644 index 0000000000000..2008995f101bf --- /dev/null +++ b/libc/src/locale/freelocale.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of freelocale --------------------------------------===// +// +// 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/locale/freelocale.h" +#include "include/llvm-libc-macros/locale-macros.h" +#include "src/locale/locale.h" + +#include "src/__support/CPP/string_view.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(void, freelocale, (locale_t)) {} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/freelocale.h b/libc/src/locale/freelocale.h new file mode 100644 index 0000000000000..77ece30430738 --- /dev/null +++ b/libc/src/locale/freelocale.h @@ -0,0 +1,22 @@ +//===-- Implementation header for freelocale --------------------*- 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_LOCALE_FREELOCALE_H +#define LLVM_LIBC_SRC_LOCALE_FREELOCALE_H + +#include "src/__support/macros/config.h" + +#include "hdr/types/locale_t.h" + +namespace LIBC_NAMESPACE_DECL { + +void freelocale(locale_t loc); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_FREELOCALE_H diff --git a/libc/src/locale/locale.cpp b/libc/src/locale/locale.cpp new file mode 100644 index 0000000000000..18ebc33ad5823 --- /dev/null +++ b/libc/src/locale/locale.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of locale ------------------------------------------===// +// +// 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/locale/locale.h" + +#include "include/llvm-libc-macros/locale-macros.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +__locale_t c_locale = {nullptr}; + +LIBC_THREAD_LOCAL locale_t locale = nullptr; + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/locale.h b/libc/src/locale/locale.h new file mode 100644 index 0000000000000..6d6db2bcacad3 --- /dev/null +++ b/libc/src/locale/locale.h @@ -0,0 +1,36 @@ +//===-- Implementation header for the locale --------------------*- 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_LOCALE_LOCALECONV_H +#define LLVM_LIBC_SRC_LOCALE_LOCALECONV_H + +#include "src/__support/macros/attributes.h" +#include "src/__support/macros/config.h" + +#include "hdr/types/locale_t.h" + +#include + +namespace LIBC_NAMESPACE_DECL { + +// We only support the "C" locale right now. +static constexpr size_t MAX_LOCALE_NAME_SIZE = 2; + +struct __locale_data { + char name[MAX_LOCALE_NAME_SIZE]; +}; + +// The pointer to the default "C" locale. +extern __locale_t c_locale; + +// The global locale instance. +LIBC_THREAD_LOCAL extern locale_t locale; + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_LOCALECONV_H diff --git a/libc/src/locale/localeconv.cpp b/libc/src/locale/localeconv.cpp new file mode 100644 index 0000000000000..e4d7536bf1ffb --- /dev/null +++ b/libc/src/locale/localeconv.cpp @@ -0,0 +1,49 @@ +//===-- Implementation of localeconv --------------------------------------===// +// +// 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/locale/localeconv.h" + +#include "src/__support/CPP/limits.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +static char DOT_STRING[] = "."; +static char EMPTY_STRING[] = ""; + +static struct lconv C_LCONV = { + .decimal_point = DOT_STRING, + .thousands_sep = EMPTY_STRING, + .grouping = EMPTY_STRING, + .mon_decimal_point = EMPTY_STRING, + .mon_thousands_sep = EMPTY_STRING, + .mon_grouping = EMPTY_STRING, + .positive_sign = EMPTY_STRING, + .negative_sign = EMPTY_STRING, + .currency_symbol = EMPTY_STRING, + .frac_digits = CHAR_MAX, + .p_cs_precedes = CHAR_MAX, + .n_cs_precedes = CHAR_MAX, + .p_sep_by_space = CHAR_MAX, + .n_sep_by_space = CHAR_MAX, + .p_sign_posn = CHAR_MAX, + .n_sign_posn = CHAR_MAX, + .int_curr_symbol = EMPTY_STRING, + .int_frac_digits = CHAR_MAX, + .int_p_cs_precedes = CHAR_MAX, + .int_n_cs_precedes = CHAR_MAX, + .int_p_sep_by_space = CHAR_MAX, + .int_n_sep_by_space = CHAR_MAX, + .int_p_sign_posn = CHAR_MAX, + .int_n_sign_posn = CHAR_MAX, +}; + +LLVM_LIBC_FUNCTION(struct lconv *, localeconv, ()) { return &C_LCONV; } + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/localeconv.h b/libc/src/locale/localeconv.h new file mode 100644 index 0000000000000..a8f7599b572bf --- /dev/null +++ b/libc/src/locale/localeconv.h @@ -0,0 +1,22 @@ +//===-- Implementation header for localeconv --------------------*- 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_LOCALE_LOCALECONV_H +#define LLVM_LIBC_SRC_LOCALE_LOCALECONV_H + +#include "src/__support/macros/config.h" + +#include "include/llvm-libc-types/struct_lconv.h" + +namespace LIBC_NAMESPACE_DECL { + +struct lconv *localeconv(); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_LOCALECONV_H diff --git a/libc/src/locale/newlocale.cpp b/libc/src/locale/newlocale.cpp new file mode 100644 index 0000000000000..379e7e6385d09 --- /dev/null +++ b/libc/src/locale/newlocale.cpp @@ -0,0 +1,28 @@ +//===-- Implementation of newlocale ---------------------------------------===// +// +// 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/locale/newlocale.h" +#include "include/llvm-libc-macros/locale-macros.h" +#include "src/locale/locale.h" + +#include "src/__support/CPP/string_view.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(locale_t, newlocale, + (int category_mask, const char *locale_name, locale_t)) { + cpp::string_view name(locale_name); + if (category_mask > LC_ALL || (!name.empty() && name != "C")) + return nullptr; + + return &c_locale; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/newlocale.h b/libc/src/locale/newlocale.h new file mode 100644 index 0000000000000..08a0071cb7aea --- /dev/null +++ b/libc/src/locale/newlocale.h @@ -0,0 +1,22 @@ +//===-- Implementation header for setlocale ---------------------*- 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_LOCALE_SETLOCALE_H +#define LLVM_LIBC_SRC_LOCALE_SETLOCALE_H + +#include "src/__support/macros/config.h" + +#include "hdr/types/locale_t.h" + +namespace LIBC_NAMESPACE_DECL { + +locale_t newlocale(int category_mask, const char *locale_name, locale_t base); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_SETLOCALE_H diff --git a/libc/src/locale/setlocale.cpp b/libc/src/locale/setlocale.cpp new file mode 100644 index 0000000000000..0950ad73cbe2c --- /dev/null +++ b/libc/src/locale/setlocale.cpp @@ -0,0 +1,28 @@ +//===-- Implementation of setlocale ---------------------------------------===// +// +// 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/locale/setlocale.h" +#include "include/llvm-libc-macros/locale-macros.h" +#include "src/locale/locale.h" + +#include "src/__support/CPP/string_view.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(char *, setlocale, (int category, const char *locale_name)) { + cpp::string_view name(locale_name); + if (category > LC_ALL || (!name.empty() && name != "C")) + return nullptr; + + static char locale_str[] = "C"; + return locale_str; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/setlocale.h b/libc/src/locale/setlocale.h new file mode 100644 index 0000000000000..a9213cf409a7b --- /dev/null +++ b/libc/src/locale/setlocale.h @@ -0,0 +1,22 @@ +//===-- Implementation header for setlocale ---------------------*- 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_LOCALE_SETLOCALE_H +#define LLVM_LIBC_SRC_LOCALE_SETLOCALE_H + +#include "src/__support/macros/config.h" + +#include "hdr/types/locale_t.h" + +namespace LIBC_NAMESPACE_DECL { + +char *setlocale(int category, const char *locale_name); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_SETLOCALE_H diff --git a/libc/src/locale/uselocale.cpp b/libc/src/locale/uselocale.cpp new file mode 100644 index 0000000000000..d6fdad248f12b --- /dev/null +++ b/libc/src/locale/uselocale.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of uselocale ---------------------------------------===// +// +// 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/locale/uselocale.h" +#include "src/locale/locale.h" + +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(locale_t, uselocale, (locale_t newloc)) { + if (!newloc) + return locale; + return locale = newloc; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/locale/uselocale.h b/libc/src/locale/uselocale.h new file mode 100644 index 0000000000000..15403490d2f8c --- /dev/null +++ b/libc/src/locale/uselocale.h @@ -0,0 +1,22 @@ +//===-- Implementation header for uselocale ---------------------*- 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_LOCALE_USELOCALE_H +#define LLVM_LIBC_SRC_LOCALE_USELOCALE_H + +#include "src/__support/macros/config.h" + +#include "hdr/types/locale_t.h" + +namespace LIBC_NAMESPACE_DECL { + +locale_t uselocale(locale_t newloc); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_LOCALE_USELOCALE_H diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt index 60ea7e6a90d71..ddc6a5c7f6965 100644 --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -82,6 +82,7 @@ add_subdirectory(setjmp) add_subdirectory(signal) add_subdirectory(spawn) add_subdirectory(time) +add_subdirectory(locale) if(${LIBC_TARGET_OS} STREQUAL "linux") add_subdirectory(pthread) diff --git a/libc/test/src/locale/CMakeLists.txt b/libc/test/src/locale/CMakeLists.txt new file mode 100644 index 0000000000000..3192004db26dd --- /dev/null +++ b/libc/test/src/locale/CMakeLists.txt @@ -0,0 +1,25 @@ +add_custom_target(libc-locale-tests) + +add_libc_test( + locale_test + SUITE + libc-locale-tests + SRCS + locale_test.cpp + DEPENDS + libc.include.locale + libc.src.locale.newlocale + libc.src.locale.uselocale + libc.src.locale.freelocale +) + +add_libc_test( + localeconv_test + SUITE + libc-locale-tests + SRCS + localeconv_test.cpp + DEPENDS + libc.include.locale + libc.src.locale.localeconv +) diff --git a/libc/test/src/locale/locale_test.cpp b/libc/test/src/locale/locale_test.cpp new file mode 100644 index 0000000000000..bc48bb851f4e4 --- /dev/null +++ b/libc/test/src/locale/locale_test.cpp @@ -0,0 +1,27 @@ +//===-- Unittests for locale ----------------------------------------------===// +// +// 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/locale/freelocale.h" +#include "src/locale/newlocale.h" +#include "src/locale/uselocale.h" + +#include "test/UnitTest/Test.h" + +#include "include/llvm-libc-macros/locale-macros.h" + +TEST(LlvmLibcLocale, DefaultLocale) { + locale_t new_locale = LIBC_NAMESPACE::newlocale(LC_ALL, "C", nullptr); + EXPECT_NE(new_locale, static_cast(nullptr)); + + locale_t old_locale = LIBC_NAMESPACE::uselocale(new_locale); + EXPECT_NE(old_locale, static_cast(nullptr)); + + LIBC_NAMESPACE::freelocale(new_locale); + + LIBC_NAMESPACE::uselocale(old_locale); +} diff --git a/libc/test/src/locale/localeconv_test.cpp b/libc/test/src/locale/localeconv_test.cpp new file mode 100644 index 0000000000000..79264276dec35 --- /dev/null +++ b/libc/test/src/locale/localeconv_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for localeconv ------------------------------------------===// +// +// 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 "include/llvm-libc-macros/locale-macros.h" +#include "src/locale/localeconv.h" + +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcLocale, DefaultLocale) { + struct lconv *conv = LIBC_NAMESPACE::localeconv(); + EXPECT_STREQ(conv->decimal_point, "."); +} From cbd92dd5624cabd18fe6f02b5d9c5aa686880e7a Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 21 Aug 2024 13:01:03 -0500 Subject: [PATCH 2/2] Update locale.cpp --- libc/src/locale/locale.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/locale/locale.cpp b/libc/src/locale/locale.cpp index 18ebc33ad5823..1610fb5dd3400 100644 --- a/libc/src/locale/locale.cpp +++ b/libc/src/locale/locale.cpp @@ -16,6 +16,6 @@ namespace LIBC_NAMESPACE_DECL { __locale_t c_locale = {nullptr}; -LIBC_THREAD_LOCAL locale_t locale = nullptr; +locale_t locale = nullptr; } // namespace LIBC_NAMESPACE_DECL