Plugins: use UNUSED_VAR instead of casting to void
[babeltrace.git] / plugins / text / text.c
1 /*
2 * text.c
3 *
4 * Babeltrace CTF Text Output Plugin
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #include <babeltrace/plugin/plugin-dev.h>
31 #include <babeltrace/component/component.h>
32 #include <babeltrace/component/component-sink.h>
33 #include <babeltrace/component/notification/notification.h>
34 #include <babeltrace/component/notification/iterator.h>
35 #include <babeltrace/component/notification/event.h>
36 #include <babeltrace/values.h>
37 #include <babeltrace/compiler.h>
38 #include <plugins-common.h>
39 #include <stdio.h>
40 #include <stdbool.h>
41 #include <glib.h>
42 #include "text.h"
43
44 static
45 const char *plugin_options[] = {
46 "output-path",
47 "debug-info-dir",
48 "debug-info-target-prefix",
49 "debug-info-full-path",
50 "no-delta",
51 "clock-cycles",
52 "clock-seconds",
53 "clock-date",
54 "clock-gmt",
55 "name-default", /* show/hide */
56 "name-payload",
57 "name-context",
58 "name-scope",
59 "name-header",
60 "field-default", /* show/hide */
61 "field-trace",
62 "field-trace:hostname",
63 "field-trace:domain",
64 "field-trace:procname",
65 "field-trace:vpid",
66 "field-loglevel",
67 "field-emf",
68 };
69
70 static
71 void destroy_text_data(struct text_component *text)
72 {
73 (void) g_string_free(text->string, TRUE);
74 g_free(text->options.output_path);
75 g_free(text->options.debug_info_dir);
76 g_free(text->options.debug_info_target_prefix);
77 g_free(text);
78 }
79
80 static
81 struct text_component *create_text(void)
82 {
83 struct text_component *text;
84
85 text = g_new0(struct text_component, 1);
86 if (!text) {
87 goto end;
88 }
89 text->string = g_string_new("");
90 if (!text->string) {
91 goto error;
92 }
93 end:
94 return text;
95
96 error:
97 g_free(text);
98 return NULL;
99 }
100
101 static
102 void destroy_text(struct bt_component *component)
103 {
104 void *data = bt_component_get_private_data(component);
105
106 destroy_text_data(data);
107 }
108
109 static
110 enum bt_component_status handle_notification(struct text_component *text,
111 struct bt_notification *notification)
112 {
113 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
114
115 if (!text) {
116 ret = BT_COMPONENT_STATUS_ERROR;
117 goto end;
118 }
119
120 switch (bt_notification_get_type(notification)) {
121 case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
122 puts("<packet>");
123 break;
124 case BT_NOTIFICATION_TYPE_PACKET_END:
125 puts("</packet>");
126 break;
127 case BT_NOTIFICATION_TYPE_EVENT:
128 {
129 struct bt_ctf_event *event = bt_notification_event_get_event(
130 notification);
131
132 if (!event) {
133 ret = BT_COMPONENT_STATUS_ERROR;
134 goto end;
135 }
136 ret = text_print_event(text, event);
137 bt_put(event);
138 if (ret != BT_COMPONENT_STATUS_OK) {
139 goto end;
140 }
141 break;
142 }
143 case BT_NOTIFICATION_TYPE_STREAM_END:
144 puts("</stream>");
145 break;
146 default:
147 puts("Unhandled notification type");
148 }
149 end:
150 return ret;
151 }
152
153 static
154 enum bt_component_status run(struct bt_component *component)
155 {
156 enum bt_component_status ret;
157 struct bt_notification *notification = NULL;
158 struct bt_notification_iterator *it;
159 struct text_component *text = bt_component_get_private_data(component);
160
161 ret = bt_component_sink_get_input_iterator(component, 0, &it);
162 if (ret != BT_COMPONENT_STATUS_OK) {
163 goto end;
164 }
165
166 if (likely(text->processed_first_event)) {
167 enum bt_notification_iterator_status it_ret;
168
169 it_ret = bt_notification_iterator_next(it);
170 switch (it_ret) {
171 case BT_NOTIFICATION_ITERATOR_STATUS_ERROR:
172 ret = BT_COMPONENT_STATUS_ERROR;
173 goto end;
174 case BT_NOTIFICATION_ITERATOR_STATUS_END:
175 ret = BT_COMPONENT_STATUS_END;
176 goto end;
177 default:
178 break;
179 }
180 }
181 notification = bt_notification_iterator_get_notification(it);
182 if (!notification) {
183 ret = BT_COMPONENT_STATUS_ERROR;
184 goto end;
185 }
186
187 ret = handle_notification(text, notification);
188 text->processed_first_event = true;
189 end:
190 bt_put(it);
191 bt_put(notification);
192 return ret;
193 }
194
195 static
196 enum bt_component_status add_params_to_map(struct bt_value *plugin_opt_map)
197 {
198 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
199 unsigned int i;
200
201 for (i = 0; i < BT_ARRAY_SIZE(plugin_options); i++) {
202 const char *key = plugin_options[i];
203 enum bt_value_status status;
204
205 status = bt_value_map_insert(plugin_opt_map, key, bt_value_null);
206 switch (status) {
207 case BT_VALUE_STATUS_OK:
208 break;
209 default:
210 ret = BT_COMPONENT_STATUS_ERROR;
211 goto end;
212 }
213 }
214 end:
215 return ret;
216 }
217
218 static
219 bool check_param_exists(const char *key, struct bt_value *object, void *data)
220 {
221 struct text_component *text = data;
222 struct bt_value *plugin_opt_map = text->plugin_opt_map;
223
224 if (!bt_value_map_get(plugin_opt_map, key)) {
225 fprintf(text->err,
226 "[warning] Parameter \"%s\" unknown to \"text\" plugin\n", key);
227 }
228 return true;
229 }
230
231 static
232 enum bt_component_status apply_one_string(const char *key,
233 struct bt_value *params,
234 char **option)
235 {
236 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
237 struct bt_value *value = NULL;
238 enum bt_value_status status;
239 const char *str;
240
241 value = bt_value_map_get(params, key);
242 if (!value) {
243 goto end;
244 }
245 if (bt_value_is_null(value)) {
246 goto end;
247 }
248 status = bt_value_string_get(value, &str);
249 switch (status) {
250 case BT_VALUE_STATUS_OK:
251 break;
252 default:
253 ret = BT_COMPONENT_STATUS_ERROR;
254 goto end;
255 }
256 *option = g_strdup(str);
257 end:
258 bt_put(value);
259 return ret;
260 }
261
262 static
263 enum bt_component_status apply_one_bool(const char *key,
264 struct bt_value *params,
265 bool *option,
266 bool *found)
267 {
268 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
269 struct bt_value *value = NULL;
270 enum bt_value_status status;
271
272 value = bt_value_map_get(params, key);
273 if (!value) {
274 goto end;
275 }
276 status = bt_value_bool_get(value, option);
277 switch (status) {
278 case BT_VALUE_STATUS_OK:
279 break;
280 default:
281 ret = BT_COMPONENT_STATUS_ERROR;
282 goto end;
283 }
284 if (found) {
285 *found = true;
286 }
287 end:
288 bt_put(value);
289 return ret;
290 }
291
292 static
293 enum bt_component_status apply_params(struct text_component *text,
294 struct bt_value *params)
295 {
296 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
297 enum bt_value_status status;
298 bool value, found;
299 char *str = NULL;
300
301 text->plugin_opt_map = bt_value_map_create();
302 if (!text->plugin_opt_map) {
303 ret = BT_COMPONENT_STATUS_ERROR;
304 goto end;
305 }
306 ret = add_params_to_map(text->plugin_opt_map);
307 if (ret != BT_COMPONENT_STATUS_OK) {
308 goto end;
309 }
310 /* Report unknown parameters. */
311 status = bt_value_map_foreach(params, check_param_exists, text);
312 switch (status) {
313 case BT_VALUE_STATUS_OK:
314 break;
315 default:
316 ret = BT_COMPONENT_STATUS_ERROR;
317 goto end;
318 }
319 /* Known parameters. */
320 ret = apply_one_string("output-path",
321 params,
322 &text->options.output_path);
323 if (ret != BT_COMPONENT_STATUS_OK) {
324 goto end;
325 }
326
327 ret = apply_one_string("debug-info-dir",
328 params,
329 &text->options.debug_info_dir);
330 if (ret != BT_COMPONENT_STATUS_OK) {
331 goto end;
332 }
333
334 ret = apply_one_string("debug-info-target-prefix",
335 params,
336 &text->options.debug_info_target_prefix);
337 if (ret != BT_COMPONENT_STATUS_OK) {
338 goto end;
339 }
340
341 value = false; /* Default. */
342 ret = apply_one_bool("debug-info-full-path", params, &value, NULL);
343 if (ret != BT_COMPONENT_STATUS_OK) {
344 goto end;
345 }
346 text->options.debug_info_full_path = value;
347
348 value = false; /* Default. */
349 ret = apply_one_bool("no-delta", params, &value, NULL);
350 if (ret != BT_COMPONENT_STATUS_OK) {
351 goto end;
352 }
353 text->options.print_delta_field = !value; /* Reverse logic. */
354
355 value = false; /* Default. */
356 ret = apply_one_bool("clock-cycles", params, &value, NULL);
357 if (ret != BT_COMPONENT_STATUS_OK) {
358 goto end;
359 }
360 text->options.print_timestamp_cycles = value;
361
362 value = false; /* Default. */
363 ret = apply_one_bool("clock-seconds", params, &value, NULL);
364 if (ret != BT_COMPONENT_STATUS_OK) {
365 goto end;
366 }
367 text->options.clock_seconds = value;
368
369 value = false; /* Default. */
370 ret = apply_one_bool("clock-date", params, &value, NULL);
371 if (ret != BT_COMPONENT_STATUS_OK) {
372 goto end;
373 }
374 text->options.clock_date = value;
375
376 value = false; /* Default. */
377 ret = apply_one_bool("clock-gmt", params, &value, NULL);
378 if (ret != BT_COMPONENT_STATUS_OK) {
379 goto end;
380 }
381 text->options.clock_gmt = value;
382
383 /* Names. */
384 ret = apply_one_string("name-default", params, &str);
385 if (ret != BT_COMPONENT_STATUS_OK) {
386 goto end;
387 }
388 if (!str) {
389 text->options.name_default = TEXT_DEFAULT_UNSET;
390 } else if (!strcmp(str, "show")) {
391 text->options.name_default = TEXT_DEFAULT_SHOW;
392 } else if (!strcmp(str, "hide")) {
393 text->options.name_default = TEXT_DEFAULT_HIDE;
394 } else {
395 ret = BT_COMPONENT_STATUS_ERROR;
396 goto end;
397 }
398 g_free(str);
399 str = NULL;
400
401 switch (text->options.name_default) {
402 case TEXT_DEFAULT_UNSET:
403 text->options.print_payload_field_names = true;
404 text->options.print_context_field_names = true;
405 text->options.print_header_field_names = false;
406 text->options.print_scope_field_names = false;
407 break;
408 case TEXT_DEFAULT_SHOW:
409 text->options.print_payload_field_names = true;
410 text->options.print_context_field_names = true;
411 text->options.print_header_field_names = true;
412 text->options.print_scope_field_names = true;
413 break;
414 case TEXT_DEFAULT_HIDE:
415 text->options.print_payload_field_names = false;
416 text->options.print_context_field_names = false;
417 text->options.print_header_field_names = false;
418 text->options.print_scope_field_names = false;
419 break;
420 default:
421 ret = BT_COMPONENT_STATUS_ERROR;
422 goto end;
423 }
424
425 value = false;
426 found = false;
427 ret = apply_one_bool("name-payload", params, &value, &found);
428 if (ret != BT_COMPONENT_STATUS_OK) {
429 goto end;
430 }
431 if (found) {
432 text->options.print_payload_field_names = value;
433 }
434
435 value = false;
436 found = false;
437 ret = apply_one_bool("name-context", params, &value, &found);
438 if (ret != BT_COMPONENT_STATUS_OK) {
439 goto end;
440 }
441 if (found) {
442 text->options.print_context_field_names = value;
443 }
444
445 value = false;
446 found = false;
447 ret = apply_one_bool("name-header", params, &value, &found);
448 if (ret != BT_COMPONENT_STATUS_OK) {
449 goto end;
450 }
451 if (found) {
452 text->options.print_header_field_names = value;
453 }
454
455 value = false;
456 found = false;
457 ret = apply_one_bool("name-scope", params, &value, &found);
458 if (ret != BT_COMPONENT_STATUS_OK) {
459 goto end;
460 }
461 if (found) {
462 text->options.print_scope_field_names = value;
463 }
464
465 /* Fields. */
466 ret = apply_one_string("field-default", params, &str);
467 if (ret != BT_COMPONENT_STATUS_OK) {
468 goto end;
469 }
470 if (!str) {
471 text->options.field_default = TEXT_DEFAULT_UNSET;
472 } else if (!strcmp(str, "show")) {
473 text->options.field_default = TEXT_DEFAULT_SHOW;
474 } else if (!strcmp(str, "hide")) {
475 text->options.field_default = TEXT_DEFAULT_HIDE;
476 } else {
477 ret = BT_COMPONENT_STATUS_ERROR;
478 goto end;
479 }
480 g_free(str);
481 str = NULL;
482
483 switch (text->options.field_default) {
484 case TEXT_DEFAULT_UNSET:
485 text->options.print_trace_field = false;
486 text->options.print_trace_hostname_field = true;
487 text->options.print_trace_domain_field = false;
488 text->options.print_trace_procname_field = true;
489 text->options.print_trace_vpid_field = true;
490 text->options.print_loglevel_field = false;
491 text->options.print_emf_field = false;
492 text->options.print_emf_field = false;
493 break;
494 case TEXT_DEFAULT_SHOW:
495 text->options.print_trace_field = true;
496 text->options.print_trace_hostname_field = true;
497 text->options.print_trace_domain_field = true;
498 text->options.print_trace_procname_field = true;
499 text->options.print_trace_vpid_field = true;
500 text->options.print_loglevel_field = true;
501 text->options.print_emf_field = true;
502 text->options.print_emf_field = true;
503 break;
504 case TEXT_DEFAULT_HIDE:
505 text->options.print_trace_field = false;
506 text->options.print_trace_hostname_field = false;
507 text->options.print_trace_domain_field = false;
508 text->options.print_trace_procname_field = false;
509 text->options.print_trace_vpid_field = false;
510 text->options.print_loglevel_field = false;
511 text->options.print_emf_field = false;
512 text->options.print_emf_field = false;
513 break;
514 default:
515 ret = BT_COMPONENT_STATUS_ERROR;
516 goto end;
517 }
518
519 value = false;
520 found = false;
521 ret = apply_one_bool("field-trace", params, &value, &found);
522 if (ret != BT_COMPONENT_STATUS_OK) {
523 goto end;
524 }
525 if (found) {
526 text->options.print_trace_field = value;
527 }
528
529 value = false;
530 found = false;
531 ret = apply_one_bool("field-trace:hostname", params, &value, &found);
532 if (ret != BT_COMPONENT_STATUS_OK) {
533 goto end;
534 }
535 if (found) {
536 text->options.print_trace_hostname_field = value;
537 }
538
539 value = false;
540 found = false;
541 ret = apply_one_bool("field-trace:domain", params, &value, &found);
542 if (ret != BT_COMPONENT_STATUS_OK) {
543 goto end;
544 }
545 if (found) {
546 text->options.print_trace_domain_field = value;
547 }
548
549 value = false;
550 found = false;
551 ret = apply_one_bool("field-trace:procname", params, &value, &found);
552 if (ret != BT_COMPONENT_STATUS_OK) {
553 goto end;
554 }
555 if (found) {
556 text->options.print_trace_procname_field = value;
557 }
558
559 value = false;
560 found = false;
561 ret = apply_one_bool("field-trace:vpid", params, &value, &found);
562 if (ret != BT_COMPONENT_STATUS_OK) {
563 goto end;
564 }
565 if (found) {
566 text->options.print_trace_vpid_field = value;
567 }
568
569 value = false;
570 found = false;
571 ret = apply_one_bool("field-loglevel", params, &value, &found);
572 if (ret != BT_COMPONENT_STATUS_OK) {
573 goto end;
574 }
575 if (found) {
576 text->options.print_loglevel_field = value;
577 }
578
579 value = false;
580 found = false;
581 ret = apply_one_bool("field-emf", params, &value, &found);
582 if (ret != BT_COMPONENT_STATUS_OK) {
583 goto end;
584 }
585 if (found) {
586 text->options.print_emf_field = value;
587 }
588
589 value = false;
590 found = false;
591 ret = apply_one_bool("field-emf", params, &value, &found);
592 if (ret != BT_COMPONENT_STATUS_OK) {
593 goto end;
594 }
595 if (found) {
596 text->options.print_emf_field = value;
597 }
598
599 end:
600 bt_put(text->plugin_opt_map);
601 text->plugin_opt_map = NULL;
602 g_free(str);
603 return ret;
604 }
605
606 static
607 enum bt_component_status text_component_init(
608 struct bt_component *component, struct bt_value *params,
609 UNUSED_VAR void *init_method_data)
610 {
611 enum bt_component_status ret;
612 struct text_component *text = create_text();
613
614 if (!text) {
615 ret = BT_COMPONENT_STATUS_NOMEM;
616 goto end;
617 }
618
619 text->out = stdout;
620 text->err = stderr;
621
622 text->delta_cycles = -1ULL;
623 text->last_cycles_timestamp = -1ULL;
624
625 text->delta_real_timestamp = -1ULL;
626 text->last_real_timestamp = -1ULL;
627
628 ret = apply_params(text, params);
629 if (ret != BT_COMPONENT_STATUS_OK) {
630 goto error;
631 }
632
633 ret = bt_component_set_private_data(component, text);
634 if (ret != BT_COMPONENT_STATUS_OK) {
635 goto error;
636 }
637 end:
638 return ret;
639 error:
640 destroy_text_data(text);
641 return ret;
642 }
643
644 /* Initialize plug-in entry points. */
645 BT_PLUGIN(text);
646 BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
647 BT_PLUGIN_AUTHOR("Jérémie Galarneau");
648 BT_PLUGIN_LICENSE("MIT");
649 BT_PLUGIN_SINK_COMPONENT_CLASS(text, run);
650 BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(text, text_component_init);
651 BT_PLUGIN_SINK_COMPONENT_CLASS_DESTROY_METHOD(text, destroy_text);
652 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(text,
653 "Formats CTF-IR to text. Formerly known as ctf-text.");
654
This page took 0.041833 seconds and 5 git commands to generate.