Skip to content

[libc] Implement locale variants for 'stdlib.h' functions #105718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions libc/config/gpu/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,19 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.rand
libc.src.stdlib.srand
libc.src.stdlib.strtod
libc.src.stdlib.strtod_l
libc.src.stdlib.strtof
libc.src.stdlib.strtof_l
libc.src.stdlib.strtol
libc.src.stdlib.strtol_l
libc.src.stdlib.strtold
libc.src.stdlib.strtold_l
libc.src.stdlib.strtoll
libc.src.stdlib.strtoll_l
libc.src.stdlib.strtoul
libc.src.stdlib.strtoul_l
libc.src.stdlib.strtoull
libc.src.stdlib.strtoull_l
libc.src.stdlib.at_quick_exit
libc.src.stdlib.quick_exit
libc.src.stdlib.getenv
Expand Down
9 changes: 9 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,15 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.ctype.tolower_l
libc.src.ctype.toupper_l

# stdlib.h entrypoints
libc.src.stdlib.strtod_l
libc.src.stdlib.strtof_l
libc.src.stdlib.strtol_l
libc.src.stdlib.strtold_l
libc.src.stdlib.strtoll_l
libc.src.stdlib.strtoul_l
libc.src.stdlib.strtoull_l

# assert.h entrypoints
libc.src.assert.__assert_fail

Expand Down
5 changes: 5 additions & 0 deletions libc/include/llvm-libc-macros/stdlib-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#ifndef MB_CUR_MAX
// We only support the "C" locale right now, so this is a constant byte.
#define MB_CUR_MAX 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this going to be stable? I remember we ran into issues with MB_LEN_MAX. Also should this be moved to limits-macros.h to be in the same place as MB_LEN_MAX?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, in a real implementation this would be non-constant. And I don't think so, this is specifically mentioned in the standard as being provided by stdlib.h

       The <stdlib.h> header shall define the following macro which shall
       expand to a positive integer expression with type size_t:

       {MB_CUR_MAX}
                   Maximum number of bytes in a character specified by the
                   current locale (category LC_CTYPE).

       In the POSIX locale the value of {MB_CUR_MAX} shall be 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me then

#endif // MB_CUR_MAX

#define RAND_MAX 2147483647

#endif // LLVM_LIBC_MACROS_STDLIB_MACROS_H
1 change: 1 addition & 0 deletions libc/include/stdlib.h.def
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_LIBC_STDLIB_H

#include "__llvm-libc-common.h"
#include "llvm-libc-types/locale_t.h"
#include "llvm-libc-macros/stdlib-macros.h"

%%public_api()
Expand Down
60 changes: 60 additions & 0 deletions libc/newhdrgen/yaml/stdlib.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,63 @@ functions:
- type: const char *__restrict
- type: char **__restrict
- type: int
- name: strtod_l
standards:
- stdc
return_type: double
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: locale_t
- name: strtof_l
standards:
- stdc
return_type: float
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: locale_t
- name: strtol_l
standards:
- stdc
return_type: long
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: int
- type: locale_t
- name: strtold_l
standards:
- stdc
return_type: long double
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: locale_t
- name: strtoll_l
standards:
- stdc
return_type: long long
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: int
- type: locale_t
- name: strtoul_l
standards:
- stdc
return_type: unsigned long
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: int
- type: locale_t
- name: strtoull_l
standards:
- stdc
return_type: unsigned long long
arguments:
- type: const char *__restrict
- type: char **__restrict
- type: int
- type: locale_t
8 changes: 8 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,14 @@ 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", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
FunctionSpec<"strtold", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<LocaleT>]>,
FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
FunctionSpec<"strtoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
FunctionSpec<"strtoul", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>, ArgSpec<LocaleT>]>,
FunctionSpec<"strtoull", 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>]>,
Expand Down
77 changes: 77 additions & 0 deletions libc/src/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,83 @@ if(NOT LLVM_LIBC_FULL_BUILD)
return()
endif()

add_entrypoint_object(
strtof_l
SRCS
strtof_l.cpp
HDRS
strtof_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_float
)

add_entrypoint_object(
strtod_l
SRCS
strtod_l.cpp
HDRS
strtod_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_float
)

add_entrypoint_object(
strtold_l
SRCS
strtold_l.cpp
HDRS
strtold_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_float
)

add_entrypoint_object(
strtol_l
SRCS
strtol_l.cpp
HDRS
strtol_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_integer
)

add_entrypoint_object(
strtoll_l
SRCS
strtoll_l.cpp
HDRS
strtoll_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_integer
)

add_entrypoint_object(
strtoul_l
SRCS
strtoul_l.cpp
HDRS
strtoul_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_integer
)

add_entrypoint_object(
strtoull_l
SRCS
strtoull_l.cpp
HDRS
strtoull_l.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_integer
)

if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
endif()
Expand Down
30 changes: 30 additions & 0 deletions libc/src/stdlib/strtod_l.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Implementation of strtod_l ----------------------------------------===//
//
// 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/stdlib/strtod_l.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/str_to_float.h"
#include "src/errno/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(double, strtod_l,
(const char *__restrict str, char **__restrict str_end,
locale_t)) {
auto result = internal::strtofloatingpoint<double>(str);
if (result.has_error())
libc_errno = result.error;

if (str_end != nullptr)
*str_end = const_cast<char *>(str + result.parsed_len);

return result.value;
}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/stdlib/strtod_l.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for strtod_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_STDLIB_STRTOD_L_H
#define LLVM_LIBC_SRC_STDLIB_STRTOD_L_H

#include "include/llvm-libc-types/locale_t.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

double strtod_l(const char *__restrict str, char **__restrict str_end,
locale_t locale);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_STDLIB_STRTOD_L_H
30 changes: 30 additions & 0 deletions libc/src/stdlib/strtof_l.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Implementation of strtof_l ----------------------------------------===//
//
// 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/stdlib/strtof_l.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/str_to_float.h"
#include "src/errno/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float, strtof_l,
(const char *__restrict str, char **__restrict str_end,
locale_t)) {
auto result = internal::strtofloatingpoint<float>(str);
if (result.has_error())
libc_errno = result.error;

if (str_end != nullptr)
*str_end = const_cast<char *>(str + result.parsed_len);

return result.value;
}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/stdlib/strtof_l.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for strtof_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_STDLIB_STRTOF_L_H
#define LLVM_LIBC_SRC_STDLIB_STRTOF_L_H

#include "include/llvm-libc-types/locale_t.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

float strtof_l(const char *__restrict str, char **__restrict str_end,
locale_t locale);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_STDLIB_STRTOF_L_H
30 changes: 30 additions & 0 deletions libc/src/stdlib/strtol_l.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Implementation of strtol_l ----------------------------------------===//
//
// 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/stdlib/strtol_l.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/str_to_integer.h"
#include "src/errno/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(long, strtol_l,
(const char *__restrict str, char **__restrict str_end,
int base, locale_t)) {
auto result = internal::strtointeger<long>(str, base);
if (result.has_error())
libc_errno = result.error;

if (str_end != nullptr)
*str_end = const_cast<char *>(str + result.parsed_len);

return result;
}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/stdlib/strtol_l.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for strtol_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_STDLIB_STRTOL_L_H
#define LLVM_LIBC_SRC_STDLIB_STRTOL_L_H

#include "include/llvm-libc-types/locale_t.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

long strtol_l(const char *__restrict str, char **__restrict str_end, int base,
locale_t locale);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_STDLIB_STRTOL_L_H
Loading
Loading