Move print attributes higher in implementation
[libside.git] / src / tracer.c
1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6 #include <stdint.h>
7 #include <inttypes.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 #include <side/trace.h>
12
13 static
14 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
15 static
16 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
17 static
18 void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
19 static
20 void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *app_ctx);
21 static
22 void tracer_print_array_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item);
23 static
24 void tracer_print_vla_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item);
25 static
26 void tracer_print_dynamic(const struct side_arg_dynamic_vec *dynamic_item);
27
28 static
29 void print_attributes(const struct side_attr *attr, uint32_t nr_attr)
30 {
31 int i;
32
33 if (!nr_attr)
34 return;
35 printf(", attributes: [ ");
36 for (i = 0; i < nr_attr; i++) {
37 printf("%s", i ? ", " : "");
38 printf("{ key: \"%s\", value: \"%s\" }",
39 attr[i].key, attr[i].value);
40 }
41 printf(" ]");
42 }
43
44 static
45 void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item)
46 {
47 switch (item->type) {
48 case SIDE_TYPE_ARRAY_U8:
49 case SIDE_TYPE_ARRAY_U16:
50 case SIDE_TYPE_ARRAY_U32:
51 case SIDE_TYPE_ARRAY_U64:
52 case SIDE_TYPE_ARRAY_S8:
53 case SIDE_TYPE_ARRAY_S16:
54 case SIDE_TYPE_ARRAY_S32:
55 case SIDE_TYPE_ARRAY_S64:
56 if (type_desc->type != SIDE_TYPE_ARRAY) {
57 printf("ERROR: type mismatch between description and arguments\n");
58 abort();
59 }
60 break;
61 case SIDE_TYPE_VLA_U8:
62 case SIDE_TYPE_VLA_U16:
63 case SIDE_TYPE_VLA_U32:
64 case SIDE_TYPE_VLA_U64:
65 case SIDE_TYPE_VLA_S8:
66 case SIDE_TYPE_VLA_S16:
67 case SIDE_TYPE_VLA_S32:
68 case SIDE_TYPE_VLA_S64:
69 if (type_desc->type != SIDE_TYPE_VLA) {
70 printf("ERROR: type mismatch between description and arguments\n");
71 abort();
72 }
73 break;
74
75 default:
76 if (type_desc->type != item->type) {
77 printf("ERROR: type mismatch between description and arguments\n");
78 abort();
79 }
80 break;
81 }
82 switch (item->type) {
83 case SIDE_TYPE_BOOL:
84 printf("%s", item->u.side_bool ? "true" : "false");
85 break;
86 case SIDE_TYPE_U8:
87 printf("%" PRIu8, item->u.side_u8);
88 break;
89 case SIDE_TYPE_U16:
90 printf("%" PRIu16, item->u.side_u16);
91 break;
92 case SIDE_TYPE_U32:
93 printf("%" PRIu32, item->u.side_u32);
94 break;
95 case SIDE_TYPE_U64:
96 printf("%" PRIu64, item->u.side_u64);
97 break;
98 case SIDE_TYPE_S8:
99 printf("%" PRId8, item->u.side_s8);
100 break;
101 case SIDE_TYPE_S16:
102 printf("%" PRId16, item->u.side_s16);
103 break;
104 case SIDE_TYPE_S32:
105 printf("%" PRId32, item->u.side_s32);
106 break;
107 case SIDE_TYPE_S64:
108 printf("%" PRId64, item->u.side_s64);
109 break;
110 case SIDE_TYPE_STRING:
111 printf("\"%s\"", item->u.string);
112 break;
113 case SIDE_TYPE_STRUCT:
114 tracer_print_struct(type_desc, item->u.side_struct);
115 break;
116 case SIDE_TYPE_ARRAY:
117 tracer_print_array(type_desc, item->u.side_array);
118 break;
119 case SIDE_TYPE_VLA:
120 tracer_print_vla(type_desc, item->u.side_vla);
121 break;
122 case SIDE_TYPE_VLA_VISITOR:
123 tracer_print_vla_visitor(type_desc, item->u.side_vla_app_visitor_ctx);
124 break;
125 case SIDE_TYPE_ARRAY_U8:
126 case SIDE_TYPE_ARRAY_U16:
127 case SIDE_TYPE_ARRAY_U32:
128 case SIDE_TYPE_ARRAY_U64:
129 case SIDE_TYPE_ARRAY_S8:
130 case SIDE_TYPE_ARRAY_S16:
131 case SIDE_TYPE_ARRAY_S32:
132 case SIDE_TYPE_ARRAY_S64:
133 tracer_print_array_fixint(type_desc, item);
134 break;
135 case SIDE_TYPE_VLA_U8:
136 case SIDE_TYPE_VLA_U16:
137 case SIDE_TYPE_VLA_U32:
138 case SIDE_TYPE_VLA_U64:
139 case SIDE_TYPE_VLA_S8:
140 case SIDE_TYPE_VLA_S16:
141 case SIDE_TYPE_VLA_S32:
142 case SIDE_TYPE_VLA_S64:
143 tracer_print_vla_fixint(type_desc, item);
144 break;
145 case SIDE_TYPE_DYNAMIC:
146 tracer_print_dynamic(&item->u.dynamic);
147 break;
148 default:
149 printf("<UNKNOWN TYPE>");
150 abort();
151 }
152 }
153
154 static
155 void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg_vec *item)
156 {
157 printf("%s: ", item_desc->field_name);
158 tracer_print_type(&item_desc->side_type, item);
159 }
160
161 static
162 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
163 {
164 const struct side_arg_vec *sav = sav_desc->sav;
165 uint32_t side_sav_len = sav_desc->len;
166 int i;
167
168 if (type_desc->u.side_struct.nr_fields != side_sav_len) {
169 printf("ERROR: number of fields mismatch between description and arguments of structure\n");
170 abort();
171 }
172 printf("{ ");
173 for (i = 0; i < side_sav_len; i++) {
174 printf("%s", i ? ", " : "");
175 tracer_print_field(&type_desc->u.side_struct.fields[i], &sav[i]);
176 }
177 printf(" }");
178 }
179
180 static
181 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
182 {
183 const struct side_arg_vec *sav = sav_desc->sav;
184 uint32_t side_sav_len = sav_desc->len;
185 int i;
186
187 if (type_desc->u.side_array.length != side_sav_len) {
188 printf("ERROR: length mismatch between description and arguments of array\n");
189 abort();
190 }
191 printf("[ ");
192 for (i = 0; i < side_sav_len; i++) {
193 printf("%s", i ? ", " : "");
194 tracer_print_type(type_desc->u.side_array.elem_type, &sav[i]);
195 }
196 printf(" ]");
197 }
198
199 static
200 void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
201 {
202 const struct side_arg_vec *sav = sav_desc->sav;
203 uint32_t side_sav_len = sav_desc->len;
204 int i;
205
206 printf("[ ");
207 for (i = 0; i < side_sav_len; i++) {
208 printf("%s", i ? ", " : "");
209 tracer_print_type(type_desc->u.side_vla.elem_type, &sav[i]);
210 }
211 printf(" ]");
212 }
213
214 struct tracer_visitor_priv {
215 const struct side_type_description *elem_type;
216 int i;
217 };
218
219 static
220 enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx,
221 const struct side_arg_vec *elem)
222 {
223 struct tracer_visitor_priv *tracer_priv = tracer_ctx->priv;
224
225 printf("%s", tracer_priv->i++ ? ", " : "");
226 tracer_print_type(tracer_priv->elem_type, elem);
227 return SIDE_VISITOR_STATUS_OK;
228 }
229
230 static
231 void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *app_ctx)
232 {
233 enum side_visitor_status status;
234 struct tracer_visitor_priv tracer_priv = {
235 .elem_type = type_desc->u.side_vla_visitor.elem_type,
236 .i = 0,
237 };
238 const struct side_tracer_visitor_ctx tracer_ctx = {
239 .write_elem = tracer_write_elem_cb,
240 .priv = &tracer_priv,
241 };
242
243 printf("[ ");
244 status = type_desc->u.side_vla_visitor.visitor(&tracer_ctx, app_ctx);
245 switch (status) {
246 case SIDE_VISITOR_STATUS_OK:
247 break;
248 case SIDE_VISITOR_STATUS_ERROR:
249 printf("ERROR: Visitor error\n");
250 abort();
251 }
252 printf(" ]");
253 }
254
255 void tracer_print_array_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item)
256 {
257 const struct side_type_description *elem_type = type_desc->u.side_array.elem_type;
258 uint32_t side_sav_len = type_desc->u.side_array.length;
259 void *p = item->u.side_array_fixint;
260 enum side_type side_type;
261 int i;
262
263 switch (item->type) {
264 case SIDE_TYPE_ARRAY_U8:
265 if (elem_type->type != SIDE_TYPE_U8)
266 goto type_error;
267 break;
268 case SIDE_TYPE_ARRAY_U16:
269 if (elem_type->type != SIDE_TYPE_U16)
270 goto type_error;
271 break;
272 case SIDE_TYPE_ARRAY_U32:
273 if (elem_type->type != SIDE_TYPE_U32)
274 goto type_error;
275 break;
276 case SIDE_TYPE_ARRAY_U64:
277 if (elem_type->type != SIDE_TYPE_U64)
278 goto type_error;
279 break;
280 case SIDE_TYPE_ARRAY_S8:
281 if (elem_type->type != SIDE_TYPE_S8)
282 goto type_error;
283 break;
284 case SIDE_TYPE_ARRAY_S16:
285 if (elem_type->type != SIDE_TYPE_S16)
286 goto type_error;
287 break;
288 case SIDE_TYPE_ARRAY_S32:
289 if (elem_type->type != SIDE_TYPE_S32)
290 goto type_error;
291 break;
292 case SIDE_TYPE_ARRAY_S64:
293 if (elem_type->type != SIDE_TYPE_S64)
294 goto type_error;
295 break;
296 default:
297 goto type_error;
298 }
299 side_type = elem_type->type;
300
301 printf("[ ");
302 for (i = 0; i < side_sav_len; i++) {
303 struct side_arg_vec sav_elem = {
304 .type = side_type,
305 };
306
307 switch (side_type) {
308 case SIDE_TYPE_U8:
309 sav_elem.u.side_u8 = ((const uint8_t *) p)[i];
310 break;
311 case SIDE_TYPE_S8:
312 sav_elem.u.side_s8 = ((const int8_t *) p)[i];
313 break;
314 case SIDE_TYPE_U16:
315 sav_elem.u.side_u16 = ((const uint16_t *) p)[i];
316 break;
317 case SIDE_TYPE_S16:
318 sav_elem.u.side_s16 = ((const int16_t *) p)[i];
319 break;
320 case SIDE_TYPE_U32:
321 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
322 break;
323 case SIDE_TYPE_S32:
324 sav_elem.u.side_s32 = ((const int32_t *) p)[i];
325 break;
326 case SIDE_TYPE_U64:
327 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
328 break;
329 case SIDE_TYPE_S64:
330 sav_elem.u.side_s64 = ((const int64_t *) p)[i];
331 break;
332
333 default:
334 printf("ERROR: Unexpected type\n");
335 abort();
336 }
337
338 printf("%s", i ? ", " : "");
339 tracer_print_type(elem_type, &sav_elem);
340 }
341 printf(" ]");
342 return;
343
344 type_error:
345 printf("ERROR: type mismatch\n");
346 abort();
347 }
348
349 void tracer_print_vla_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item)
350 {
351 const struct side_type_description *elem_type = type_desc->u.side_vla.elem_type;
352 uint32_t side_sav_len = item->u.side_vla_fixint.length;
353 void *p = item->u.side_vla_fixint.p;
354 enum side_type side_type;
355 int i;
356
357 switch (item->type) {
358 case SIDE_TYPE_VLA_U8:
359 if (elem_type->type != SIDE_TYPE_U8)
360 goto type_error;
361 break;
362 case SIDE_TYPE_VLA_U16:
363 if (elem_type->type != SIDE_TYPE_U16)
364 goto type_error;
365 break;
366 case SIDE_TYPE_VLA_U32:
367 if (elem_type->type != SIDE_TYPE_U32)
368 goto type_error;
369 break;
370 case SIDE_TYPE_VLA_U64:
371 if (elem_type->type != SIDE_TYPE_U64)
372 goto type_error;
373 break;
374 case SIDE_TYPE_VLA_S8:
375 if (elem_type->type != SIDE_TYPE_S8)
376 goto type_error;
377 break;
378 case SIDE_TYPE_VLA_S16:
379 if (elem_type->type != SIDE_TYPE_S16)
380 goto type_error;
381 break;
382 case SIDE_TYPE_VLA_S32:
383 if (elem_type->type != SIDE_TYPE_S32)
384 goto type_error;
385 break;
386 case SIDE_TYPE_VLA_S64:
387 if (elem_type->type != SIDE_TYPE_S64)
388 goto type_error;
389 break;
390 default:
391 goto type_error;
392 }
393 side_type = elem_type->type;
394
395 printf("[ ");
396 for (i = 0; i < side_sav_len; i++) {
397 struct side_arg_vec sav_elem = {
398 .type = side_type,
399 };
400
401 switch (side_type) {
402 case SIDE_TYPE_U8:
403 sav_elem.u.side_u8 = ((const uint8_t *) p)[i];
404 break;
405 case SIDE_TYPE_S8:
406 sav_elem.u.side_s8 = ((const int8_t *) p)[i];
407 break;
408 case SIDE_TYPE_U16:
409 sav_elem.u.side_u16 = ((const uint16_t *) p)[i];
410 break;
411 case SIDE_TYPE_S16:
412 sav_elem.u.side_s16 = ((const int16_t *) p)[i];
413 break;
414 case SIDE_TYPE_U32:
415 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
416 break;
417 case SIDE_TYPE_S32:
418 sav_elem.u.side_s32 = ((const int32_t *) p)[i];
419 break;
420 case SIDE_TYPE_U64:
421 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
422 break;
423 case SIDE_TYPE_S64:
424 sav_elem.u.side_s64 = ((const int64_t *) p)[i];
425 break;
426
427 default:
428 printf("ERROR: Unexpected type\n");
429 abort();
430 }
431
432 printf("%s", i ? ", " : "");
433 tracer_print_type(elem_type, &sav_elem);
434 }
435 printf(" ]");
436 return;
437
438 type_error:
439 printf("ERROR: type mismatch\n");
440 abort();
441 }
442
443 static
444 void tracer_print_dynamic_struct(const struct side_arg_dynamic_event_struct *dynamic_struct)
445 {
446 const struct side_arg_dynamic_event_field *fields = dynamic_struct->fields;
447 uint32_t len = dynamic_struct->len;
448 int i;
449
450 printf("[ ");
451 for (i = 0; i < len; i++) {
452 printf("%s", i ? ", " : "");
453 printf("%s:: ", fields[i].field_name);
454 tracer_print_dynamic(&fields[i].elem);
455 }
456 printf(" ]");
457 }
458
459 struct tracer_dynamic_struct_visitor_priv {
460 int i;
461 };
462
463 static
464 enum side_visitor_status tracer_dynamic_struct_write_elem_cb(
465 const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
466 const struct side_arg_dynamic_event_field *dynamic_field)
467 {
468 struct tracer_dynamic_struct_visitor_priv *tracer_priv = tracer_ctx->priv;
469
470 printf("%s", tracer_priv->i++ ? ", " : "");
471 printf("%s:: ", dynamic_field->field_name);
472 tracer_print_dynamic(&dynamic_field->elem);
473 return SIDE_VISITOR_STATUS_OK;
474 }
475
476 static
477 void tracer_print_dynamic_struct_visitor(const struct side_arg_dynamic_vec *item)
478 {
479 enum side_visitor_status status;
480 struct tracer_dynamic_struct_visitor_priv tracer_priv = {
481 .i = 0,
482 };
483 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = {
484 .write_field = tracer_dynamic_struct_write_elem_cb,
485 .priv = &tracer_priv,
486 };
487 void *app_ctx = item->u.side_dynamic_struct_visitor.app_ctx;
488
489 printf("[ ");
490 status = item->u.side_dynamic_struct_visitor.visitor(&tracer_ctx, app_ctx);
491 switch (status) {
492 case SIDE_VISITOR_STATUS_OK:
493 break;
494 case SIDE_VISITOR_STATUS_ERROR:
495 printf("ERROR: Visitor error\n");
496 abort();
497 }
498 printf(" ]");
499 }
500
501 static
502 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vec_vla *vla)
503 {
504 const struct side_arg_dynamic_vec *sav = vla->sav;
505 uint32_t side_sav_len = vla->len;
506 int i;
507
508 printf("[ ");
509 for (i = 0; i < side_sav_len; i++) {
510 printf("%s", i ? ", " : "");
511 tracer_print_dynamic(&sav[i]);
512 }
513 printf(" ]");
514 }
515
516 struct tracer_dynamic_vla_visitor_priv {
517 int i;
518 };
519
520 static
521 enum side_visitor_status tracer_dynamic_vla_write_elem_cb(
522 const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
523 const struct side_arg_dynamic_vec *elem)
524 {
525 struct tracer_dynamic_vla_visitor_priv *tracer_priv = tracer_ctx->priv;
526
527 printf("%s", tracer_priv->i++ ? ", " : "");
528 tracer_print_dynamic(elem);
529 return SIDE_VISITOR_STATUS_OK;
530 }
531
532 static
533 void tracer_print_dynamic_vla_visitor(const struct side_arg_dynamic_vec *item)
534 {
535 enum side_visitor_status status;
536 struct tracer_dynamic_vla_visitor_priv tracer_priv = {
537 .i = 0,
538 };
539 const struct side_tracer_dynamic_vla_visitor_ctx tracer_ctx = {
540 .write_elem = tracer_dynamic_vla_write_elem_cb,
541 .priv = &tracer_priv,
542 };
543 void *app_ctx = item->u.side_dynamic_vla_visitor.app_ctx;
544
545 printf("[ ");
546 status = item->u.side_dynamic_vla_visitor.visitor(&tracer_ctx, app_ctx);
547 switch (status) {
548 case SIDE_VISITOR_STATUS_OK:
549 break;
550 case SIDE_VISITOR_STATUS_ERROR:
551 printf("ERROR: Visitor error\n");
552 abort();
553 }
554 printf(" ]");
555 }
556
557 static
558 void tracer_print_dynamic(const struct side_arg_dynamic_vec *item)
559 {
560 switch (item->dynamic_type) {
561 case SIDE_DYNAMIC_TYPE_NULL:
562 printf("<NULL TYPE>");
563 break;
564 case SIDE_DYNAMIC_TYPE_BOOL:
565 printf("%s", item->u.side_bool ? "true" : "false");
566 break;
567 case SIDE_DYNAMIC_TYPE_U8:
568 printf("%" PRIu8, item->u.side_u8);
569 break;
570 case SIDE_DYNAMIC_TYPE_U16:
571 printf("%" PRIu16, item->u.side_u16);
572 break;
573 case SIDE_DYNAMIC_TYPE_U32:
574 printf("%" PRIu32, item->u.side_u32);
575 break;
576 case SIDE_DYNAMIC_TYPE_U64:
577 printf("%" PRIu64, item->u.side_u64);
578 break;
579 case SIDE_DYNAMIC_TYPE_S8:
580 printf("%" PRId8, item->u.side_s8);
581 break;
582 case SIDE_DYNAMIC_TYPE_S16:
583 printf("%" PRId16, item->u.side_s16);
584 break;
585 case SIDE_DYNAMIC_TYPE_S32:
586 printf("%" PRId32, item->u.side_s32);
587 break;
588 case SIDE_DYNAMIC_TYPE_S64:
589 printf("%" PRId64, item->u.side_s64);
590 break;
591 case SIDE_DYNAMIC_TYPE_STRING:
592 printf("\"%s\"", item->u.string);
593 break;
594 case SIDE_DYNAMIC_TYPE_STRUCT:
595 tracer_print_dynamic_struct(item->u.side_dynamic_struct);
596 break;
597 case SIDE_DYNAMIC_TYPE_STRUCT_VISITOR:
598 tracer_print_dynamic_struct_visitor(item);
599 break;
600 case SIDE_DYNAMIC_TYPE_VLA:
601 tracer_print_dynamic_vla(item->u.side_dynamic_vla);
602 break;
603 case SIDE_DYNAMIC_TYPE_VLA_VISITOR:
604 tracer_print_dynamic_vla_visitor(item);
605 break;
606 default:
607 printf("<UNKNOWN TYPE>");
608 abort();
609 }
610 }
611
612 static
613 void tracer_print_static_fields(const struct side_event_description *desc,
614 const struct side_arg_vec_description *sav_desc,
615 int *nr_items)
616 {
617 const struct side_arg_vec *sav = sav_desc->sav;
618 uint32_t side_sav_len = sav_desc->len;
619 int i;
620
621 printf("provider: %s, event: %s", desc->provider_name, desc->event_name);
622 if (desc->nr_fields != side_sav_len) {
623 printf("ERROR: number of fields mismatch between description and arguments\n");
624 abort();
625 }
626 print_attributes(desc->attr, desc->nr_attr);
627 printf("%s", side_sav_len ? ", " : "");
628 for (i = 0; i < side_sav_len; i++) {
629 printf("%s", i ? ", " : "");
630 tracer_print_field(&desc->fields[i], &sav[i]);
631 }
632 if (nr_items)
633 *nr_items = i;
634 }
635
636 void tracer_call(const struct side_event_description *desc, const struct side_arg_vec_description *sav_desc)
637 {
638 if (side_unlikely(desc->flags & SIDE_EVENT_FLAG_VARIADIC)) {
639 printf("ERROR: unexpected variadic event description\n");
640 abort();
641 }
642 tracer_print_static_fields(desc, sav_desc, NULL);
643 printf("\n");
644 }
645
646 void tracer_call_variadic(const struct side_event_description *desc,
647 const struct side_arg_vec_description *sav_desc,
648 const struct side_arg_dynamic_event_struct *var_struct)
649 {
650 uint32_t var_struct_len = var_struct->len;
651 int nr_fields = 0, i;
652
653 tracer_print_static_fields(desc, sav_desc, &nr_fields);
654
655 if (side_unlikely(!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))) {
656 printf("ERROR: unexpected non-variadic event description\n");
657 abort();
658 }
659 printf("%s", var_struct_len && !nr_fields ? ", " : "");
660 for (i = 0; i < var_struct_len; i++, nr_fields++) {
661 printf("%s", nr_fields ? ", " : "");
662 printf("%s:: ", var_struct->fields[i].field_name);
663 tracer_print_dynamic(&var_struct->fields[i].elem);
664 }
665 printf("\n");
666 }
This page took 0.053965 seconds and 5 git commands to generate.