xref: /llvm-project/libc/src/__support/StringUtil/signal_to_string.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
107793f95SMichael Jones //===-- Implementation of a class for mapping signals to strings ----------===//
207793f95SMichael Jones //
307793f95SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
407793f95SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
507793f95SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
607793f95SMichael Jones //
707793f95SMichael Jones //===----------------------------------------------------------------------===//
807793f95SMichael Jones 
925174976SSiva Chandra Reddy #include "signal_to_string.h"
1025174976SSiva Chandra Reddy #include "platform_signals.h"
1107793f95SMichael Jones 
1207793f95SMichael Jones #include "src/__support/CPP/span.h"
1307793f95SMichael Jones #include "src/__support/CPP/string_view.h"
1407793f95SMichael Jones #include "src/__support/CPP/stringstream.h"
1507793f95SMichael Jones #include "src/__support/StringUtil/message_mapper.h"
1607793f95SMichael Jones #include "src/__support/integer_to_string.h"
17daeee567SSiva Chandra Reddy #include "src/__support/macros/attributes.h"
18*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
1907793f95SMichael Jones 
2007793f95SMichael Jones #include <signal.h>
2107793f95SMichael Jones #include <stddef.h>
2207793f95SMichael Jones 
23*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
2407793f95SMichael Jones namespace internal {
2507793f95SMichael Jones 
2607793f95SMichael Jones constexpr size_t max_buff_size() {
2707793f95SMichael Jones   constexpr size_t base_str_len = sizeof("Real-time signal");
2807793f95SMichael Jones   // the buffer should be able to hold "Real-time signal" + ' ' + num_str
29b555912eSGuillaume Chatelet   return (base_str_len + 1 + IntegerToString<int>::buffer_size()) *
30b555912eSGuillaume Chatelet          sizeof(char);
3107793f95SMichael Jones }
3207793f95SMichael Jones 
3307793f95SMichael Jones // This is to hold signal strings that have to be custom built. It may be
3407793f95SMichael Jones // rewritten on every call to strsignal (or other signal to string function).
3507793f95SMichael Jones constexpr size_t SIG_BUFFER_SIZE = max_buff_size();
36daeee567SSiva Chandra Reddy LIBC_THREAD_LOCAL char signal_buffer[SIG_BUFFER_SIZE];
3707793f95SMichael Jones 
38bb2ebbd1SSiva Chandra Reddy constexpr size_t TOTAL_STR_LEN = total_str_len(PLATFORM_SIGNALS);
3907793f95SMichael Jones 
40bb2ebbd1SSiva Chandra Reddy constexpr size_t SIG_ARRAY_SIZE = max_key_val(PLATFORM_SIGNALS) + 1;
4107793f95SMichael Jones 
42bb2ebbd1SSiva Chandra Reddy constexpr MessageMapper<SIG_ARRAY_SIZE, TOTAL_STR_LEN>
43bb2ebbd1SSiva Chandra Reddy     signal_mapper(PLATFORM_SIGNALS);
4407793f95SMichael Jones 
4507793f95SMichael Jones cpp::string_view build_signal_string(int sig_num, cpp::span<char> buffer) {
4607793f95SMichael Jones   cpp::string_view base_str;
4707793f95SMichael Jones   if (sig_num >= SIGRTMIN && sig_num <= SIGRTMAX) {
4807793f95SMichael Jones     base_str = cpp::string_view("Real-time signal");
4907793f95SMichael Jones     sig_num -= SIGRTMIN;
5007793f95SMichael Jones   } else {
5107793f95SMichael Jones     base_str = cpp::string_view("Unknown signal");
5207793f95SMichael Jones   }
5307793f95SMichael Jones 
5407793f95SMichael Jones   // if the buffer can't hold "Unknown signal" + ' ' + num_str, then just
5507793f95SMichael Jones   // return "Unknown signal".
5607793f95SMichael Jones   if (buffer.size() <
57b555912eSGuillaume Chatelet       (base_str.size() + 1 + IntegerToString<int>::buffer_size()))
5807793f95SMichael Jones     return base_str;
5907793f95SMichael Jones 
6007793f95SMichael Jones   cpp::StringStream buffer_stream(
6107793f95SMichael Jones       {const_cast<char *>(buffer.data()), buffer.size()});
6207793f95SMichael Jones   buffer_stream << base_str << ' ' << sig_num << '\0';
6307793f95SMichael Jones   return buffer_stream.str();
6407793f95SMichael Jones }
6507793f95SMichael Jones 
6607793f95SMichael Jones } // namespace internal
6707793f95SMichael Jones 
6807793f95SMichael Jones cpp::string_view get_signal_string(int sig_num) {
6907793f95SMichael Jones   return get_signal_string(
7007793f95SMichael Jones       sig_num, {internal::signal_buffer, internal::SIG_BUFFER_SIZE});
7107793f95SMichael Jones }
7207793f95SMichael Jones 
7307793f95SMichael Jones cpp::string_view get_signal_string(int sig_num, cpp::span<char> buffer) {
7407793f95SMichael Jones   auto opt_str = internal::signal_mapper.get_str(sig_num);
7507793f95SMichael Jones   if (opt_str)
7607793f95SMichael Jones     return *opt_str;
7707793f95SMichael Jones   else
7807793f95SMichael Jones     return internal::build_signal_string(sig_num, buffer);
7907793f95SMichael Jones }
8007793f95SMichael Jones 
81*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
82