forked from OSchip/llvm-project
[libc] Add implementations of feof, ferror and clearerr.
The corresponding _unlocked functions have also been added. Reviewed By: lntue, michaelrj Differential Revision: https://reviews.llvm.org/D124311
This commit is contained in:
parent
97b8a54b25
commit
9db0037bf1
|
@ -251,8 +251,14 @@ if(LLVM_LIBC_FULL_BUILD)
|
||||||
libc.src.stdlib.getenv
|
libc.src.stdlib.getenv
|
||||||
|
|
||||||
# stdio.h entrypoints
|
# stdio.h entrypoints
|
||||||
|
libc.src.stdio.clearerr
|
||||||
|
libc.src.stdio.clearerr_unlocked
|
||||||
libc.src.stdio.fclose
|
libc.src.stdio.fclose
|
||||||
libc.src.stdio.flockfile
|
libc.src.stdio.flockfile
|
||||||
|
libc.src.stdio.feof
|
||||||
|
libc.src.stdio.feof_unlocked
|
||||||
|
libc.src.stdio.ferror
|
||||||
|
libc.src.stdio.ferror_unlocked
|
||||||
libc.src.stdio.fflush
|
libc.src.stdio.fflush
|
||||||
libc.src.stdio.fopen
|
libc.src.stdio.fopen
|
||||||
libc.src.stdio.fopencookie
|
libc.src.stdio.fopencookie
|
||||||
|
|
|
@ -72,6 +72,21 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
|
||||||
[CookieIOFunctionsT], // Types
|
[CookieIOFunctionsT], // Types
|
||||||
[], // Enumerations
|
[], // Enumerations
|
||||||
[
|
[
|
||||||
|
FunctionSpec<
|
||||||
|
"clearerr_unlocked",
|
||||||
|
RetValSpec<VoidType>,
|
||||||
|
[ArgSpec<FILEPtr>]
|
||||||
|
>,
|
||||||
|
FunctionSpec<
|
||||||
|
"feof_unlocked",
|
||||||
|
RetValSpec<IntType>,
|
||||||
|
[ArgSpec<FILEPtr>]
|
||||||
|
>,
|
||||||
|
FunctionSpec<
|
||||||
|
"ferror_unlocked",
|
||||||
|
RetValSpec<IntType>,
|
||||||
|
[ArgSpec<FILEPtr>]
|
||||||
|
>,
|
||||||
FunctionSpec<
|
FunctionSpec<
|
||||||
"fopencookie",
|
"fopencookie",
|
||||||
RetValSpec<FILEPtr>,
|
RetValSpec<FILEPtr>,
|
||||||
|
|
|
@ -478,11 +478,26 @@ def StdC : StandardSpec<"stdc"> {
|
||||||
],
|
],
|
||||||
[], // Enumerations
|
[], // Enumerations
|
||||||
[
|
[
|
||||||
|
FunctionSpec<
|
||||||
|
"clearerr",
|
||||||
|
RetValSpec<VoidType>,
|
||||||
|
[ArgSpec<FILEPtr>]
|
||||||
|
>,
|
||||||
FunctionSpec<
|
FunctionSpec<
|
||||||
"fclose",
|
"fclose",
|
||||||
RetValSpec<IntType>,
|
RetValSpec<IntType>,
|
||||||
[ArgSpec<FILEPtr>]
|
[ArgSpec<FILEPtr>]
|
||||||
>,
|
>,
|
||||||
|
FunctionSpec<
|
||||||
|
"feof",
|
||||||
|
RetValSpec<IntType>,
|
||||||
|
[ArgSpec<FILEPtr>]
|
||||||
|
>,
|
||||||
|
FunctionSpec<
|
||||||
|
"ferror",
|
||||||
|
RetValSpec<IntType>,
|
||||||
|
[ArgSpec<FILEPtr>]
|
||||||
|
>,
|
||||||
FunctionSpec<
|
FunctionSpec<
|
||||||
"fflush",
|
"fflush",
|
||||||
RetValSpec<IntType>,
|
RetValSpec<IntType>,
|
||||||
|
|
|
@ -97,6 +97,19 @@ private:
|
||||||
bool eof;
|
bool eof;
|
||||||
bool err;
|
bool err;
|
||||||
|
|
||||||
|
// This is a convenience RAII class to lock and unlock file objects.
|
||||||
|
class FileLock {
|
||||||
|
File *file;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FileLock(File *f) : file(f) { file->lock(); }
|
||||||
|
|
||||||
|
~FileLock() { file->unlock(); }
|
||||||
|
|
||||||
|
FileLock(const FileLock &) = delete;
|
||||||
|
FileLock(FileLock &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool write_allowed() const {
|
bool write_allowed() const {
|
||||||
return mode & (static_cast<ModeFlags>(OpenMode::WRITE) |
|
return mode & (static_cast<ModeFlags>(OpenMode::WRITE) |
|
||||||
|
@ -150,10 +163,8 @@ public:
|
||||||
|
|
||||||
// Buffered write of |len| bytes from |data| under the file lock.
|
// Buffered write of |len| bytes from |data| under the file lock.
|
||||||
size_t write(const void *data, size_t len) {
|
size_t write(const void *data, size_t len) {
|
||||||
lock();
|
FileLock l(this);
|
||||||
size_t ret = write_unlocked(data, len);
|
return write_unlocked(data, len);
|
||||||
unlock();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffered read of |len| bytes into |data| without the file lock.
|
// Buffered read of |len| bytes into |data| without the file lock.
|
||||||
|
@ -161,10 +172,8 @@ public:
|
||||||
|
|
||||||
// Buffered read of |len| bytes into |data| under the file lock.
|
// Buffered read of |len| bytes into |data| under the file lock.
|
||||||
size_t read(void *data, size_t len) {
|
size_t read(void *data, size_t len) {
|
||||||
lock();
|
FileLock l(this);
|
||||||
size_t ret = read_unlocked(data, len);
|
return read_unlocked(data, len);
|
||||||
unlock();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int seek(long offset, int whence);
|
int seek(long offset, int whence);
|
||||||
|
@ -184,28 +193,32 @@ public:
|
||||||
void lock() { mutex.lock(); }
|
void lock() { mutex.lock(); }
|
||||||
void unlock() { mutex.unlock(); }
|
void unlock() { mutex.unlock(); }
|
||||||
|
|
||||||
bool error() const { return err; }
|
bool error_unlocked() const { return err; }
|
||||||
void clearerr() { err = false; }
|
|
||||||
bool iseof() const { return eof; }
|
bool error() {
|
||||||
|
FileLock l(this);
|
||||||
|
return error_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearerr_unlocked() { err = false; }
|
||||||
|
|
||||||
|
void clearerr() {
|
||||||
|
FileLock l(this);
|
||||||
|
clearerr_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iseof_unlocked() { return eof; }
|
||||||
|
|
||||||
|
bool iseof() {
|
||||||
|
FileLock l(this);
|
||||||
|
return iseof_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an bit map of flags corresponding to enumerations of
|
// Returns an bit map of flags corresponding to enumerations of
|
||||||
// OpenMode, ContentType and CreateType.
|
// OpenMode, ContentType and CreateType.
|
||||||
static ModeFlags mode_flags(const char *mode);
|
static ModeFlags mode_flags(const char *mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a convenience RAII class to lock and unlock file objects.
|
|
||||||
class FileLock {
|
|
||||||
File *file;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FileLock(File *f) : file(f) { file->lock(); }
|
|
||||||
|
|
||||||
~FileLock() { file->unlock(); }
|
|
||||||
|
|
||||||
FileLock(const FileLock &) = delete;
|
|
||||||
FileLock(FileLock &&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The implementaiton of this function is provided by the platfrom_file
|
// The implementaiton of this function is provided by the platfrom_file
|
||||||
// library.
|
// library.
|
||||||
File *openfile(const char *path, const char *mode);
|
File *openfile(const char *path, const char *mode);
|
||||||
|
|
|
@ -24,6 +24,78 @@ add_entrypoint_object(
|
||||||
libc.src.__support.File.platform_file
|
libc.src.__support.File.platform_file
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
clearerr
|
||||||
|
SRCS
|
||||||
|
clearerr.cpp
|
||||||
|
HDRS
|
||||||
|
clearerr.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.__support.File.file
|
||||||
|
libc.src.__support.File.platform_file
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
clearerr_unlocked
|
||||||
|
SRCS
|
||||||
|
clearerr_unlocked.cpp
|
||||||
|
HDRS
|
||||||
|
clearerr_unlocked.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.__support.File.file
|
||||||
|
libc.src.__support.File.platform_file
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
feof
|
||||||
|
SRCS
|
||||||
|
feof.cpp
|
||||||
|
HDRS
|
||||||
|
feof.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.__support.File.file
|
||||||
|
libc.src.__support.File.platform_file
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
feof_unlocked
|
||||||
|
SRCS
|
||||||
|
feof_unlocked.cpp
|
||||||
|
HDRS
|
||||||
|
feof_unlocked.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.__support.File.file
|
||||||
|
libc.src.__support.File.platform_file
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
ferror
|
||||||
|
SRCS
|
||||||
|
ferror.cpp
|
||||||
|
HDRS
|
||||||
|
ferror.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.__support.File.file
|
||||||
|
libc.src.__support.File.platform_file
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
ferror_unlocked
|
||||||
|
SRCS
|
||||||
|
ferror_unlocked.cpp
|
||||||
|
HDRS
|
||||||
|
ferror_unlocked.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.__support.File.file
|
||||||
|
libc.src.__support.File.platform_file
|
||||||
|
)
|
||||||
|
|
||||||
add_entrypoint_object(
|
add_entrypoint_object(
|
||||||
fflush
|
fflush
|
||||||
SRCS
|
SRCS
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation of clearerr ----------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/clearerr.h"
|
||||||
|
#include "src/__support/File/file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(void, clearerr, (::FILE * stream)) {
|
||||||
|
reinterpret_cast<__llvm_libc::File *>(stream)->clearerr();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation header of clearerr -----------------------*- 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_CLEARERR_H
|
||||||
|
#define LLVM_LIBC_SRC_STDIO_CLEARERR_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
void clearerr(::FILE *stream);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_STDIO_CLEARERR_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation of clearerr_unlocked -------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/clearerr_unlocked.h"
|
||||||
|
#include "src/__support/File/file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(void, clearerr_unlocked, (::FILE * stream)) {
|
||||||
|
reinterpret_cast<__llvm_libc::File *>(stream)->clearerr_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation header of clearerr_unlocked --------------*- 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_CLEARERR_UNLOCKED_H
|
||||||
|
#define LLVM_LIBC_SRC_STDIO_CLEARERR_UNLOCKED_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
void clearerr_unlocked(::FILE *stream);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_STDIO_CLEARERR_UNLOCKED_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation of feof --------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/feof.h"
|
||||||
|
#include "src/__support/File/file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(int, feof, (::FILE * stream)) {
|
||||||
|
return reinterpret_cast<__llvm_libc::File *>(stream)->iseof();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation header of feof ---------------------------*- 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_FEOF_H
|
||||||
|
#define LLVM_LIBC_SRC_STDIO_FEOF_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
int feof(::FILE *stream);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_STDIO_FEOF_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation of feof_unlocked -----------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/feof_unlocked.h"
|
||||||
|
#include "src/__support/File/file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(int, feof_unlocked, (::FILE * stream)) {
|
||||||
|
return reinterpret_cast<__llvm_libc::File *>(stream)->iseof_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation header of feof_unlocked ------------------*- 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_FEOF_UNLOCKED_H
|
||||||
|
#define LLVM_LIBC_SRC_STDIO_FEOF_UNLOCKED_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
int feof_unlocked(::FILE *stream);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_STDIO_FEOF_UNLOCKED_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation of ferror ------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/ferror.h"
|
||||||
|
#include "src/__support/File/file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(int, ferror, (::FILE * stream)) {
|
||||||
|
return reinterpret_cast<__llvm_libc::File *>(stream)->error();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation header of ferror -------------------------*- 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_FERROR_H
|
||||||
|
#define LLVM_LIBC_SRC_STDIO_FERROR_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
int ferror(::FILE *stream);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_STDIO_FERROR_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation of ferror_unlocked ---------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/ferror_unlocked.h"
|
||||||
|
#include "src/__support/File/file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(int, ferror_unlocked, (::FILE * stream)) {
|
||||||
|
return reinterpret_cast<__llvm_libc::File *>(stream)->error_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
||||||
|
//===-- Implementation header of ferror_unlocked ----------------*- 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_FERROR_UNLOCKED_H
|
||||||
|
#define LLVM_LIBC_SRC_STDIO_FERROR_UNLOCKED_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
int ferror_unlocked(::FILE *stream);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_STDIO_FERROR_UNLOCKED_H
|
|
@ -7,7 +7,12 @@ add_libc_unittest(
|
||||||
SRCS
|
SRCS
|
||||||
fileop_test.cpp
|
fileop_test.cpp
|
||||||
DEPENDS
|
DEPENDS
|
||||||
|
libc.include.errno
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.stdio.clearerr
|
||||||
libc.src.stdio.fclose
|
libc.src.stdio.fclose
|
||||||
|
libc.src.stdio.feof
|
||||||
|
libc.src.stdio.ferror
|
||||||
libc.src.stdio.fflush
|
libc.src.stdio.fflush
|
||||||
libc.src.stdio.fopen
|
libc.src.stdio.fopen
|
||||||
libc.src.stdio.fread
|
libc.src.stdio.fread
|
||||||
|
@ -22,7 +27,12 @@ add_libc_unittest(
|
||||||
SRCS
|
SRCS
|
||||||
unlocked_fileop_test.cpp
|
unlocked_fileop_test.cpp
|
||||||
DEPENDS
|
DEPENDS
|
||||||
|
libc.include.errno
|
||||||
|
libc.include.stdio
|
||||||
|
libc.src.stdio.clearerr_unlocked
|
||||||
libc.src.stdio.fclose
|
libc.src.stdio.fclose
|
||||||
|
libc.src.stdio.feof_unlocked
|
||||||
|
libc.src.stdio.ferror_unlocked
|
||||||
libc.src.stdio.flockfile
|
libc.src.stdio.flockfile
|
||||||
libc.src.stdio.fopen
|
libc.src.stdio.fopen
|
||||||
libc.src.stdio.fread_unlocked
|
libc.src.stdio.fread_unlocked
|
||||||
|
@ -40,7 +50,10 @@ add_libc_unittest(
|
||||||
libc.include.errno
|
libc.include.errno
|
||||||
libc.include.stdio
|
libc.include.stdio
|
||||||
libc.include.stdlib
|
libc.include.stdlib
|
||||||
|
libc.src.stdio.clearerr
|
||||||
libc.src.stdio.fclose
|
libc.src.stdio.fclose
|
||||||
|
libc.src.stdio.feof
|
||||||
|
libc.src.stdio.ferror
|
||||||
libc.src.stdio.fflush
|
libc.src.stdio.fflush
|
||||||
libc.src.stdio.fopencookie
|
libc.src.stdio.fopencookie
|
||||||
libc.src.stdio.fread
|
libc.src.stdio.fread
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/stdio/clearerr.h"
|
||||||
#include "src/stdio/fclose.h"
|
#include "src/stdio/fclose.h"
|
||||||
|
#include "src/stdio/feof.h"
|
||||||
|
#include "src/stdio/ferror.h"
|
||||||
#include "src/stdio/fflush.h"
|
#include "src/stdio/fflush.h"
|
||||||
#include "src/stdio/fopen.h"
|
#include "src/stdio/fopen.h"
|
||||||
#include "src/stdio/fread.h"
|
#include "src/stdio/fread.h"
|
||||||
|
@ -14,15 +17,27 @@
|
||||||
#include "src/stdio/fwrite.h"
|
#include "src/stdio/fwrite.h"
|
||||||
#include "utils/UnitTest/Test.h"
|
#include "utils/UnitTest/Test.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
TEST(LlvmLibcStdio, SimpleOperations) {
|
TEST(LlvmLibcFILETest, SimpleFileOperations) {
|
||||||
constexpr char FILENAME[] = "testdata/simple_operations.test";
|
constexpr char FILENAME[] = "testdata/simple_operations.test";
|
||||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
|
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
|
||||||
ASSERT_FALSE(file == nullptr);
|
ASSERT_FALSE(file == nullptr);
|
||||||
constexpr char CONTENT[] = "1234567890987654321";
|
constexpr char CONTENT[] = "1234567890987654321";
|
||||||
ASSERT_EQ(sizeof(CONTENT) - 1,
|
ASSERT_EQ(sizeof(CONTENT) - 1,
|
||||||
__llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file));
|
__llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file));
|
||||||
|
|
||||||
|
// This is not a readable file.
|
||||||
|
char read_data[sizeof(CONTENT)];
|
||||||
|
ASSERT_EQ(__llvm_libc::fread(read_data, 1, sizeof(CONTENT), file), size_t(0));
|
||||||
|
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||||
|
EXPECT_NE(errno, 0);
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr(file);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror(file), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||||
|
|
||||||
file = __llvm_libc::fopen(FILENAME, "r");
|
file = __llvm_libc::fopen(FILENAME, "r");
|
||||||
|
@ -40,10 +55,24 @@ TEST(LlvmLibcStdio, SimpleOperations) {
|
||||||
ASSERT_EQ(__llvm_libc::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
|
ASSERT_EQ(__llvm_libc::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
|
||||||
ASSERT_STREQ(data, "9098");
|
ASSERT_STREQ(data, "9098");
|
||||||
|
|
||||||
|
// Reading another time should trigger eof.
|
||||||
|
ASSERT_NE(sizeof(CONTENT),
|
||||||
|
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), file));
|
||||||
|
ASSERT_NE(__llvm_libc::feof(file), 0);
|
||||||
|
|
||||||
|
// Should be an error to write.
|
||||||
|
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), file));
|
||||||
|
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||||
|
ASSERT_NE(errno, 0);
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr(file);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror(file), 0);
|
||||||
|
|
||||||
ASSERT_EQ(__llvm_libc::fclose(file), 0);
|
ASSERT_EQ(__llvm_libc::fclose(file), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LlvmLibcFILE, FFlushTest) {
|
TEST(LlvmLibcFILETest, FFlush) {
|
||||||
constexpr char FILENAME[] = "testdata/fflush.test";
|
constexpr char FILENAME[] = "testdata/fflush.test";
|
||||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w+");
|
::FILE *file = __llvm_libc::fopen(FILENAME, "w+");
|
||||||
ASSERT_FALSE(file == nullptr);
|
ASSERT_FALSE(file == nullptr);
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/stdio/clearerr.h"
|
||||||
#include "src/stdio/fclose.h"
|
#include "src/stdio/fclose.h"
|
||||||
|
#include "src/stdio/feof.h"
|
||||||
|
#include "src/stdio/ferror.h"
|
||||||
#include "src/stdio/fflush.h"
|
#include "src/stdio/fflush.h"
|
||||||
#include "src/stdio/fopencookie.h"
|
#include "src/stdio/fopencookie.h"
|
||||||
#include "src/stdio/fread.h"
|
#include "src/stdio/fread.h"
|
||||||
|
@ -102,12 +105,21 @@ TEST(LlvmLibcFOpenCookie, ReadOnlyCookieTest) {
|
||||||
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), f));
|
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), f));
|
||||||
ASSERT_STREQ(read_data, CONTENT);
|
ASSERT_STREQ(read_data, CONTENT);
|
||||||
|
|
||||||
|
// Reading another time should trigger eof.
|
||||||
|
ASSERT_NE(sizeof(CONTENT),
|
||||||
|
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), f));
|
||||||
|
ASSERT_NE(__llvm_libc::feof(f), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, __llvm_libc::fseek(f, 0, SEEK_SET));
|
ASSERT_EQ(0, __llvm_libc::fseek(f, 0, SEEK_SET));
|
||||||
// Should be an error to write.
|
// Should be an error to write.
|
||||||
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), f));
|
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), f));
|
||||||
ASSERT_EQ(errno, EBADF);
|
ASSERT_NE(__llvm_libc::ferror(f), 0);
|
||||||
|
ASSERT_NE(errno, 0);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr(f);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror(f), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
||||||
free(ss);
|
free(ss);
|
||||||
}
|
}
|
||||||
|
@ -134,9 +146,13 @@ TEST(LlvmLibcFOpenCookie, WriteOnlyCookieTest) {
|
||||||
char read_data[sizeof(WRITE_DATA)];
|
char read_data[sizeof(WRITE_DATA)];
|
||||||
// Should be an error to read.
|
// Should be an error to read.
|
||||||
ASSERT_EQ(size_t(0), __llvm_libc::fread(read_data, 1, sizeof(WRITE_DATA), f));
|
ASSERT_EQ(size_t(0), __llvm_libc::fread(read_data, 1, sizeof(WRITE_DATA), f));
|
||||||
|
ASSERT_NE(__llvm_libc::ferror(f), 0);
|
||||||
ASSERT_EQ(errno, EBADF);
|
ASSERT_EQ(errno, EBADF);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr(f);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror(f), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
||||||
free(ss);
|
free(ss);
|
||||||
}
|
}
|
||||||
|
@ -159,9 +175,13 @@ TEST(LlvmLibcFOpenCookie, AppendOnlyCookieTest) {
|
||||||
char read_data[READ_SIZE];
|
char read_data[READ_SIZE];
|
||||||
// This is not a readable file.
|
// This is not a readable file.
|
||||||
ASSERT_EQ(__llvm_libc::fread(read_data, 1, READ_SIZE, f), size_t(0));
|
ASSERT_EQ(__llvm_libc::fread(read_data, 1, READ_SIZE, f), size_t(0));
|
||||||
|
ASSERT_NE(__llvm_libc::ferror(f), 0);
|
||||||
EXPECT_NE(errno, 0);
|
EXPECT_NE(errno, 0);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr(f);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror(f), 0);
|
||||||
|
|
||||||
ASSERT_EQ(__llvm_libc::fwrite(WRITE_DATA, 1, sizeof(WRITE_DATA), f),
|
ASSERT_EQ(__llvm_libc::fwrite(WRITE_DATA, 1, sizeof(WRITE_DATA), f),
|
||||||
sizeof(WRITE_DATA));
|
sizeof(WRITE_DATA));
|
||||||
EXPECT_EQ(__llvm_libc::fflush(f), 0);
|
EXPECT_EQ(__llvm_libc::fflush(f), 0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//===-- Unittests for file operations like fopen, flcose etc --------------===//
|
//===-- Unittests for f operations like fopen, flcose etc --------------===//
|
||||||
//
|
//
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
@ -6,7 +6,10 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/stdio/clearerr_unlocked.h"
|
||||||
#include "src/stdio/fclose.h"
|
#include "src/stdio/fclose.h"
|
||||||
|
#include "src/stdio/feof_unlocked.h"
|
||||||
|
#include "src/stdio/ferror_unlocked.h"
|
||||||
#include "src/stdio/flockfile.h"
|
#include "src/stdio/flockfile.h"
|
||||||
#include "src/stdio/fopen.h"
|
#include "src/stdio/fopen.h"
|
||||||
#include "src/stdio/fread_unlocked.h"
|
#include "src/stdio/fread_unlocked.h"
|
||||||
|
@ -14,31 +17,60 @@
|
||||||
#include "src/stdio/fwrite_unlocked.h"
|
#include "src/stdio/fwrite_unlocked.h"
|
||||||
#include "utils/UnitTest/Test.h"
|
#include "utils/UnitTest/Test.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
TEST(LlvmLibcFILETest, UnlockedReadAndWrite) {
|
TEST(LlvmLibcFILETest, UnlockedReadAndWrite) {
|
||||||
constexpr char FILENAME[] = "testdata/unlocked_read_and_write.test";
|
constexpr char fNAME[] = "testdata/unlocked_read_and_write.test";
|
||||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
|
::FILE *f = __llvm_libc::fopen(fNAME, "w");
|
||||||
ASSERT_FALSE(file == nullptr);
|
ASSERT_FALSE(f == nullptr);
|
||||||
constexpr char CONTENT[] = "1234567890987654321";
|
constexpr char CONTENT[] = "1234567890987654321";
|
||||||
__llvm_libc::flockfile(file);
|
__llvm_libc::flockfile(f);
|
||||||
ASSERT_EQ(sizeof(CONTENT) - 1, __llvm_libc::fwrite_unlocked(
|
ASSERT_EQ(sizeof(CONTENT) - 1,
|
||||||
CONTENT, 1, sizeof(CONTENT) - 1, file));
|
__llvm_libc::fwrite_unlocked(CONTENT, 1, sizeof(CONTENT) - 1, f));
|
||||||
__llvm_libc::funlockfile(file);
|
// Should be an error to read.
|
||||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
|
||||||
|
|
||||||
file = __llvm_libc::fopen(FILENAME, "r");
|
|
||||||
ASSERT_FALSE(file == nullptr);
|
|
||||||
|
|
||||||
constexpr size_t READ_SIZE = 5;
|
constexpr size_t READ_SIZE = 5;
|
||||||
char data[READ_SIZE * 2 + 1];
|
char data[READ_SIZE * 2 + 1];
|
||||||
data[READ_SIZE * 2] = '\0';
|
data[READ_SIZE * 2] = '\0';
|
||||||
__llvm_libc::flockfile(file);
|
|
||||||
ASSERT_EQ(__llvm_libc::fread_unlocked(data, 1, READ_SIZE, file), READ_SIZE);
|
ASSERT_EQ(size_t(0),
|
||||||
ASSERT_EQ(__llvm_libc::fread_unlocked(data + READ_SIZE, 1, READ_SIZE, file),
|
__llvm_libc::fread_unlocked(data, 1, sizeof(READ_SIZE), f));
|
||||||
|
ASSERT_NE(__llvm_libc::ferror_unlocked(f), 0);
|
||||||
|
ASSERT_NE(errno, 0);
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr_unlocked(f);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror_unlocked(f), 0);
|
||||||
|
|
||||||
|
__llvm_libc::funlockfile(f);
|
||||||
|
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
||||||
|
|
||||||
|
f = __llvm_libc::fopen(fNAME, "r");
|
||||||
|
ASSERT_FALSE(f == nullptr);
|
||||||
|
|
||||||
|
__llvm_libc::flockfile(f);
|
||||||
|
ASSERT_EQ(__llvm_libc::fread_unlocked(data, 1, READ_SIZE, f), READ_SIZE);
|
||||||
|
ASSERT_EQ(__llvm_libc::fread_unlocked(data + READ_SIZE, 1, READ_SIZE, f),
|
||||||
READ_SIZE);
|
READ_SIZE);
|
||||||
__llvm_libc::funlockfile(file);
|
|
||||||
|
// Should be an error to write.
|
||||||
|
ASSERT_EQ(size_t(0),
|
||||||
|
__llvm_libc::fwrite_unlocked(CONTENT, 1, sizeof(CONTENT), f));
|
||||||
|
ASSERT_NE(__llvm_libc::ferror_unlocked(f), 0);
|
||||||
|
ASSERT_NE(errno, 0);
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
__llvm_libc::clearerr_unlocked(f);
|
||||||
|
ASSERT_EQ(__llvm_libc::ferror_unlocked(f), 0);
|
||||||
|
|
||||||
|
// Reading more should trigger eof.
|
||||||
|
char large_data[sizeof(CONTENT)];
|
||||||
|
ASSERT_NE(sizeof(CONTENT),
|
||||||
|
__llvm_libc::fread_unlocked(large_data, 1, sizeof(CONTENT), f));
|
||||||
|
ASSERT_NE(__llvm_libc::feof_unlocked(f), 0);
|
||||||
|
|
||||||
|
__llvm_libc::funlockfile(f);
|
||||||
ASSERT_STREQ(data, "1234567890");
|
ASSERT_STREQ(data, "1234567890");
|
||||||
|
|
||||||
ASSERT_EQ(__llvm_libc::fclose(file), 0);
|
ASSERT_EQ(__llvm_libc::fclose(f), 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue