[libc] Add implementations for isblank, iscntrl, isgraph, ispunct.
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D85059
GitOrigin-RevId: 6cd50e7b75ed39ba1218c724401117cb6e12748d
diff --git a/config/linux/aarch64/entrypoints.txt b/config/linux/aarch64/entrypoints.txt
index 8314df8..565fbf7 100644
--- a/config/linux/aarch64/entrypoints.txt
+++ b/config/linux/aarch64/entrypoints.txt
@@ -2,8 +2,12 @@
# ctype.h entrypoints
libc.src.ctype.isalnum
libc.src.ctype.isalpha
+ libc.src.ctype.isblank
+ libc.src.ctype.iscntrl
libc.src.ctype.isdigit
+ libc.src.ctype.isgraph
libc.src.ctype.islower
+ libc.src.ctype.ispunct
libc.src.ctype.isupper
# errno.h entrypoints
diff --git a/config/linux/api.td b/config/linux/api.td
index 03d5d66..a57c703 100644
--- a/config/linux/api.td
+++ b/config/linux/api.td
@@ -90,8 +90,12 @@
let Functions = [
"isalnum",
"isalpha",
+ "isblank",
+ "iscntrl",
"isdigit",
+ "isgraph",
"islower",
+ "ispunct",
"isupper",
];
}
diff --git a/config/linux/x86_64/entrypoints.txt b/config/linux/x86_64/entrypoints.txt
index 56a99d0..3cc243e 100644
--- a/config/linux/x86_64/entrypoints.txt
+++ b/config/linux/x86_64/entrypoints.txt
@@ -5,8 +5,12 @@
# ctype.h entrypoints
libc.src.ctype.isalnum
libc.src.ctype.isalpha
+ libc.src.ctype.isblank
+ libc.src.ctype.iscntrl
libc.src.ctype.isdigit
+ libc.src.ctype.isgraph
libc.src.ctype.islower
+ libc.src.ctype.ispunct
libc.src.ctype.isupper
# errno.h entrypoints
diff --git a/spec/stdc.td b/spec/stdc.td
index 4fffc5c..1f14f76 100644
--- a/spec/stdc.td
+++ b/spec/stdc.td
@@ -57,16 +57,36 @@
[ArgSpec<IntType>]
>,
FunctionSpec<
+ "isblank",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "iscntrl",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
"isdigit",
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
FunctionSpec<
+ "isgraph",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
"islower",
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
FunctionSpec<
+ "ispunct",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
"isupper",
RetValSpec<IntType>,
[ArgSpec<IntType>]
diff --git a/src/ctype/CMakeLists.txt b/src/ctype/CMakeLists.txt
index 30995ab..c554e6c 100644
--- a/src/ctype/CMakeLists.txt
+++ b/src/ctype/CMakeLists.txt
@@ -25,6 +25,22 @@
)
add_entrypoint_object(
+ isblank
+ SRCS
+ isblank.cpp
+ HDRS
+ isblank.h
+)
+
+add_entrypoint_object(
+ iscntrl
+ SRCS
+ iscntrl.cpp
+ HDRS
+ iscntrl.h
+)
+
+add_entrypoint_object(
isdigit
SRCS
isdigit.cpp
@@ -35,6 +51,16 @@
)
add_entrypoint_object(
+ isgraph
+ SRCS
+ isgraph.cpp
+ HDRS
+ isgraph.h
+ DEPENDS
+ .ctype_utils
+)
+
+add_entrypoint_object(
islower
SRCS
islower.cpp
@@ -43,6 +69,16 @@
)
add_entrypoint_object(
+ ispunct
+ SRCS
+ ispunct.cpp
+ HDRS
+ ispunct.h
+ DEPENDS
+ .ctype_utils
+)
+
+add_entrypoint_object(
isupper
SRCS
isupper.cpp
diff --git a/src/ctype/ctype_utils.h b/src/ctype/ctype_utils.h
index 4e8d396..787a19e 100644
--- a/src/ctype/ctype_utils.h
+++ b/src/ctype/ctype_utils.h
@@ -18,15 +18,13 @@
// of a function call by inlining them.
// ------------------------------------------------------
-static inline int isdigit(int c) {
- const unsigned ch = c;
- return (ch - '0') < 10;
-}
+static inline int isdigit(unsigned ch) { return (ch - '0') < 10; }
-static inline int isalpha(int c) {
- const unsigned ch = c;
- return (ch | 32) - 'a' < 26;
-}
+static inline int isalpha(unsigned ch) { return (ch | 32) - 'a' < 26; }
+
+static inline int isalnum(unsigned ch) { return isalpha(ch) || isdigit(ch); }
+
+static inline int isgraph(unsigned ch) { return 0x20 < ch && ch < 0x7f; }
} // namespace internal
} // namespace __llvm_libc
diff --git a/src/ctype/isalnum.cpp b/src/ctype/isalnum.cpp
index 08b6520..54c4f80 100644
--- a/src/ctype/isalnum.cpp
+++ b/src/ctype/isalnum.cpp
@@ -15,8 +15,6 @@
// TODO: Currently restricted to default locale.
// These should be extended using locale information.
-int LLVM_LIBC_ENTRYPOINT(isalnum)(int c) {
- return internal::isalpha(c) || internal::isdigit(c);
-}
+int LLVM_LIBC_ENTRYPOINT(isalnum)(int c) { return internal::isalnum(c); }
} // namespace __llvm_libc
diff --git a/src/ctype/isblank.cpp b/src/ctype/isblank.cpp
new file mode 100644
index 0000000..fa28d84
--- /dev/null
+++ b/src/ctype/isblank.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of isblank------------------------------------------===//
+//
+// 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/isblank.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(isblank)(int c) {
+ const unsigned char ch = c;
+ return ch == ' ' || ch == '\t';
+}
+
+} // namespace __llvm_libc
diff --git a/src/ctype/isblank.h b/src/ctype/isblank.h
new file mode 100644
index 0000000..0554322
--- /dev/null
+++ b/src/ctype/isblank.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for isblank -------------------------*-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_ISBLANK_H
+#define LLVM_LIBC_SRC_CTYPE_ISBLANK_H
+
+namespace __llvm_libc {
+
+int isblank(int c);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_CTYPE_ISBLANK_H
diff --git a/src/ctype/iscntrl.cpp b/src/ctype/iscntrl.cpp
new file mode 100644
index 0000000..06ee7cc
--- /dev/null
+++ b/src/ctype/iscntrl.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of iscntrl------------------------------------------===//
+//
+// 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/iscntrl.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(iscntrl)(int c) {
+ const unsigned char ch = c;
+ return ch < 0x20 || ch == 0x7f;
+}
+
+} // namespace __llvm_libc
diff --git a/src/ctype/iscntrl.h b/src/ctype/iscntrl.h
new file mode 100644
index 0000000..26f0940
--- /dev/null
+++ b/src/ctype/iscntrl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for iscntrl -------------------------*-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_ISCNTRL_H
+#define LLVM_LIBC_SRC_CTYPE_ISCNTRL_H
+
+namespace __llvm_libc {
+
+int iscntrl(int c);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_CTYPE_ISCNTRL_H
diff --git a/src/ctype/isgraph.cpp b/src/ctype/isgraph.cpp
new file mode 100644
index 0000000..c7a488c
--- /dev/null
+++ b/src/ctype/isgraph.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of isgraph------------------------------------------===//
+//
+// 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/isgraph.h"
+
+#include "src/__support/common.h"
+#include "src/ctype/ctype_utils.h"
+
+namespace __llvm_libc {
+
+// TODO: Currently restricted to default locale.
+// These should be extended using locale information.
+int LLVM_LIBC_ENTRYPOINT(isgraph)(int c) { return internal::isgraph(c); }
+
+} // namespace __llvm_libc
diff --git a/src/ctype/isgraph.h b/src/ctype/isgraph.h
new file mode 100644
index 0000000..421d0ff
--- /dev/null
+++ b/src/ctype/isgraph.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for isgraph -------------------------*-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_ISGRAPH_H
+#define LLVM_LIBC_SRC_CTYPE_ISGRAPH_H
+
+namespace __llvm_libc {
+
+int isgraph(int c);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_CTYPE_ISGRAPH_H
diff --git a/src/ctype/ispunct.cpp b/src/ctype/ispunct.cpp
new file mode 100644
index 0000000..a810c64
--- /dev/null
+++ b/src/ctype/ispunct.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of ispunct------------------------------------------===//
+//
+// 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/ispunct.h"
+
+#include "src/__support/common.h"
+#include "src/ctype/ctype_utils.h"
+
+namespace __llvm_libc {
+
+// TODO: Currently restricted to default locale.
+// These should be extended using locale information.
+int LLVM_LIBC_ENTRYPOINT(ispunct)(int c) {
+ return !internal::isalnum(c) && internal::isgraph(c);
+}
+
+} // namespace __llvm_libc
diff --git a/src/ctype/ispunct.h b/src/ctype/ispunct.h
new file mode 100644
index 0000000..23cc08a
--- /dev/null
+++ b/src/ctype/ispunct.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ispunct -------------------------*-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_ISPUNCT_H
+#define LLVM_LIBC_SRC_CTYPE_ISPUNCT_H
+
+namespace __llvm_libc {
+
+int ispunct(int c);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_CTYPE_ISPUNCT_H
diff --git a/test/src/ctype/CMakeLists.txt b/test/src/ctype/CMakeLists.txt
index c995946..3adf573 100644
--- a/test/src/ctype/CMakeLists.txt
+++ b/test/src/ctype/CMakeLists.txt
@@ -21,6 +21,26 @@
)
add_libc_unittest(
+ isblank
+ SUITE
+ libc_ctype_unittests
+ SRCS
+ isblank_test.cpp
+ DEPENDS
+ libc.src.ctype.isblank
+)
+
+add_libc_unittest(
+ iscntrl
+ SUITE
+ libc_ctype_unittests
+ SRCS
+ iscntrl_test.cpp
+ DEPENDS
+ libc.src.ctype.iscntrl
+)
+
+add_libc_unittest(
isdigit
SUITE
libc_ctype_unittests
@@ -31,6 +51,16 @@
)
add_libc_unittest(
+ isgraph
+ SUITE
+ libc_ctype_unittests
+ SRCS
+ isgraph_test.cpp
+ DEPENDS
+ libc.src.ctype.isgraph
+)
+
+add_libc_unittest(
islower
SUITE
libc_ctype_unittests
@@ -41,6 +71,16 @@
)
add_libc_unittest(
+ ispunct
+ SUITE
+ libc_ctype_unittests
+ SRCS
+ ispunct_test.cpp
+ DEPENDS
+ libc.src.ctype.ispunct
+)
+
+add_libc_unittest(
isupper
SUITE
libc_ctype_unittests
diff --git a/test/src/ctype/isblank_test.cpp b/test/src/ctype/isblank_test.cpp
new file mode 100644
index 0000000..f024ef6
--- /dev/null
+++ b/test/src/ctype/isblank_test.cpp
@@ -0,0 +1,21 @@
+//===-- Unittests for isblank----------------------------------------------===//
+//
+// 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/isblank.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(IsBlank, DefaultLocale) {
+ // Loops through all characters, verifying that space and horizontal tab
+ // return a non-zero integer and everything else returns zero.
+ for (int ch = 0; ch < 255; ++ch) {
+ if (ch == ' ' || ch == '\t')
+ EXPECT_NE(__llvm_libc::isblank(ch), 0);
+ else
+ EXPECT_EQ(__llvm_libc::isblank(ch), 0);
+ }
+}
diff --git a/test/src/ctype/iscntrl_test.cpp b/test/src/ctype/iscntrl_test.cpp
new file mode 100644
index 0000000..5af7457
--- /dev/null
+++ b/test/src/ctype/iscntrl_test.cpp
@@ -0,0 +1,21 @@
+//===-- Unittests for iscntrl----------------------------------------------===//
+//
+// 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/iscntrl.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(IsCntrl, DefaultLocale) {
+ // Loops through all characters, verifying that control characters
+ // return a non-zero integer, all others return zero.
+ for (int ch = 0; ch < 255; ++ch) {
+ if ((0 <= ch && ch <= 0x1f /*US*/) || ch == 0x7f /*DEL*/)
+ EXPECT_NE(__llvm_libc::iscntrl(ch), 0);
+ else
+ EXPECT_EQ(__llvm_libc::iscntrl(ch), 0);
+ }
+}
diff --git a/test/src/ctype/isgraph_test.cpp b/test/src/ctype/isgraph_test.cpp
new file mode 100644
index 0000000..1ed1ec7
--- /dev/null
+++ b/test/src/ctype/isgraph_test.cpp
@@ -0,0 +1,21 @@
+//===-- Unittests for isgraph----------------------------------------------===//
+//
+// 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/isgraph.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(IsGraph, DefaultLocale) {
+ // Loops through all characters, verifying that graphical characters
+ // return a non-zero integer, everything else returns zero.
+ for (int ch = 0; ch < 255; ++ch) {
+ if ('!' <= ch && ch <= '~') // A-Z, a-z, 0-9, punctuation.
+ EXPECT_NE(__llvm_libc::isgraph(ch), 0);
+ else
+ EXPECT_EQ(__llvm_libc::isgraph(ch), 0);
+ }
+}
diff --git a/test/src/ctype/ispunct_test.cpp b/test/src/ctype/ispunct_test.cpp
new file mode 100644
index 0000000..07e83fb
--- /dev/null
+++ b/test/src/ctype/ispunct_test.cpp
@@ -0,0 +1,34 @@
+//===-- Unittests for ispunct----------------------------------------------===//
+//
+// 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/ispunct.h"
+#include "utils/UnitTest/Test.h"
+
+// Helper function to mark the sections of the ASCII table that are
+// punctuation characters. These are listed below:
+// Decimal | Symbol
+// -----------------------------------------
+// 33 - 47 | ! " $ % & ' ( ) * + , - . /
+// 58 - 64 | : ; < = > ? @
+// 91 - 96 | [ \ ] ^ _ `
+// 123 - 126 | { | } ~
+static inline int is_punctuation_character(int c) {
+ return ('!' <= c && c <= '/') || (':' <= c && c <= '@') ||
+ ('[' <= c && c <= '`') || ('{' <= c && c <= '~');
+}
+
+TEST(IsPunct, DefaultLocale) {
+ // Loops through all characters, verifying that punctuation characters
+ // return a non-zero integer, and everything else returns zero.
+ for (int ch = 0; ch < 255; ++ch) {
+ if (is_punctuation_character(ch))
+ EXPECT_NE(__llvm_libc::ispunct(ch), 0);
+ else
+ EXPECT_EQ(__llvm_libc::ispunct(ch), 0);
+ }
+}