[libc-commits] [libc] [libc] Add `locale.h` and related stubs (PR #97494)

via libc-commits libc-commits at lists.llvm.org
Tue Jul 2 17:24:03 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Izaak Schroeder (izaakschroeder)

<details>
<summary>Changes</summary>

Does what it says on the box. Calls the non `_l` versions and throws `locale_t` out the window.

---

Patch is 56.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/97494.diff


61 Files Affected:

- (modified) libc/config/linux/aarch64/entrypoints.txt (+27) 
- (modified) libc/config/linux/aarch64/headers.txt (+2) 
- (modified) libc/config/linux/api.td (+7) 
- (modified) libc/config/linux/x86_64/entrypoints.txt (+27) 
- (modified) libc/config/linux/x86_64/headers.txt (+2) 
- (modified) libc/include/CMakeLists.txt (+13) 
- (modified) libc/include/ctype.h.def (+1) 
- (modified) libc/include/llvm-libc-macros/CMakeLists.txt (+6) 
- (added) libc/include/llvm-libc-macros/locale-macros.h (+32) 
- (modified) libc/include/llvm-libc-macros/stdlib-macros.h (+4) 
- (modified) libc/include/llvm-libc-types/CMakeLists.txt (+2) 
- (added) libc/include/llvm-libc-types/locale_t.h (+18) 
- (added) libc/include/llvm-libc-types/struct_lconv.h (+39) 
- (added) libc/include/locale.h.def (+18) 
- (modified) libc/include/stdlib.h.def (+1) 
- (modified) libc/include/time.h.def (+2) 
- (modified) libc/spec/posix.td (+57) 
- (modified) libc/spec/stdc.td (+56-1) 
- (modified) libc/src/CMakeLists.txt (+1) 
- (modified) libc/src/ctype/CMakeLists.txt (+73) 
- (added) libc/src/ctype/isdigit_l.cpp (+19) 
- (added) libc/src/ctype/isdigit_l.h (+20) 
- (added) libc/src/ctype/islower_l.cpp (+22) 
- (added) libc/src/ctype/islower_l.h (+20) 
- (added) libc/src/ctype/isupper_l.cpp (+22) 
- (added) libc/src/ctype/isupper_l.h (+20) 
- (added) libc/src/ctype/isxdigit_l.cpp (+23) 
- (added) libc/src/ctype/isxdigit_l.h (+20) 
- (added) libc/src/ctype/tolower_l.cpp (+20) 
- (added) libc/src/ctype/tolower_l.h (+20) 
- (added) libc/src/ctype/toupper_l.cpp (+23) 
- (added) libc/src/ctype/toupper_l.h (+20) 
- (added) libc/src/locale/CMakeLists.txt (+60) 
- (added) libc/src/locale/duplocale.cpp (+18) 
- (added) libc/src/locale/duplocale.h (+20) 
- (added) libc/src/locale/freelocale.cpp (+18) 
- (added) libc/src/locale/freelocale.h (+20) 
- (added) libc/src/locale/localeconv.cpp (+46) 
- (added) libc/src/locale/localeconv.h (+20) 
- (added) libc/src/locale/newlocale.cpp (+18) 
- (added) libc/src/locale/newlocale.h (+20) 
- (added) libc/src/locale/setlocale.cpp (+18) 
- (added) libc/src/locale/setlocale.h (+18) 
- (added) libc/src/locale/uselocale.cpp (+18) 
- (added) libc/src/locale/uselocale.h (+20) 
- (modified) libc/src/stdlib/CMakeLists.txt (+60) 
- (added) libc/src/stdlib/strtod_l.cpp (+21) 
- (added) libc/src/stdlib/strtod_l.h (+20) 
- (added) libc/src/stdlib/strtof_l.cpp (+20) 
- (added) libc/src/stdlib/strtof_l.h (+20) 
- (added) libc/src/stdlib/strtold_l.cpp (+21) 
- (added) libc/src/stdlib/strtold_l.h (+20) 
- (added) libc/src/stdlib/strtoll_l.cpp (+22) 
- (added) libc/src/stdlib/strtoll_l.h (+21) 
- (added) libc/src/stdlib/strtoull_l.cpp (+22) 
- (added) libc/src/stdlib/strtoull_l.h (+21) 
- (modified) libc/src/string/CMakeLists.txt (+22) 
- (added) libc/src/string/strcoll_l.cpp (+21) 
- (added) libc/src/string/strcoll_l.h (+20) 
- (added) libc/src/string/strxfrm_l.cpp (+23) 
- (added) libc/src/string/strxfrm_l.h (+21) 


``````````diff
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 940df63e3912b..8119cd6d300fe 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -17,6 +17,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.ctype.tolower
     libc.src.ctype.toupper
 
+    # ctype.h localized entrypoints
+    libc.src.ctype.isdigit_l
+    libc.src.ctype.isxdigit_l
+    libc.src.ctype.islower_l
+    libc.src.ctype.isupper_l
+    libc.src.ctype.tolower_l
+    libc.src.ctype.toupper_l
+
     # errno.h entrypoints
     libc.src.errno.errno
 
@@ -85,6 +93,10 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.string.strtok
     libc.src.string.strtok_r
 
+    # string.h localized entrypoints
+    libc.src.string.strxfrm_l
+    libc.src.string.strcoll_l
+
     # inttypes.h entrypoints
     libc.src.inttypes.imaxabs
     libc.src.inttypes.imaxdiv
@@ -194,6 +206,13 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.malloc
     libc.src.stdlib.realloc
 
+    # stdlib.h localized entrypoints
+    libc.src.stdlib.strtof_l
+    libc.src.stdlib.strtod_l
+    libc.src.stdlib.strtold_l
+    libc.src.stdlib.strtoull_l
+    libc.src.stdlib.strtoll_l
+
     # stdio.h entrypoints
     libc.src.stdio.fdopen
     #libc.src.stdio.fscanf
@@ -308,6 +327,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.unlink
     libc.src.unistd.unlinkat
     libc.src.unistd.write
+    
+    # locale.h entrypoints
+    libc.src.locale.duplocale
+    libc.src.locale.freelocale
+    libc.src.locale.localeconv
+    libc.src.locale.newlocale
+    libc.src.locale.setlocale
+    libc.src.locale.uselocale
 )
 
 set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt
index 7d25877cefcc8..48716f8e2b404 100644
--- a/libc/config/linux/aarch64/headers.txt
+++ b/libc/config/linux/aarch64/headers.txt
@@ -31,4 +31,6 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.sys_ioctl
     # Disabled due to epoll_wait syscalls not being available on this platform.
     # libc.include.sys_epoll
+
+    libc.include.locale
 )
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index eb0090c80b0da..ae94e2cf4b2c8 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -308,3 +308,10 @@ def SearchAPI : PublicAPI<"search.h"> {
 def SysStatvfsAPI : PublicAPI<"sys/statvfs.h"> {
   let Types = ["fsblkcnt_t", "fsfilcnt_t", "struct statvfs"];
 }
+
+def LocaleAPI : PublicAPI<"locale.h"> {
+  let Types = [
+    "struct lconv",
+    "locale_t"
+  ];
+}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 09f04fb31dfd8..0b92b751d6c70 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -17,6 +17,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.ctype.tolower
     libc.src.ctype.toupper
 
+    # ctype.h localized entrypoints
+    libc.src.ctype.isdigit_l
+    libc.src.ctype.isxdigit_l
+    libc.src.ctype.islower_l
+    libc.src.ctype.isupper_l
+    libc.src.ctype.tolower_l
+    libc.src.ctype.toupper_l
+
     # errno.h entrypoints
     libc.src.errno.errno
 
@@ -87,6 +95,10 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.string.strtok_r
     libc.src.string.strxfrm
 
+    # string.h localized entrypoints
+    libc.src.string.strxfrm_l
+    libc.src.string.strcoll_l
+
     # inttypes.h entrypoints
     libc.src.inttypes.imaxabs
     libc.src.inttypes.imaxdiv
@@ -199,6 +211,13 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.malloc
     libc.src.stdlib.realloc
 
+    # stdlib.h localized entrypoints
+    libc.src.stdlib.strtof_l
+    libc.src.stdlib.strtod_l
+    libc.src.stdlib.strtold_l
+    libc.src.stdlib.strtoull_l
+    libc.src.stdlib.strtoll_l
+
     # stdio.h entrypoints
     libc.src.stdio.fdopen
     libc.src.stdio.fileno
@@ -330,6 +349,14 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # wchar.h entrypoints
     libc.src.wchar.wctob
+
+    # locale.h entrypoints
+    libc.src.locale.duplocale
+    libc.src.locale.freelocale
+    libc.src.locale.localeconv
+    libc.src.locale.newlocale
+    libc.src.locale.setlocale
+    libc.src.locale.uselocale
 )
 
 set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index 44d640b75e2bf..211354e20ad47 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -49,4 +49,6 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.sys_types
     libc.include.sys_utsname
     libc.include.sys_wait
+
+    libc.include.locale
 )
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 3ab7817d8568b..e47d0e81d5ec5 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -199,6 +199,8 @@ add_gen_header(
     .llvm-libc-types.struct_timespec
     .llvm-libc-types.struct_timeval
     .llvm-libc-types.clockid_t
+    .llvm-libc-types.size_t
+    .llvm-libc-types.locale_t
 )
 
 add_gen_header(
@@ -358,6 +360,17 @@ add_gen_header(
     .llvm-libc-types.posix_spawn_file_actions_t
 )
 
+add_gen_header(
+  locale
+  DEF_FILE locale.h.def
+  GEN_HDR locale.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-types.struct_lconv
+    .llvm-libc-types.locale_t
+    .llvm-libc-macros.locale_macros
+)
+
 # TODO: Not all platforms will have a include/sys directory. Add the sys
 # directory and the targets for sys/*.h files conditional to the OS requiring
 # them.
diff --git a/libc/include/ctype.h.def b/libc/include/ctype.h.def
index a9bb786931ead..a6fc61a61fced 100644
--- a/libc/include/ctype.h.def
+++ b/libc/include/ctype.h.def
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_CTYPE_H
 
 #include "__llvm-libc-common.h"
+#include "llvm-libc-types/locale_t.h"
 
 %%public_api()
 
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index f6af11abd4dd7..05e1eb574f203 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -277,3 +277,9 @@ add_macro_header(
   HDR
     stdckdint-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..3c9098cb97207
--- /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
+
+// HACK(@izaakschroeder): Stubs
+#define LC_ALL 0
+#define LC_COLLATE 0
+#define LC_CTYPE 0
+#define LC_MESSAGES 0
+#define LC_MONETARY 0
+#define LC_NUMERIC 0
+#define LC_TIME 0
+
+// HACK(@izaakschroeder): Stubs
+#define LC_ALL_MASK 0
+#define LC_COLLATE_MASK 0
+#define LC_CTYPE_MASK 0
+#define LC_MESSAGES_MASK 0
+#define LC_MONETARY_MASK 0
+#define LC_NUMERIC_MASK 0
+#define LC_TIME_MASK 0
+
+
+
+#endif // LLVM_LIBC_MACROS_LOCALE_MACROS_H
diff --git a/libc/include/llvm-libc-macros/stdlib-macros.h b/libc/include/llvm-libc-macros/stdlib-macros.h
index 5fcbfef97b328..f53328b3d9e99 100644
--- a/libc/include/llvm-libc-macros/stdlib-macros.h
+++ b/libc/include/llvm-libc-macros/stdlib-macros.h
@@ -19,4 +19,8 @@
 
 #define RAND_MAX 2147483647
 
+// N.B. If current thread is utf8 then this is 4
+// otherwise it is 1. Leaving at 4 to be safe.
+#define MB_CUR_MAX 4
+
 #endif // LLVM_LIBC_MACROS_STDLIB_MACROS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index d8b975572e0dd..5d579c832954d 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -89,6 +89,8 @@ add_header(thrd_t HDR thrd_t.h DEPENDS .__thread_type)
 add_header(tss_t HDR tss_t.h)
 add_header(tss_dtor_t HDR tss_dtor_t.h)
 add_header(__atexithandler_t HDR __atexithandler_t.h)
+add_header(struct_lconv HDR struct_lconv.h)
+add_header(locale_t HDR locale_t.h)
 add_header(speed_t HDR speed_t.h)
 add_header(tcflag_t HDR tcflag_t.h)
 add_header(struct_termios HDR struct_termios.h DEPENDS .cc_t .speed_t .tcflag_t)
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..32014588532a8
--- /dev/null
+++ b/libc/include/llvm-libc-types/locale_t.h
@@ -0,0 +1,18 @@
+
+//===-- 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
+
+// HACK(@izaakschroeder): Placeholder.
+// NOTE: According to `libcxx` the `locale_t` type has to be at least
+// coercible to a `bool`.
+typedef void* 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..a5067a2d373d4
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_lconv.h
@@ -0,0 +1,39 @@
+//===-- Definition of type struct 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_STRUCT_LCONV_H
+#define LLVM_LIBC_TYPES_STRUCT_LCONV_H
+
+struct lconv {
+  char *currency_symbol;
+	char *decimal_point;
+  char *grouping;
+  char *int_curr_symbol;
+  char *mon_decimal_point;
+  char *mon_grouping;
+	char *mon_thousands_sep;
+  char *negative_sign;
+  char *positive_sign;
+	char *thousands_sep;
+  char frac_digits;
+  char int_frac_digits;
+  char int_p_cs_precedes;
+	char int_p_sep_by_space;
+	char int_n_cs_precedes;
+	char int_n_sep_by_space;
+  char int_n_sign_posn;
+	char int_p_sign_posn;
+  char n_cs_precedes;
+	char n_sep_by_space;
+  char n_sign_posn;
+	char p_cs_precedes;
+	char p_sep_by_space;
+	char p_sign_posn;	
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_LCONV_H
diff --git a/libc/include/locale.h.def b/libc/include/locale.h.def
new file mode 100644
index 0000000000000..656344031d927
--- /dev/null
+++ b/libc/include/locale.h.def
@@ -0,0 +1,18 @@
+//===-- 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-macros/locale-macros.h"
+#include "llvm-libc-types/locale_t.h"
+#include "llvm-libc-types/struct_lconv.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_LINK_H
diff --git a/libc/include/stdlib.h.def b/libc/include/stdlib.h.def
index d523f7a53024a..34a11d4e78a77 100644
--- a/libc/include/stdlib.h.def
+++ b/libc/include/stdlib.h.def
@@ -11,6 +11,7 @@
 
 #include "__llvm-libc-common.h"
 #include "llvm-libc-macros/stdlib-macros.h"
+#include "llvm-libc-types/locale_t.h"
 
 %%public_api()
 
diff --git a/libc/include/time.h.def b/libc/include/time.h.def
index 2355e8822fad7..f23488720bac4 100644
--- a/libc/include/time.h.def
+++ b/libc/include/time.h.def
@@ -11,6 +11,8 @@
 
 #include "__llvm-libc-common.h"
 #include "llvm-libc-macros/time-macros.h"
+#include "llvm-libc-types/size_t.h"
+#include "llvm-libc-types/locale_t.h"
 
 %%public_api()
 
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index d14047548e104..565db1cc4ef35 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -21,6 +21,10 @@ def PThreadOnceT : NamedType<"pthread_once_t">;
 def PThreadOnceTPtr : PtrType<PThreadOnceT>;
 def PThreadOnceCallback : NamedType<"__pthread_once_func_t">;
 
+def StructLconv : NamedType<"struct lconv">;
+def StructLconvPtr : PtrType<StructLconv>;
+def LocaleT : NamedType<"locale_t">;
+
 def InoT : NamedType<"ino_t">;
 def UidT : NamedType<"uid_t">;
 def GidT : NamedType<"gid_t">;
@@ -1686,12 +1690,65 @@ def POSIX : StandardSpec<"POSIX"> {
     []  // Functions
   >;
 
+  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 = [
     ArpaInet,
     CType,
     Dirent,
     Errno,
     FCntl,
+    Locale,
     PThread,
     Sched,
     Signal,
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 9ff40bf76700c..ecea09f8af05c 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -2,12 +2,14 @@ def StdC : StandardSpec<"stdc"> {
 
   NamedType StructTmType = NamedType<"struct tm">;
   PtrType StructTmPtr = PtrType<StructTmType>;
+
   PtrType TimeTTypePtr = PtrType<TimeTType>;
   NamedType ClockT = NamedType<"clock_t">;
 
   NamedType DivTType = NamedType<"div_t">;
   NamedType LDivTType = NamedType<"ldiv_t">;
   NamedType LLDivTType = NamedType<"lldiv_t">;
+  NamedType LocaleTType = NamedType<"locale_t">;
 
   NamedType JmpBuf = NamedType<"jmp_buf">;
 
@@ -107,6 +109,36 @@ def StdC : StandardSpec<"stdc"> {
               RetValSpec<IntType>,
               [ArgSpec<IntType>]
           >,
+          FunctionSpec<
+              "isdigit_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleTType>]
+          >,
+          FunctionSpec<
+              "isxdigit_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleTType>]
+          >,
+          FunctionSpec<
+              "tolower_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleTType>]
+          >,
+          FunctionSpec<
+              "toupper_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleTType>]
+          >,
+          FunctionSpec<
+              "islower_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleTType>]
+          >,
+          FunctionSpec<
+              "isupper_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleTType>]
+          >,
       ]
   >;
 
@@ -1139,6 +1171,29 @@ def StdC : StandardSpec<"stdc"> {
           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<LocaleTType>]>,
+          FunctionSpec<"strtod_l", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleTType>]>,
+          FunctionSpec<"strtold_l", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleTType>]>,
+          FunctionSpec<"strtol_l", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleTType>]>,
+          FunctionSpec<"strtoll_l", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleTType>]>,
+          FunctionSpec<"strtoul_l", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleTType>]>,
+          FunctionSpec<"strtoull_l", RetValSpec<UnsignedLongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleTType>]>,
+
+          FunctionSpec<
+              "strxfrm_l",
+              RetValSpec<SizeTType>,
+              [ArgSpec<CharRestrictedPtr>,
+               ArgSpec<ConstCharRestrictedPtr>,
+               ArgSpec<SizeTType>,
+               ArgSpec<LocaleTType>]
+          >,
+          FunctionSpec<
+              "strcoll_l",
+              RetValSpec<IntType>,
+              [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<LocaleTType>]
+          >,
+
           FunctionSpec<"malloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>]>,
           FunctionSpec<"calloc", RetValSpec<VoidPtr>, [ArgSpec<SizeTType>, ArgSpec<SizeTType>]>,
           FunctionSpec<"realloc", RetValSpec<VoidPtr>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]>,
@@ -1439,7 +1494,7 @@ def StdC : StandardSpec<"stdc"> {
               "mktime",
               RetValSpec<TimeTType>,
               [ArgSpec<StructTmPtr>]
-          >,
+          >,      
           FunctionSpec<
               "time",
               RetValSpec<TimeTType>,
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 09b16be1e2d42..00dc2bba141aa 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -4,6 +4,7 @@ add_subdirectory(ctype)
 add_subdirectory(errno)
 add_subdirectory(fenv)
 add_subdirectory(inttypes)
+add_subdirectory(locale)
 add_subdirectory(math)
 add_subdirectory(stdbit)
 add_subdirectory(stdfix)
diff --git a/libc/src/ctype/CMakeLists.txt b/libc/src/ctype/CMakeLists.txt
index ae4eec9615dc1..19e5ef609e93c 100644
--- a/libc/src/ctype/CMakeLists.txt
+++ b/libc/src/ctype/CMakeLists.txt
@@ -146,3 +146,76 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.ctype_utils
 )
+
+add_entrypoint_object(
+  isdigit_l
+  SRCS
+    isdigit_l.cpp
+  HDRS
+    isdigit_l.h
+  DEPENDS
+    libc.src.ctype.isdigit
+    libc.include.llvm-libc-types.locale_t
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isxdigit_l
+  SRCS
+    isxdigit_l.cpp
+  HDRS
+    isxdigit_l.h
+  DEPENDS
+    libc.src.ctype.isxdigit
+    libc.include.llvm-libc-types.locale_t
+    libc.src.__support.ctype_utils
+)
+
+
+add_entrypoint_object(
+  islower_l
+  SRCS
+    islower_l.cpp
+  HDRS
+    islower_l.h
+  DEPENDS
+    libc.src.ctype.islower
+    libc.include.llvm-libc-types.locale_t
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isupper_l
+  SRCS
+    isupper_l.cpp
+  HDRS
+    isupper_l.h
+  DEPENDS
+    libc.src.ctype.isupper
+    libc.include.llvm-libc-types.locale_t
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  tolower_l
+  SRCS
+    tolower_l.cpp
+  HDRS
+    tolower_l.h
+  DEPENDS
+    libc.src.ctype.tolower
+    libc.include.llvm-libc-types.locale_t
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  toupper_l
+  SRCS
+    toupper_l.cpp
+  HDRS
+    toupper_l.h
+  DEPENDS
+    libc.src.ctype.toupper
+    libc.include.llvm-libc-types.locale_t
+    libc.src.__support.ctype_utils
+)
diff --git a/libc/src/ctype/isdigit_l.cpp b/libc/src/ctype/isdigit_l.cpp
new file mode 100644
index 0000000000000..24efd563582cc
--- /dev/null
+++ b/libc/src/ctype/isdigit_l....
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/97494


More information about the libc-commits mailing list