Skip to content

Commit a5a008f

Browse files
[libc] Refactor scanf reader to match printf (#66023)
In a previous patch, the printf writer was rewritten to use a single writer class with a buffer and a callback hook. This patch refactors scanf's reader to match conceptually.
1 parent bfa501b commit a5a008f

27 files changed

+226
-301
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ set(TARGET_LIBC_ENTRYPOINTS
126126
libc.src.stdio.snprintf
127127
libc.src.stdio.vsprintf
128128
libc.src.stdio.vsnprintf
129+
#libc.src.stdio.sscanf
130+
#libc.src.stdio.scanf
131+
#libc.src.stdio.fscanf
129132

130133
# sys/mman.h entrypoints
131134
libc.src.sys.mman.madvise

libc/config/linux/riscv64/entrypoints.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ set(TARGET_LIBC_ENTRYPOINTS
132132
libc.src.stdio.vsnprintf
133133
libc.src.stdio.vfprintf
134134
libc.src.stdio.vprintf
135+
libc.src.stdio.sscanf
136+
libc.src.stdio.scanf
137+
libc.src.stdio.fscanf
135138

136139
# sys/mman.h entrypoints
137140
libc.src.sys.mman.madvise
@@ -439,10 +442,6 @@ if(LLVM_LIBC_FULL_BUILD)
439442
libc.src.stdio.getc_unlocked
440443
libc.src.stdio.getchar
441444
libc.src.stdio.getchar_unlocked
442-
libc.src.stdio.printf
443-
libc.src.stdio.sscanf
444-
libc.src.stdio.scanf
445-
libc.src.stdio.fscanf
446445
libc.src.stdio.putc
447446
libc.src.stdio.putchar
448447
libc.src.stdio.puts

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ set(TARGET_LIBC_ENTRYPOINTS
132132
libc.src.stdio.vsnprintf
133133
libc.src.stdio.vfprintf
134134
libc.src.stdio.vprintf
135+
libc.src.stdio.sscanf
136+
libc.src.stdio.scanf
137+
libc.src.stdio.fscanf
135138

136139
# sys/mman.h entrypoints
137140
libc.src.sys.mman.madvise
@@ -445,9 +448,6 @@ if(LLVM_LIBC_FULL_BUILD)
445448
libc.src.stdio.getc_unlocked
446449
libc.src.stdio.getchar
447450
libc.src.stdio.getchar_unlocked
448-
libc.src.stdio.sscanf
449-
libc.src.stdio.scanf
450-
libc.src.stdio.fscanf
451451
libc.src.stdio.putc
452452
libc.src.stdio.putchar
453453
libc.src.stdio.puts

libc/docs/dev/printf_behavior.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ General Flags:
3030
These compile-time flags will change the behavior of LLVM-libc's printf when it
3131
is compiled. Combinations of flags that are incompatible will be marked.
3232

33-
LIBC_COPT_PRINTF_USE_SYSTEM_FILE
34-
--------------------------------
33+
LIBC_COPT_STDIO_USE_SYSTEM_FILE
34+
-------------------------------
3535
When set, this flag changes fprintf and printf to use the FILE API from the
3636
system's libc, instead of LLVM-libc's internal FILE API. This is set by default
3737
when LLVM-libc is built in overlay mode.

libc/src/stdio/CMakeLists.txt

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,21 @@ add_entrypoint_object(
126126
libc.src.__support.File.platform_file
127127
)
128128

129+
list(APPEND scanf_deps
130+
libc.src.__support.arg_list
131+
libc.src.stdio.scanf_core.vfscanf_internal
132+
)
133+
134+
if(LLVM_LIBC_FULL_BUILD)
135+
list(APPEND scanf_deps
136+
libc.src.__support.File.file
137+
libc.src.__support.File.platform_file
138+
libc.src.__support.File.platform_stdin
139+
)
140+
else()
141+
list(APPEND scanf_copts "-DLIBC_COPT_STDIO_USE_SYSTEM_FILE")
142+
endif()
143+
129144
add_entrypoint_object(
130145
sscanf
131146
SRCS
@@ -134,7 +149,6 @@ add_entrypoint_object(
134149
sscanf.h
135150
DEPENDS
136151
libc.src.__support.arg_list
137-
libc.src.stdio.scanf_core.string_reader
138152
libc.src.stdio.scanf_core.reader
139153
libc.src.stdio.scanf_core.scanf_main
140154
)
@@ -146,8 +160,9 @@ add_entrypoint_object(
146160
HDRS
147161
fscanf.h
148162
DEPENDS
149-
libc.src.__support.arg_list
150-
libc.src.stdio.scanf_core.vfscanf_internal
163+
${scanf_deps}
164+
COMPILE_OPTIONS
165+
${scanf_copts}
151166
)
152167

153168
add_entrypoint_object(
@@ -157,8 +172,9 @@ add_entrypoint_object(
157172
HDRS
158173
scanf.h
159174
DEPENDS
160-
libc.src.__support.arg_list
161-
libc.src.stdio.scanf_core.vfscanf_internal
175+
${scanf_deps}
176+
COMPILE_OPTIONS
177+
${scanf_copts}
162178
)
163179

164180
add_entrypoint_object(
@@ -208,7 +224,7 @@ if(LLVM_LIBC_FULL_BUILD)
208224
libc.src.__support.File.platform_stdout
209225
)
210226
else()
211-
list(APPEND printf_copts "-DLIBC_COPT_PRINTF_USE_SYSTEM_FILE")
227+
list(APPEND printf_copts "-DLIBC_COPT_STDIO_USE_SYSTEM_FILE")
212228
endif()
213229

214230
add_entrypoint_object(

libc/src/stdio/printf.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
#include <stdarg.h>
1616
#include <stdio.h>
1717

18-
#ifndef LIBC_COPT_PRINTF_USE_SYSTEM_FILE
18+
#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
1919
#define PRINTF_STDOUT __llvm_libc::stdout
20-
#else // LIBC_COPT_PRINTF_USE_SYSTEM_FILE
20+
#else // LIBC_COPT_STDIO_USE_SYSTEM_FILE
2121
#define PRINTF_STDOUT ::stdout
22-
#endif // LIBC_COPT_PRINTF_USE_SYSTEM_FILE
22+
#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
2323

2424
namespace __llvm_libc {
2525

libc/src/stdio/printf_core/vfprintf_internal.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
namespace __llvm_libc {
2222

2323
namespace internal {
24-
#ifndef LIBC_COPT_PRINTF_USE_SYSTEM_FILE
24+
#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
2525
LIBC_INLINE int ferror_unlocked(FILE *f) {
2626
return reinterpret_cast<__llvm_libc::File *>(f)->error_unlocked();
2727
}
@@ -39,7 +39,7 @@ LIBC_INLINE size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb,
3939
return reinterpret_cast<__llvm_libc::File *>(f)->write_unlocked(ptr,
4040
size * nmemb);
4141
}
42-
#else // defined(LIBC_COPT_PRINTF_USE_SYSTEM_FILE)
42+
#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE)
4343
LIBC_INLINE int ferror_unlocked(::FILE *f) { return ::ferror_unlocked(f); }
4444

4545
LIBC_INLINE void flockfile(::FILE *f) { ::flockfile(f); }
@@ -50,7 +50,7 @@ LIBC_INLINE size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb,
5050
::FILE *f) {
5151
return ::fwrite_unlocked(ptr, size, nmemb, f);
5252
}
53-
#endif // LIBC_COPT_PRINTF_USE_SYSTEM_FILE
53+
#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
5454
} // namespace internal
5555

5656
namespace printf_core {

libc/src/stdio/scanf.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
#include <stdarg.h>
1616
#include <stdio.h>
1717

18+
#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
19+
#define SCANF_STDIN __llvm_libc::stdin
20+
#else // LIBC_COPT_STDIO_USE_SYSTEM_FILE
21+
#define SCANF_STDIN ::stdin
22+
#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
23+
1824
namespace __llvm_libc {
1925

2026
LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
@@ -25,7 +31,7 @@ LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
2531
// destruction automatically.
2632
va_end(vlist);
2733
int ret_val = scanf_core::vfscanf_internal(
28-
reinterpret_cast<::FILE *>(__llvm_libc::stdin), format, args);
34+
reinterpret_cast<::FILE *>(SCANF_STDIN), format, args);
2935
// This is done to avoid including stdio.h in the internals. On most systems
3036
// EOF is -1, so this will be transformed into just "return ret_val".
3137
return (ret_val == -1) ? EOF : ret_val;

libc/src/stdio/scanf_core/CMakeLists.txt

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ add_header_library(
2222
libc.src.__support.CPP.string_view
2323
)
2424

25-
if(NOT (TARGET libc.src.__support.File.file))
26-
# Not all platforms have a file implementation. If file is unvailable,
27-
# then we must skip all the parts that need file.
28-
return()
29-
endif()
30-
3125
add_object_library(
3226
scanf_main
3327
SRCS
@@ -42,33 +36,14 @@ add_object_library(
4236
libc.src.__support.arg_list
4337
)
4438

45-
add_object_library(
46-
string_reader
47-
SRCS
48-
string_reader.cpp
49-
HDRS
50-
string_reader.h
51-
)
52-
53-
add_object_library(
54-
file_reader
55-
SRCS
56-
file_reader.cpp
57-
HDRS
58-
file_reader.h
59-
DEPENDS
60-
libc.src.__support.File.file
61-
)
62-
6339
add_object_library(
6440
reader
6541
SRCS
6642
reader.cpp
6743
HDRS
6844
reader.h
6945
DEPENDS
70-
.string_reader
71-
.file_reader
46+
libc.src.__support.macros.attributes
7247
)
7348

7449
add_object_library(
@@ -99,15 +74,20 @@ add_object_library(
9974
libc.src.__support.str_to_float
10075
)
10176

102-
add_object_library(
77+
if(NOT (TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD)
78+
# Not all platforms have a file implementation. If file is unvailable, and a
79+
# full build is requested, then we must skip all file based printf sections.
80+
return()
81+
endif()
82+
83+
add_header_library(
10384
vfscanf_internal
104-
SRCS
105-
vfscanf_internal.cpp
10685
HDRS
10786
vfscanf_internal.h
10887
DEPENDS
10988
.reader
110-
.file_reader
11189
.scanf_main
90+
libc.include.stdio
91+
libc.src.__support.File.file
11292
libc.src.__support.arg_list
11393
)

libc/src/stdio/scanf_core/file_reader.cpp

Lines changed: 0 additions & 27 deletions
This file was deleted.

libc/src/stdio/scanf_core/file_reader.h

Lines changed: 0 additions & 39 deletions
This file was deleted.

libc/src/stdio/scanf_core/reader.cpp

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,17 @@
1212
namespace __llvm_libc {
1313
namespace scanf_core {
1414

15-
char Reader::getc() {
16-
++cur_chars_read;
17-
if (reader_type == ReaderType::String) {
18-
return string_reader->get_char();
19-
} else {
20-
return file_reader->get_char();
21-
}
22-
}
23-
2415
void Reader::ungetc(char c) {
2516
--cur_chars_read;
26-
if (reader_type == ReaderType::String) {
27-
// The string reader ignores the char c passed to unget since it doesn't
28-
// need to place anything back into a buffer, and modifying the source
29-
// string would be dangerous.
30-
return string_reader->unget_char();
31-
} else {
32-
return file_reader->unget_char(c);
17+
if (rb != nullptr && rb->buff_cur > 0) {
18+
// While technically c should be written back to the buffer, in scanf we
19+
// always write the character that was already there. Additionally, the
20+
// buffer is most likely to contain a string that isn't part of a file,
21+
// which may not be writable.
22+
--(rb->buff_cur);
23+
return;
3324
}
25+
stream_ungetc(static_cast<int>(c), input_stream);
3426
}
35-
36-
bool Reader::has_error() {
37-
if (reader_type == ReaderType::File) {
38-
return file_reader->has_error();
39-
}
40-
return false;
41-
}
42-
4327
} // namespace scanf_core
4428
} // namespace __llvm_libc

0 commit comments

Comments
 (0)