diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -70,8 +70,10 @@ libc.src.stdlib.strtof libc.src.stdlib.strtol libc.src.stdlib.strtoll + libc.src.stdlib.strtoq libc.src.stdlib.strtoul libc.src.stdlib.strtoull + libc.src.stdlib.strtouq ) set(TARGET_LIBM_ENTRYPOINTS diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -510,8 +510,10 @@ FunctionSpec<"strtof", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"strtol", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoll", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"strtoq", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoul", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoull", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"strtouq", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"_Exit", RetValSpec, [ArgSpec]>, ] diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt --- a/libc/src/stdlib/CMakeLists.txt +++ b/libc/src/stdlib/CMakeLists.txt @@ -78,6 +78,16 @@ libc.src.__support.str_conv_utils ) +add_entrypoint_object( + strtoq + SRCS + strtoq.cpp + HDRS + strtoq.h + DEPENDS + libc.src.__support.str_conv_utils +) + add_entrypoint_object( strtoul SRCS @@ -98,6 +108,16 @@ libc.src.__support.str_conv_utils ) +add_entrypoint_object( + strtouq + SRCS + strtouq.cpp + HDRS + strtouq.h + DEPENDS + libc.src.__support.str_conv_utils +) + add_entrypoint_object( abs SRCS diff --git a/libc/src/stdlib/strtoq.h b/libc/src/stdlib/strtoq.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtoq.h @@ -0,0 +1,19 @@ +//===-- Implementation header for strtoq ------------------------*- 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_STRTOQ_H +#define LLVM_LIBC_SRC_STDLIB_STRTOQ_H + +namespace __llvm_libc { + +long long strtoq(const char *__restrict str, char **__restrict str_end, + int base); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_STRTOQ_H diff --git a/libc/src/stdlib/strtoq.cpp b/libc/src/stdlib/strtoq.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtoq.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of strtoq -----------------------------------------===// +// +// 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/strtoq.h" +#include "src/__support/common.h" +#include "src/__support/str_conv_utils.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(long long, strtoq, + (const char *__restrict str, char **__restrict str_end, + int base)) { + return internal::strtointeger(str, str_end, base); +} + +} // namespace __llvm_libc diff --git a/libc/src/stdlib/strtouq.h b/libc/src/stdlib/strtouq.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtouq.h @@ -0,0 +1,19 @@ +//===-- Implementation header for strtouq -----------------------*- 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_STRTOUQ_H +#define LLVM_LIBC_SRC_STDLIB_STRTOUQ_H + +namespace __llvm_libc { + +unsigned long long strtouq(const char *__restrict str, + char **__restrict str_end, int base); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_STRTOUQ_H diff --git a/libc/src/stdlib/strtouq.cpp b/libc/src/stdlib/strtouq.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtouq.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of strtouq -----------------------------------------===// +// +// 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/strtouq.h" +#include "src/__support/common.h" +#include "src/__support/str_conv_utils.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(unsigned long long, strtouq, + (const char *__restrict str, char **__restrict str_end, + int base)) { + return internal::strtointeger(str, str_end, base); +} + +} // namespace __llvm_libc diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt --- a/libc/test/src/stdlib/CMakeLists.txt +++ b/libc/test/src/stdlib/CMakeLists.txt @@ -80,6 +80,16 @@ libc.src.stdlib.strtoll ) +add_libc_unittest( + strtoq_test + SUITE + libc_stdlib_unittests + SRCS + strtoq_test.cpp + DEPENDS + libc.src.stdlib.strtoq +) + add_libc_unittest( strtoul_test SUITE @@ -100,6 +110,16 @@ libc.src.stdlib.strtoull ) +add_libc_unittest( + strtouq_test + SUITE + libc_stdlib_unittests + SRCS + strtouq_test.cpp + DEPENDS + libc.src.stdlib.strtouq +) + if(NOT LLVM_LIBC_FULL_BUILD) return() endif() diff --git a/libc/test/src/stdlib/strtoq_test.cpp b/libc/test/src/stdlib/strtoq_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/stdlib/strtoq_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for strtoq ----------------------------------------------===// +// +// 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/strtoq.h" + +#include "utils/UnitTest/Test.h" + +#include +#include +#include + +// strtoq is equivalent to strtoll on all currently supported configurations. +// Thus to avoid duplicating code there is just one test to make sure that +// strtoq works at all. For real tests see stdlib/strtoll_test.cpp. + +TEST(LlvmLibcStrToQTest, SimpleCheck) { + const char *ten = "10"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoq(ten, nullptr, 10), 10ll); + ASSERT_EQ(errno, 0); +} diff --git a/libc/test/src/stdlib/strtouq_test.cpp b/libc/test/src/stdlib/strtouq_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/stdlib/strtouq_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for strtouq -------------------------------------------===// +// +// 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/strtouq.h" + +#include "utils/UnitTest/Test.h" + +#include +#include +#include + +// strtouq is equivalent to strtoull on all currently supported configurations. +// Thus to avoid duplicating code there is just one test to make sure that +// strtouq works at all. For real tests see stdlib/strtoull_test.cpp. + +TEST(LlvmLibcStrToUQTest, SimpleCheck) { + const char *ten = "10"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtouq(ten, nullptr, 10), 10ull); + ASSERT_EQ(errno, 0); +}