[libc] add putc, fputc, and putchar

These three functions are simple, but needed for libc build testing.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D135990
This commit is contained in:
Michael Jones 2022-10-14 14:03:46 -07:00
parent 7732c97f52
commit 40b494396b
11 changed files with 255 additions and 0 deletions

View File

@ -359,6 +359,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdio.ferror_unlocked
libc.src.stdio.fflush
libc.src.stdio.fopen
libc.src.stdio.fputc
libc.src.stdio.fputs
libc.src.stdio.fopencookie
libc.src.stdio.fread
@ -369,6 +370,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdio.fwrite_unlocked
libc.src.stdio.fprintf
libc.src.stdio.printf
libc.src.stdio.putc
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.stderr
libc.src.stdio.stdout

View File

@ -535,6 +535,23 @@ def StdC : StandardSpec<"stdc"> {
[ArgSpec<ConstCharPtr>,
ArgSpec<ConstCharPtr>]
>,
FunctionSpec<
"fputc",
RetValSpec<IntType>,
[ArgSpec<IntType>,
ArgSpec<FILEPtr>]
>,
FunctionSpec<
"putc",
RetValSpec<IntType>,
[ArgSpec<IntType>,
ArgSpec<FILEPtr>]
>,
FunctionSpec<
"putchar",
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
FunctionSpec<
"fputs",
RetValSpec<IntType>,

View File

@ -184,6 +184,42 @@ add_entrypoint_object(
libc.src.__support.File.platform_file
)
add_entrypoint_object(
fputc
SRCS
fputc.cpp
HDRS
fputc.h
DEPENDS
libc.include.stdio
libc.src.__support.File.file
libc.src.__support.File.platform_file
)
add_entrypoint_object(
putc
SRCS
putc.cpp
HDRS
putc.h
DEPENDS
libc.include.stdio
libc.src.__support.File.file
libc.src.__support.File.platform_file
)
add_entrypoint_object(
putchar
SRCS
putchar.cpp
HDRS
putchar.h
DEPENDS
libc.include.stdio
libc.src.__support.File.file
libc.src.__support.File.platform_file
)
add_entrypoint_object(
fputs
SRCS

26
libc/src/stdio/fputc.cpp Normal file
View File

@ -0,0 +1,26 @@
//===-- Implementation of fputc -------------------------------------------===//
//
// 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/stdio/fputc.h"
#include "src/__support/File/file.h"
#include <stdio.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, fputc, (int c, ::FILE *stream)) {
unsigned char uc = static_cast<unsigned char>(c);
size_t written = reinterpret_cast<__llvm_libc::File *>(stream)->write(&uc, 1);
if (1 != written) {
// The stream should be in an error state in this case.
return EOF;
}
return 0;
}
} // namespace __llvm_libc

20
libc/src/stdio/fputc.h Normal file
View File

@ -0,0 +1,20 @@
//===-- Implementation header of fputc --------------------------*- 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_STDIO_FPUTC_H
#define LLVM_LIBC_SRC_STDIO_FPUTC_H
#include <stdio.h>
namespace __llvm_libc {
int fputc(int c, ::FILE *stream);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STDIO_FPUTC_H

26
libc/src/stdio/putc.cpp Normal file
View File

@ -0,0 +1,26 @@
//===-- Implementation of putc --------------------------------------------===//
//
// 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/stdio/putc.h"
#include "src/__support/File/file.h"
#include <stdio.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, putc, (int c, ::FILE *stream)) {
unsigned char uc = static_cast<unsigned char>(c);
size_t written = reinterpret_cast<__llvm_libc::File *>(stream)->write(&uc, 1);
if (1 != written) {
// The stream should be in an error state in this case.
return EOF;
}
return 0;
}
} // namespace __llvm_libc

20
libc/src/stdio/putc.h Normal file
View File

@ -0,0 +1,20 @@
//===-- Implementation header of putc ---------------------------*- 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_STDIO_PUTC_H
#define LLVM_LIBC_SRC_STDIO_PUTC_H
#include <stdio.h>
namespace __llvm_libc {
int putc(int c, ::FILE *stream);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STDIO_PUTC_H

View File

@ -0,0 +1,26 @@
//===-- Implementation of putchar -----------------------------------------===//
//
// 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/stdio/putchar.h"
#include "src/__support/File/file.h"
#include <stdio.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, putchar, (int c)) {
unsigned char uc = static_cast<unsigned char>(c);
size_t written = __llvm_libc::stdout->write(&uc, 1);
if (1 != written) {
// The stream should be in an error state in this case.
return EOF;
}
return 0;
}
} // namespace __llvm_libc

20
libc/src/stdio/putchar.h Normal file
View File

@ -0,0 +1,20 @@
//===-- Implementation header of putchar ------------------------*- 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_STDIO_PUTCHAR_H
#define LLVM_LIBC_SRC_STDIO_PUTCHAR_H
#include <stdio.h>
namespace __llvm_libc {
int putchar(int c);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STDIO_PUTCHAR_H

View File

@ -121,6 +121,20 @@ add_libc_unittest(
libc.src.stdio.puts
)
add_libc_unittest(
putc_test
SUITE
libc_stdio_unittests
SRCS
putc_test.cpp
DEPENDS
libc.src.stdio.putc
libc.src.stdio.fclose
libc.src.stdio.ferror
libc.src.stdio.fopen
libc.src.stdio.fread
)
if(${LIBC_TARGET_OS} STREQUAL "linux")
add_libc_unittest(
remove_test

View File

@ -0,0 +1,47 @@
//===-- Unittests for putc ---------------------------------------------===//
//
// 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/stdio/fclose.h"
#include "src/stdio/ferror.h"
#include "src/stdio/fopen.h"
#include "src/stdio/fread.h"
#include "src/stdio/putc.h"
#include "utils/UnitTest/Test.h"
#include <errno.h>
#include <stdio.h>
TEST(LlvmLibcPutcTest, WriteToFile) {
constexpr char FILENAME[] = "testdata/putc_output.test";
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
ASSERT_FALSE(file == nullptr);
constexpr char simple[] = "simple letters";
for (size_t i = 0; i < sizeof(simple); ++i) {
ASSERT_EQ(__llvm_libc::putc(simple[i], file), 0);
}
ASSERT_EQ(0, __llvm_libc::fclose(file));
file = __llvm_libc::fopen(FILENAME, "r");
ASSERT_FALSE(file == nullptr);
char data[50];
ASSERT_EQ(__llvm_libc::fread(data, 1, sizeof(simple) - 1, file),
sizeof(simple) - 1);
data[sizeof(simple) - 1] = '\0';
ASSERT_STREQ(data, simple);
ASSERT_EQ(__llvm_libc::ferror(file), 0);
EXPECT_LT(__llvm_libc::putc('L', file), 0);
ASSERT_EQ(__llvm_libc::fclose(file), 0);
}