diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -7,8 +7,11 @@ libc.src.ctype.isdigit libc.src.ctype.isgraph libc.src.ctype.islower + libc.src.ctype.isprint libc.src.ctype.ispunct + libc.src.ctype.isspace libc.src.ctype.isupper + libc.src.ctype.isxdigit # errno.h entrypoints libc.src.errno.__errno_location 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 @@ -10,8 +10,11 @@ libc.src.ctype.isdigit libc.src.ctype.isgraph libc.src.ctype.islower + libc.src.ctype.isprint libc.src.ctype.ispunct + libc.src.ctype.isspace libc.src.ctype.isupper + libc.src.ctype.isxdigit # errno.h entrypoints libc.src.errno.__errno_location diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -81,16 +81,31 @@ RetValSpec, [ArgSpec] >, + FunctionSpec< + "isprint", + RetValSpec, + [ArgSpec] + >, FunctionSpec< "ispunct", RetValSpec, [ArgSpec] >, + FunctionSpec< + "isspace", + RetValSpec, + [ArgSpec] + >, FunctionSpec< "isupper", RetValSpec, [ArgSpec] >, + FunctionSpec< + "isxdigit", + RetValSpec, + [ArgSpec] + >, ] >; diff --git a/libc/src/ctype/CMakeLists.txt b/libc/src/ctype/CMakeLists.txt --- a/libc/src/ctype/CMakeLists.txt +++ b/libc/src/ctype/CMakeLists.txt @@ -68,6 +68,14 @@ islower.h ) +add_entrypoint_object( + isprint + SRCS + isprint.cpp + HDRS + isprint.h +) + add_entrypoint_object( ispunct SRCS @@ -78,6 +86,14 @@ .ctype_utils ) +add_entrypoint_object( + isspace + SRCS + isspace.cpp + HDRS + isspace.h +) + add_entrypoint_object( isupper SRCS @@ -85,3 +101,13 @@ HDRS isupper.h ) + +add_entrypoint_object( + isxdigit + SRCS + isxdigit.cpp + HDRS + isxdigit.h + DEPENDS + .ctype_utils +) diff --git a/libc/src/ctype/isprint.h b/libc/src/ctype/isprint.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isprint.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isprint -------------------------*-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_CTYPE_ISPRINT_H +#define LLVM_LIBC_SRC_CTYPE_ISPRINT_H + +namespace __llvm_libc { + +int isprint(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISPRINT_H diff --git a/libc/src/ctype/isprint.cpp b/libc/src/ctype/isprint.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isprint.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of isprint------------------------------------------===// +// +// 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/ctype/isprint.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Currently restricted to default locale. +// These should be extended using locale information. +int LLVM_LIBC_ENTRYPOINT(isprint)(int c) { + const unsigned ch = c; + return (ch - ' ') < 95; +} + +} // namespace __llvm_libc diff --git a/libc/src/ctype/isspace.h b/libc/src/ctype/isspace.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isspace.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isspace -------------------------*-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_CTYPE_ISSPACE_H +#define LLVM_LIBC_SRC_CTYPE_ISSPACE_H + +namespace __llvm_libc { + +int isspace(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISSPACE_H diff --git a/libc/src/ctype/isspace.cpp b/libc/src/ctype/isspace.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isspace.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of isspace------------------------------------------===// +// +// 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/ctype/isspace.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Currently restricted to default locale. +// These should be extended using locale information. +int LLVM_LIBC_ENTRYPOINT(isspace)(int c) { + const unsigned ch = c; + return ch == ' ' || (ch - '\t') < 5; +} + +} // namespace __llvm_libc diff --git a/libc/src/ctype/isxdigit.h b/libc/src/ctype/isxdigit.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isxdigit.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isxdigit ------------------------*-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_CTYPE_ISXDIGIT_H +#define LLVM_LIBC_SRC_CTYPE_ISXDIGIT_H + +namespace __llvm_libc { + +int isxdigit(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISXDIGIT_H diff --git a/libc/src/ctype/isxdigit.cpp b/libc/src/ctype/isxdigit.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isxdigit.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of isxdigit-----------------------------------------===// +// +// 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/ctype/isxdigit.h" +#include "src/ctype/ctype_utils.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Currently restricted to default locale. +// These should be extended using locale information. +int LLVM_LIBC_ENTRYPOINT(isxdigit)(int c) { + const unsigned ch = c; + return internal::isdigit(ch) || (ch | 32) - 'a' < 6; +} + +} // namespace __llvm_libc diff --git a/libc/test/src/ctype/CMakeLists.txt b/libc/test/src/ctype/CMakeLists.txt --- a/libc/test/src/ctype/CMakeLists.txt +++ b/libc/test/src/ctype/CMakeLists.txt @@ -70,6 +70,16 @@ libc.src.ctype.islower ) +add_libc_unittest( + isprint + SUITE + libc_ctype_unittests + SRCS + isprint_test.cpp + DEPENDS + libc.src.ctype.isprint +) + add_libc_unittest( ispunct SUITE @@ -80,6 +90,16 @@ libc.src.ctype.ispunct ) +add_libc_unittest( + isspace + SUITE + libc_ctype_unittests + SRCS + isspace_test.cpp + DEPENDS + libc.src.ctype.isspace +) + add_libc_unittest( isupper SUITE @@ -89,3 +109,13 @@ DEPENDS libc.src.ctype.isupper ) + +add_libc_unittest( + isxdigit + SUITE + libc_ctype_unittests + SRCS + isxdigit_test.cpp + DEPENDS + libc.src.ctype.isxdigit +) diff --git a/libc/test/src/ctype/isprint_test.cpp b/libc/test/src/ctype/isprint_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isprint_test.cpp @@ -0,0 +1,19 @@ +//===-- Unittests for isprint----------------------------------------------===// +// +// 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/ctype/isprint.h" +#include "utils/UnitTest/Test.h" + +TEST(IsPrint, DefaultLocale) { + for (int ch = 0; ch < 255; ++ch) { + if (' ' <= ch && ch <= '~') // A-Z, a-z, 0-9, punctuation, space. + EXPECT_NE(__llvm_libc::isprint(ch), 0); + else + EXPECT_EQ(__llvm_libc::isprint(ch), 0); + } +} diff --git a/libc/test/src/ctype/isspace_test.cpp b/libc/test/src/ctype/isspace_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isspace_test.cpp @@ -0,0 +1,28 @@ +//===-- Unittests for isspace----------------------------------------------===// +// +// 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/ctype/isspace.h" +#include "utils/UnitTest/Test.h" + +TEST(IsSpace, DefaultLocale) { + // Loops through all characters, verifying that space characters + // return true and everything else returns false. + // Hexadecimal | Symbol + // --------------------------- + // 0x09 | horizontal tab + // 0x0a | line feed + // 0x0b | vertical tab + // 0x0d | carriage return + // 0x20 | space + for (int ch = 0; ch < 255; ++ch) { + if (ch == 0x20 || (0x09 <= ch && ch <= 0x0d)) + EXPECT_NE(__llvm_libc::isspace(ch), 0); + else + EXPECT_EQ(__llvm_libc::isspace(ch), 0); + } +} diff --git a/libc/test/src/ctype/isxdigit_test.cpp b/libc/test/src/ctype/isxdigit_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isxdigit_test.cpp @@ -0,0 +1,20 @@ +//===-- Unittests for isxdigit---------------------------------------------===// +// +// 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/ctype/isxdigit.h" +#include "utils/UnitTest/Test.h" + +TEST(IsXDigit, DefaultLocale) { + for (int ch = 0; ch < 255; ++ch) { + if (('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || + ('A' <= ch && ch <= 'F')) + EXPECT_NE(__llvm_libc::isxdigit(ch), 0); + else + EXPECT_EQ(__llvm_libc::isxdigit(ch), 0); + } +}