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