blob: 68b4ad644caab7cd90c9f2a708a842ed889bb763 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
//===-- Implementation of perror ------------------------------------------===//
//
// 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/perror.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/File/file.h"
#include "src/__support/StringUtil/error_to_string.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
static int write_out(cpp::string_view str_view, File *f) {
if (str_view.size() > 0) {
auto result = f->write_unlocked(str_view.data(), str_view.size());
if (result.has_error())
return result.error;
}
return 0;
}
// separate function so that we can return early on error but still get the
// unlock. This function sets errno and should not be called elsewhere.
static void write_sequence(cpp::string_view str_view,
cpp::string_view err_str) {
int write_err;
// TODO: this seems like there should be some sort of queue system to
// deduplicate this code.
// FORMAT:
// if str != nullptr and doesn't start with a null byte:
// "[str]: [strerror(errno)]\n"
// else
// "[strerror(errno)]\n"
if (str_view.size() > 0) {
write_err = write_out(str_view, LIBC_NAMESPACE::stderr);
if (write_err != 0) {
libc_errno = write_err;
return;
}
write_err = write_out(": ", LIBC_NAMESPACE::stderr);
if (write_err != 0) {
libc_errno = write_err;
return;
}
}
write_err = write_out(err_str, LIBC_NAMESPACE::stderr);
if (write_err != 0) {
libc_errno = write_err;
return;
}
write_err = write_out("\n", LIBC_NAMESPACE::stderr);
if (write_err != 0) {
libc_errno = write_err;
return;
}
}
LLVM_LIBC_FUNCTION(void, perror, (const char *str)) {
const char empty_str[1] = {'\0'};
if (str == nullptr)
str = empty_str;
cpp::string_view str_view(str);
cpp::string_view err_str = get_error_string(libc_errno);
// We need to lock the stream to ensure the newline is always appended.
LIBC_NAMESPACE::stderr->lock();
write_sequence(str_view, err_str);
LIBC_NAMESPACE::stderr->unlock();
}
} // namespace LIBC_NAMESPACE_DECL
|