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 @@ -1,4 +1,7 @@ set(TARGET_LIBC_ENTRYPOINTS + # ctype.h entrypoints + libc.src.ctype.isalpha + # errno.h entrypoints libc.src.errno.__errno_location diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -86,6 +86,14 @@ ]; } +def CTypeAPI : PublicAPI<"ctype.h"> { + let TypeDeclarations = []; + + let Functions = [ + "isalpha", + ]; +} + def MathErrHandlingMacro : MacroDef<"math_errhandling"> { let Defn = [{ #ifndef math_errhandling 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 @@ -1,6 +1,9 @@ set(TARGET_LIBC_ENTRYPOINTS # assert.h entrypoints libc.src.assert.__assert_fail + + # ctype.h entrypoints + libc.src.ctype.isalpha # errno.h entrypoints libc.src.errno.__errno_location diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -17,10 +17,10 @@ __llvm-libc-stdc-types.h ) -add_header( +add_gen_header( ctype - HDR - ctype.h + DEF_FILE ctype.h.def + GEN_HDR ctype.h DEPENDS .llvm_libc_common_h ) diff --git a/libc/include/ctype.h.def b/libc/include/ctype.h.def new file mode 100644 --- /dev/null +++ b/libc/include/ctype.h.def @@ -0,0 +1,16 @@ +//===-- C standard library header ctype.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_CTYPE_H +#define LLVM_LIBC_CTYPE_H + +#include <__llvm-libc-common.h> + +%%public_api() + +#endif // LLVM_LIBC_CTYPE_H diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -39,7 +39,21 @@ [], // Enumerations [] >; - + + HeaderSpec CType = HeaderSpec< + "ctype.h", + [], // Macros + [], // Types + [], // Enumerations + [ + FunctionSpec< + "isalpha", + RetValSpec, + [ArgSpec] + >, + ] + >; + HeaderSpec String = HeaderSpec< "string.h", [ @@ -386,6 +400,7 @@ let Headers = [ Assert, + CType, Errno, Math, String, diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(assert) +add_subdirectory(ctype) add_subdirectory(errno) add_subdirectory(math) add_subdirectory(signal) diff --git a/libc/src/ctype/CMakeLists.txt b/libc/src/ctype/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/src/ctype/CMakeLists.txt @@ -0,0 +1,7 @@ +add_entrypoint_object( + isalpha + SRCS + isalpha.cpp + HDRS + isalpha.h +) diff --git a/libc/src/ctype/isalpha.h b/libc/src/ctype/isalpha.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isalpha.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isalpha -------------------------*-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_ISALPHA_H +#define LLVM_LIBC_SRC_CTYPE_ISALPHA_H + +namespace __llvm_libc { + +int isalpha(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISALPHA_H diff --git a/libc/src/ctype/isalpha.cpp b/libc/src/ctype/isalpha.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isalpha.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of isalpha------------------------------------------===// +// +// 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/isalpha.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(isalpha)(int c) { + const unsigned ch = c; + return (ch | 32) - 'a' < 26; +} + +} // namespace __llvm_libc diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(assert) +add_subdirectory(ctype) add_subdirectory(errno) add_subdirectory(math) add_subdirectory(signal) @@ -91,4 +92,4 @@ target_link_libraries(libc-integration-test PRIVATE ${library_files} -) \ No newline at end of file +) diff --git a/libc/test/src/ctype/CMakeLists.txt b/libc/test/src/ctype/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/CMakeLists.txt @@ -0,0 +1,11 @@ +add_libc_testsuite(libc_ctype_unittests) + +add_libc_unittest( + isalpha + SUITE + libc_ctype_unittests + SRCS + isalpha_test.cpp + DEPENDS + libc.src.ctype.isalpha +) diff --git a/libc/test/src/ctype/isalpha_test.cpp b/libc/test/src/ctype/isalpha_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isalpha_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for isalpha----------------------------------------------===// +// +// 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/isalpha.h" +#include "utils/UnitTest/Test.h" + +// Helper function that makes a call to isalpha a bit cleaner +// for use with testing utilities, since it explicitly requires +// a boolean value for EXPECT_TRUE and EXPECT_FALSE. +bool call_isalpha(int c) { return __llvm_libc::isalpha(c); } + +TEST(IsAlpha, DefaultLocale) { + // Loops through all characters, verifying that letters return true + // and everything else returns false. + for (int ch = 0; ch < 255; ++ch) { + if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) + EXPECT_TRUE(call_isalpha(ch)); + else + EXPECT_FALSE(call_isalpha(ch)); + } +}