1 /* 2 * Copyright (c) 2018 Oticon A/S 3 * Copyright (c) 2023 Nordic Semiconductor ASA 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 /* 9 * Utility functions for printing info/warning/error messages and exit execution. 10 * 11 * These functions provide an optional but recommended way of printing messages from 12 * programs which use bsim. By using this functions you ensure both a consistent, 13 * not-interleaved message output. 14 * 15 * Several types of traces can be done: Errors, Warnings, Info, Debug and "raw" messages. 16 * By default, errors and warnings will be printed to the process stderr, the rest to stdout. 17 * 18 * Info, debug and "raw" messages have an associated verbosity level: an integer between 0 and 9. 19 * Users have the option (thru the command line argument `-v=<verbosity_level>`) to select up to 20 * which verbosity they want messages to be displayed. Any message over the selected verbosity 21 * will be discarded. 22 * 23 * All messages will be prefixed with a small string given by the program 24 * (typically 5 characters long). 25 * For Physical layer simulation programs, this will be a short of the Phy name; 26 * For devices typically "d_<%02i>:", where %02i will be the device number, 27 * using at least 2 digits. 28 * 29 * Error and warning traces will, by default and when routed to a tty, be colored. 30 * Coloring will be disabled by default when printing to a file or another process. 31 * Coloring can be controlled with command line options. 32 * 33 * "Exit" traces can also be produced, this will print an error, and exit the program execution. 34 * In this case the registered main exit cleanup function will be called. 35 * 36 * The main API for users are the bs_trace_{exit|error|warning|info|debug|raw}[_line][_time] macros. 37 * The "_line" variants will print the file and line from which the trace originated together with the 38 * message. 39 * The "_time" variants will also print the current simulated time (as reported by the time function 40 * registered with `bs_trace_register_time_function()` ) 41 * "_manual_time" versions exists only to support bizarre use cases, and it is recommended to not use 42 * them in general. 43 * 44 * All these macros have printf() like semantics (after the verbosity level). 45 */ 46 47 #ifndef UTIL_BS_TRACING_H 48 #define UTIL_BS_TRACING_H 49 50 #ifdef __cplusplus 51 extern "C"{ 52 #endif 53 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <stdarg.h> 57 #include <stddef.h> 58 #include "bs_types.h" 59 #include "bs_utils.h" 60 61 typedef uint8_t (*main_cleanup_f)(void); 62 typedef bs_time_t (*time_f)(void); 63 64 /* 65 * Disable color in traces 66 * 67 * This is an API meant for the controlling program. 68 * Normal users of this functionality are not expected to call it. 69 */ 70 void bs_trace_disable_color(char * argv, int offset); 71 72 /* 73 * Enable color in traces. 74 * This will only enable color when printing to a tty. 75 * 76 * This is an API meant for the controlling program. 77 * Normal users of this functionality are not expected to call it. 78 */ 79 void bs_trace_enable_color(char * argv, int offset); 80 81 /* 82 * For color in traces enabled. 83 * Even if not printing to a tty. 84 * 85 * This is an API meant for the controlling program. 86 * Normal users of this functionality are not expected to call it. 87 */ 88 void bs_trace_force_color(char * argv, int offset); 89 90 /* 91 * Is <file_number> connected to a tty. 92 * Where file_number is 0 for stdout, 1 for stderr. 93 * 94 * returns: 1 if a tty, 0 otherwise. 95 * 96 * This is an API meant for the controlling program. 97 * Normal users of this functionality are not expected to call it. 98 */ 99 int bs_trace_is_tty(int file_number); 100 101 /* 102 * Set the tracing level. 103 * 104 * Normally this function will be only called from the command 105 * from the command line argument parsing. 106 */ 107 void bs_trace_set_level(int new_trace_level); 108 109 /* 110 * Will a message with a given verbosity level be printed or discarded 111 * 112 * Returns 1 if it will be printed, 0 otherwise. 113 */ 114 int bs_trace_will_it_be_traced(int this_message_trace_level); 115 116 /* 117 * Register the function to be called from the exit() APIs to terminate 118 * the program. If none is registered the libC standard exit() will be called. 119 */ 120 void bs_trace_register_cleanup_function(main_cleanup_f cleanup_f); 121 122 /* 123 * Register a function which returns the current simulated time 124 */ 125 void bs_trace_register_time_function(time_f t_f); 126 127 /* 128 * Set prefix for prints 129 */ 130 void bs_trace_set_prefix(const char* prefix); 131 132 /* 133 * Set prefix for prints: Phy variant 134 */ 135 void bs_trace_set_prefix_phy(const char* prefix); 136 137 /* 138 * Set prefix for prints: device variant 139 */ 140 void bs_trace_set_prefix_dev(int device_nbr); 141 142 /* 143 * Exit without printing an error message 144 */ 145 void bs_trace_silent_exit(uint8_t code); 146 147 typedef enum {BS_TRACE_EXIT = 0, /*To Stdout, with EXIT prefix*/ 148 BS_TRACE_ERROR, /*To Stderr, with ERROR prefix*/ 149 BS_TRACE_WARNING, /*To Stderr, with WARNING prefix*/ 150 BS_TRACE_INFO, /*To Stdout, with INFO prefix*/ 151 BS_TRACE_DEBUG, /*To Stdout, with DEBUG prefix*/ 152 BS_TRACE_RAW, /*To Stdout, no extra prefix */ 153 } base_trace_type_t; 154 typedef enum { BS_TRACE_NOTIME = 0, BS_TRACE_TIME_PROVIDED, BS_TRACE_AUTOTIME} base_trace_timed_type_t; 155 156 /* 157 * Underlying functions for the bs_trace_ macros. 158 * 159 * It is recommended to use the bs_trace_ macros defined below instead 160 */ 161 void bs_trace_print(base_trace_type_t type, 162 const char *caller_filename, unsigned int caller_line, 163 int this_message_trace_level, 164 base_trace_timed_type_t time_type, bs_time_t time, 165 const char *format, ...); 166 void bs_trace_vprint(base_trace_type_t type, 167 const char *caller_filename, unsigned int caller_line, 168 int this_message_trace_level, 169 base_trace_timed_type_t time_type, bs_time_t time, 170 const char *format, va_list variable_args); 171 172 #define bs_trace_exit(...) do { bs_trace_print(BS_TRACE_EXIT ,NULL, 0, 5,BS_TRACE_NOTIME, 0,__VA_ARGS__); \ 173 BS_UNREACHABLE; } while(0) 174 #define bs_trace_exit_line(...) do { bs_trace_print(BS_TRACE_EXIT ,__FILE__,__LINE__,5,BS_TRACE_NOTIME, 0,__VA_ARGS__); \ 175 BS_UNREACHABLE; } while(0) 176 #define bs_trace_exit_line_time(...) do { bs_trace_print(BS_TRACE_EXIT ,__FILE__,__LINE__,5,BS_TRACE_AUTOTIME, 0,__VA_ARGS__); \ 177 BS_UNREACHABLE; } while(0) 178 #define bs_trace_exit_time_line(...) do { bs_trace_print(BS_TRACE_EXIT ,__FILE__,__LINE__,5,BS_TRACE_AUTOTIME, 0,__VA_ARGS__); \ 179 BS_UNREACHABLE; } while(0) 180 #define bs_trace_exit_time(...) do { bs_trace_print(BS_TRACE_EXIT ,NULL, 0, 5,BS_TRACE_AUTOTIME, 0,__VA_ARGS__); \ 181 BS_UNREACHABLE; } while(0) 182 183 #define bs_trace_error(...) do { bs_trace_print(BS_TRACE_ERROR ,NULL, 0, 0,BS_TRACE_NOTIME, 0,__VA_ARGS__); \ 184 BS_UNREACHABLE; } while(0) 185 #define bs_trace_error_line(...) do { bs_trace_print(BS_TRACE_ERROR ,__FILE__,__LINE__,0,BS_TRACE_NOTIME, 0,__VA_ARGS__); \ 186 BS_UNREACHABLE; } while(0) 187 #define bs_trace_error_line_time(...) do { bs_trace_print(BS_TRACE_ERROR ,__FILE__,__LINE__,0,BS_TRACE_AUTOTIME, 0,__VA_ARGS__); \ 188 BS_UNREACHABLE; } while(0) 189 #define bs_trace_error_time_line(...) do { bs_trace_print(BS_TRACE_ERROR ,__FILE__,__LINE__,0,BS_TRACE_AUTOTIME, 0,__VA_ARGS__); \ 190 BS_UNREACHABLE; } while(0) 191 #define bs_trace_error_time(...) do { bs_trace_print(BS_TRACE_ERROR ,NULL, 0, 0,BS_TRACE_AUTOTIME, 0,__VA_ARGS__); \ 192 BS_UNREACHABLE; } while(0) 193 #define bs_trace_error_manual_time(t,...) do { bs_trace_print(BS_TRACE_ERROR ,NULL, 0, 0,BS_TRACE_TIME_PROVIDED,t,__VA_ARGS__); \ 194 BS_UNREACHABLE; } while(0) 195 196 #define bs_trace_warning(...) bs_trace_print(BS_TRACE_WARNING,NULL, 0, 0,BS_TRACE_NOTIME, 0,__VA_ARGS__) 197 #define bs_trace_warning_line(...) bs_trace_print(BS_TRACE_WARNING,__FILE__,__LINE__,0,BS_TRACE_NOTIME, 0,__VA_ARGS__) 198 #define bs_trace_warning_line_time(...) bs_trace_print(BS_TRACE_WARNING,__FILE__,__LINE__,0,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 199 #define bs_trace_warning_time_line(...) bs_trace_print(BS_TRACE_WARNING,__FILE__,__LINE__,0,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 200 #define bs_trace_warning_time(...) bs_trace_print(BS_TRACE_WARNING,NULL, 0, 0,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 201 #define bs_trace_warning_manual_time(t,...) bs_trace_print(BS_TRACE_WARNING ,NULL, 0, 0,BS_TRACE_TIME_PROVIDED,t,__VA_ARGS__) 202 #define bs_trace_warning_manual_time_line(t,...) bs_trace_print(BS_TRACE_WARNING ,__FILE__,__LINE__, 0,BS_TRACE_TIME_PROVIDED,t,__VA_ARGS__) 203 204 #define bs_trace_info(l,...) bs_trace_print(BS_TRACE_INFO ,NULL, 0, l,BS_TRACE_NOTIME, 0,__VA_ARGS__) 205 #define bs_trace_info_line(l,...) bs_trace_print(BS_TRACE_INFO ,__FILE__,__LINE__,l,BS_TRACE_NOTIME, 0,__VA_ARGS__) 206 #define bs_trace_info_line_time(l,...) bs_trace_print(BS_TRACE_INFO ,__FILE__,__LINE__,l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 207 #define bs_trace_info_time_line(l,...) bs_trace_print(BS_TRACE_INFO ,__FILE__,__LINE__,l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 208 #define bs_trace_info_time(l,...) bs_trace_print(BS_TRACE_INFO ,NULL, 0, l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 209 210 #define bs_trace_debug(l,...) bs_trace_print(BS_TRACE_DEBUG ,NULL, 0, l,BS_TRACE_NOTIME, 0,__VA_ARGS__) 211 #define bs_trace_debug_line(l,...) bs_trace_print(BS_TRACE_DEBUG ,__FILE__,__LINE__,l,BS_TRACE_NOTIME, 0,__VA_ARGS__) 212 #define bs_trace_debug_line_time(l,...) bs_trace_print(BS_TRACE_DEBUG ,__FILE__,__LINE__,l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 213 #define bs_trace_debug_time_line(l,...) bs_trace_print(BS_TRACE_DEBUG ,__FILE__,__LINE__,l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 214 #define bs_trace_debug_time(l,...) bs_trace_print(BS_TRACE_DEBUG ,NULL, 0, l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 215 216 #define bs_trace_raw(l,...) bs_trace_print(BS_TRACE_RAW ,NULL, 0, l,BS_TRACE_NOTIME, 0,__VA_ARGS__) 217 #define bs_trace_raw_line(l,...) bs_trace_print(BS_TRACE_RAW ,__FILE__,__LINE__,l,BS_TRACE_NOTIME, 0,__VA_ARGS__) 218 #define bs_trace_raw_line_time(l,...) bs_trace_print(BS_TRACE_RAW ,__FILE__,__LINE__,l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 219 #define bs_trace_raw_time_line(l,...) bs_trace_print(BS_TRACE_RAW ,__FILE__,__LINE__,l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 220 #define bs_trace_raw_time(l,...) bs_trace_print(BS_TRACE_RAW ,NULL, 0, l,BS_TRACE_AUTOTIME, 0,__VA_ARGS__) 221 #define bs_trace_raw_manual_time(l,t,...) bs_trace_print(BS_TRACE_RAW ,NULL, 0, l,BS_TRACE_TIME_PROVIDED,t,__VA_ARGS__) 222 223 #ifdef __cplusplus 224 } 225 #endif 226 227 #endif /* UTIL_BS_TRACING_H */ 228