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> |
3228cc1d | 43 | #include "pretty.h" |
af9a82eb | 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 | 71 | static |
3228cc1d | 72 | enum bt_component_status print_field(struct pretty_component *pretty, |
2b4c4a7c JD |
73 | struct bt_ctf_field *field, bool print_names, |
74 | GQuark *filters_fields, int filter_array_len); | |
6a18b281 | 75 | |
ad96d936 | 76 | static |
3228cc1d | 77 | void print_name_equal(struct pretty_component *pretty, const char *name) |
ad96d936 | 78 | { |
3228cc1d PP |
79 | if (pretty->use_colors) { |
80 | fprintf(pretty->out, "%s%s%s = ", COLOR_NAME, name, COLOR_RST); | |
ad96d936 | 81 | } else { |
3228cc1d | 82 | fprintf(pretty->out, "%s = ", name); |
ad96d936 PP |
83 | } |
84 | } | |
85 | ||
86 | static | |
3228cc1d | 87 | void print_field_name_equal(struct pretty_component *pretty, const char *name) |
ad96d936 | 88 | { |
3228cc1d PP |
89 | if (pretty->use_colors) { |
90 | fprintf(pretty->out, "%s%s%s = ", COLOR_FIELD_NAME, name, | |
ad96d936 PP |
91 | COLOR_RST); |
92 | } else { | |
3228cc1d | 93 | fprintf(pretty->out, "%s = ", name); |
ad96d936 PP |
94 | } |
95 | } | |
96 | ||
af9a82eb | 97 | static |
3228cc1d | 98 | void print_timestamp_cycles(struct pretty_component *pretty, |
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 | 107 | if (!clock_value) { |
3228cc1d | 108 | fputs("????????????????????", pretty->out); |
1556a1af JG |
109 | return; |
110 | } | |
111 | ||
112 | ret = bt_ctf_clock_value_get_value(clock_value, &cycles); | |
113 | bt_put(clock_value); | |
114 | if (ret) { | |
3228cc1d | 115 | fprintf(pretty->out, "Error"); |
1556a1af JG |
116 | return; |
117 | } | |
3228cc1d | 118 | fprintf(pretty->out, "%020" PRIu64, cycles); |
3af83b5a | 119 | |
3228cc1d PP |
120 | if (pretty->last_cycles_timestamp != -1ULL) { |
121 | pretty->delta_cycles = cycles - pretty->last_cycles_timestamp; | |
3af83b5a | 122 | } |
3228cc1d | 123 | pretty->last_cycles_timestamp = cycles; |
af9a82eb JG |
124 | } |
125 | ||
126 | static | |
3228cc1d | 127 | void print_timestamp_wall(struct pretty_component *pretty, |
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 | 139 | if (!clock_value) { |
3228cc1d | 140 | fputs("??:??:??.?????????", pretty->out); |
1556a1af JG |
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) { | |
3228cc1d | 147 | fprintf(pretty->out, "Error"); |
1556a1af JG |
148 | return; |
149 | } | |
150 | ||
3228cc1d PP |
151 | if (pretty->last_real_timestamp != -1ULL) { |
152 | pretty->delta_real_timestamp = ts_nsec - pretty->last_real_timestamp; | |
3af83b5a | 153 | } |
3228cc1d | 154 | pretty->last_real_timestamp = ts_nsec; |
3af83b5a | 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 | ||
3228cc1d | 184 | if (!pretty->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 | ||
3228cc1d | 193 | if (!pretty->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 | } | |
3228cc1d | 210 | if (pretty->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 | } | |
3228cc1d | 221 | fprintf(pretty->out, "%s", timestr); |
1556a1af JG |
222 | } |
223 | /* Print time in HH:MM:SS.ns */ | |
3228cc1d | 224 | fprintf(pretty->out, "%02d:%02d:%02d.%09" PRIu64, |
1556a1af JG |
225 | tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs); |
226 | goto end; | |
227 | } | |
228 | seconds: | |
3228cc1d | 229 | fprintf(pretty->out, "%s%" PRId64 ".%09" PRIu64, |
1556a1af JG |
230 | is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs); |
231 | end: | |
232 | return; | |
af9a82eb JG |
233 | } |
234 | ||
235 | static | |
3228cc1d | 236 | enum bt_component_status print_event_timestamp(struct pretty_component *pretty, |
c3c30b08 | 237 | struct bt_ctf_event *event, bool *start_line) |
af9a82eb | 238 | { |
3228cc1d | 239 | bool print_names = pretty->options.print_header_field_names; |
af9a82eb | 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; |
3228cc1d | 245 | FILE *out = pretty->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 | 269 | if (print_names) { |
3228cc1d | 270 | print_name_equal(pretty, "timestamp"); |
ad96d936 PP |
271 | } else { |
272 | fputs("[", out); | |
273 | } | |
3228cc1d PP |
274 | if (pretty->use_colors) { |
275 | fputs(COLOR_TIMESTAMP, pretty->out); | |
ad96d936 | 276 | } |
3228cc1d PP |
277 | if (pretty->options.print_timestamp_cycles) { |
278 | print_timestamp_cycles(pretty, clock_class, event); | |
af9a82eb | 279 | } else { |
3228cc1d | 280 | print_timestamp_wall(pretty, clock_class, event); |
af9a82eb | 281 | } |
3228cc1d PP |
282 | if (pretty->use_colors) { |
283 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 284 | } |
af9a82eb | 285 | |
c3c30b08 MD |
286 | if (!print_names) |
287 | fputs("] ", out); | |
c3c30b08 | 288 | |
3228cc1d | 289 | if (pretty->options.print_delta_field) { |
ad96d936 | 290 | if (print_names) { |
3228cc1d PP |
291 | fputs(", ", pretty->out); |
292 | print_name_equal(pretty, "delta"); | |
ad96d936 | 293 | } else { |
3228cc1d | 294 | fputs("(", pretty->out); |
ad96d936 | 295 | } |
3228cc1d PP |
296 | if (pretty->options.print_timestamp_cycles) { |
297 | if (pretty->delta_cycles == -1ULL) { | |
298 | fputs("+??????????\?\?) ", pretty->out); /* Not a trigraph. */ | |
3af83b5a | 299 | } else { |
3228cc1d | 300 | fprintf(pretty->out, "+%012" PRIu64, pretty->delta_cycles); |
3af83b5a MD |
301 | } |
302 | } else { | |
3228cc1d | 303 | if (pretty->delta_real_timestamp != -1ULL) { |
3af83b5a | 304 | uint64_t delta_sec, delta_nsec, delta; |
f504043c | 305 | |
3228cc1d | 306 | delta = pretty->delta_real_timestamp; |
3af83b5a MD |
307 | delta_sec = delta / NSEC_PER_SEC; |
308 | delta_nsec = delta % NSEC_PER_SEC; | |
3228cc1d | 309 | fprintf(pretty->out, "+%" PRIu64 ".%09" PRIu64, |
3af83b5a MD |
310 | delta_sec, delta_nsec); |
311 | } else { | |
3228cc1d | 312 | fputs("+?.?????????", pretty->out); |
3af83b5a MD |
313 | } |
314 | } | |
315 | if (!print_names) { | |
3228cc1d | 316 | fputs(") ", pretty->out); |
3af83b5a MD |
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 |
3228cc1d | 330 | enum bt_component_status print_event_header(struct pretty_component *pretty, |
af9a82eb JG |
331 | struct bt_ctf_event *event) |
332 | { | |
3228cc1d | 333 | bool print_names = pretty->options.print_header_field_names; |
6a18b281 MD |
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 | } | |
3228cc1d | 355 | ret = print_event_timestamp(pretty, event, &pretty->start_line); |
af9a82eb JG |
356 | if (ret != BT_COMPONENT_STATUS_OK) { |
357 | goto end; | |
358 | } | |
3228cc1d | 359 | if (pretty->options.print_trace_field) { |
c3c30b08 MD |
360 | const char *name; |
361 | ||
362 | name = bt_ctf_trace_get_name(trace_class); | |
363 | if (name) { | |
3228cc1d PP |
364 | if (!pretty->start_line) { |
365 | fputs(", ", pretty->out); | |
c3c30b08 | 366 | } |
c3c30b08 | 367 | if (print_names) { |
3228cc1d | 368 | print_name_equal(pretty, "trace"); |
c3c30b08 | 369 | } |
3228cc1d | 370 | fprintf(pretty->out, "%s", name); |
60535549 | 371 | if (!print_names) { |
3228cc1d | 372 | fprintf(pretty->out, " "); |
60535549 | 373 | } |
c3c30b08 MD |
374 | } |
375 | } | |
3228cc1d | 376 | if (pretty->options.print_trace_hostname_field) { |
c3c30b08 MD |
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 | ||
3228cc1d PP |
384 | if (!pretty->start_line) { |
385 | fputs(", ", pretty->out); | |
c3c30b08 | 386 | } |
c3c30b08 | 387 | if (print_names) { |
3228cc1d | 388 | print_name_equal(pretty, "trace:hostname"); |
c3c30b08 MD |
389 | } |
390 | if (bt_value_string_get(hostname_str, &str) | |
391 | == BT_VALUE_STATUS_OK) { | |
3228cc1d | 392 | fprintf(pretty->out, "%s", str); |
c3c30b08 MD |
393 | } |
394 | bt_put(hostname_str); | |
60535549 | 395 | dom_print = 1; |
c3c30b08 MD |
396 | } |
397 | } | |
3228cc1d | 398 | if (pretty->options.print_trace_domain_field) { |
c3c30b08 MD |
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 | ||
3228cc1d PP |
406 | if (!pretty->start_line) { |
407 | fputs(", ", pretty->out); | |
c3c30b08 | 408 | } |
c3c30b08 | 409 | if (print_names) { |
3228cc1d | 410 | print_name_equal(pretty, "trace:domain"); |
60535549 | 411 | } else if (dom_print) { |
3228cc1d | 412 | fputs(":", pretty->out); |
c3c30b08 MD |
413 | } |
414 | if (bt_value_string_get(domain_str, &str) | |
415 | == BT_VALUE_STATUS_OK) { | |
3228cc1d | 416 | fprintf(pretty->out, "%s", str); |
c3c30b08 MD |
417 | } |
418 | bt_put(domain_str); | |
60535549 | 419 | dom_print = 1; |
c3c30b08 MD |
420 | } |
421 | } | |
3228cc1d | 422 | if (pretty->options.print_trace_procname_field) { |
c3c30b08 MD |
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 | ||
3228cc1d PP |
430 | if (!pretty->start_line) { |
431 | fputs(", ", pretty->out); | |
c3c30b08 | 432 | } |
c3c30b08 | 433 | if (print_names) { |
3228cc1d | 434 | print_name_equal(pretty, "trace:procname"); |
60535549 | 435 | } else if (dom_print) { |
3228cc1d | 436 | fputs(":", pretty->out); |
c3c30b08 MD |
437 | } |
438 | if (bt_value_string_get(procname_str, &str) | |
439 | == BT_VALUE_STATUS_OK) { | |
3228cc1d | 440 | fprintf(pretty->out, "%s", str); |
c3c30b08 MD |
441 | } |
442 | bt_put(procname_str); | |
60535549 | 443 | dom_print = 1; |
c3c30b08 MD |
444 | } |
445 | } | |
3228cc1d | 446 | if (pretty->options.print_trace_vpid_field) { |
c3c30b08 MD |
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 | ||
3228cc1d PP |
454 | if (!pretty->start_line) { |
455 | fputs(", ", pretty->out); | |
c3c30b08 | 456 | } |
c3c30b08 | 457 | if (print_names) { |
3228cc1d | 458 | print_name_equal(pretty, "trace:vpid"); |
60535549 | 459 | } else if (dom_print) { |
3228cc1d | 460 | fputs(":", pretty->out); |
c3c30b08 MD |
461 | } |
462 | if (bt_value_integer_get(vpid_value, &value) | |
463 | == BT_VALUE_STATUS_OK) { | |
3228cc1d | 464 | fprintf(pretty->out, "(%" PRId64 ")", value); |
c3c30b08 MD |
465 | } |
466 | bt_put(vpid_value); | |
60535549 | 467 | dom_print = 1; |
c3c30b08 MD |
468 | } |
469 | } | |
3228cc1d | 470 | if (pretty->options.print_loglevel_field) { |
c3c30b08 MD |
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 | ||
3228cc1d PP |
480 | if (!pretty->start_line) { |
481 | fputs(", ", pretty->out); | |
c3c30b08 | 482 | } |
c3c30b08 | 483 | if (print_names) { |
3228cc1d | 484 | print_name_equal(pretty, "loglevel"); |
60535549 | 485 | } else if (dom_print) { |
3228cc1d | 486 | fputs(":", pretty->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) { | |
3228cc1d | 493 | fprintf(pretty->out, "%s", str); |
c3c30b08 MD |
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) { | |
3228cc1d | 502 | fprintf(pretty->out, "%s(%" PRId64 ")", |
c3c30b08 MD |
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 | } | |
3228cc1d | 511 | if (pretty->options.print_emf_field) { |
c3c30b08 MD |
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) { | |
3228cc1d PP |
517 | if (!pretty->start_line) { |
518 | fputs(", ", pretty->out); | |
c3c30b08 | 519 | } |
c3c30b08 | 520 | if (print_names) { |
3228cc1d | 521 | print_name_equal(pretty, "model.emf.uri"); |
60535549 | 522 | } else if (dom_print) { |
3228cc1d | 523 | fputs(":", pretty->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) { | |
3228cc1d | 530 | fprintf(pretty->out, "%s", str); |
c3c30b08 MD |
531 | } |
532 | } | |
533 | bt_put(uri_str); | |
60535549 | 534 | dom_print = 1; |
c3c30b08 MD |
535 | } |
536 | } | |
60535549 | 537 | if (dom_print && !print_names) { |
3228cc1d | 538 | fputs(" ", pretty->out); |
60535549 | 539 | } |
3228cc1d PP |
540 | if (!pretty->start_line) { |
541 | fputs(", ", pretty->out); | |
c3c30b08 | 542 | } |
3228cc1d | 543 | pretty->start_line = true; |
6a18b281 | 544 | if (print_names) { |
3228cc1d | 545 | print_name_equal(pretty, "name"); |
ad96d936 | 546 | } |
3228cc1d PP |
547 | if (pretty->use_colors) { |
548 | fputs(COLOR_EVENT_NAME, pretty->out); | |
6a18b281 | 549 | } |
3228cc1d PP |
550 | fputs(bt_ctf_event_class_get_name(event_class), pretty->out); |
551 | if (pretty->use_colors) { | |
552 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 553 | } |
60535549 | 554 | if (!print_names) { |
3228cc1d | 555 | fputs(": ", pretty->out); |
60535549 | 556 | } else { |
3228cc1d | 557 | fputs(", ", pretty->out); |
60535549 | 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 | |
3228cc1d | 567 | enum bt_component_status print_integer(struct pretty_component *pretty, |
6a18b281 MD |
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: | |
3228cc1d | 607 | g_string_append_c(pretty->string, (int) v.u); |
6a18b281 MD |
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 | ||
3228cc1d PP |
617 | if (pretty->use_colors) { |
618 | fputs(COLOR_NUMBER_VALUE, pretty->out); | |
ad96d936 PP |
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 | } | |
3228cc1d | 633 | fprintf(pretty->out, "0b"); |
6a18b281 MD |
634 | v.u = _bt_piecewise_lshift(v.u, 64 - len); |
635 | for (bitnr = 0; bitnr < len; bitnr++) { | |
3228cc1d | 636 | fprintf(pretty->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0); |
6a18b281 MD |
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 | ||
3228cc1d | 661 | fprintf(pretty->out, "0%" PRIo64, v.u); |
6a18b281 MD |
662 | break; |
663 | } | |
664 | case BT_CTF_INTEGER_BASE_DECIMAL: | |
665 | if (!signedness) { | |
3228cc1d | 666 | fprintf(pretty->out, "%" PRIu64, v.u); |
6a18b281 | 667 | } else { |
3228cc1d | 668 | fprintf(pretty->out, "%" PRId64, v.s); |
6a18b281 MD |
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 | ||
3228cc1d | 687 | fprintf(pretty->out, "0x%" PRIX64, v.u); |
6a18b281 MD |
688 | break; |
689 | } | |
690 | default: | |
691 | ret = BT_COMPONENT_STATUS_ERROR; | |
692 | goto end; | |
693 | } | |
694 | end: | |
ad96d936 | 695 | if (rst_color) { |
3228cc1d | 696 | fputs(COLOR_RST, pretty->out); |
ad96d936 | 697 | } |
6a18b281 MD |
698 | bt_put(field_type); |
699 | return ret; | |
700 | } | |
701 | ||
93a4161c | 702 | static |
3228cc1d | 703 | void print_escape_string(struct pretty_component *pretty, const char *str) |
93a4161c JD |
704 | { |
705 | int i; | |
706 | ||
3228cc1d | 707 | fputc('"', pretty->out); |
93a4161c JD |
708 | for (i = 0; i < strlen(str); i++) { |
709 | /* Escape sequences not recognized by iscntrl(). */ | |
710 | switch (str[i]) { | |
711 | case '\\': | |
3228cc1d | 712 | fputs("\\\\", pretty->out); |
93a4161c JD |
713 | continue; |
714 | case '\'': | |
3228cc1d | 715 | fputs("\\\'", pretty->out); |
93a4161c JD |
716 | continue; |
717 | case '\"': | |
3228cc1d | 718 | fputs("\\\"", pretty->out); |
93a4161c JD |
719 | continue; |
720 | case '\?': | |
3228cc1d | 721 | fputs("\\\?", pretty->out); |
93a4161c JD |
722 | continue; |
723 | } | |
724 | ||
725 | /* Standard characters. */ | |
726 | if (!iscntrl(str[i])) { | |
3228cc1d | 727 | fputc(str[i], pretty->out); |
93a4161c JD |
728 | continue; |
729 | } | |
730 | ||
731 | switch (str[i]) { | |
732 | case '\0': | |
3228cc1d | 733 | fputs("\\0", pretty->out); |
93a4161c JD |
734 | break; |
735 | case '\a': | |
3228cc1d | 736 | fputs("\\a", pretty->out); |
93a4161c JD |
737 | break; |
738 | case '\b': | |
3228cc1d | 739 | fputs("\\b", pretty->out); |
93a4161c JD |
740 | break; |
741 | case '\e': | |
3228cc1d | 742 | fputs("\\e", pretty->out); |
93a4161c JD |
743 | break; |
744 | case '\f': | |
3228cc1d | 745 | fputs("\\f", pretty->out); |
93a4161c JD |
746 | break; |
747 | case '\n': | |
3228cc1d | 748 | fputs("\\n", pretty->out); |
93a4161c JD |
749 | break; |
750 | case '\r': | |
3228cc1d | 751 | fputs("\\r", pretty->out); |
93a4161c JD |
752 | break; |
753 | case '\t': | |
3228cc1d | 754 | fputs("\\t", pretty->out); |
93a4161c JD |
755 | break; |
756 | case '\v': | |
3228cc1d | 757 | fputs("\\v", pretty->out); |
93a4161c JD |
758 | break; |
759 | default: | |
760 | /* Unhandled control-sequence, print as hex. */ | |
3228cc1d | 761 | fprintf(pretty->out, "\\x%02x", str[i]); |
93a4161c JD |
762 | break; |
763 | } | |
764 | } | |
3228cc1d | 765 | fputc('"', pretty->out); |
93a4161c JD |
766 | } |
767 | ||
6a18b281 | 768 | static |
3228cc1d | 769 | enum bt_component_status print_enum(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d | 825 | fprintf(pretty->out, "( "); |
96e8f959 MD |
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++) | |
3228cc1d PP |
835 | fprintf(pretty->out, ", "); |
836 | if (pretty->use_colors) { | |
837 | fputs(COLOR_ENUM_MAPPING_NAME, pretty->out); | |
ad96d936 | 838 | } |
3228cc1d PP |
839 | print_escape_string(pretty, mapping_name); |
840 | if (pretty->use_colors) { | |
841 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 842 | } |
96e8f959 MD |
843 | if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) { |
844 | break; | |
845 | } | |
846 | } | |
847 | if (!nr_mappings) { | |
3228cc1d PP |
848 | if (pretty->use_colors) { |
849 | fputs(COLOR_UNKNOWN, pretty->out); | |
ad96d936 | 850 | } |
3228cc1d PP |
851 | fprintf(pretty->out, "<unknown>"); |
852 | if (pretty->use_colors) { | |
853 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 854 | } |
6a18b281 | 855 | } |
3228cc1d PP |
856 | fprintf(pretty->out, " : container = "); |
857 | ret = print_integer(pretty, container_field); | |
6a18b281 MD |
858 | if (ret != BT_COMPONENT_STATUS_OK) { |
859 | goto end; | |
860 | } | |
3228cc1d | 861 | fprintf(pretty->out, " )"); |
6a18b281 | 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 | 870 | static |
3228cc1d | 871 | int filter_field_name(struct pretty_component *pretty, const char *field_name, |
2b4c4a7c JD |
872 | GQuark *filter_fields, int filter_array_len) |
873 | { | |
874 | int i; | |
875 | GQuark field_quark = g_quark_try_string(field_name); | |
876 | ||
3228cc1d | 877 | if (!field_quark || pretty->options.verbose) { |
2b4c4a7c JD |
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 | 889 | static |
3228cc1d | 890 | enum bt_component_status print_struct_field(struct pretty_component *pretty, |
6a18b281 MD |
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 | ||
3228cc1d | 912 | if (filter_fields && !filter_field_name(pretty, field_name, |
2b4c4a7c JD |
913 | filter_fields, filter_array_len)) { |
914 | ret = BT_COMPONENT_STATUS_OK; | |
915 | goto end; | |
916 | } | |
917 | ||
918 | if (*nr_printed_fields > 0) { | |
3228cc1d | 919 | fprintf(pretty->out, ", "); |
6a18b281 | 920 | } else { |
3228cc1d | 921 | fprintf(pretty->out, " "); |
6a18b281 MD |
922 | } |
923 | if (print_names) { | |
3228cc1d | 924 | print_field_name_equal(pretty, rem_(field_name)); |
6a18b281 | 925 | } |
3228cc1d | 926 | ret = print_field(pretty, field, print_names, NULL, 0); |
2b4c4a7c | 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 | |
3228cc1d | 935 | enum bt_component_status print_struct(struct pretty_component *pretty, |
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 | } | |
3228cc1d PP |
953 | fprintf(pretty->out, "{"); |
954 | pretty->depth++; | |
2b4c4a7c | 955 | nr_printed_fields = 0; |
6a18b281 | 956 | for (i = 0; i < nr_fields; i++) { |
3228cc1d | 957 | ret = print_struct_field(pretty, _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 | } | |
3228cc1d PP |
964 | pretty->depth--; |
965 | fprintf(pretty->out, " }"); | |
6a18b281 MD |
966 | end: |
967 | bt_put(struct_type); | |
968 | return ret; | |
969 | } | |
970 | ||
971 | static | |
3228cc1d | 972 | enum bt_component_status print_array_field(struct pretty_component *pretty, |
6a18b281 MD |
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) { | |
3228cc1d | 981 | fprintf(pretty->out, ", "); |
6a18b281 | 982 | } else { |
3228cc1d | 983 | fprintf(pretty->out, " "); |
6a18b281 | 984 | } |
60535549 | 985 | if (print_names) { |
3228cc1d | 986 | fprintf(pretty->out, "[%" PRIu64 "] = ", i); |
60535549 | 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 | } | |
3228cc1d | 994 | ret = print_field(pretty, field, print_names, NULL, 0); |
6a18b281 MD |
995 | end: |
996 | bt_put(field); | |
997 | return ret; | |
998 | } | |
999 | ||
1000 | static | |
3228cc1d | 1001 | enum bt_component_status print_array(struct pretty_component *pretty, |
6a18b281 MD |
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) { | |
3228cc1d | 1051 | g_string_assign(pretty->string, ""); |
6a18b281 | 1052 | } else { |
3228cc1d | 1053 | fprintf(pretty->out, "["); |
6a18b281 MD |
1054 | } |
1055 | ||
3228cc1d | 1056 | pretty->depth++; |
6a18b281 | 1057 | for (i = 0; i < len; i++) { |
3228cc1d | 1058 | ret = print_array_field(pretty, array, i, is_string, print_names); |
6a18b281 MD |
1059 | if (ret != BT_COMPONENT_STATUS_OK) { |
1060 | goto end; | |
1061 | } | |
1062 | } | |
3228cc1d | 1063 | pretty->depth--; |
6a18b281 MD |
1064 | |
1065 | if (is_string) { | |
3228cc1d PP |
1066 | if (pretty->use_colors) { |
1067 | fputs(COLOR_STRING_VALUE, pretty->out); | |
ad96d936 | 1068 | } |
3228cc1d PP |
1069 | print_escape_string(pretty, pretty->string->str); |
1070 | if (pretty->use_colors) { | |
1071 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 1072 | } |
6a18b281 | 1073 | } else { |
3228cc1d | 1074 | fprintf(pretty->out, " ]"); |
6a18b281 MD |
1075 | } |
1076 | end: | |
1077 | bt_put(field_type); | |
1078 | bt_put(array_type); | |
1079 | return ret; | |
1080 | } | |
1081 | ||
1082 | static | |
3228cc1d | 1083 | enum bt_component_status print_sequence_field(struct pretty_component *pretty, |
6a18b281 MD |
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) { | |
3228cc1d | 1092 | fprintf(pretty->out, ", "); |
6a18b281 | 1093 | } else { |
3228cc1d | 1094 | fprintf(pretty->out, " "); |
6a18b281 | 1095 | } |
60535549 | 1096 | if (print_names) { |
3228cc1d | 1097 | fprintf(pretty->out, "[%" PRIu64 "] = ", i); |
60535549 | 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 | } | |
3228cc1d | 1105 | ret = print_field(pretty, field, print_names, NULL, 0); |
6a18b281 MD |
1106 | end: |
1107 | bt_put(field); | |
1108 | return ret; | |
1109 | } | |
1110 | ||
1111 | static | |
3228cc1d | 1112 | enum bt_component_status print_sequence(struct pretty_component *pretty, |
6a18b281 MD |
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) { | |
3228cc1d | 1169 | g_string_assign(pretty->string, ""); |
6a18b281 | 1170 | } else { |
3228cc1d | 1171 | fprintf(pretty->out, "["); |
6a18b281 MD |
1172 | } |
1173 | ||
3228cc1d | 1174 | pretty->depth++; |
6a18b281 | 1175 | for (i = 0; i < len; i++) { |
3228cc1d | 1176 | ret = print_sequence_field(pretty, seq, i, |
6a18b281 MD |
1177 | is_string, print_names); |
1178 | if (ret != BT_COMPONENT_STATUS_OK) { | |
1179 | goto end; | |
1180 | } | |
1181 | } | |
3228cc1d | 1182 | pretty->depth--; |
6a18b281 MD |
1183 | |
1184 | if (is_string) { | |
3228cc1d PP |
1185 | if (pretty->use_colors) { |
1186 | fputs(COLOR_STRING_VALUE, pretty->out); | |
ad96d936 | 1187 | } |
3228cc1d PP |
1188 | print_escape_string(pretty, pretty->string->str); |
1189 | if (pretty->use_colors) { | |
1190 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 1191 | } |
6a18b281 | 1192 | } else { |
3228cc1d | 1193 | fprintf(pretty->out, " ]"); |
6a18b281 MD |
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 | |
3228cc1d | 1203 | enum bt_component_status print_variant(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1214 | fprintf(pretty->out, "{ "); |
1215 | pretty->depth++; | |
6a18b281 | 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 | } | |
3228cc1d | 1244 | print_field_name_equal(pretty, rem_(tag_choice)); |
6a18b281 | 1245 | bt_put(tag_field); |
e0f15669 | 1246 | bt_put(iter); |
6a18b281 | 1247 | } |
3228cc1d | 1248 | ret = print_field(pretty, field, print_names, NULL, 0); |
6a18b281 MD |
1249 | if (ret != BT_COMPONENT_STATUS_OK) { |
1250 | goto end; | |
1251 | } | |
3228cc1d PP |
1252 | pretty->depth--; |
1253 | fprintf(pretty->out, " }"); | |
6a18b281 MD |
1254 | end: |
1255 | bt_put(field); | |
1256 | return ret; | |
1257 | } | |
1258 | ||
1259 | static | |
3228cc1d | 1260 | enum bt_component_status print_field(struct pretty_component *pretty, |
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: | |
3228cc1d | 1269 | return print_integer(pretty, field); |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1277 | if (pretty->use_colors) { |
1278 | fputs(COLOR_NUMBER_VALUE, pretty->out); | |
ad96d936 | 1279 | } |
3228cc1d PP |
1280 | fprintf(pretty->out, "%g", v); |
1281 | if (pretty->use_colors) { | |
1282 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 1283 | } |
6a18b281 MD |
1284 | return BT_COMPONENT_STATUS_OK; |
1285 | } | |
1286 | case CTF_TYPE_ENUM: | |
3228cc1d | 1287 | return print_enum(pretty, field); |
6a18b281 | 1288 | case CTF_TYPE_STRING: |
3228cc1d PP |
1289 | if (pretty->use_colors) { |
1290 | fputs(COLOR_STRING_VALUE, pretty->out); | |
ad96d936 | 1291 | } |
3228cc1d PP |
1292 | print_escape_string(pretty, bt_ctf_field_string_get_value(field)); |
1293 | if (pretty->use_colors) { | |
1294 | fputs(COLOR_RST, pretty->out); | |
ad96d936 | 1295 | } |
6a18b281 MD |
1296 | return BT_COMPONENT_STATUS_OK; |
1297 | case CTF_TYPE_STRUCT: | |
3228cc1d | 1298 | return print_struct(pretty, field, print_names, filter_fields, |
2b4c4a7c | 1299 | filter_array_len); |
6a18b281 MD |
1300 | case CTF_TYPE_UNTAGGED_VARIANT: |
1301 | case CTF_TYPE_VARIANT: | |
3228cc1d | 1302 | return print_variant(pretty, field, print_names); |
6a18b281 | 1303 | case CTF_TYPE_ARRAY: |
3228cc1d | 1304 | return print_array(pretty, field, print_names); |
6a18b281 | 1305 | case CTF_TYPE_SEQUENCE: |
3228cc1d | 1306 | return print_sequence(pretty, field, print_names); |
6a18b281 | 1307 | default: |
3228cc1d | 1308 | fprintf(pretty->err, "[error] Unknown type id: %d\n", (int) type_id); |
6a18b281 MD |
1309 | return BT_COMPONENT_STATUS_ERROR; |
1310 | } | |
1311 | } | |
1312 | ||
1313 | static | |
3228cc1d | 1314 | enum bt_component_status print_stream_packet_context(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1330 | if (!pretty->start_line) { |
1331 | fputs(", ", pretty->out); | |
6e1bc0df | 1332 | } |
3228cc1d PP |
1333 | pretty->start_line = false; |
1334 | if (pretty->options.print_scope_field_names) { | |
1335 | print_name_equal(pretty, "stream.packet.context"); | |
6a18b281 | 1336 | } |
3228cc1d PP |
1337 | ret = print_field(pretty, main_field, |
1338 | pretty->options.print_context_field_names, | |
2b4c4a7c JD |
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 | |
3228cc1d | 1348 | enum bt_component_status print_event_header_raw(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1358 | if (!pretty->start_line) { |
1359 | fputs(", ", pretty->out); | |
6e1bc0df | 1360 | } |
3228cc1d PP |
1361 | pretty->start_line = false; |
1362 | if (pretty->options.print_scope_field_names) { | |
1363 | print_name_equal(pretty, "stream.event.header"); | |
6a18b281 | 1364 | } |
3228cc1d PP |
1365 | ret = print_field(pretty, main_field, |
1366 | pretty->options.print_header_field_names, NULL, 0); | |
6a18b281 MD |
1367 | end: |
1368 | bt_put(main_field); | |
1369 | return ret; | |
1370 | } | |
1371 | ||
1372 | static | |
3228cc1d | 1373 | enum bt_component_status print_stream_event_context(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1383 | if (!pretty->start_line) { |
1384 | fputs(", ", pretty->out); | |
6e1bc0df | 1385 | } |
3228cc1d PP |
1386 | pretty->start_line = false; |
1387 | if (pretty->options.print_scope_field_names) { | |
1388 | print_name_equal(pretty, "stream.event.context"); | |
6a18b281 | 1389 | } |
3228cc1d PP |
1390 | ret = print_field(pretty, main_field, |
1391 | pretty->options.print_context_field_names, NULL, 0); | |
6a18b281 MD |
1392 | end: |
1393 | bt_put(main_field); | |
1394 | return ret; | |
1395 | } | |
1396 | ||
1397 | static | |
3228cc1d | 1398 | enum bt_component_status print_event_context(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1408 | if (!pretty->start_line) { |
1409 | fputs(", ", pretty->out); | |
6e1bc0df | 1410 | } |
3228cc1d PP |
1411 | pretty->start_line = false; |
1412 | if (pretty->options.print_scope_field_names) { | |
1413 | print_name_equal(pretty, "event.context"); | |
6a18b281 | 1414 | } |
3228cc1d PP |
1415 | ret = print_field(pretty, main_field, |
1416 | pretty->options.print_context_field_names, NULL, 0); | |
6a18b281 MD |
1417 | end: |
1418 | bt_put(main_field); | |
1419 | return ret; | |
1420 | } | |
1421 | ||
1422 | static | |
3228cc1d | 1423 | enum bt_component_status print_event_payload(struct pretty_component *pretty, |
6a18b281 MD |
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 | } | |
3228cc1d PP |
1433 | if (!pretty->start_line) { |
1434 | fputs(", ", pretty->out); | |
6e1bc0df | 1435 | } |
3228cc1d PP |
1436 | pretty->start_line = false; |
1437 | if (pretty->options.print_scope_field_names) { | |
1438 | print_name_equal(pretty, "event.fields"); | |
6a18b281 | 1439 | } |
3228cc1d PP |
1440 | ret = print_field(pretty, main_field, |
1441 | pretty->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 | |
3228cc1d | 1448 | enum bt_component_status pretty_print_event(struct pretty_component *pretty, |
af9a82eb JG |
1449 | struct bt_ctf_event *event) |
1450 | { | |
1451 | enum bt_component_status ret; | |
1452 | ||
3228cc1d PP |
1453 | pretty->start_line = true; |
1454 | ret = print_event_header(pretty, event); | |
af9a82eb JG |
1455 | if (ret != BT_COMPONENT_STATUS_OK) { |
1456 | goto end; | |
1457 | } | |
6a18b281 | 1458 | |
3228cc1d | 1459 | ret = print_stream_packet_context(pretty, event); |
6a18b281 MD |
1460 | if (ret != BT_COMPONENT_STATUS_OK) { |
1461 | goto end; | |
1462 | } | |
6a18b281 | 1463 | |
3228cc1d PP |
1464 | if (pretty->options.verbose) { |
1465 | ret = print_event_header_raw(pretty, event); | |
60535549 JD |
1466 | if (ret != BT_COMPONENT_STATUS_OK) { |
1467 | goto end; | |
1468 | } | |
6a18b281 | 1469 | } |
6a18b281 | 1470 | |
3228cc1d | 1471 | ret = print_stream_event_context(pretty, event); |
6a18b281 MD |
1472 | if (ret != BT_COMPONENT_STATUS_OK) { |
1473 | goto end; | |
1474 | } | |
6a18b281 | 1475 | |
3228cc1d | 1476 | ret = print_event_context(pretty, event); |
6a18b281 MD |
1477 | if (ret != BT_COMPONENT_STATUS_OK) { |
1478 | goto end; | |
1479 | } | |
6a18b281 | 1480 | |
3228cc1d | 1481 | ret = print_event_payload(pretty, event); |
6a18b281 MD |
1482 | if (ret != BT_COMPONENT_STATUS_OK) { |
1483 | goto end; | |
1484 | } | |
af9a82eb | 1485 | |
3228cc1d | 1486 | fputc('\n', pretty->out); |
af9a82eb JG |
1487 | end: |
1488 | return ret; | |
1489 | } |