Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- Strerror Converter for printf ---------------------------*- 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_PRINTF_CORE_STRERROR_CONVERTER_H
10#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_STRERROR_CONVERTER_H
11
12#include "src/__support/StringUtil/error_to_string.h"
13#include "src/__support/macros/config.h"
14#include "src/stdio/printf_core/core_structs.h"
15#include "src/stdio/printf_core/int_converter.h"
16#include "src/stdio/printf_core/string_converter.h"
17#include "src/stdio/printf_core/writer.h"
18
19namespace LIBC_NAMESPACE_DECL {
20namespace printf_core {
21
22template <WriteMode write_mode>
23LIBC_INLINE int convert_strerror(Writer<write_mode> *writer,
24 const FormatSection &to_conv) {
25 FormatSection new_conv = to_conv;
26 const int error_num = static_cast<int>(to_conv.conv_val_raw);
27
28 // The %m conversion takes no arguments passes the result of strerror(errno)
29 // to a string conversion (including all options). If the alternate form flag
30 // is set, then if errno is a valid error number the string of the errno macro
31 // is passed to a string conversion, else the integer value of errno is passed
32 // to an integer conversion.
33
34 // It's assumed that errno is passed in to_conv.conv_val_raw.
35
36 // normal form
37 if ((to_conv.flags & FormatFlags::ALTERNATE_FORM) == 0) {
38 char strerror_buff[64];
39 auto strerror_result = get_error_string(error_num, strerror_buff);
40 new_conv.conv_val_ptr =
41 reinterpret_cast<void *>(const_cast<char *>(strerror_result.data()));
42 new_conv.conv_name = 's';
43 return convert_string(writer, new_conv);
44 } else {
45 // alt form
46
47 // The handling of errno = 0 is in alt form weird. The rule for %m in alt
48 // form is "named macros print their name, else print errno as int." There
49 // isn't a specific name for errno = 0, but it does have an explicit meaning
50 // (success). Due to the way the string mappings work, it's easiest to just
51 // say that 0 is a valid macro with a string of "0". This works fine for
52 // most cases, but for precision and the int flags it changes the behavior.
53 // Given that this behavior is so incredibly deep in the weeds I doubt
54 // anyone would notice, I'm going to leave it as the simplest to implement
55 // (0 maps to "0"), which also happens to match what other libc
56 // implementations have done.
57
58 auto errno_name = try_get_errno_name(error_num);
59 // if there's a name available, use it.
60 if (errno_name) {
61 new_conv.conv_val_ptr =
62 reinterpret_cast<void *>(const_cast<char *>(errno_name->data()));
63 new_conv.conv_name = 's';
64 return convert_string(writer, new_conv);
65 } else {
66 // else do an int conversion
67 new_conv.conv_name = 'd';
68 return convert_int(writer, new_conv);
69 }
70 }
71}
72
73} // namespace printf_core
74} // namespace LIBC_NAMESPACE_DECL
75
76#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_STRERROR_CONVERTER_H
77

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of libc/src/stdio/printf_core/strerror_converter.h