Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc] Support for scanf on baremetal #131043

Merged
merged 7 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions libc/config/baremetal/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,22 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.inttypes.strtoumax

# stdio.h entrypoints
libc.src.stdio.asprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.remove
libc.src.stdio.scanf
libc.src.stdio.snprintf
libc.src.stdio.sprintf
libc.src.stdio.asprintf
libc.src.stdio.sscanf
libc.src.stdio.vasprintf
libc.src.stdio.vprintf
libc.src.stdio.vscanf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
libc.src.stdio.vasprintf
libc.src.stdio.vsscanf

# stdbit.h entrypoints
libc.src.stdbit.stdc_bit_ceil_uc
Expand Down
8 changes: 6 additions & 2 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,22 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.inttypes.strtoumax

# stdio.h entrypoints
libc.src.stdio.asprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.remove
libc.src.stdio.scanf
libc.src.stdio.snprintf
libc.src.stdio.sprintf
libc.src.stdio.asprintf
libc.src.stdio.sscanf
libc.src.stdio.vasprintf
libc.src.stdio.vprintf
libc.src.stdio.vscanf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
libc.src.stdio.vasprintf
libc.src.stdio.vsscanf

# stdbit.h entrypoints
libc.src.stdbit.stdc_bit_ceil_uc
Expand Down
8 changes: 6 additions & 2 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,22 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.inttypes.strtoumax

# stdio.h entrypoints
libc.src.stdio.asprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.remove
libc.src.stdio.scanf
libc.src.stdio.snprintf
libc.src.stdio.sprintf
libc.src.stdio.asprintf
libc.src.stdio.sscanf
libc.src.stdio.vasprintf
libc.src.stdio.vprintf
libc.src.stdio.vscanf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
libc.src.stdio.vasprintf
libc.src.stdio.vsscanf

# stdbit.h entrypoints
libc.src.stdbit.stdc_bit_ceil_uc
Expand Down
58 changes: 4 additions & 54 deletions libc/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,6 @@ add_entrypoint_object(
libc.src.__support.File.platform_file
)

list(APPEND scanf_deps
libc.src.__support.arg_list
libc.src.stdio.scanf_core.vfscanf_internal
libc.hdr.types.FILE
)

if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not needed anymore?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was moved to libc/src/stdio/generic/CMakeLists.txt.

list(APPEND scanf_deps
libc.src.__support.File.file
libc.src.__support.File.platform_file
libc.src.__support.File.platform_stdin
)
endif()

add_entrypoint_object(
sscanf
SRCS
Expand All @@ -133,46 +119,6 @@ add_entrypoint_object(
libc.src.stdio.scanf_core.string_reader
)

add_entrypoint_object(
fscanf
SRCS
fscanf.cpp
HDRS
fscanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
vfscanf
SRCS
vfscanf.cpp
HDRS
vfscanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
scanf
SRCS
scanf.cpp
HDRS
scanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
vscanf
SRCS
vscanf.cpp
HDRS
vscanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
sprintf
SRCS
Expand Down Expand Up @@ -295,8 +241,12 @@ add_stdio_entrypoint_object(getchar)
add_stdio_entrypoint_object(getchar_unlocked)
add_stdio_entrypoint_object(fgets)
add_stdio_entrypoint_object(ungetc)
add_stdio_entrypoint_object(scanf)
add_stdio_entrypoint_object(fscanf)
add_stdio_entrypoint_object(stdin)
add_stdio_entrypoint_object(stdout)
add_stdio_entrypoint_object(stderr)
add_stdio_entrypoint_object(vprintf)
add_stdio_entrypoint_object(vfprintf)
add_stdio_entrypoint_object(vscanf)
add_stdio_entrypoint_object(vfscanf)
35 changes: 35 additions & 0 deletions libc/src/stdio/baremetal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,28 @@ add_entrypoint_object(
libc.src.__support.CPP.string_view
)

add_header_library(
scanf_internal
HDRS
scanf_internal.h
DEPENDS
libc.src.stdio.scanf_core.reader
libc.src.__support.OSUtil.osutil
)

add_entrypoint_object(
scanf
SRCS
scanf.cpp
HDRS
../scanf.h
DEPENDS
.scanf_internal
libc.src.stdio.scanf_core.scanf_main
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)

add_entrypoint_object(
vprintf
SRCS
Expand All @@ -67,3 +89,16 @@ add_entrypoint_object(
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)

add_entrypoint_object(
vscanf
SRCS
vscanf.cpp
HDRS
../vscanf.h
DEPENDS
.scanf_internal
libc.src.stdio.scanf_core.scanf_main
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)
2 changes: 1 addition & 1 deletion libc/src/stdio/baremetal/getchar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, getchar, ()) {
char buf[1];
auto result = read_from_stdin(buf, sizeof(buf));
if (result < 0)
if (result <= 0)
return EOF;
return buf[0];
}
Expand Down
37 changes: 37 additions & 0 deletions libc/src/stdio/baremetal/scanf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===-- Implementation of scanf ---------------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/stdio/scanf.h"

#include "hdr/stdio_macros.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/arg_list.h"
#include "src/__support/macros/config.h"
#include "src/stdio/baremetal/scanf_internal.h"
#include "src/stdio/scanf_core/scanf_main.h"

#include <stdarg.h>

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
va_list vlist;
va_start(vlist, format);
internal::ArgList args(vlist); // This holder class allows for easier copying
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);

scanf_core::StdinReader reader;
int retval = scanf_core::scanf_main(&reader, format, args);
// This is done to avoid including stdio.h in the internals. On most systems
// EOF is -1, so this will be transformed into just "return retval".
return (retval == -1) ? EOF : retval;
}

} // namespace LIBC_NAMESPACE_DECL
30 changes: 30 additions & 0 deletions libc/src/stdio/baremetal/scanf_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Internal implementation header of scanf -----------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/OSUtil/io.h"
#include "src/__support/macros/config.h"
#include "src/stdio/scanf_core/reader.h"

namespace LIBC_NAMESPACE_DECL {

namespace scanf_core {

struct StdinReader : public Reader<StdinReader> {
LIBC_INLINE char getc() {
char buf[1];
auto result = read_from_stdin(buf, sizeof(buf));
if (result <= 0)
return EOF;
return buf[0];
}
LIBC_INLINE void ungetc(int) {}
};

} // namespace scanf_core

} // namespace LIBC_NAMESPACE_DECL
36 changes: 36 additions & 0 deletions libc/src/stdio/baremetal/vscanf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- Implementation of vscanf --------------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/stdio/vscanf.h"

#include "hdr/stdio_macros.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/arg_list.h"
#include "src/__support/macros/config.h"
#include "src/stdio/baremetal/scanf_internal.h"
#include "src/stdio/scanf_core/scanf_main.h"

#include <stdarg.h>

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, vscanf,
(const char *__restrict format, va_list vlist)) {
internal::ArgList args(vlist); // This holder class allows for easier copying
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);

scanf_core::StdinReader reader;
int retval = scanf_core::scanf_main(&reader, format, args);
// This is done to avoid including stdio.h in the internals. On most systems
// EOF is -1, so this will be transformed into just "return retval".
return (retval == -1) ? EOF : retval;
}

} // namespace LIBC_NAMESPACE_DECL
54 changes: 54 additions & 0 deletions libc/src/stdio/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,60 @@ add_entrypoint_object(
${fprintf_deps}
)

list(APPEND scanf_deps
libc.src.__support.arg_list
libc.src.stdio.scanf_core.vfscanf_internal
libc.hdr.types.FILE
)

if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
list(APPEND scanf_deps
libc.src.__support.File.file
libc.src.__support.File.platform_file
libc.src.__support.File.platform_stdin
)
endif()

add_entrypoint_object(
fscanf
SRCS
fscanf.cpp
HDRS
../fscanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
vfscanf
SRCS
vfscanf.cpp
HDRS
../vfscanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
scanf
SRCS
scanf.cpp
HDRS
../scanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
vscanf
SRCS
vscanf.cpp
HDRS
../vscanf.h
DEPENDS
${scanf_deps}
)

add_entrypoint_object(
fgets
SRCS
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading