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