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 @@ -157,6 +157,9 @@ libc.src.stdlib._Exit libc.src.stdlib.abort libc.src.stdlib.abs + libc.src.stdlib.atoi + libc.src.stdlib.atol + libc.src.stdlib.atoll libc.src.stdlib.labs libc.src.stdlib.llabs libc.src.stdlib.strtol diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -476,6 +476,9 @@ [ FunctionSpec<"abort", RetValSpec, [ArgSpec]>, FunctionSpec<"abs", RetValSpec, [ArgSpec]>, + FunctionSpec<"atoi", RetValSpec, [ArgSpec]>, + FunctionSpec<"atol", RetValSpec, [ArgSpec]>, + FunctionSpec<"atoll", RetValSpec, [ArgSpec]>, FunctionSpec<"labs", RetValSpec, [ArgSpec]>, FunctionSpec<"llabs", RetValSpec, [ArgSpec]>, FunctionSpec<"strtol", RetValSpec, [ArgSpec, ArgSpec, 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 @@ -31,6 +31,36 @@ libc.src.__support.integer_operations ) +add_entrypoint_object( + atoi + SRCS + atoi.cpp + HDRS + atoi.h + DEPENDS + libc.src.__support.str_conv_utils +) + +add_entrypoint_object( + atol + SRCS + atol.cpp + HDRS + atol.h + DEPENDS + libc.src.__support.str_conv_utils +) + +add_entrypoint_object( + atoll + SRCS + atoll.cpp + HDRS + atoll.h + DEPENDS + libc.src.__support.str_conv_utils +) + add_entrypoint_object( labs SRCS diff --git a/libc/src/stdlib/atoi.h b/libc/src/stdlib/atoi.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/atoi.h @@ -0,0 +1,18 @@ +//===-- Implementation header for atoi --------------------------*- 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_ATOI_H +#define LLVM_LIBC_SRC_STDLIB_ATOI_H + +namespace __llvm_libc { + +int atoi(const char *str); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_ATOI_H diff --git a/libc/src/stdlib/atoi.cpp b/libc/src/stdlib/atoi.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/atoi.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of atoi --------------------------------------------===// +// +// 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/atoi.h" +#include "src/__support/common.h" +#include "src/__support/str_conv_utils.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, atoi, (const char *str)) { + return internal::strtointeger(str, nullptr, 10); +} + +} // namespace __llvm_libc diff --git a/libc/src/stdlib/atol.h b/libc/src/stdlib/atol.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/atol.h @@ -0,0 +1,18 @@ +//===-- Implementation header for atol --------------------------*- 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_ATOL_H +#define LLVM_LIBC_SRC_STDLIB_ATOL_H + +namespace __llvm_libc { + +long atol(const char *str); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_ATOL_H diff --git a/libc/src/stdlib/atol.cpp b/libc/src/stdlib/atol.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/atol.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of atol --------------------------------------------===// +// +// 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/atol.h" +#include "src/__support/common.h" +#include "src/__support/str_conv_utils.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(long, atol, (const char *str)) { + return internal::strtointeger(str, nullptr, 10); +} + +} // namespace __llvm_libc diff --git a/libc/src/stdlib/atoll.h b/libc/src/stdlib/atoll.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/atoll.h @@ -0,0 +1,18 @@ +//===-- Implementation header for atoll -------------------------*- 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_ATOLL_H +#define LLVM_LIBC_SRC_STDLIB_ATOLL_H + +namespace __llvm_libc { + +long long atoll(const char *str); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_ATOLL_H diff --git a/libc/src/stdlib/atoll.cpp b/libc/src/stdlib/atoll.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/atoll.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of atoll -------------------------------------------===// +// +// 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/atoll.h" +#include "src/__support/common.h" +#include "src/__support/str_conv_utils.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(long long, atoll, (const char *str)) { + return internal::strtointeger(str, nullptr, 10); +} + +} // namespace __llvm_libc diff --git a/libc/test/src/stdlib/atoi_test.cpp b/libc/test/src/stdlib/atoi_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/stdlib/atoi_test.cpp @@ -0,0 +1,68 @@ +//===-- Unittests for atoi -----------------------------------------------===// +// +// 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/atoi.h" + +#include "utils/UnitTest/Test.h" + +#include + +TEST(LlvmLibcAToITest, ValidNumbers) { + const char *zero = "0"; + ASSERT_EQ(__llvm_libc::atoi(zero), 0); + + const char *ten = "10"; + ASSERT_EQ(__llvm_libc::atoi(ten), 10); + + const char *negative_hundred = "-100"; + ASSERT_EQ(__llvm_libc::atoi(negative_hundred), -100); + + const char *positive_thousand = "+1000"; + ASSERT_EQ(__llvm_libc::atoi(positive_thousand), 1000); + + const char *spaces_before = " 12345"; + ASSERT_EQ(__llvm_libc::atoi(spaces_before), 12345); + + const char *tabs_before = "\t\t\t\t67890"; + ASSERT_EQ(__llvm_libc::atoi(tabs_before), 67890); + + const char *letters_after = "123abc"; + ASSERT_EQ(__llvm_libc::atoi(letters_after), 123); + + const char *letters_between = "456def789"; + ASSERT_EQ(__llvm_libc::atoi(letters_between), 456); + + const char *all_together = "\t 110 times 5 = 550"; + ASSERT_EQ(__llvm_libc::atoi(all_together), 110); + + const char *biggest_int = "2147483647"; + ASSERT_EQ(__llvm_libc::atoi(biggest_int), INT_MAX); + + const char *smallest_int = "-2147483648"; + ASSERT_EQ(__llvm_libc::atoi(smallest_int), INT_MIN); +} + +TEST(LlvmLibcAToITest, NonBaseTenWholeNumbers) { + const char *hexadecimal = "0x10"; + ASSERT_EQ(__llvm_libc::atoi(hexadecimal), 0); + + const char *octal = "010"; + ASSERT_EQ(__llvm_libc::atoi(octal), 10); + + const char *decimal_point = "5.9"; + ASSERT_EQ(__llvm_libc::atoi(decimal_point), 5); +} + +TEST(LlvmLibcAToITest, NotNumbers) { + const char *ten_as_word = "ten"; + ASSERT_EQ(__llvm_libc::atoi(ten_as_word), 0); + + const char *lots_of_letters = + "wtragsdhfgjykutjdyfhgnchgmjhkyurktfgjhlu;po7urtdjyfhgklyk"; + ASSERT_EQ(__llvm_libc::atoi(lots_of_letters), 0); +} diff --git a/libc/test/src/stdlib/atol_test.cpp b/libc/test/src/stdlib/atol_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/stdlib/atol_test.cpp @@ -0,0 +1,62 @@ +//===-- Unittests for atol -----------------------------------------------===// +// +// 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/atol.h" + +#include "utils/UnitTest/Test.h" + +#include + +TEST(LlvmLibcAToLTest, ValidNumbers) { + const char *zero = "0"; + ASSERT_EQ(__llvm_libc::atol(zero), 0l); + + const char *ten = "10"; + ASSERT_EQ(__llvm_libc::atol(ten), 10l); + + const char *negative_hundred = "-100"; + ASSERT_EQ(__llvm_libc::atol(negative_hundred), -100l); + + const char *positive_thousand = "+1000"; + ASSERT_EQ(__llvm_libc::atol(positive_thousand), 1000l); + + const char *spaces_before = " 12345"; + ASSERT_EQ(__llvm_libc::atol(spaces_before), 12345l); + + const char *tabs_before = "\t\t\t\t67890"; + ASSERT_EQ(__llvm_libc::atol(tabs_before), 67890l); + + const char *letters_after = "123abc"; + ASSERT_EQ(__llvm_libc::atol(letters_after), 123l); + + const char *letters_between = "456def789"; + ASSERT_EQ(__llvm_libc::atol(letters_between), 456l); + + const char *all_together = "\t 110 times 5 = 550"; + ASSERT_EQ(__llvm_libc::atol(all_together), 110l); +} + +TEST(LlvmLibcAToLTest, NonBaseTenWholeNumbers) { + const char *hexadecimal = "0x10"; + ASSERT_EQ(__llvm_libc::atol(hexadecimal), 0l); + + const char *octal = "010"; + ASSERT_EQ(__llvm_libc::atol(hexadecimal), 10l); + + const char *decimal_point = "5.9"; + ASSERT_EQ(__llvm_libc::atol(decimal_point), 5l); +} + +TEST(LlvmLibcAToLTest, NotNumbers) { + const char *ten_as_word = "ten"; + ASSERT_EQ(__llvm_libc::atol(ten_as_word), 0l); + + const char *lots_of_letters = + "wtragsdhfgjykutjdyfhgnchgmjhkyurktfgjhlu;po7urtdjyfhgklyk"; + ASSERT_EQ(__llvm_libc::atol(lots_of_letters), 0l); +} diff --git a/libc/test/src/stdlib/atoll_test.cpp b/libc/test/src/stdlib/atoll_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/stdlib/atoll_test.cpp @@ -0,0 +1,68 @@ +//===-- Unittests for atoll -----------------------------------------------===// +// +// 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/atoll.h" + +#include "utils/UnitTest/Test.h" + +#include + +TEST(LlvmLibcAToLLTest, ValidNumbers) { + const char *zero = "0"; + ASSERT_EQ(__llvm_libc::atoll(zero), 0ll); + + const char *ten = "10"; + ASSERT_EQ(__llvm_libc::atoll(ten), 10ll); + + const char *negative_hundred = "-100"; + ASSERT_EQ(__llvm_libc::atoll(negative_hundred), -100ll); + + const char *positive_thousand = "+1000"; + ASSERT_EQ(__llvm_libc::atoll(positive_thousand), 1000ll); + + const char *spaces_before = " 12345"; + ASSERT_EQ(__llvm_libc::atoll(spaces_before), 12345ll); + + const char *tabs_before = "\t\t\t\t67890"; + ASSERT_EQ(__llvm_libc::atoll(tabs_before), 67890ll); + + const char *letters_after = "123abc"; + ASSERT_EQ(__llvm_libc::atoll(letters_after), 123ll); + + const char *letters_between = "456def789"; + ASSERT_EQ(__llvm_libc::atoll(letters_between), 456ll); + + const char *all_together = "\t 110 times 5 = 550"; + ASSERT_EQ(__llvm_libc::atoll(all_together), 110ll); + + const char *biggest_long_long = "9223372036854775807"; + ASSERT_EQ(__llvm_libc::atoll(biggest_int), LLONG_MAX); + + const char *smallest_long_long = "-9223372036854775808"; + ASSERT_EQ(__llvm_libc::atoll(smallest_int), LLONG_MIN); +} + +TEST(LlvmLibcAToLLTest, NonBaseTenWholeNumbers) { + const char *hexadecimal = "0x10"; + ASSERT_EQ(__llvm_libc::atoll(hexadecimal), 0ll); + + const char *octal = "010"; + ASSERT_EQ(__llvm_libc::atoll(hexadecimal), 10ll); + + const char *decimal_point = "5.9"; + ASSERT_EQ(__llvm_libc::atol(decimal_point), 5l); +} + +TEST(LlvmLibcAToLLTest, NotNumbers) { + const char *ten_as_word = "ten"; + ASSERT_EQ(__llvm_libc::atoll(ten_as_word), 0ll); + + const char *lots_of_letters = + "wtragsdhfgjykutjdyfhgnchgmjhkyurktfgjhlu;po7urtdjyfhgklyk"; + ASSERT_EQ(__llvm_libc::atoll(lots_of_letters), 0ll); +}