1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
18 #endif /* __cplusplus */
23 #include "support.h" /* bool type and fc__attribute */
27 LOG_ERROR
, /* non-fatal errors */
29 LOG_VERBOSE
, /* not shown by default */
30 LOG_DEBUG
/* suppressed unless DEBUG defined */
33 /* If one wants to compare autogames with lots of code changes, the line
34 * numbers can cause a lot of noise. In that case set this to a fixed
36 #define __FC_LINE__ __LINE__
38 /* Dummy log message. */
39 extern const char *nologmsg
;
40 #define NOLOGMSG nologmsg
42 /* Preparation of the log message, i.e. add a backtrace. */
43 typedef void (*log_pre_callback_fn
)(enum log_level
, bool print_from_where
,
44 const char *where
, const char *msg
);
46 /* A function type to enable custom output of log messages other than
47 * via fputs(stderr). Eg, to the server console while handling prompts,
48 * rfcstyle, client notifications; Eg, to the client window output window?
50 typedef void (*log_callback_fn
)(enum log_level
, const char *, bool file_too
);
52 /* A function type to generate a custom prefix for the log messages, e.g.
53 * add the turn and/or time of the log message. */
54 typedef const char *(*log_prefix_fn
)(void);
56 void log_init(const char *filename
, enum log_level initial_level
,
57 log_callback_fn callback
, log_prefix_fn prefix
,
58 int fatal_assertions
);
60 bool log_parse_level_str(const char *level_str
, enum log_level
*ret_level
);
62 log_pre_callback_fn
log_set_pre_callback(log_pre_callback_fn precallback
);
63 log_callback_fn
log_set_callback(log_callback_fn callback
);
64 log_prefix_fn
log_set_prefix(log_prefix_fn prefix
);
65 void log_set_level(enum log_level level
);
66 enum log_level
log_get_level(void);
68 bool log_do_output_for_level_at_location(enum log_level level
,
69 const char *file
, int line
);
72 void vdo_log(const char *file
, const char *function
, int line
,
73 bool print_from_where
, enum log_level level
,
74 char *buf
, int buflen
, const char *message
, va_list args
);
75 void do_log(const char *file
, const char *function
, int line
,
76 bool print_from_where
, enum log_level level
,
77 const char *message
, ...)
78 fc__attribute((__format__ (__printf__
, 6, 7)));
81 #define log_do_output_for_level(level) \
82 log_do_output_for_level_at_location(level, __FILE__, __FC_LINE__)
84 #define log_do_output_for_level(level) (log_get_level() >= level)
85 #endif /* FREECIV_DEBUG */
89 #define log_base(level, message, ...) \
90 if (log_do_output_for_level(level)) { \
91 do_log(__FILE__, __FUNCTION__, __FC_LINE__, FALSE, \
92 level, message, ## __VA_ARGS__); \
94 /* This one doesn't need check, fatal messages are always displayed. */
95 #define log_fatal(message, ...) \
96 do_log(__FILE__, __FUNCTION__, __FC_LINE__, FALSE, \
97 LOG_FATAL, message, ## __VA_ARGS__);
98 #define log_error(message, ...) \
99 log_base(LOG_ERROR, message, ## __VA_ARGS__)
100 #define log_normal(message, ...) \
101 log_base(LOG_NORMAL, message, ## __VA_ARGS__)
102 #define log_verbose(message, ...) \
103 log_base(LOG_VERBOSE, message, ## __VA_ARGS__)
105 # define log_debug(message, ...) \
106 log_base(LOG_DEBUG, message, ## __VA_ARGS__)
108 # define log_debug(message, ...) /* Do nothing. */
109 #endif /* FREECIV_DEBUG */
110 #ifdef FREECIV_TESTMATIC
111 #define log_testmatic(message, ...) \
112 log_base(LOG_ERROR, message, ## __VA_ARGS__)
113 #define log_testmatic_alt(altlvl, message, ...) \
114 log_base(LOG_ERROR, message, ## __VA_ARGS__)
115 #else /* FREECIV_TESTMATIC */
116 #define log_testmatic(message, ...) /* Do nothing. */
117 #define log_testmatic_alt(altlvl, message, ...) \
118 log_base(altlvl, message, ## __VA_ARGS__)
119 #endif /* FREECIV_TESTMATIC */
121 #define log_va_list(level, msg, args) \
122 if (log_do_output_for_level(level)) { \
124 vdo_log(__FILE__, __FUNCTION__, __FC_LINE__, FALSE, \
125 level, __buf_, sizeof(__buf_), msg, args); \
128 /* Used by game debug command */
129 #define log_test log_normal
130 #define log_packet log_verbose
131 #define log_packet_detailed log_debug
132 #define LOG_TEST LOG_NORMAL /* needed by citylog_*() functions */
136 void fc_assert_set_fatal(int fatal_assertions
);
137 #ifdef FREECIV_NDEBUG
138 /* Disable the assertion failures, but not the tests! */
139 #define fc_assert_fail(...) (void) 0
141 void fc_assert_fail(const char *file
, const char *function
, int line
,
142 const char *assertion
, const char *message
, ...)
143 fc__attribute((__format__ (__printf__
, 5, 6)));
144 #endif /* FREECIV_NDEBUG */
146 #define fc_assert_full(file, function, line, \
147 condition, action, message, ...) \
148 if (!(condition)) { \
149 fc_assert_fail(file, function, line, #condition, \
150 message, ## __VA_ARGS__); \
153 (void) 0 /* Force the usage of ';' at the end of the call. */
155 #ifdef FREECIV_NDEBUG
157 #define fc_assert(...) (void) 0
158 #define fc_assert_msg(...) (void) 0
161 #define fc_assert(condition) \
162 ((condition) ? (void) 0 \
163 : fc_assert_fail(__FILE__, __FUNCTION__, __FC_LINE__, #condition, \
165 /* Like assert() with extra message. */
166 #define fc_assert_msg(condition, message, ...) \
167 ((condition) ? (void) 0 \
168 : fc_assert_fail(__FILE__, __FUNCTION__, __FC_LINE__, \
169 #condition, message, ## __VA_ARGS__))
170 #endif /* FREECIV_NDEBUG */
172 /* Do action on failure. */
173 #define fc_assert_action(condition, action) \
174 fc_assert_full(__FILE__, __FUNCTION__, __FC_LINE__, condition, action, \
176 /* Return on failure. */
177 #define fc_assert_ret(condition) \
178 fc_assert_action(condition, return)
179 /* Return a value on failure. */
180 #define fc_assert_ret_val(condition, val) \
181 fc_assert_action(condition, return val)
182 /* Exit on failure. */
183 #define fc_assert_exit(condition) \
184 fc_assert_action(condition, exit(EXIT_FAILURE))
186 /* Do action on failure with extra message. */
187 #define fc_assert_action_msg(condition, action, message, ...) \
188 fc_assert_full(__FILE__, __FUNCTION__, __FC_LINE__, condition, action, \
189 message, ## __VA_ARGS__)
190 /* Return on failure with extra message. */
191 #define fc_assert_ret_msg(condition, message, ...) \
192 fc_assert_action_msg(condition, return, message, ## __VA_ARGS__)
193 /* Return a value on failure with extra message. */
194 #define fc_assert_ret_val_msg(condition, val, message, ...) \
195 fc_assert_action_msg(condition, return val, message, ## __VA_ARGS__)
196 /* Exit on failure with extra message. */
197 #define fc_assert_exit_msg(condition, message, ...) \
198 fc_assert_action(condition, \
199 log_fatal(message, ## __VA_ARGS__); exit(EXIT_FAILURE))
202 #ifdef FREECIV_CXX11_STATIC_ASSERT
203 #define FC_STATIC_ASSERT(cond, tag) static_assert(cond, #tag)
204 #endif /* FREECIV_CXX11_STATIC_ASSERT */
205 #else /* __cplusplus */
206 #ifdef FREECIV_C11_STATIC_ASSERT
207 #define FC_STATIC_ASSERT(cond, tag) _Static_assert(cond, #tag)
208 #endif /* FREECIV_C11_STATIC_ASSERT */
209 #endif /* __cplusplus */
211 #ifndef FC_STATIC_ASSERT
212 /* Static (compile-time) assertion.
213 * "tag" is a semi-meaningful C identifier which will appear in the
214 * compiler error message if the assertion fails. */
215 #define FC_STATIC_ASSERT(cond, tag) \
216 enum { static_assert_ ## tag = 1 / (!!(cond)) }
221 #endif /* __cplusplus */
223 #endif /* FC__LOG_H */