status.h
1 /* 2 * SPDX-FileCopyrightText: 2023-2024 Le’ 3 * 4 * SPDX-License-Identifier: LGPL-3.0-or-later 5 */ 6 7 #ifndef LE_STATUS_H 8 # define LE_STATUS_H 9 10 # include <stdint.h> 11 # include <stddef.h> 12 13 # ifdef __cplusplus 14 extern "C" { 15 # endif 16 17 /* 18 * The status code structure is modelled after OpenVMS condition codes. 19 * As a matter of fact, they are exactly the same, with one exceptions: 20 * 21 * The UNIT and REASON fields must always have their highest bit set, 22 * thus making them user generated codes, not to be mixed with system 23 * codes. 24 */ 25 26 typedef uint32_t LE_STATUS; 27 28 # define LE_M_STATUS_CONTROL UINT32_C(0xF0000000) 29 # define LE_V_STATUS_CONTROL 28 30 # define LE_M_STATUS_UNIT UINT32_C(0x0FFF0000) 31 # define LE_V_STATUS_UNIT 16 32 # define LE_M_STATUS_REASON UINT32_C(0x0000FFF8) 33 # define LE_V_STATUS_REASON 3 34 # define LE_M_STATUS_SEVERITY UINT32_C(0x00000007) 35 # define LE_V_STATUS_SEVERITY 0 36 37 # define LE_status_control(sts) \ 38 (((sts) & LE_M_STATUS_CONTROL) >> LE_V_STATUS_CONTROL) 39 # define LE_status_module(sts) \ 40 (((sts) & LE_M_STATUS_MODULE) >> LE_V_STATUS_MODULE) 41 # define LE_status_code(sts) \ 42 (((sts) & LE_M_STATUS_CODE) >> LE_V_STATUS_CODE) 43 # define LE_status_severity(sts) \ 44 (((sts) & LE_M_STATUS_SEVERITY) >> LE_V_STATUS_SEVERITY) 45 46 # define LE_STATUS_SEVERITY_WARNING 0 47 # define LE_STATUS_SEVERITY_SUCCESS 1 48 # define LE_STATUS_SEVERITY_ERROR 2 49 # define LE_STATUS_SEVERITY_INFORMATION 3 50 # define LE_STATUS_SEVERITY_SEVERE 4 51 # define LE_STATUS_SEVERITY_FATAL 4 52 # define LE_status_is_OK(status) \ 53 (((status) & 1) != 0) 54 # define LE_status_is_warning(status) \ 55 (LE_status_severity(status) == LE_STATUS_SEVERITY_WARNING) 56 # define LE_status_is_success(status) \ 57 (LE_status_severity(status) == LE_STATUS_SEVERITY_SUCCESS) 58 # define LE_status_is_error(status) \ 59 (LE_status_severity(status) == LE_STATUS_SEVERITY_ERROR) 60 # define LE_status_is_information(status) \ 61 (LE_status_severity(status) == LE_STATUS_SEVERITY_INFORMATION) 62 # define LE_status_is_severe(status) \ 63 (LE_status_severity(status) == LE_STATUS_SEVERITY_SEVERE) 64 # define LE_status_is_fatal(status) \ 65 (LE_status_severity(status) == LE_STATUS_SEVERITY_FATAL) 66 67 /* 68 * Unit 0 isn't a unit at all, it represents statuses that can be used by 69 * anyone at any time. 70 */ 71 72 /* 73 * A few generic status codes that can be return anywhere. Their use should 74 * be replaced with "real" status codes as soon as possible. There are no 75 * messages associated with these. 76 * 77 * Note that all severity codes aren't represented here, as they are not 78 * all relevant for this level of simplicity. 79 */ 80 # define LE_STS_WARNING (0 | LE_STATUS_SEVERITY_WARNING) 81 # define LE_STS_SUCCESS (0 | LE_STATUS_SEVERITY_SUCCESS) 82 # define LE_STS_ERROR (0 | LE_STATUS_SEVERITY_ERROR) 83 # define LE_STS_FATAL_ERROR (0 | LE_STATUS_SEVERITY_FATAL) 84 85 /* 86 * A few generic status codes for some common cases. Note that they can 87 * be used with other severities, as the application desires. 88 */ 89 # define LE_STS_ALLOC_FAILURE (1 | LE_STATUS_SEVERITY_FATAL) 90 # define LE_STS_NOT_IMPLEMENTED (2 | LE_STATUS_SEVERITY_ERROR) 91 # define LE_STS_NOT_SUPPORTED (3 | LE_STATUS_SEVERITY_WARNING) 92 # define LE_STS_INVALID_PARAMETER (4 | LE_STATUS_SEVERITY_ERROR) 93 94 /* 95 * For processing errors further than just returning a status code, 96 * storage and functions to register and retrieve messages are needed. 97 * The storage structure is opaque. 98 */ 99 100 typedef struct LE_messages_st LE_messages_t; 101 102 LE_STATUS LE_new_status_messages(LE_messages_t **mdata); 103 LE_STATUS LE_free_status_messages(LE_messages_t **mdata); 104 LE_STATUS LE_register_status_unit(LE_messages_t *mdata, LE_STATUS sts, 105 const char *name); 106 LE_STATUS LE_register_status_message(LE_messages_t *mdata, LE_STATUS sts, 107 const char *identity, const char *text); 108 109 /* 110 * Formats the text for the message given by |sts|. The message text 111 * is formatted like this: 112 * 113 * {prefix}:{unit}-{severity}-{identity}, {message-text} 114 * 115 * The {prefix} is: 116 * 117 * - for the severities ERROR, SEVERE and FATAL: error 118 * - for the severity WARNING: warning 119 * - for the severities SUCCESS and INFORMATION: note 120 * 121 * The {unit} is the unit identity, or "NOUNIT" if the unit name hasn't 122 * been registered. 123 * 124 * The {severity} is one character indicating the exact severity: 125 * 126 * - W for WARNING 127 * - S for SUCCESS 128 * - E for ERROR 129 * - I for INFORMATION 130 * - F for SEVERE or FATAL 131 * 132 * The {identity} is the registered message identity, or "NOMSG" if the 133 * message identity hasn't been registered. 134 * 135 * The {message-text} is the registered message text, or "Status=0x{sts-hex}" 136 * with {sts-hexh} replaced with the hexadecimal rendition of |sts| 137 */ 138 LE_STATUS LE_get_status_text(const LE_messages_t *mdata, LE_STATUS sts, 139 char *buf, size_t *buflen, size_t bufsize); 140 141 /* 142 * Utility to print messages, with additional text for each message. 143 * The data for the messages are passed with the |message_vector|, and 144 * may include additional text for each message in that vector. 145 * 146 * Each message in the message vector is passed to LE_get_status_text(), 147 * and the result is formatted like this: 148 * 149 * 1st message: 150 * 151 * {status-text} 152 * {additional text} 153 * 154 * 2nd..nth message 155 * 156 * -{status-text} 157 * {additional text} 158 * 159 * {status-text} is the text provided by LE_get_status_text(), and 160 * {additional-text} is the concatenation of all the additional texts 161 * in the message vector. 162 * 163 * |action| is an optional routine that is called for each message being 164 * printed. If it is NULL or returns true, LE_print_status will proceed 165 * with printing the message to stderr, otherwise it will not. 166 */ 167 typedef struct LE_message_vector_st { 168 LE_STATUS sts; 169 size_t additional_text_count; 170 const char **additional_text; 171 } LE_message_vector_t; 172 LE_STATUS LE_print_status(const LE_messages_t *mdata, 173 size_t message_vector_count, 174 LE_message_vector_t *message_vector, 175 _Bool (*action)(const char *message)); 176 177 # ifdef __cplusplus 178 } 179 # endif 180 181 #endif