Skip to content

Commit

Permalink
[libc] add basic wide char functions
Browse files Browse the repository at this point in the history
This patch adds the wchar header, as well as the functions to convert to
and from wide chars. The header also sets up the definitions for wint
and wchar.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D145995
  • Loading branch information
michaelrj-google committed Mar 20, 2023
1 parent c600b99 commit 46b5087
Show file tree
Hide file tree
Showing 25 changed files with 354 additions and 1 deletion.
8 changes: 8 additions & 0 deletions libc/config/linux/api.td
Expand Up @@ -178,6 +178,14 @@ def UniStdAPI : PublicAPI<"unistd.h"> {
"ssize_t", "uid_t", "__getoptargv_t"];
}

def WCharAPI : PublicAPI<"wchar.h"> {
let Types = [
"wchar_t",
"wint_t",
"size_t",
];
}

def SysRandomAPI : PublicAPI<"sys/random.h"> {
let Types = ["size_t", "ssize_t"];
}
Expand Down
3 changes: 3 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Expand Up @@ -193,6 +193,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.unlink
libc.src.unistd.unlinkat
libc.src.unistd.write

# wchar.h entrypoints
libc.src.wchar.wctob
)

set(TARGET_LIBM_ENTRYPOINTS
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/headers.txt
Expand Up @@ -20,6 +20,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.threads
libc.include.time
libc.include.unistd
libc.include.wchar

libc.include.arpa_inet

Expand Down
9 changes: 9 additions & 0 deletions libc/include/CMakeLists.txt
Expand Up @@ -468,6 +468,15 @@ add_gen_header(
.llvm-libc-types.tcflag_t
)

add_gen_header(
wchar
DEF_FILE wchar.h.def
GEN_HDR wchar.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.wchar_macros
)

if(NOT LLVM_LIBC_FULL_BUILD)
# We don't install headers in non-fullbuild mode.
return()
Expand Down
6 changes: 6 additions & 0 deletions libc/include/llvm-libc-macros/CMakeLists.txt
Expand Up @@ -166,3 +166,9 @@ add_header(
DEPENDS
.linux.unistd_macros
)

add_header(
wchar_macros
HDR
wchar-macros.h
)
16 changes: 16 additions & 0 deletions libc/include/llvm-libc-macros/wchar-macros.h
@@ -0,0 +1,16 @@
//===-- Macros defined in wchar.h header file -----------------------------===//
//
// 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_MACROS_WCHAR_MACROS_H
#define __LLVM_LIBC_MACROS_WCHAR_MACROS_H

#ifndef WEOF
#define WEOF 0xffffffffu
#endif

#endif // __LLVM_LIBC_MACROS_WCHAR_MACROS_H
2 changes: 2 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Expand Up @@ -84,3 +84,5 @@ add_header(speed_t HDR speed_t.h)
add_header(tcflag_t HDR tcflag_t.h)
add_header(struct_termios HDR struct_termios.h DEPENDS .cc_t .speed_t .tcflag_t)
add_header(__getoptargv_t HDR __getoptargv_t.h)
add_header(wchar_t HDR wchar_t.h)
add_header(wint_t HDR wint_t.h)
3 changes: 2 additions & 1 deletion libc/include/llvm-libc-types/size_t.h
Expand Up @@ -11,8 +11,9 @@

// Since __need_size_t is defined, we get the definition of size_t from the
// standalone C header stddef.h. Also, because __need_size_t is defined,
// including stddef.h will pull only the type size_t and nothing else.a
// including stddef.h will pull only the type size_t and nothing else.
#define __need_size_t
#include <stddef.h>
#undef __need_size_t

#endif // __LLVM_LIBC_TYPES_SIZE_T_H__
19 changes: 19 additions & 0 deletions libc/include/llvm-libc-types/wchar_t.h
@@ -0,0 +1,19 @@
//===-- Definition of wchar_t types ---------------------------------------===//
//
// 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_TYPES_WCHAR_T_H__
#define __LLVM_LIBC_TYPES_WCHAR_T_H__

// Since __need_wchar_t is defined, we get the definition of wchar_t from the
// standalone C header stddef.h. Also, because __need_wchar_t is defined,
// including stddef.h will pull only the type wchar_t and nothing else.
#define __need_wchar_t
#include <stddef.h>
#undef __need_wchar_t

#endif // __LLVM_LIBC_TYPES_WCHAR_T_H__
19 changes: 19 additions & 0 deletions libc/include/llvm-libc-types/wint_t.h
@@ -0,0 +1,19 @@
//===-- Definition of wint_t types ----------------------------------------===//
//
// 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_TYPES_WINT_T_H__
#define __LLVM_LIBC_TYPES_WINT_T_H__

// Since __need_wint_t is defined, we get the definition of wint_t from the
// standalone C header stddef.h. Also, because __need_wint_t is defined,
// including stddef.h will pull only the type wint_t and nothing else.
#define __need_wint_t
#include <stddef.h>
#undef __need_wint_t

#endif // __LLVM_LIBC_TYPES_WINT_T_H__
17 changes: 17 additions & 0 deletions libc/include/wchar.h.def
@@ -0,0 +1,17 @@
//===-- C standard library header wchar.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_WCHAR_H
#define LLVM_LIBC_WCHAR_H

#include <__llvm-libc-common.h>
#include <llvm-libc-macros/wchar-macros.h>

%%public_api()

#endif // LLVM_LIBC_WCHAR_H
4 changes: 4 additions & 0 deletions libc/spec/spec.td
Expand Up @@ -59,6 +59,10 @@ def SizeTType : NamedType<"size_t">;
def SizeTPtr : PtrType<SizeTType>;
def RestrictedSizeTPtr : RestrictedPtrType<SizeTType>;

def WCharType : NamedType<"wchar_t">;
def WIntType : NamedType<"wint_t">;
def MBStateType : NamedType<"mbstate_t">;

def LongDoublePtr : PtrType<LongDoubleType>;

def IntMaxTType : NamedType<"intmax_t">;
Expand Down
24 changes: 24 additions & 0 deletions libc/spec/stdc.td
Expand Up @@ -1069,6 +1069,29 @@ def StdC : StandardSpec<"stdc"> {
]
>;

HeaderSpec WChar = HeaderSpec<
"wchar.h",
[ // Macros
Macro<"WEOF">,
],
[ //Types
SizeTType,
WIntType,
WCharType,
MBStateType,
StructTmType,
],
[], // Enumerations
[
FunctionSpec<
"wctob",
RetValSpec<IntType>,
[ArgSpec<WIntType>]
>,
]
>;


let Headers = [
Assert,
CType,
Expand All @@ -1083,5 +1106,6 @@ def StdC : StandardSpec<"stdc"> {
Signal,
Threads,
Time,
WChar,
];
}
1 change: 1 addition & 0 deletions libc/src/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ add_subdirectory(math)
add_subdirectory(string)
add_subdirectory(stdlib)
add_subdirectory(stdio)
add_subdirectory(wchar)

if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(dirent)
Expand Down
6 changes: 6 additions & 0 deletions libc/src/__support/CMakeLists.txt
Expand Up @@ -51,6 +51,12 @@ add_header_library(
ctype_utils.h
)

add_header_library(
wctype_utils
HDRS
wctype_utils.h
)

add_header_library(
str_to_num_result
HDRS
Expand Down
45 changes: 45 additions & 0 deletions libc/src/__support/wctype_utils.h
@@ -0,0 +1,45 @@
//===-- Collection of utils for implementing wide char functions --*-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_SUPPORT_WCTYPE_UTILS_H
#define LLVM_LIBC_SRC_SUPPORT_WCTYPE_UTILS_H

#include "src/__support/CPP/optional.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE

#define __need_wint_t
#define __need_wchar_t
#include <stddef.h> // needed for wint_t and wchar_t

namespace __llvm_libc {
namespace internal {

// ------------------------------------------------------
// Rationale: Since these classification functions are
// called in other functions, we will avoid the overhead
// of a function call by inlining them.
// ------------------------------------------------------

LIBC_INLINE cpp::optional<int> wctob(wint_t c) {
// This needs to be translated to EOF at the callsite. This is to avoid
// including stdio.h in this file.
if (c > 127 || c < 0)
return cpp::nullopt;
return static_cast<int>(c);
}

LIBC_INLINE cpp::optional<wint_t> btowc(int c) {
if (c > 127 || c < 0)
return cpp::nullopt;
return static_cast<wint_t>(c);
}

} // namespace internal
} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_SUPPORT_WCTYPE_UTILS_H
10 changes: 10 additions & 0 deletions libc/src/wchar/CMakeLists.txt
@@ -0,0 +1,10 @@

add_entrypoint_object(
wctob
SRCS
wctob.cpp
HDRS
wctob.h
DEPENDS
libc.src.__support.wctype_utils
)
26 changes: 26 additions & 0 deletions libc/src/wchar/btowc.cpp
@@ -0,0 +1,26 @@
//===-- Implementation of btowc -------------------------------------------===//
//
// 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/wchar/btowc.h"
#include "src/__support/common.h"
#include "src/__support/wctype_utils.h"

#include <stdio.h> // for EOF.

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, btowc, (wint_t c)) {
auto result = internal::btowc(c);
if (result.has_value()) {
return result.value();
} else {
return WEOF;
}
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/wchar/btowc.h
@@ -0,0 +1,20 @@
//===-- Implementation header for btowc -------------------------*- 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_WCHAR_BTOWC_H
#define LLVM_LIBC_SRC_WCHAR_BTOWC_H

#include <wchar.h>

namespace __llvm_libc {

wint_t btowc(int c);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_WCHAR_BTOWC_H
26 changes: 26 additions & 0 deletions libc/src/wchar/wctob.cpp
@@ -0,0 +1,26 @@
//===-- Implementation of wctob -------------------------------------------===//
//
// 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/wchar/wctob.h"
#include "src/__support/common.h"
#include "src/__support/wctype_utils.h"

#include <stdio.h> // for EOF.

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, wctob, (wint_t c)) {
auto result = internal::wctob(c);
if (result.has_value()) {
return result.value();
} else {
return EOF;
}
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/wchar/wctob.h
@@ -0,0 +1,20 @@
//===-- Implementation header for wctob -------------------------*- 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_WCHAR_WCTOB_H
#define LLVM_LIBC_SRC_WCHAR_WCTOB_H

#include <wchar.h>

namespace __llvm_libc {

int wctob(wint_t c);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_WCHAR_WCTOB_H
1 change: 1 addition & 0 deletions libc/test/src/CMakeLists.txt
Expand Up @@ -35,6 +35,7 @@ add_subdirectory(string)
add_subdirectory(stdlib)
add_subdirectory(inttypes)
add_subdirectory(stdio)
add_subdirectory(wchar)

if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(fcntl)
Expand Down

0 comments on commit 46b5087

Please sign in to comment.