Commit | Line | Data |
---|---|---|
af9a82eb JG |
1 | /* |
2 | * print.c | |
3 | * | |
4 | * Babeltrace CTF Text Output Plugin Event Printing | |
5 | * | |
6 | * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
f504043c | 7 | * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
af9a82eb JG |
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/ctf-ir/event.h> | |
31 | #include <babeltrace/ctf-ir/event-class.h> | |
6a18b281 | 32 | #include <babeltrace/ctf-ir/packet.h> |
af9a82eb JG |
33 | #include <babeltrace/ctf-ir/stream.h> |
34 | #include <babeltrace/ctf-ir/stream-class.h> | |
ac0c6bdd | 35 | #include <babeltrace/ctf-ir/clock-class.h> |
6a18b281 MD |
36 | #include <babeltrace/ctf-ir/field-types.h> |
37 | #include <babeltrace/ctf-ir/fields.h> | |
1556a1af | 38 | #include <babeltrace/ctf-ir/trace.h> |
3d9990ac | 39 | #include <babeltrace/bitfield-internal.h> |
ad96d936 | 40 | #include <babeltrace/common-internal.h> |
6a18b281 | 41 | #include <inttypes.h> |
93a4161c | 42 | #include <ctype.h> |
af9a82eb JG |
43 | #include "text.h" |
44 | ||
1556a1af JG |
45 | #define NSEC_PER_SEC 1000000000LL |
46 | ||
ad96d936 PP |
47 | #define COLOR_NAME BT_COMMON_COLOR_BOLD |
48 | #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN | |
49 | #define COLOR_RST BT_COMMON_COLOR_RESET | |
0a2d9024 JG |
50 | #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD |
51 | #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD | |
52 | #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD | |
8f3f0945 | 53 | #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED |
ad96d936 PP |
54 | #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA |
55 | #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW | |
56 | ||
6a18b281 MD |
57 | static inline |
58 | const char *rem_(const char *str) | |
59 | { | |
60 | if (str[0] == '_') | |
61 | return &str[1]; | |
62 | else | |
63 | return str; | |
64 | } | |
65 | ||
af9a82eb JG |
66 | struct timestamp { |
67 | int64_t real_timestamp; /* Relative to UNIX epoch. */ | |
68 | uint64_t clock_value; /* In cycles. */ | |
69 | }; | |
70 | ||
6a18b281 MD |
71 | static |
72 | enum bt_component_status print_field(struct text_component *text, | |
2b4c4a7c JD |
73 | struct bt_ctf_field *field, bool print_names, |
74 | GQuark *filters_fields, int filter_array_len); | |
6a18b281 | 75 | |
ad96d936 PP |
76 | static |
77 | void print_name_equal(struct text_component *text, const char *name) | |
78 | { | |
79 | if (text->use_colors) { | |
80 | fprintf(text->out, "%s%s%s = ", COLOR_NAME, name, COLOR_RST); | |
81 | } else { | |
06e8da8b | 82 | fprintf(text->out, "%s = ", name); |
ad96d936 PP |
83 | } |
84 | } | |
85 | ||
86 | static | |
87 | void print_field_name_equal(struct text_component *text, const char *name) | |
88 | { | |
89 | if (text->use_colors) { | |
90 | fprintf(text->out, "%s%s%s = ", COLOR_FIELD_NAME, name, | |
91 | COLOR_RST); | |
92 | } else { | |
06e8da8b | 93 | fprintf(text->out, "%s = ", name); |
ad96d936 PP |
94 | } |
95 | } | |
96 | ||
af9a82eb JG |
97 | static |
98 | void print_timestamp_cycles(struct text_component *text, | |
ac0c6bdd | 99 | struct bt_ctf_clock_class *clock_class, |
af9a82eb JG |
100 | struct bt_ctf_event *event) |
101 | { | |
1556a1af JG |
102 | int ret; |
103 | struct bt_ctf_clock_value *clock_value; | |
104 | uint64_t cycles; | |
105 | ||
ac0c6bdd | 106 | clock_value = bt_ctf_event_get_clock_value(event, clock_class); |
1556a1af JG |
107 | if (!clock_value) { |
108 | fputs("????????????????????", text->out); | |
109 | return; | |
110 | } | |
111 | ||
112 | ret = bt_ctf_clock_value_get_value(clock_value, &cycles); | |
113 | bt_put(clock_value); | |
114 | if (ret) { | |
115 | fprintf(text->out, "Error"); | |
116 | return; | |
117 | } | |
118 | fprintf(text->out, "%020" PRIu64, cycles); | |
3af83b5a MD |
119 | |
120 | if (text->last_cycles_timestamp != -1ULL) { | |
121 | text->delta_cycles = cycles - text->last_cycles_timestamp; | |
122 | } | |
123 | text->last_cycles_timestamp = cycles; | |
af9a82eb JG |
124 | } |
125 | ||
126 | static | |
127 | void print_timestamp_wall(struct text_component *text, | |
ac0c6bdd | 128 | struct bt_ctf_clock_class *clock_class, |
af9a82eb JG |
129 | struct bt_ctf_event *event) |
130 | { | |
1556a1af JG |
131 | int ret; |
132 | struct bt_ctf_clock_value *clock_value; | |
133 | int64_t ts_nsec = 0; /* add configurable offset */ | |
134 | int64_t ts_sec = 0; /* add configurable offset */ | |
135 | uint64_t ts_sec_abs, ts_nsec_abs; | |
136 | bool is_negative; | |
af9a82eb | 137 | |
ac0c6bdd | 138 | clock_value = bt_ctf_event_get_clock_value(event, clock_class); |
1556a1af JG |
139 | if (!clock_value) { |
140 | fputs("??:??:??.?????????", text->out); | |
141 | return; | |
142 | } | |
143 | ||
144 | ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec); | |
145 | bt_put(clock_value); | |
146 | if (ret) { | |
147 | fprintf(text->out, "Error"); | |
148 | return; | |
149 | } | |
150 | ||
3af83b5a MD |
151 | if (text->last_real_timestamp != -1ULL) { |
152 | text->delta_real_timestamp = ts_nsec - text->last_real_timestamp; | |
153 | } | |
154 | text->last_real_timestamp = ts_nsec; | |
155 | ||
1556a1af JG |
156 | ts_sec += ts_nsec / NSEC_PER_SEC; |
157 | ts_nsec = ts_nsec % NSEC_PER_SEC; | |
158 | if (ts_sec >= 0 && ts_nsec >= 0) { | |
159 | is_negative = false; | |
160 | ts_sec_abs = ts_sec; | |
161 | ts_nsec_abs = ts_nsec; | |
162 | } else if (ts_sec > 0 && ts_nsec < 0) { | |
163 | is_negative = false; | |
164 | ts_sec_abs = ts_sec - 1; | |
165 | ts_nsec_abs = NSEC_PER_SEC + ts_nsec; | |
166 | } else if (ts_sec == 0 && ts_nsec < 0) { | |
167 | is_negative = true; | |
168 | ts_sec_abs = ts_sec; | |
169 | ts_nsec_abs = -ts_nsec; | |
170 | } else if (ts_sec < 0 && ts_nsec > 0) { | |
171 | is_negative = true; | |
172 | ts_sec_abs = -(ts_sec + 1); | |
173 | ts_nsec_abs = NSEC_PER_SEC - ts_nsec; | |
174 | } else if (ts_sec < 0 && ts_nsec == 0) { | |
175 | is_negative = true; | |
176 | ts_sec_abs = -ts_sec; | |
177 | ts_nsec_abs = ts_nsec; | |
178 | } else { /* (ts_sec < 0 && ts_nsec < 0) */ | |
179 | is_negative = true; | |
180 | ts_sec_abs = -ts_sec; | |
181 | ts_nsec_abs = -ts_nsec; | |
182 | } | |
183 | ||
f504043c | 184 | if (!text->options.clock_seconds) { |
1556a1af JG |
185 | struct tm tm; |
186 | time_t time_s = (time_t) ts_sec_abs; | |
187 | ||
188 | if (is_negative) { | |
189 | fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n"); | |
190 | goto seconds; | |
191 | } | |
192 | ||
f504043c | 193 | if (!text->options.clock_gmt) { |
1556a1af JG |
194 | struct tm *res; |
195 | ||
196 | res = localtime_r(&time_s, &tm); | |
197 | if (!res) { | |
198 | fprintf(stderr, "[warning] Unable to get localtime.\n"); | |
199 | goto seconds; | |
200 | } | |
201 | } else { | |
202 | struct tm *res; | |
203 | ||
204 | res = gmtime_r(&time_s, &tm); | |
205 | if (!res) { | |
206 | fprintf(stderr, "[warning] Unable to get gmtime.\n"); | |
207 | goto seconds; | |
208 | } | |
209 | } | |
f504043c | 210 | if (text->options.clock_date) { |
1556a1af JG |
211 | char timestr[26]; |
212 | size_t res; | |
213 | ||
214 | /* Print date and time */ | |
215 | res = strftime(timestr, sizeof(timestr), | |
216 | "%F ", &tm); | |
217 | if (!res) { | |
218 | fprintf(stderr, "[warning] Unable to print ascii time.\n"); | |
219 | goto seconds; | |
220 | } | |
221 | fprintf(text->out, "%s", timestr); | |
222 | } | |
223 | /* Print time in HH:MM:SS.ns */ | |
224 | fprintf(text->out, "%02d:%02d:%02d.%09" PRIu64, | |
225 | tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs); | |
226 | goto end; | |
227 | } | |
228 | seconds: | |
229 | fprintf(text->out, "%s%" PRId64 ".%09" PRIu64, | |
230 | is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs); | |
231 | end: | |
232 | return; | |
af9a82eb JG |
233 | } |
234 | ||
235 | static | |
236 | enum bt_component_status print_event_timestamp(struct text_component *text, | |
c3c30b08 | 237 | struct bt_ctf_event *event, bool *start_line) |
af9a82eb JG |
238 | { |
239 | bool print_names = text->options.print_header_field_names; | |
240 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
6a18b281 | 241 | struct bt_ctf_stream *stream = NULL; |
1556a1af JG |
242 | struct bt_ctf_stream_class *stream_class = NULL; |
243 | struct bt_ctf_trace *trace = NULL; | |
ac0c6bdd | 244 | struct bt_ctf_clock_class *clock_class = NULL; |
af9a82eb | 245 | FILE *out = text->out; |
af9a82eb JG |
246 | |
247 | stream = bt_ctf_event_get_stream(event); | |
248 | if (!stream) { | |
249 | ret = BT_COMPONENT_STATUS_ERROR; | |
250 | goto end; | |
251 | } | |
252 | ||
1556a1af | 253 | stream_class = bt_ctf_stream_get_class(stream); |
f504043c MD |
254 | if (!stream_class) { |
255 | ret = BT_COMPONENT_STATUS_ERROR; | |
256 | goto end; | |
257 | } | |
1556a1af | 258 | trace = bt_ctf_stream_class_get_trace(stream_class); |
f504043c MD |
259 | if (!trace) { |
260 | ret = BT_COMPONENT_STATUS_ERROR; | |
261 | goto end; | |
262 | } | |
ac0c6bdd PP |
263 | clock_class = bt_ctf_trace_get_clock_class(trace, 0); |
264 | if (!clock_class) { | |
f504043c MD |
265 | ret = BT_COMPONENT_STATUS_ERROR; |
266 | goto end; | |
267 | } | |
af9a82eb | 268 | |
ad96d936 PP |
269 | if (print_names) { |
270 | print_name_equal(text, "timestamp"); | |
271 | } else { | |
272 | fputs("[", out); | |
273 | } | |
274 | if (text->use_colors) { | |
275 | fputs(COLOR_TIMESTAMP, text->out); | |
276 | } | |
af9a82eb | 277 | if (text->options.print_timestamp_cycles) { |
ac0c6bdd | 278 | print_timestamp_cycles(text, clock_class, event); |
af9a82eb | 279 | } else { |
ac0c6bdd | 280 | print_timestamp_wall(text, clock_class, event); |
af9a82eb | 281 | } |
ad96d936 PP |
282 | if (text->use_colors) { |
283 | fputs(COLOR_RST, text->out); | |
284 | } | |
af9a82eb | 285 | |
c3c30b08 MD |
286 | if (!print_names) |
287 | fputs("] ", out); | |
c3c30b08 | 288 | |
3af83b5a | 289 | if (text->options.print_delta_field) { |
ad96d936 PP |
290 | if (print_names) { |
291 | fputs(", ", text->out); | |
292 | print_name_equal(text, "delta"); | |
293 | } else { | |
3af83b5a | 294 | fputs("(", text->out); |
ad96d936 | 295 | } |
3af83b5a MD |
296 | if (text->options.print_timestamp_cycles) { |
297 | if (text->delta_cycles == -1ULL) { | |
298 | fputs("+??????????\?\?) ", text->out); /* Not a trigraph. */ | |
299 | } else { | |
300 | fprintf(text->out, "+%012" PRIu64, text->delta_cycles); | |
301 | } | |
302 | } else { | |
303 | if (text->delta_real_timestamp != -1ULL) { | |
304 | uint64_t delta_sec, delta_nsec, delta; | |
f504043c | 305 | |
3af83b5a MD |
306 | delta = text->delta_real_timestamp; |
307 | delta_sec = delta / NSEC_PER_SEC; | |
308 | delta_nsec = delta % NSEC_PER_SEC; | |
309 | fprintf(text->out, "+%" PRIu64 ".%09" PRIu64, | |
310 | delta_sec, delta_nsec); | |
311 | } else { | |
312 | fputs("+?.?????????", text->out); | |
313 | } | |
314 | } | |
315 | if (!print_names) { | |
316 | fputs(") ", text->out); | |
317 | } | |
318 | } | |
319 | *start_line = !print_names; | |
f504043c | 320 | |
af9a82eb JG |
321 | end: |
322 | bt_put(stream); | |
ac0c6bdd | 323 | bt_put(clock_class); |
1556a1af JG |
324 | bt_put(stream_class); |
325 | bt_put(trace); | |
af9a82eb JG |
326 | return ret; |
327 | } | |
328 | ||
6a18b281 | 329 | static |
af9a82eb JG |
330 | enum bt_component_status print_event_header(struct text_component *text, |
331 | struct bt_ctf_event *event) | |
332 | { | |
6a18b281 MD |
333 | bool print_names = text->options.print_header_field_names; |
334 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
335 | struct bt_ctf_event_class *event_class = NULL; | |
c3c30b08 MD |
336 | struct bt_ctf_stream_class *stream_class = NULL; |
337 | struct bt_ctf_trace *trace_class = NULL; | |
60535549 | 338 | int dom_print = 0; |
af9a82eb | 339 | |
6a18b281 MD |
340 | event_class = bt_ctf_event_get_class(event); |
341 | if (!event_class) { | |
342 | ret = BT_COMPONENT_STATUS_ERROR; | |
343 | goto end; | |
344 | } | |
c3c30b08 MD |
345 | stream_class = bt_ctf_event_class_get_stream_class(event_class); |
346 | if (!stream_class) { | |
347 | ret = BT_COMPONENT_STATUS_ERROR; | |
348 | goto end; | |
349 | } | |
350 | trace_class = bt_ctf_stream_class_get_trace(stream_class); | |
351 | if (!trace_class) { | |
352 | ret = BT_COMPONENT_STATUS_ERROR; | |
353 | goto end; | |
354 | } | |
c3c30b08 | 355 | ret = print_event_timestamp(text, event, &text->start_line); |
af9a82eb JG |
356 | if (ret != BT_COMPONENT_STATUS_OK) { |
357 | goto end; | |
358 | } | |
c3c30b08 MD |
359 | if (text->options.print_trace_field) { |
360 | const char *name; | |
361 | ||
362 | name = bt_ctf_trace_get_name(trace_class); | |
363 | if (name) { | |
364 | if (!text->start_line) { | |
365 | fputs(", ", text->out); | |
366 | } | |
c3c30b08 | 367 | if (print_names) { |
ad96d936 | 368 | print_name_equal(text, "trace"); |
c3c30b08 MD |
369 | } |
370 | fprintf(text->out, "%s", name); | |
60535549 JD |
371 | if (!print_names) { |
372 | fprintf(text->out, " "); | |
373 | } | |
c3c30b08 MD |
374 | } |
375 | } | |
376 | if (text->options.print_trace_hostname_field) { | |
377 | struct bt_value *hostname_str; | |
378 | ||
379 | hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, | |
380 | "hostname"); | |
381 | if (hostname_str) { | |
382 | const char *str; | |
383 | ||
384 | if (!text->start_line) { | |
385 | fputs(", ", text->out); | |
386 | } | |
c3c30b08 | 387 | if (print_names) { |
ad96d936 | 388 | print_name_equal(text, "trace:hostname"); |
c3c30b08 MD |
389 | } |
390 | if (bt_value_string_get(hostname_str, &str) | |
391 | == BT_VALUE_STATUS_OK) { | |
392 | fprintf(text->out, "%s", str); | |
393 | } | |
394 | bt_put(hostname_str); | |
60535549 | 395 | dom_print = 1; |
c3c30b08 MD |
396 | } |
397 | } | |
398 | if (text->options.print_trace_domain_field) { | |
399 | struct bt_value *domain_str; | |
400 | ||
401 | domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, | |
402 | "domain"); | |
403 | if (domain_str) { | |
404 | const char *str; | |
405 | ||
406 | if (!text->start_line) { | |
407 | fputs(", ", text->out); | |
408 | } | |
c3c30b08 | 409 | if (print_names) { |
ad96d936 | 410 | print_name_equal(text, "trace:domain"); |
60535549 JD |
411 | } else if (dom_print) { |
412 | fputs(":", text->out); | |
c3c30b08 MD |
413 | } |
414 | if (bt_value_string_get(domain_str, &str) | |
415 | == BT_VALUE_STATUS_OK) { | |
416 | fprintf(text->out, "%s", str); | |
417 | } | |
418 | bt_put(domain_str); | |
60535549 | 419 | dom_print = 1; |
c3c30b08 MD |
420 | } |
421 | } | |
422 | if (text->options.print_trace_procname_field) { | |
423 | struct bt_value *procname_str; | |
424 | ||
425 | procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class, | |
426 | "procname"); | |
427 | if (procname_str) { | |
428 | const char *str; | |
429 | ||
430 | if (!text->start_line) { | |
431 | fputs(", ", text->out); | |
432 | } | |
c3c30b08 | 433 | if (print_names) { |
ad96d936 | 434 | print_name_equal(text, "trace:procname"); |
60535549 JD |
435 | } else if (dom_print) { |
436 | fputs(":", text->out); | |
c3c30b08 MD |
437 | } |
438 | if (bt_value_string_get(procname_str, &str) | |
439 | == BT_VALUE_STATUS_OK) { | |
440 | fprintf(text->out, "%s", str); | |
441 | } | |
442 | bt_put(procname_str); | |
60535549 | 443 | dom_print = 1; |
c3c30b08 MD |
444 | } |
445 | } | |
446 | if (text->options.print_trace_vpid_field) { | |
447 | struct bt_value *vpid_value; | |
448 | ||
449 | vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class, | |
450 | "vpid"); | |
451 | if (vpid_value) { | |
452 | int64_t value; | |
453 | ||
454 | if (!text->start_line) { | |
455 | fputs(", ", text->out); | |
456 | } | |
c3c30b08 | 457 | if (print_names) { |
ad96d936 | 458 | print_name_equal(text, "trace:vpid"); |
60535549 JD |
459 | } else if (dom_print) { |
460 | fputs(":", text->out); | |
c3c30b08 MD |
461 | } |
462 | if (bt_value_integer_get(vpid_value, &value) | |
463 | == BT_VALUE_STATUS_OK) { | |
464 | fprintf(text->out, "(%" PRId64 ")", value); | |
465 | } | |
466 | bt_put(vpid_value); | |
60535549 | 467 | dom_print = 1; |
c3c30b08 MD |
468 | } |
469 | } | |
470 | if (text->options.print_loglevel_field) { | |
471 | struct bt_value *loglevel_str, *loglevel_value; | |
472 | ||
473 | loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class, | |
474 | "loglevel_string"); | |
475 | loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class, | |
476 | "loglevel"); | |
477 | if (loglevel_str || loglevel_value) { | |
478 | bool has_str = false; | |
479 | ||
480 | if (!text->start_line) { | |
481 | fputs(", ", text->out); | |
482 | } | |
c3c30b08 | 483 | if (print_names) { |
ad96d936 | 484 | print_name_equal(text, "loglevel"); |
60535549 JD |
485 | } else if (dom_print) { |
486 | fputs(":", text->out); | |
c3c30b08 MD |
487 | } |
488 | if (loglevel_str) { | |
489 | const char *str; | |
490 | ||
491 | if (bt_value_string_get(loglevel_str, &str) | |
492 | == BT_VALUE_STATUS_OK) { | |
493 | fprintf(text->out, "%s", str); | |
494 | has_str = true; | |
495 | } | |
496 | } | |
497 | if (loglevel_value) { | |
498 | int64_t value; | |
499 | ||
500 | if (bt_value_integer_get(loglevel_value, &value) | |
501 | == BT_VALUE_STATUS_OK) { | |
502 | fprintf(text->out, "%s(%" PRId64 ")", | |
503 | has_str ? " " : "", value); | |
504 | } | |
505 | } | |
506 | bt_put(loglevel_str); | |
507 | bt_put(loglevel_value); | |
60535549 | 508 | dom_print = 1; |
c3c30b08 MD |
509 | } |
510 | } | |
511 | if (text->options.print_emf_field) { | |
512 | struct bt_value *uri_str; | |
513 | ||
514 | uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class, | |
515 | "model.emf.uri"); | |
516 | if (uri_str) { | |
517 | if (!text->start_line) { | |
518 | fputs(", ", text->out); | |
519 | } | |
c3c30b08 | 520 | if (print_names) { |
ad96d936 | 521 | print_name_equal(text, "model.emf.uri"); |
60535549 JD |
522 | } else if (dom_print) { |
523 | fputs(":", text->out); | |
c3c30b08 MD |
524 | } |
525 | if (uri_str) { | |
526 | const char *str; | |
527 | ||
528 | if (bt_value_string_get(uri_str, &str) | |
529 | == BT_VALUE_STATUS_OK) { | |
530 | fprintf(text->out, "%s", str); | |
531 | } | |
532 | } | |
533 | bt_put(uri_str); | |
60535549 | 534 | dom_print = 1; |
c3c30b08 MD |
535 | } |
536 | } | |
60535549 JD |
537 | if (dom_print && !print_names) { |
538 | fputs(" ", text->out); | |
539 | } | |
c3c30b08 MD |
540 | if (!text->start_line) { |
541 | fputs(", ", text->out); | |
542 | } | |
60535549 | 543 | text->start_line = true; |
6a18b281 | 544 | if (print_names) { |
ad96d936 PP |
545 | print_name_equal(text, "name"); |
546 | } | |
547 | if (text->use_colors) { | |
548 | fputs(COLOR_EVENT_NAME, text->out); | |
6a18b281 | 549 | } |
af9a82eb | 550 | fputs(bt_ctf_event_class_get_name(event_class), text->out); |
ad96d936 PP |
551 | if (text->use_colors) { |
552 | fputs(COLOR_RST, text->out); | |
553 | } | |
60535549 JD |
554 | if (!print_names) { |
555 | fputs(": ", text->out); | |
556 | } else { | |
557 | fputs(", ", text->out); | |
558 | } | |
af9a82eb | 559 | end: |
c3c30b08 MD |
560 | bt_put(trace_class); |
561 | bt_put(stream_class); | |
6a18b281 MD |
562 | bt_put(event_class); |
563 | return ret; | |
564 | } | |
565 | ||
566 | static | |
567 | enum bt_component_status print_integer(struct text_component *text, | |
568 | struct bt_ctf_field *field) | |
569 | { | |
570 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
571 | struct bt_ctf_field_type *field_type = NULL; | |
572 | enum bt_ctf_integer_base base; | |
573 | enum bt_ctf_string_encoding encoding; | |
574 | int signedness; | |
575 | union { | |
576 | uint64_t u; | |
577 | int64_t s; | |
578 | } v; | |
ad96d936 | 579 | bool rst_color = false; |
6a18b281 MD |
580 | |
581 | field_type = bt_ctf_field_get_type(field); | |
582 | if (!field_type) { | |
583 | ret = BT_COMPONENT_STATUS_ERROR; | |
584 | goto end; | |
585 | } | |
586 | signedness = bt_ctf_field_type_integer_get_signed(field_type); | |
587 | if (signedness < 0) { | |
588 | ret = BT_COMPONENT_STATUS_ERROR; | |
589 | goto end; | |
590 | } | |
591 | if (!signedness) { | |
592 | if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) { | |
593 | ret = BT_COMPONENT_STATUS_ERROR; | |
594 | goto end; | |
595 | } | |
596 | } else { | |
597 | if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) { | |
598 | ret = BT_COMPONENT_STATUS_ERROR; | |
599 | goto end; | |
600 | } | |
601 | } | |
602 | ||
603 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
604 | switch (encoding) { | |
605 | case BT_CTF_STRING_ENCODING_UTF8: | |
606 | case BT_CTF_STRING_ENCODING_ASCII: | |
607 | g_string_append_c(text->string, (int) v.u); | |
608 | goto end; | |
609 | case BT_CTF_STRING_ENCODING_NONE: | |
610 | case BT_CTF_STRING_ENCODING_UNKNOWN: | |
611 | break; | |
612 | default: | |
613 | ret = BT_COMPONENT_STATUS_ERROR; | |
614 | goto end; | |
615 | } | |
616 | ||
ad96d936 PP |
617 | if (text->use_colors) { |
618 | fputs(COLOR_NUMBER_VALUE, text->out); | |
619 | rst_color = true; | |
620 | } | |
621 | ||
6a18b281 MD |
622 | base = bt_ctf_field_type_integer_get_base(field_type); |
623 | switch (base) { | |
624 | case BT_CTF_INTEGER_BASE_BINARY: | |
625 | { | |
626 | int bitnr, len; | |
627 | ||
628 | len = bt_ctf_field_type_integer_get_size(field_type); | |
629 | if (len < 0) { | |
630 | ret = BT_COMPONENT_STATUS_ERROR; | |
631 | goto end; | |
632 | } | |
633 | fprintf(text->out, "0b"); | |
634 | v.u = _bt_piecewise_lshift(v.u, 64 - len); | |
635 | for (bitnr = 0; bitnr < len; bitnr++) { | |
636 | fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0); | |
637 | v.u = _bt_piecewise_lshift(v.u, 1); | |
638 | } | |
639 | break; | |
640 | } | |
641 | case BT_CTF_INTEGER_BASE_OCTAL: | |
642 | { | |
643 | if (signedness) { | |
644 | int len; | |
645 | ||
646 | len = bt_ctf_field_type_integer_get_size(field_type); | |
647 | if (len < 0) { | |
648 | ret = BT_COMPONENT_STATUS_ERROR; | |
649 | goto end; | |
650 | } | |
651 | if (len < 64) { | |
652 | size_t rounded_len; | |
653 | ||
654 | assert(len != 0); | |
655 | /* Round length to the nearest 3-bit */ | |
656 | rounded_len = (((len - 1) / 3) + 1) * 3; | |
657 | v.u &= ((uint64_t) 1 << rounded_len) - 1; | |
658 | } | |
659 | } | |
660 | ||
661 | fprintf(text->out, "0%" PRIo64, v.u); | |
662 | break; | |
663 | } | |
664 | case BT_CTF_INTEGER_BASE_DECIMAL: | |
665 | if (!signedness) { | |
666 | fprintf(text->out, "%" PRIu64, v.u); | |
667 | } else { | |
668 | fprintf(text->out, "%" PRId64, v.s); | |
669 | } | |
670 | break; | |
671 | case BT_CTF_INTEGER_BASE_HEXADECIMAL: | |
672 | { | |
673 | int len; | |
674 | ||
675 | len = bt_ctf_field_type_integer_get_size(field_type); | |
676 | if (len < 0) { | |
677 | ret = BT_COMPONENT_STATUS_ERROR; | |
678 | goto end; | |
679 | } | |
680 | if (len < 64) { | |
681 | /* Round length to the nearest nibble */ | |
682 | uint8_t rounded_len = ((len + 3) & ~0x3); | |
683 | ||
684 | v.u &= ((uint64_t) 1 << rounded_len) - 1; | |
685 | } | |
686 | ||
687 | fprintf(text->out, "0x%" PRIX64, v.u); | |
688 | break; | |
689 | } | |
690 | default: | |
691 | ret = BT_COMPONENT_STATUS_ERROR; | |
692 | goto end; | |
693 | } | |
694 | end: | |
ad96d936 PP |
695 | if (rst_color) { |
696 | fputs(COLOR_RST, text->out); | |
697 | } | |
6a18b281 MD |
698 | bt_put(field_type); |
699 | return ret; | |
700 | } | |
701 | ||
93a4161c JD |
702 | static |
703 | void print_escape_string(struct text_component *text, const char *str) | |
704 | { | |
705 | int i; | |
706 | ||
707 | fputc('"', text->out); | |
708 | for (i = 0; i < strlen(str); i++) { | |
709 | /* Escape sequences not recognized by iscntrl(). */ | |
710 | switch (str[i]) { | |
711 | case '\\': | |
712 | fputs("\\\\", text->out); | |
713 | continue; | |
714 | case '\'': | |
715 | fputs("\\\'", text->out); | |
716 | continue; | |
717 | case '\"': | |
718 | fputs("\\\"", text->out); | |
719 | continue; | |
720 | case '\?': | |
721 | fputs("\\\?", text->out); | |
722 | continue; | |
723 | } | |
724 | ||
725 | /* Standard characters. */ | |
726 | if (!iscntrl(str[i])) { | |
727 | fputc(str[i], text->out); | |
728 | continue; | |
729 | } | |
730 | ||
731 | switch (str[i]) { | |
732 | case '\0': | |
733 | fputs("\\0", text->out); | |
734 | break; | |
735 | case '\a': | |
736 | fputs("\\a", text->out); | |
737 | break; | |
738 | case '\b': | |
739 | fputs("\\b", text->out); | |
740 | break; | |
741 | case '\e': | |
742 | fputs("\\e", text->out); | |
743 | break; | |
744 | case '\f': | |
745 | fputs("\\f", text->out); | |
746 | break; | |
747 | case '\n': | |
748 | fputs("\\n", text->out); | |
749 | break; | |
750 | case '\r': | |
751 | fputs("\\r", text->out); | |
752 | break; | |
753 | case '\t': | |
754 | fputs("\\t", text->out); | |
755 | break; | |
756 | case '\v': | |
757 | fputs("\\v", text->out); | |
758 | break; | |
759 | default: | |
760 | /* Unhandled control-sequence, print as hex. */ | |
761 | fprintf(text->out, "\\x%02x", str[i]); | |
762 | break; | |
763 | } | |
764 | } | |
765 | fputc('"', text->out); | |
766 | } | |
767 | ||
6a18b281 MD |
768 | static |
769 | enum bt_component_status print_enum(struct text_component *text, | |
770 | struct bt_ctf_field *field) | |
771 | { | |
772 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
773 | struct bt_ctf_field *container_field = NULL; | |
96e8f959 MD |
774 | struct bt_ctf_field_type *enumeration_field_type = NULL; |
775 | struct bt_ctf_field_type *container_field_type = NULL; | |
776 | struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; | |
777 | int nr_mappings = 0; | |
778 | int is_signed; | |
779 | ||
780 | enumeration_field_type = bt_ctf_field_get_type(field); | |
781 | if (!enumeration_field_type) { | |
782 | ret = BT_COMPONENT_STATUS_ERROR; | |
783 | goto end; | |
784 | } | |
6a18b281 MD |
785 | container_field = bt_ctf_field_enumeration_get_container(field); |
786 | if (!container_field) { | |
787 | ret = BT_COMPONENT_STATUS_ERROR; | |
788 | goto end; | |
789 | } | |
96e8f959 MD |
790 | container_field_type = bt_ctf_field_get_type(container_field); |
791 | if (!container_field_type) { | |
792 | ret = BT_COMPONENT_STATUS_ERROR; | |
793 | goto end; | |
794 | } | |
795 | is_signed = bt_ctf_field_type_integer_get_signed(container_field_type); | |
796 | if (is_signed < 0) { | |
797 | ret = BT_COMPONENT_STATUS_ERROR; | |
798 | goto end; | |
799 | } | |
800 | if (is_signed) { | |
801 | int64_t value; | |
802 | ||
803 | if (bt_ctf_field_signed_integer_get_value(container_field, | |
804 | &value)) { | |
805 | ret = BT_COMPONENT_STATUS_ERROR; | |
806 | goto end; | |
807 | } | |
808 | iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value( | |
809 | enumeration_field_type, value); | |
6a18b281 | 810 | } else { |
96e8f959 MD |
811 | uint64_t value; |
812 | ||
813 | if (bt_ctf_field_unsigned_integer_get_value(container_field, | |
814 | &value)) { | |
815 | ret = BT_COMPONENT_STATUS_ERROR; | |
816 | goto end; | |
817 | } | |
818 | iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( | |
819 | enumeration_field_type, value); | |
820 | } | |
821 | if (!iter) { | |
822 | ret = BT_COMPONENT_STATUS_ERROR; | |
823 | goto end; | |
824 | } | |
825 | fprintf(text->out, "( "); | |
826 | for (;;) { | |
827 | const char *mapping_name; | |
828 | ||
829 | if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed( | |
830 | iter, &mapping_name, NULL, NULL) < 0) { | |
831 | ret = BT_COMPONENT_STATUS_ERROR; | |
832 | goto end; | |
833 | } | |
834 | if (nr_mappings++) | |
835 | fprintf(text->out, ", "); | |
ad96d936 PP |
836 | if (text->use_colors) { |
837 | fputs(COLOR_ENUM_MAPPING_NAME, text->out); | |
838 | } | |
93a4161c | 839 | print_escape_string(text, mapping_name); |
ad96d936 PP |
840 | if (text->use_colors) { |
841 | fputs(COLOR_RST, text->out); | |
842 | } | |
96e8f959 MD |
843 | if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) { |
844 | break; | |
845 | } | |
846 | } | |
847 | if (!nr_mappings) { | |
ad96d936 PP |
848 | if (text->use_colors) { |
849 | fputs(COLOR_UNKNOWN, text->out); | |
850 | } | |
96e8f959 | 851 | fprintf(text->out, "<unknown>"); |
ad96d936 PP |
852 | if (text->use_colors) { |
853 | fputs(COLOR_RST, text->out); | |
854 | } | |
6a18b281 MD |
855 | } |
856 | fprintf(text->out, " : container = "); | |
857 | ret = print_integer(text, container_field); | |
858 | if (ret != BT_COMPONENT_STATUS_OK) { | |
859 | goto end; | |
860 | } | |
861 | fprintf(text->out, " )"); | |
862 | end: | |
96e8f959 MD |
863 | bt_put(iter); |
864 | bt_put(container_field_type); | |
6a18b281 | 865 | bt_put(container_field); |
96e8f959 | 866 | bt_put(enumeration_field_type); |
6a18b281 MD |
867 | return ret; |
868 | } | |
869 | ||
2b4c4a7c JD |
870 | static |
871 | int filter_field_name(struct text_component *text, const char *field_name, | |
872 | GQuark *filter_fields, int filter_array_len) | |
873 | { | |
874 | int i; | |
875 | GQuark field_quark = g_quark_try_string(field_name); | |
876 | ||
877 | if (!field_quark || text->options.verbose) { | |
878 | return 1; | |
879 | } | |
880 | ||
881 | for (i = 0; i < filter_array_len; i++) { | |
882 | if (field_quark == filter_fields[i]) { | |
883 | return 0; | |
884 | } | |
885 | } | |
886 | return 1; | |
887 | } | |
888 | ||
6a18b281 MD |
889 | static |
890 | enum bt_component_status print_struct_field(struct text_component *text, | |
891 | struct bt_ctf_field *_struct, | |
892 | struct bt_ctf_field_type *struct_type, | |
2b4c4a7c JD |
893 | int i, bool print_names, int *nr_printed_fields, |
894 | GQuark *filter_fields, int filter_array_len) | |
6a18b281 MD |
895 | { |
896 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
897 | const char *field_name; | |
898 | struct bt_ctf_field *field = NULL; | |
899 | struct bt_ctf_field_type *field_type = NULL;; | |
900 | ||
901 | field = bt_ctf_field_structure_get_field_by_index(_struct, i); | |
902 | if (!field) { | |
903 | ret = BT_COMPONENT_STATUS_ERROR; | |
904 | goto end; | |
905 | } | |
906 | if (bt_ctf_field_type_structure_get_field(struct_type, | |
907 | &field_name, &field_type, i) < 0) { | |
908 | ret = BT_COMPONENT_STATUS_ERROR; | |
909 | goto end; | |
910 | } | |
911 | ||
2b4c4a7c JD |
912 | if (filter_fields && !filter_field_name(text, field_name, |
913 | filter_fields, filter_array_len)) { | |
914 | ret = BT_COMPONENT_STATUS_OK; | |
915 | goto end; | |
916 | } | |
917 | ||
918 | if (*nr_printed_fields > 0) { | |
6a18b281 MD |
919 | fprintf(text->out, ", "); |
920 | } else { | |
921 | fprintf(text->out, " "); | |
922 | } | |
923 | if (print_names) { | |
ad96d936 | 924 | print_field_name_equal(text, rem_(field_name)); |
6a18b281 | 925 | } |
2b4c4a7c JD |
926 | ret = print_field(text, field, print_names, NULL, 0); |
927 | *nr_printed_fields += 1; | |
6a18b281 MD |
928 | end: |
929 | bt_put(field_type); | |
930 | bt_put(field); | |
931 | return ret; | |
932 | } | |
933 | ||
934 | static | |
935 | enum bt_component_status print_struct(struct text_component *text, | |
2b4c4a7c JD |
936 | struct bt_ctf_field *_struct, bool print_names, |
937 | GQuark *filter_fields, int filter_array_len) | |
6a18b281 MD |
938 | { |
939 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
940 | struct bt_ctf_field_type *struct_type = NULL; | |
2b4c4a7c | 941 | int nr_fields, i, nr_printed_fields; |
6a18b281 MD |
942 | |
943 | struct_type = bt_ctf_field_get_type(_struct); | |
944 | if (!struct_type) { | |
945 | ret = BT_COMPONENT_STATUS_ERROR; | |
946 | goto end; | |
947 | } | |
948 | nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type); | |
949 | if (nr_fields < 0) { | |
950 | ret = BT_COMPONENT_STATUS_ERROR; | |
951 | goto end; | |
952 | } | |
953 | fprintf(text->out, "{"); | |
954 | text->depth++; | |
2b4c4a7c | 955 | nr_printed_fields = 0; |
6a18b281 MD |
956 | for (i = 0; i < nr_fields; i++) { |
957 | ret = print_struct_field(text, _struct, struct_type, i, | |
2b4c4a7c JD |
958 | print_names, &nr_printed_fields, filter_fields, |
959 | filter_array_len); | |
6a18b281 MD |
960 | if (ret != BT_COMPONENT_STATUS_OK) { |
961 | goto end; | |
962 | } | |
963 | } | |
964 | text->depth--; | |
965 | fprintf(text->out, " }"); | |
966 | end: | |
967 | bt_put(struct_type); | |
968 | return ret; | |
969 | } | |
970 | ||
971 | static | |
972 | enum bt_component_status print_array_field(struct text_component *text, | |
973 | struct bt_ctf_field *array, uint64_t i, | |
974 | bool is_string, bool print_names) | |
975 | { | |
976 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
977 | struct bt_ctf_field *field = NULL; | |
978 | ||
979 | if (!is_string) { | |
980 | if (i != 0) { | |
981 | fprintf(text->out, ", "); | |
982 | } else { | |
983 | fprintf(text->out, " "); | |
984 | } | |
60535549 JD |
985 | if (print_names) { |
986 | fprintf(text->out, "[%" PRIu64 "] = ", i); | |
987 | } | |
6a18b281 MD |
988 | } |
989 | field = bt_ctf_field_array_get_field(array, i); | |
990 | if (!field) { | |
991 | ret = BT_COMPONENT_STATUS_ERROR; | |
992 | goto end; | |
993 | } | |
2b4c4a7c | 994 | ret = print_field(text, field, print_names, NULL, 0); |
6a18b281 MD |
995 | end: |
996 | bt_put(field); | |
997 | return ret; | |
998 | } | |
999 | ||
1000 | static | |
1001 | enum bt_component_status print_array(struct text_component *text, | |
1002 | struct bt_ctf_field *array, bool print_names) | |
1003 | { | |
1004 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1005 | struct bt_ctf_field_type *array_type = NULL, *field_type = NULL; | |
1487a16a | 1006 | enum bt_ctf_field_type_id type_id; |
6a18b281 MD |
1007 | int64_t len; |
1008 | uint64_t i; | |
1009 | bool is_string = false; | |
1010 | ||
1011 | array_type = bt_ctf_field_get_type(array); | |
1012 | if (!array_type) { | |
1013 | ret = BT_COMPONENT_STATUS_ERROR; | |
1014 | goto end; | |
1015 | } | |
1016 | field_type = bt_ctf_field_type_array_get_element_type(array_type); | |
1017 | if (!field_type) { | |
1018 | ret = BT_COMPONENT_STATUS_ERROR; | |
1019 | goto end; | |
1020 | } | |
1021 | len = bt_ctf_field_type_array_get_length(array_type); | |
1022 | if (len < 0) { | |
1023 | ret = BT_COMPONENT_STATUS_ERROR; | |
1024 | goto end; | |
1025 | } | |
1026 | type_id = bt_ctf_field_type_get_type_id(field_type); | |
1487a16a | 1027 | if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) { |
6a18b281 MD |
1028 | enum bt_ctf_string_encoding encoding; |
1029 | ||
1030 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
1031 | if (encoding == BT_CTF_STRING_ENCODING_UTF8 | |
1032 | || encoding == BT_CTF_STRING_ENCODING_ASCII) { | |
1033 | int integer_len, integer_alignment; | |
1034 | ||
1035 | integer_len = bt_ctf_field_type_integer_get_size(field_type); | |
1036 | if (integer_len < 0) { | |
1037 | return BT_COMPONENT_STATUS_ERROR; | |
1038 | } | |
1039 | integer_alignment = bt_ctf_field_type_get_alignment(field_type); | |
1040 | if (integer_alignment < 0) { | |
1041 | return BT_COMPONENT_STATUS_ERROR; | |
1042 | } | |
1043 | if (integer_len == CHAR_BIT | |
1044 | && integer_alignment == CHAR_BIT) { | |
1045 | is_string = true; | |
1046 | } | |
1047 | } | |
1048 | } | |
1049 | ||
1050 | if (is_string) { | |
1051 | g_string_assign(text->string, ""); | |
1052 | } else { | |
1053 | fprintf(text->out, "["); | |
1054 | } | |
1055 | ||
1056 | text->depth++; | |
1057 | for (i = 0; i < len; i++) { | |
1058 | ret = print_array_field(text, array, i, is_string, print_names); | |
1059 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1060 | goto end; | |
1061 | } | |
1062 | } | |
1063 | text->depth--; | |
1064 | ||
1065 | if (is_string) { | |
ad96d936 PP |
1066 | if (text->use_colors) { |
1067 | fputs(COLOR_STRING_VALUE, text->out); | |
1068 | } | |
93a4161c | 1069 | print_escape_string(text, text->string->str); |
ad96d936 PP |
1070 | if (text->use_colors) { |
1071 | fputs(COLOR_RST, text->out); | |
1072 | } | |
6a18b281 MD |
1073 | } else { |
1074 | fprintf(text->out, " ]"); | |
1075 | } | |
1076 | end: | |
1077 | bt_put(field_type); | |
1078 | bt_put(array_type); | |
1079 | return ret; | |
1080 | } | |
1081 | ||
1082 | static | |
1083 | enum bt_component_status print_sequence_field(struct text_component *text, | |
1084 | struct bt_ctf_field *seq, uint64_t i, | |
1085 | bool is_string, bool print_names) | |
1086 | { | |
1087 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1088 | struct bt_ctf_field *field = NULL; | |
1089 | ||
1090 | if (!is_string) { | |
1091 | if (i != 0) { | |
1092 | fprintf(text->out, ", "); | |
1093 | } else { | |
1094 | fprintf(text->out, " "); | |
1095 | } | |
60535549 JD |
1096 | if (print_names) { |
1097 | fprintf(text->out, "[%" PRIu64 "] = ", i); | |
1098 | } | |
6a18b281 MD |
1099 | } |
1100 | field = bt_ctf_field_sequence_get_field(seq, i); | |
1101 | if (!field) { | |
1102 | ret = BT_COMPONENT_STATUS_ERROR; | |
1103 | goto end; | |
1104 | } | |
2b4c4a7c | 1105 | ret = print_field(text, field, print_names, NULL, 0); |
6a18b281 MD |
1106 | end: |
1107 | bt_put(field); | |
1108 | return ret; | |
1109 | } | |
1110 | ||
1111 | static | |
1112 | enum bt_component_status print_sequence(struct text_component *text, | |
1113 | struct bt_ctf_field *seq, bool print_names) | |
1114 | { | |
1115 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1116 | struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL; | |
1117 | struct bt_ctf_field *length_field = NULL; | |
1487a16a | 1118 | enum bt_ctf_field_type_id type_id; |
6a18b281 MD |
1119 | uint64_t len; |
1120 | uint64_t i; | |
1121 | bool is_string = false; | |
1122 | ||
1123 | seq_type = bt_ctf_field_get_type(seq); | |
1124 | if (!seq_type) { | |
1125 | ret = BT_COMPONENT_STATUS_ERROR; | |
1126 | goto end; | |
1127 | } | |
1128 | length_field = bt_ctf_field_sequence_get_length(seq); | |
1129 | if (!length_field) { | |
1130 | ret = BT_COMPONENT_STATUS_ERROR; | |
1131 | goto end; | |
1132 | } | |
1133 | if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) { | |
1134 | ret = BT_COMPONENT_STATUS_ERROR; | |
1135 | goto end; | |
1136 | } | |
1137 | field_type = bt_ctf_field_type_sequence_get_element_type(seq_type); | |
1138 | if (!field_type) { | |
1139 | ret = BT_COMPONENT_STATUS_ERROR; | |
1140 | goto end; | |
1141 | } | |
1142 | type_id = bt_ctf_field_type_get_type_id(field_type); | |
1487a16a | 1143 | if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) { |
6a18b281 MD |
1144 | enum bt_ctf_string_encoding encoding; |
1145 | ||
1146 | encoding = bt_ctf_field_type_integer_get_encoding(field_type); | |
1147 | if (encoding == BT_CTF_STRING_ENCODING_UTF8 | |
1148 | || encoding == BT_CTF_STRING_ENCODING_ASCII) { | |
1149 | int integer_len, integer_alignment; | |
1150 | ||
1151 | integer_len = bt_ctf_field_type_integer_get_size(field_type); | |
1152 | if (integer_len < 0) { | |
1153 | ret = BT_COMPONENT_STATUS_ERROR; | |
1154 | goto end; | |
1155 | } | |
1156 | integer_alignment = bt_ctf_field_type_get_alignment(field_type); | |
1157 | if (integer_alignment < 0) { | |
1158 | ret = BT_COMPONENT_STATUS_ERROR; | |
1159 | goto end; | |
1160 | } | |
1161 | if (integer_len == CHAR_BIT | |
1162 | && integer_alignment == CHAR_BIT) { | |
1163 | is_string = true; | |
1164 | } | |
1165 | } | |
1166 | } | |
1167 | ||
1168 | if (is_string) { | |
1169 | g_string_assign(text->string, ""); | |
1170 | } else { | |
1171 | fprintf(text->out, "["); | |
1172 | } | |
1173 | ||
1174 | text->depth++; | |
1175 | for (i = 0; i < len; i++) { | |
1176 | ret = print_sequence_field(text, seq, i, | |
1177 | is_string, print_names); | |
1178 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1179 | goto end; | |
1180 | } | |
1181 | } | |
1182 | text->depth--; | |
1183 | ||
1184 | if (is_string) { | |
ad96d936 PP |
1185 | if (text->use_colors) { |
1186 | fputs(COLOR_STRING_VALUE, text->out); | |
1187 | } | |
93a4161c | 1188 | print_escape_string(text, text->string->str); |
ad96d936 PP |
1189 | if (text->use_colors) { |
1190 | fputs(COLOR_RST, text->out); | |
1191 | } | |
6a18b281 MD |
1192 | } else { |
1193 | fprintf(text->out, " ]"); | |
1194 | } | |
1195 | end: | |
1196 | bt_put(length_field); | |
1197 | bt_put(field_type); | |
1198 | bt_put(seq_type); | |
1199 | return ret; | |
1200 | } | |
1201 | ||
1202 | static | |
1203 | enum bt_component_status print_variant(struct text_component *text, | |
1204 | struct bt_ctf_field *variant, bool print_names) | |
1205 | { | |
1206 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1207 | struct bt_ctf_field *field = NULL; | |
1208 | ||
1209 | field = bt_ctf_field_variant_get_current_field(variant); | |
1210 | if (!field) { | |
1211 | ret = BT_COMPONENT_STATUS_ERROR; | |
1212 | goto end; | |
1213 | } | |
1214 | fprintf(text->out, "{ "); | |
1215 | text->depth++; | |
1216 | if (print_names) { | |
e0f15669 | 1217 | int iter_ret; |
6a18b281 MD |
1218 | struct bt_ctf_field *tag_field = NULL; |
1219 | const char *tag_choice; | |
e0f15669 | 1220 | struct bt_ctf_field_type_enumeration_mapping_iterator *iter; |
6a18b281 MD |
1221 | |
1222 | tag_field = bt_ctf_field_variant_get_tag(variant); | |
1223 | if (!tag_field) { | |
1224 | ret = BT_COMPONENT_STATUS_ERROR; | |
1225 | goto end; | |
1226 | } | |
e0f15669 JG |
1227 | |
1228 | iter = bt_ctf_field_enumeration_get_mappings(tag_field); | |
1229 | if (!iter) { | |
1230 | bt_put(tag_field); | |
1231 | ret = BT_COMPONENT_STATUS_ERROR; | |
1232 | goto end; | |
1233 | } | |
1234 | ||
1235 | iter_ret = | |
8803be2a JG |
1236 | bt_ctf_field_type_enumeration_mapping_iterator_get_signed( |
1237 | iter, &tag_choice, NULL, NULL); | |
e0f15669 JG |
1238 | if (iter_ret) { |
1239 | bt_put(iter); | |
6a18b281 MD |
1240 | bt_put(tag_field); |
1241 | ret = BT_COMPONENT_STATUS_ERROR; | |
1242 | goto end; | |
1243 | } | |
ad96d936 | 1244 | print_field_name_equal(text, rem_(tag_choice)); |
6a18b281 | 1245 | bt_put(tag_field); |
e0f15669 | 1246 | bt_put(iter); |
6a18b281 | 1247 | } |
2b4c4a7c | 1248 | ret = print_field(text, field, print_names, NULL, 0); |
6a18b281 MD |
1249 | if (ret != BT_COMPONENT_STATUS_OK) { |
1250 | goto end; | |
1251 | } | |
1252 | text->depth--; | |
1253 | fprintf(text->out, " }"); | |
1254 | end: | |
1255 | bt_put(field); | |
1256 | return ret; | |
1257 | } | |
1258 | ||
1259 | static | |
1260 | enum bt_component_status print_field(struct text_component *text, | |
2b4c4a7c JD |
1261 | struct bt_ctf_field *field, bool print_names, |
1262 | GQuark *filter_fields, int filter_array_len) | |
6a18b281 | 1263 | { |
1487a16a | 1264 | enum bt_ctf_field_type_id type_id; |
6a18b281 MD |
1265 | |
1266 | type_id = bt_ctf_field_get_type_id(field); | |
1267 | switch (type_id) { | |
1268 | case CTF_TYPE_INTEGER: | |
1269 | return print_integer(text, field); | |
1270 | case CTF_TYPE_FLOAT: | |
1271 | { | |
1272 | double v; | |
1273 | ||
1274 | if (bt_ctf_field_floating_point_get_value(field, &v)) { | |
1275 | return BT_COMPONENT_STATUS_ERROR; | |
1276 | } | |
ad96d936 PP |
1277 | if (text->use_colors) { |
1278 | fputs(COLOR_NUMBER_VALUE, text->out); | |
1279 | } | |
6a18b281 | 1280 | fprintf(text->out, "%g", v); |
ad96d936 PP |
1281 | if (text->use_colors) { |
1282 | fputs(COLOR_RST, text->out); | |
1283 | } | |
6a18b281 MD |
1284 | return BT_COMPONENT_STATUS_OK; |
1285 | } | |
1286 | case CTF_TYPE_ENUM: | |
1287 | return print_enum(text, field); | |
1288 | case CTF_TYPE_STRING: | |
ad96d936 PP |
1289 | if (text->use_colors) { |
1290 | fputs(COLOR_STRING_VALUE, text->out); | |
1291 | } | |
93a4161c | 1292 | print_escape_string(text, bt_ctf_field_string_get_value(field)); |
ad96d936 PP |
1293 | if (text->use_colors) { |
1294 | fputs(COLOR_RST, text->out); | |
1295 | } | |
6a18b281 MD |
1296 | return BT_COMPONENT_STATUS_OK; |
1297 | case CTF_TYPE_STRUCT: | |
2b4c4a7c JD |
1298 | return print_struct(text, field, print_names, filter_fields, |
1299 | filter_array_len); | |
6a18b281 MD |
1300 | case CTF_TYPE_UNTAGGED_VARIANT: |
1301 | case CTF_TYPE_VARIANT: | |
1302 | return print_variant(text, field, print_names); | |
1303 | case CTF_TYPE_ARRAY: | |
1304 | return print_array(text, field, print_names); | |
1305 | case CTF_TYPE_SEQUENCE: | |
1306 | return print_sequence(text, field, print_names); | |
1307 | default: | |
1308 | fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id); | |
1309 | return BT_COMPONENT_STATUS_ERROR; | |
1310 | } | |
1311 | } | |
1312 | ||
1313 | static | |
1314 | enum bt_component_status print_stream_packet_context(struct text_component *text, | |
1315 | struct bt_ctf_event *event) | |
1316 | { | |
1317 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1318 | struct bt_ctf_packet *packet = NULL; | |
1319 | struct bt_ctf_field *main_field = NULL; | |
1320 | ||
1321 | packet = bt_ctf_event_get_packet(event); | |
1322 | if (!packet) { | |
1323 | ret = BT_COMPONENT_STATUS_ERROR; | |
1324 | goto end; | |
1325 | } | |
1326 | main_field = bt_ctf_packet_get_context(packet); | |
1327 | if (!main_field) { | |
6a18b281 MD |
1328 | goto end; |
1329 | } | |
6e1bc0df MD |
1330 | if (!text->start_line) { |
1331 | fputs(", ", text->out); | |
1332 | } | |
1333 | text->start_line = false; | |
6a18b281 | 1334 | if (text->options.print_scope_field_names) { |
ad96d936 | 1335 | print_name_equal(text, "stream.packet.context"); |
6a18b281 MD |
1336 | } |
1337 | ret = print_field(text, main_field, | |
2b4c4a7c JD |
1338 | text->options.print_context_field_names, |
1339 | stream_packet_context_quarks, | |
1340 | STREAM_PACKET_CONTEXT_QUARKS_LEN); | |
6a18b281 MD |
1341 | end: |
1342 | bt_put(main_field); | |
1343 | bt_put(packet); | |
1344 | return ret; | |
1345 | } | |
1346 | ||
1347 | static | |
1348 | enum bt_component_status print_event_header_raw(struct text_component *text, | |
1349 | struct bt_ctf_event *event) | |
1350 | { | |
1351 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1352 | struct bt_ctf_field *main_field = NULL; | |
1353 | ||
1354 | main_field = bt_ctf_event_get_header(event); | |
1355 | if (!main_field) { | |
6a18b281 MD |
1356 | goto end; |
1357 | } | |
6e1bc0df MD |
1358 | if (!text->start_line) { |
1359 | fputs(", ", text->out); | |
1360 | } | |
1361 | text->start_line = false; | |
6a18b281 | 1362 | if (text->options.print_scope_field_names) { |
ad96d936 | 1363 | print_name_equal(text, "stream.event.header"); |
6a18b281 MD |
1364 | } |
1365 | ret = print_field(text, main_field, | |
2b4c4a7c | 1366 | text->options.print_header_field_names, NULL, 0); |
6a18b281 MD |
1367 | end: |
1368 | bt_put(main_field); | |
1369 | return ret; | |
1370 | } | |
1371 | ||
1372 | static | |
1373 | enum bt_component_status print_stream_event_context(struct text_component *text, | |
1374 | struct bt_ctf_event *event) | |
1375 | { | |
1376 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1377 | struct bt_ctf_field *main_field = NULL; | |
1378 | ||
1379 | main_field = bt_ctf_event_get_stream_event_context(event); | |
1380 | if (!main_field) { | |
6a18b281 MD |
1381 | goto end; |
1382 | } | |
6e1bc0df MD |
1383 | if (!text->start_line) { |
1384 | fputs(", ", text->out); | |
1385 | } | |
1386 | text->start_line = false; | |
6a18b281 | 1387 | if (text->options.print_scope_field_names) { |
ad96d936 | 1388 | print_name_equal(text, "stream.event.context"); |
6a18b281 MD |
1389 | } |
1390 | ret = print_field(text, main_field, | |
2b4c4a7c | 1391 | text->options.print_context_field_names, NULL, 0); |
6a18b281 MD |
1392 | end: |
1393 | bt_put(main_field); | |
1394 | return ret; | |
1395 | } | |
1396 | ||
1397 | static | |
1398 | enum bt_component_status print_event_context(struct text_component *text, | |
1399 | struct bt_ctf_event *event) | |
1400 | { | |
1401 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1402 | struct bt_ctf_field *main_field = NULL; | |
1403 | ||
1404 | main_field = bt_ctf_event_get_event_context(event); | |
1405 | if (!main_field) { | |
6a18b281 MD |
1406 | goto end; |
1407 | } | |
6e1bc0df MD |
1408 | if (!text->start_line) { |
1409 | fputs(", ", text->out); | |
1410 | } | |
1411 | text->start_line = false; | |
6a18b281 | 1412 | if (text->options.print_scope_field_names) { |
ad96d936 | 1413 | print_name_equal(text, "event.context"); |
6a18b281 MD |
1414 | } |
1415 | ret = print_field(text, main_field, | |
2b4c4a7c | 1416 | text->options.print_context_field_names, NULL, 0); |
6a18b281 MD |
1417 | end: |
1418 | bt_put(main_field); | |
1419 | return ret; | |
1420 | } | |
1421 | ||
1422 | static | |
1423 | enum bt_component_status print_event_payload(struct text_component *text, | |
1424 | struct bt_ctf_event *event) | |
1425 | { | |
1426 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
1427 | struct bt_ctf_field *main_field = NULL; | |
1428 | ||
1429 | main_field = bt_ctf_event_get_payload_field(event); | |
1430 | if (!main_field) { | |
6a18b281 MD |
1431 | goto end; |
1432 | } | |
6e1bc0df MD |
1433 | if (!text->start_line) { |
1434 | fputs(", ", text->out); | |
1435 | } | |
1436 | text->start_line = false; | |
6a18b281 | 1437 | if (text->options.print_scope_field_names) { |
ad96d936 | 1438 | print_name_equal(text, "event.fields"); |
6a18b281 MD |
1439 | } |
1440 | ret = print_field(text, main_field, | |
2b4c4a7c | 1441 | text->options.print_payload_field_names, NULL, 0); |
6a18b281 MD |
1442 | end: |
1443 | bt_put(main_field); | |
af9a82eb JG |
1444 | return ret; |
1445 | } | |
1446 | ||
1447 | BT_HIDDEN | |
1448 | enum bt_component_status text_print_event(struct text_component *text, | |
1449 | struct bt_ctf_event *event) | |
1450 | { | |
1451 | enum bt_component_status ret; | |
1452 | ||
6e1bc0df | 1453 | text->start_line = true; |
af9a82eb JG |
1454 | ret = print_event_header(text, event); |
1455 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1456 | goto end; | |
1457 | } | |
6a18b281 MD |
1458 | |
1459 | ret = print_stream_packet_context(text, event); | |
1460 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1461 | goto end; | |
1462 | } | |
6a18b281 | 1463 | |
60535549 JD |
1464 | if (text->options.verbose) { |
1465 | ret = print_event_header_raw(text, event); | |
1466 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1467 | goto end; | |
1468 | } | |
6a18b281 | 1469 | } |
6a18b281 MD |
1470 | |
1471 | ret = print_stream_event_context(text, event); | |
1472 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1473 | goto end; | |
1474 | } | |
6a18b281 MD |
1475 | |
1476 | ret = print_event_context(text, event); | |
1477 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1478 | goto end; | |
1479 | } | |
6a18b281 MD |
1480 | |
1481 | ret = print_event_payload(text, event); | |
1482 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1483 | goto end; | |
1484 | } | |
af9a82eb JG |
1485 | |
1486 | fputc('\n', text->out); | |
1487 | end: | |
1488 | return ret; | |
1489 | } |