Force usage of assert() condition when NDEBUG is defined
[lttng-tools.git] / src / bin / lttng / loglevel.c
1 /*
2 * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include "loglevel.h"
9 #include <string.h>
10 #include <strings.h>
11 #include <ctype.h>
12
13 struct loglevel_name_value {
14 const char *name;
15 int value;
16 };
17
18 static
19 const struct loglevel_name_value loglevel_values[] = {
20 { .name = "EMERG", .value = LTTNG_LOGLEVEL_EMERG },
21 { .name = "TRACE_EMERG", .value = LTTNG_LOGLEVEL_EMERG },
22 { .name = "ALERT", .value = LTTNG_LOGLEVEL_ALERT },
23 { .name = "TRACE_ALERT", .value = LTTNG_LOGLEVEL_ALERT },
24 { .name = "CRIT", .value = LTTNG_LOGLEVEL_CRIT },
25 { .name = "TRACE_CRIT", .value = LTTNG_LOGLEVEL_CRIT },
26 { .name = "ERR", .value = LTTNG_LOGLEVEL_ERR },
27 { .name = "TRACE_ERR", .value = LTTNG_LOGLEVEL_ERR },
28 { .name = "WARNING", .value = LTTNG_LOGLEVEL_WARNING },
29 { .name = "TRACE_WARNING", .value = LTTNG_LOGLEVEL_WARNING },
30 { .name = "NOTICE", .value = LTTNG_LOGLEVEL_NOTICE },
31 { .name = "TRACE_NOTICE", .value = LTTNG_LOGLEVEL_NOTICE },
32 { .name = "INFO", .value = LTTNG_LOGLEVEL_INFO },
33 { .name = "TRACE_INFO", .value = LTTNG_LOGLEVEL_INFO },
34 { .name = "DEBUG_SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
35 { .name = "TRACE_DEBUG_SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
36 { .name = "SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
37 { .name = "DEBUG_PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
38 { .name = "TRACE_DEBUG_PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
39 { .name = "PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
40 { .name = "DEBUG_PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
41 { .name = "TRACE_DEBUG_PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
42 { .name = "PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
43 { .name = "DEBUG_MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
44 { .name = "TRACE_DEBUG_MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
45 { .name = "MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
46 { .name = "DEBUG_UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
47 { .name = "TRACE_DEBUG_UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
48 { .name = "UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
49 { .name = "DEBUG_FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
50 { .name = "TRACE_DEBUG_FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
51 { .name = "FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
52 { .name = "DEBUG_LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
53 { .name = "TRACE_DEBUG_LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
54 { .name = "LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
55 { .name = "DEBUG", .value = LTTNG_LOGLEVEL_DEBUG },
56 { .name = "TRACE_DEBUG", .value = LTTNG_LOGLEVEL_DEBUG },
57 };
58
59 static
60 const struct loglevel_name_value loglevel_log4j_values[] = {
61 { .name = "OFF", .value = LTTNG_LOGLEVEL_LOG4J_OFF },
62 { .name = "LOG4J_OFF", .value = LTTNG_LOGLEVEL_LOG4J_OFF },
63 { .name = "FATAL", .value = LTTNG_LOGLEVEL_LOG4J_FATAL },
64 { .name = "LOG4J_FATAL", .value = LTTNG_LOGLEVEL_LOG4J_FATAL },
65 { .name = "ERROR", .value = LTTNG_LOGLEVEL_LOG4J_ERROR },
66 { .name = "LOG4J_ERROR", .value = LTTNG_LOGLEVEL_LOG4J_ERROR },
67 { .name = "WARN", .value = LTTNG_LOGLEVEL_LOG4J_WARN },
68 { .name = "LOG4J_WARN", .value = LTTNG_LOGLEVEL_LOG4J_WARN },
69 { .name = "INFO", .value = LTTNG_LOGLEVEL_LOG4J_INFO },
70 { .name = "LOG4J_INFO", .value = LTTNG_LOGLEVEL_LOG4J_INFO },
71 { .name = "DEBUG", .value = LTTNG_LOGLEVEL_LOG4J_DEBUG },
72 { .name = "LOG4J_DEBUG", .value = LTTNG_LOGLEVEL_LOG4J_DEBUG },
73 { .name = "TRACE", .value = LTTNG_LOGLEVEL_LOG4J_TRACE },
74 { .name = "LOG4J_TRACE", .value = LTTNG_LOGLEVEL_LOG4J_TRACE },
75 { .name = "ALL", .value = LTTNG_LOGLEVEL_LOG4J_ALL },
76 { .name = "LOG4J_ALL", .value = LTTNG_LOGLEVEL_LOG4J_ALL },
77 };
78
79 static
80 const struct loglevel_name_value loglevel_jul_values[] = {
81 { .name = "OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
82 { .name = "JUL_OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
83 { .name = "SEVERE", .value = LTTNG_LOGLEVEL_JUL_SEVERE },
84 { .name = "JUL_SEVERE", .value = LTTNG_LOGLEVEL_JUL_SEVERE },
85 { .name = "WARNING", .value = LTTNG_LOGLEVEL_JUL_WARNING },
86 { .name = "JUL_WARNING", .value = LTTNG_LOGLEVEL_JUL_WARNING },
87 { .name = "INFO", .value = LTTNG_LOGLEVEL_JUL_INFO },
88 { .name = "JUL_INFO", .value = LTTNG_LOGLEVEL_JUL_INFO },
89 { .name = "CONFIG", .value = LTTNG_LOGLEVEL_JUL_CONFIG },
90 { .name = "JUL_CONFIG", .value = LTTNG_LOGLEVEL_JUL_CONFIG },
91 { .name = "FINE", .value = LTTNG_LOGLEVEL_JUL_FINE },
92 { .name = "JUL_FINE", .value = LTTNG_LOGLEVEL_JUL_FINE },
93 { .name = "FINER", .value = LTTNG_LOGLEVEL_JUL_FINER },
94 { .name = "JUL_FINER", .value = LTTNG_LOGLEVEL_JUL_FINER },
95 { .name = "FINEST", .value = LTTNG_LOGLEVEL_JUL_FINEST },
96 { .name = "JUL_FINEST", .value = LTTNG_LOGLEVEL_JUL_FINEST },
97 { .name = "ALL", .value = LTTNG_LOGLEVEL_JUL_ALL },
98 { .name = "JUL_ALL", .value = LTTNG_LOGLEVEL_JUL_ALL },
99 };
100
101 static
102 const struct loglevel_name_value loglevel_python_values[] = {
103 { .name = "CRITICAL", .value = LTTNG_LOGLEVEL_PYTHON_CRITICAL },
104 { .name = "PYTHON_CRITICAL", .value = LTTNG_LOGLEVEL_PYTHON_CRITICAL },
105 { .name = "ERROR", .value = LTTNG_LOGLEVEL_PYTHON_ERROR },
106 { .name = "PYTHON_ERROR", .value = LTTNG_LOGLEVEL_PYTHON_ERROR },
107 { .name = "WARNING", .value = LTTNG_LOGLEVEL_PYTHON_WARNING },
108 { .name = "PYTHON_WARNING", .value = LTTNG_LOGLEVEL_PYTHON_WARNING },
109 { .name = "INFO", .value = LTTNG_LOGLEVEL_PYTHON_INFO },
110 { .name = "PYTHON_INFO", .value = LTTNG_LOGLEVEL_PYTHON_INFO },
111 { .name = "DEBUG", .value = LTTNG_LOGLEVEL_PYTHON_DEBUG },
112 { .name = "PYTNON_DEBUG", .value = LTTNG_LOGLEVEL_PYTHON_DEBUG },
113 { .name = "NOTSET", .value = LTTNG_LOGLEVEL_PYTHON_NOTSET },
114 { .name = "PYTHON_NOTSET", .value = LTTNG_LOGLEVEL_PYTHON_NOTSET },
115 };
116
117 static
118 bool string_equal_insensitive(const char *a, const char *b)
119 {
120 return strcasecmp(a, b) == 0;
121 }
122
123 static
124 int lookup_value_from_name(const struct loglevel_name_value values[],
125 size_t values_count, const char *name)
126 {
127 size_t i;
128 int ret = -1;
129
130 if (!name) {
131 goto end;
132 }
133
134 for (i = 0; i < values_count; i++) {
135 if (string_equal_insensitive(values[i].name, name)) {
136 /* Match found. */
137 ret = values[i].value;
138 goto end;
139 }
140 }
141
142 end:
143 return ret;
144 }
145
146 static bool loglevel_parse_range_string_common(const char *str,
147 const struct loglevel_name_value *nvs,
148 size_t nvs_count,
149 int *min,
150 int *max)
151 {
152 bool ret;
153 int i;
154 const struct loglevel_name_value *nv;
155
156 for (i = 0; i < nvs_count; i++) {
157 nv = &nvs[i];
158
159 if (strncmp(str, nv->name, strlen(nv->name)) == 0) {
160 break;
161 }
162 }
163
164 if (i == nvs_count) {
165 goto error;
166 }
167
168 *min = nv->value;
169 str += strlen(nv->name);
170
171 if (*str == '\0') {
172 *max = nv->value;
173 ret = true;
174 goto end;
175 }
176
177 if (strncmp(str, "..", strlen("..")) != 0) {
178 goto error;
179 }
180
181 str += strlen("..");
182
183 if (*str == '\0') {
184 *max = LTTNG_LOGLEVEL_EMERG;
185 ret = true;
186 goto end;
187 }
188
189 for (i = 0; i < nvs_count; i++) {
190 nv = &nvs[i];
191
192 if (strcmp(str, nv->name) == 0) {
193 break;
194 }
195 }
196
197 if (i == nvs_count) {
198 goto error;
199 }
200
201 *max = nv->value;
202
203 ret = true;
204 goto end;
205
206 error:
207 ret = false;
208
209 end:
210 return ret;
211 }
212
213 LTTNG_HIDDEN
214 int loglevel_name_to_value(const char *name, enum lttng_loglevel *loglevel)
215 {
216 int ret = lookup_value_from_name(loglevel_values,
217 ARRAY_SIZE(loglevel_values), name);
218
219 if (ret >= 0) {
220 *loglevel = (typeof(*loglevel)) ret;
221 ret = 0;
222 }
223
224 return ret;
225 }
226
227 LTTNG_HIDDEN
228 bool loglevel_parse_range_string(const char *str,
229 enum lttng_loglevel *min,
230 enum lttng_loglevel *max)
231 {
232 int min_int, max_int;
233 bool ret = loglevel_parse_range_string_common(str, loglevel_values,
234 ARRAY_SIZE(loglevel_values), &min_int, &max_int);
235
236 *min = min_int;
237 *max = max_int;
238
239 return ret;
240 }
241
242 LTTNG_HIDDEN
243 int loglevel_log4j_name_to_value(
244 const char *name, enum lttng_loglevel_log4j *loglevel)
245 {
246 int ret = lookup_value_from_name(loglevel_log4j_values,
247 ARRAY_SIZE(loglevel_log4j_values),
248 name);
249
250 if (ret >= 0) {
251 *loglevel = (typeof(*loglevel)) ret;
252 ret = 0;
253 }
254
255 return ret;
256 }
257
258 LTTNG_HIDDEN
259 bool loglevel_log4j_parse_range_string(const char *str,
260 enum lttng_loglevel_log4j *min,
261 enum lttng_loglevel_log4j *max)
262 {
263 int min_int, max_int;
264 bool ret = loglevel_parse_range_string_common(str,
265 loglevel_log4j_values,
266 ARRAY_SIZE(loglevel_log4j_values), &min_int, &max_int);
267
268 *min = min_int;
269 *max = max_int;
270
271 return ret;
272 }
273
274 LTTNG_HIDDEN
275 int loglevel_jul_name_to_value(
276 const char *name, enum lttng_loglevel_jul *loglevel)
277 {
278 int ret = lookup_value_from_name(loglevel_jul_values,
279 ARRAY_SIZE(loglevel_jul_values),
280 name);
281
282 if (ret >= 0) {
283 *loglevel = (typeof(*loglevel)) ret;
284 ret = 0;
285 }
286
287 return ret;
288 }
289
290 LTTNG_HIDDEN
291 bool loglevel_jul_parse_range_string(const char *str,
292 enum lttng_loglevel_jul *min,
293 enum lttng_loglevel_jul *max)
294 {
295 int min_int, max_int;
296 bool ret = loglevel_parse_range_string_common(str, loglevel_jul_values,
297 ARRAY_SIZE(loglevel_jul_values), &min_int, &max_int);
298
299 *min = min_int;
300 *max = max_int;
301
302 return ret;
303 }
304
305 LTTNG_HIDDEN
306 int loglevel_python_name_to_value(
307 const char *name, enum lttng_loglevel_python *loglevel)
308 {
309 int ret = lookup_value_from_name(loglevel_python_values,
310 ARRAY_SIZE(loglevel_python_values),
311 name);
312
313 if (ret >= 0) {
314 *loglevel = (typeof(*loglevel)) ret;
315 ret = 0;
316 }
317
318 return ret;
319 }
320
321 LTTNG_HIDDEN
322 bool loglevel_python_parse_range_string(const char *str,
323 enum lttng_loglevel_python *min,
324 enum lttng_loglevel_python *max)
325 {
326 int min_int, max_int;
327 bool ret = loglevel_parse_range_string_common(str,
328 loglevel_python_values,
329 ARRAY_SIZE(loglevel_python_values), &min_int, &max_int);
330
331 *min = min_int;
332 *max = max_int;
333
334 return ret;
335 }
336
337 static
338 const char *lookup_name_from_value(const struct loglevel_name_value values[],
339 size_t values_count, int loglevel)
340 {
341 size_t i;
342 const char *name = NULL;
343
344 for (i = 0; i < values_count; i++) {
345 if (values[i].value == loglevel) {
346 /* Match found. */
347 name = values[i].name;
348 goto end;
349 }
350 }
351
352 end:
353 return name;
354 }
355
356 LTTNG_HIDDEN
357 const char *loglevel_value_to_name(int loglevel)
358 {
359 return lookup_name_from_value(
360 loglevel_values, ARRAY_SIZE(loglevel_values), loglevel);
361 }
362
363 LTTNG_HIDDEN
364 const char *loglevel_log4j_value_to_name(int loglevel)
365 {
366 return lookup_name_from_value(loglevel_log4j_values,
367 ARRAY_SIZE(loglevel_log4j_values), loglevel);
368 }
369
370 LTTNG_HIDDEN
371 const char *loglevel_jul_value_to_name(int loglevel)
372 {
373 return lookup_name_from_value(loglevel_jul_values,
374 ARRAY_SIZE(loglevel_jul_values), loglevel);
375 }
376
377 LTTNG_HIDDEN
378 const char *loglevel_python_value_to_name(int loglevel)
379 {
380 return lookup_name_from_value(loglevel_python_values,
381 ARRAY_SIZE(loglevel_python_values), loglevel);
382 }
This page took 0.03642 seconds and 4 git commands to generate.