Skip to content

Commit 36991d8

Browse files
[libc] add scanf entrypoints
This patch adds scanf, sscanf, and fscanf entrypoints. It also adds unit tests for sscanf and a basic test to fscanf. The scanf function is basically impossible to test in an automated fashion due to it recieving user input. Reviewed By: sivachandra, lntue Differential Revision: https://reviews.llvm.org/D138076
1 parent 98bfd7f commit 36991d8

File tree

15 files changed

+415
-0
lines changed

15 files changed

+415
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ if(LLVM_LIBC_FULL_BUILD)
394394
libc.src.stdio.getc
395395
libc.src.stdio.getc_unlocked
396396
libc.src.stdio.printf
397+
libc.src.stdio.sscanf
398+
libc.src.stdio.scanf
399+
libc.src.stdio.fscanf
397400
libc.src.stdio.putc
398401
libc.src.stdio.putchar
399402
libc.src.stdio.puts

libc/spec/stdc.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,26 @@ def StdC : StandardSpec<"stdc"> {
633633
RetValSpec<IntType>,
634634
[ArgSpec<FILERestrictedPtr>, ArgSpec<CharRestrictedPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
635635
>,
636+
FunctionSpec<
637+
"sscanf",
638+
RetValSpec<IntType>,
639+
[ArgSpec<ConstCharRestrictedPtr>,
640+
ArgSpec<ConstCharRestrictedPtr>,
641+
ArgSpec<VarArgType>]
642+
>,
643+
FunctionSpec<
644+
"scanf",
645+
RetValSpec<IntType>,
646+
[ArgSpec<ConstCharRestrictedPtr>,
647+
ArgSpec<VarArgType>]
648+
>,
649+
FunctionSpec<
650+
"fscanf",
651+
RetValSpec<IntType>,
652+
[ArgSpec<FILERestrictedPtr>,
653+
ArgSpec<ConstCharRestrictedPtr>,
654+
ArgSpec<VarArgType>]
655+
>,
636656
FunctionSpec<
637657
"sprintf",
638658
RetValSpec<IntType>,

libc/src/stdio/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,41 @@ add_entrypoint_object(
403403
libc.src.__support.File.platform_file
404404
)
405405

406+
add_entrypoint_object(
407+
sscanf
408+
SRCS
409+
sscanf.cpp
410+
HDRS
411+
sscanf.h
412+
DEPENDS
413+
libc.src.__support.arg_list
414+
libc.src.stdio.scanf_core.string_reader
415+
libc.src.stdio.scanf_core.reader
416+
libc.src.stdio.scanf_core.scanf_main
417+
)
418+
419+
add_entrypoint_object(
420+
fscanf
421+
SRCS
422+
fscanf.cpp
423+
HDRS
424+
fscanf.h
425+
DEPENDS
426+
libc.src.__support.arg_list
427+
libc.src.stdio.scanf_core.vfscanf_internal
428+
)
429+
430+
add_entrypoint_object(
431+
scanf
432+
SRCS
433+
scanf.cpp
434+
HDRS
435+
scanf.h
436+
DEPENDS
437+
libc.src.__support.arg_list
438+
libc.src.stdio.scanf_core.vfscanf_internal
439+
)
440+
406441
add_entrypoint_object(
407442
sprintf
408443
SRCS

libc/src/stdio/fscanf.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===-- Implementation of fscanf --------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdio/fscanf.h"
10+
11+
#include "src/__support/File/file.h"
12+
#include "src/__support/arg_list.h"
13+
#include "src/stdio/scanf_core/vfscanf_internal.h"
14+
15+
#include <stdarg.h>
16+
#include <stdio.h>
17+
18+
namespace __llvm_libc {
19+
20+
LLVM_LIBC_FUNCTION(int, fscanf,
21+
(::FILE *__restrict stream, const char *__restrict format,
22+
...)) {
23+
va_list vlist;
24+
va_start(vlist, format);
25+
internal::ArgList args(vlist); // This holder class allows for easier copying
26+
// and pointer semantics, as well as handling
27+
// destruction automatically.
28+
va_end(vlist);
29+
int ret_val = scanf_core::vfscanf_internal(stream, format, args);
30+
// This is done to avoid including stdio.h in the internals. On most systems
31+
// EOF is -1, so this will be transformed into just "return ret_val".
32+
return (ret_val == -1) ? EOF : ret_val;
33+
}
34+
35+
} // namespace __llvm_libc

libc/src/stdio/fscanf.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header of fscanf -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDIO_FSCANF_H
10+
#define LLVM_LIBC_SRC_STDIO_FSCANF_H
11+
12+
#include <stdio.h>
13+
14+
namespace __llvm_libc {
15+
16+
int fscanf(::FILE *__restrict stream, const char *__restrict format, ...);
17+
18+
} // namespace __llvm_libc
19+
20+
#endif // LLVM_LIBC_SRC_STDIO_FSCANF_H

libc/src/stdio/scanf.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- Implementation of scanf ---------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdio/scanf.h"
10+
11+
#include "src/__support/File/file.h"
12+
#include "src/__support/arg_list.h"
13+
#include "src/stdio/scanf_core/vfscanf_internal.h"
14+
15+
#include <stdarg.h>
16+
#include <stdio.h>
17+
18+
namespace __llvm_libc {
19+
20+
LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
21+
va_list vlist;
22+
va_start(vlist, format);
23+
internal::ArgList args(vlist); // This holder class allows for easier copying
24+
// and pointer semantics, as well as handling
25+
// destruction automatically.
26+
va_end(vlist);
27+
int ret_val = scanf_core::vfscanf_internal(
28+
reinterpret_cast<::FILE *>(__llvm_libc::stdin), format, args);
29+
// This is done to avoid including stdio.h in the internals. On most systems
30+
// EOF is -1, so this will be transformed into just "return ret_val".
31+
return (ret_val == -1) ? EOF : ret_val;
32+
}
33+
34+
} // namespace __llvm_libc

libc/src/stdio/scanf.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===-- Implementation header of scanf --------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDIO_SCANF_H
10+
#define LLVM_LIBC_SRC_STDIO_SCANF_H
11+
12+
namespace __llvm_libc {
13+
14+
int scanf(const char *__restrict format, ...);
15+
16+
} // namespace __llvm_libc
17+
18+
#endif // LLVM_LIBC_SRC_STDIO_SCANF_H

libc/src/stdio/scanf_core/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,16 @@ add_object_library(
8989
libc.src.__support.CPP.string_view
9090
libc.src.__support.CPP.limits
9191
)
92+
93+
add_object_library(
94+
vfscanf_internal
95+
SRCS
96+
vfscanf_internal.cpp
97+
HDRS
98+
vfscanf_internal.h
99+
DEPENDS
100+
.reader
101+
.file_reader
102+
.scanf_main
103+
libc.src.__support.arg_list
104+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===-- Internal implementation of vfscanf ---------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdio/scanf_core/vfscanf_internal.h"
10+
11+
#include "src/__support/arg_list.h"
12+
#include "src/stdio/scanf_core/file_reader.h"
13+
#include "src/stdio/scanf_core/reader.h"
14+
#include "src/stdio/scanf_core/scanf_main.h"
15+
16+
#include <stdio.h>
17+
18+
namespace __llvm_libc {
19+
namespace scanf_core {
20+
21+
int vfscanf_internal(::FILE *__restrict stream, const char *__restrict format,
22+
internal::ArgList &args) {
23+
FileReader file_reader(stream);
24+
scanf_core::Reader reader(&file_reader);
25+
return scanf_core::scanf_main(&reader, format, args);
26+
}
27+
28+
} // namespace scanf_core
29+
} // namespace __llvm_libc
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-- Internal implementation header of vfscanf ---------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_VFSCANF_INTERNAL_H
10+
#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_VFSCANF_INTERNAL_H
11+
12+
#include "src/__support/arg_list.h"
13+
14+
#include <stdio.h>
15+
16+
namespace __llvm_libc {
17+
namespace scanf_core {
18+
19+
int vfscanf_internal(::FILE *__restrict stream, const char *__restrict format,
20+
internal::ArgList &args);
21+
} // namespace scanf_core
22+
} // namespace __llvm_libc
23+
24+
#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_VFSCANF_INTERNAL_H

0 commit comments

Comments
 (0)