Create "untagged" variant structure
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
1 /*
2 * ctf-visitor-generate-io-struct.c
3 *
4 * Common Trace Format Metadata Visitor (generate I/O structures).
5 *
6 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <glib.h>
25 #include <inttypes.h>
26 #include <errno.h>
27 #include <babeltrace/list.h>
28 #include <uuid/uuid.h>
29 #include "ctf-scanner.h"
30 #include "ctf-parser.h"
31 #include "ctf-ast.h"
32
33 #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
34
35 #define _cds_list_first_entry(ptr, type, member) \
36 cds_list_entry((ptr)->next, type, member)
37
38 static
39 int ctf_visitor_print_type_specifier(FILE *fd, int depth, struct ctf_node *node)
40 {
41 print_tabs(fd, depth);
42 fprintf(fd, "<type_specifier \"");
43
44 switch (node->u.type_specifier.type) {
45 case TYPESPEC_VOID:
46 fprintf(fd, "void");
47 break;
48 case TYPESPEC_CHAR:
49 fprintf(fd, "char");
50 break;
51 case TYPESPEC_SHORT:
52 fprintf(fd, "short");
53 break;
54 case TYPESPEC_INT:
55 fprintf(fd, "int");
56 break;
57 case TYPESPEC_LONG:
58 fprintf(fd, "long");
59 break;
60 case TYPESPEC_FLOAT:
61 fprintf(fd, "float");
62 break;
63 case TYPESPEC_DOUBLE:
64 fprintf(fd, "double");
65 break;
66 case TYPESPEC_SIGNED:
67 fprintf(fd, "signed");
68 break;
69 case TYPESPEC_UNSIGNED:
70 fprintf(fd, "unsigned");
71 break;
72 case TYPESPEC_BOOL:
73 fprintf(fd, "bool");
74 break;
75 case TYPESPEC_COMPLEX:
76 fprintf(fd, "_Complex");
77 break;
78 case TYPESPEC_IMAGINARY:
79 fprintf(fd, "_Imaginary");
80 break;
81 case TYPESPEC_CONST:
82 fprintf(fd, "const");
83 break;
84 case TYPESPEC_ID_TYPE:
85 fprintf(fd, "%s", node->u.type_specifier.id_type);
86 break;
87
88 case TYPESPEC_UNKNOWN:
89 default:
90 fprintf(stderr, "[error] %s: unknown type specifier %d\n", __func__,
91 (int) node->u.type_specifier.type);
92 return -EINVAL;
93 }
94 fprintf(fd, "\"/>\n");
95 return 0;
96 }
97
98 static
99 int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node)
100 {
101 int ret = 0;
102 struct ctf_node *iter;
103
104 print_tabs(fd, depth);
105 fprintf(fd, "<type_declarator>\n");
106 depth++;
107
108 if (!cds_list_empty(&node->u.type_declarator.pointers)) {
109 print_tabs(fd, depth);
110 fprintf(fd, "<pointers>\n");
111 cds_list_for_each_entry(iter, &node->u.type_declarator.pointers,
112 siblings) {
113 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
114 if (ret)
115 return ret;
116 }
117 print_tabs(fd, depth);
118 fprintf(fd, "</pointers>\n");
119 }
120
121 switch (node->u.type_declarator.type) {
122 case TYPEDEC_ID:
123 if (node->u.type_declarator.u.id) {
124 print_tabs(fd, depth);
125 fprintf(fd, "<id \"");
126 fprintf(fd, "%s", node->u.type_declarator.u.id);
127 fprintf(fd, "\" />\n");
128 }
129 break;
130 case TYPEDEC_NESTED:
131 if (node->u.type_declarator.u.nested.type_declarator) {
132 print_tabs(fd, depth);
133 fprintf(fd, "<type_declarator>\n");
134 ret = ctf_visitor_print_xml(fd, depth + 1,
135 node->u.type_declarator.u.nested.type_declarator);
136 if (ret)
137 return ret;
138 print_tabs(fd, depth);
139 fprintf(fd, "</type_declarator>\n");
140 }
141 if (node->u.type_declarator.u.nested.length) {
142 print_tabs(fd, depth);
143 fprintf(fd, "<length>\n");
144 ret = ctf_visitor_print_xml(fd, depth + 1,
145 node->u.type_declarator.u.nested.length);
146 if (ret)
147 return ret;
148 print_tabs(fd, depth);
149 fprintf(fd, "</length>\n");
150 }
151 if (node->u.type_declarator.u.nested.abstract_array) {
152 print_tabs(fd, depth);
153 fprintf(fd, "<length>\n");
154 print_tabs(fd, depth);
155 fprintf(fd, "</length>\n");
156 }
157 if (node->u.type_declarator.bitfield_len) {
158 print_tabs(fd, depth);
159 fprintf(fd, "<bitfield_len>\n");
160 ret = ctf_visitor_print_xml(fd, depth + 1,
161 node->u.type_declarator.bitfield_len);
162 if (ret)
163 return ret;
164 print_tabs(fd, depth);
165 fprintf(fd, "</bitfield_len>\n");
166 }
167 break;
168 case TYPEDEC_UNKNOWN:
169 default:
170 fprintf(stderr, "[error] %s: unknown type declarator %d\n", __func__,
171 (int) node->u.type_declarator.type);
172 return -EINVAL;
173 }
174
175 depth--;
176 print_tabs(fd, depth);
177 fprintf(fd, "</type_declarator>\n");
178 return 0;
179 }
180
181 /*
182 * String returned must be freed by the caller using g_free.
183 */
184 static
185 char *concatenate_unary_strings(struct list_head *head)
186 {
187 struct ctf_node *node;
188 GString *str;
189 int i = 0;
190
191 str = g_string_new();
192 cds_list_for_each_entry(node, head, siblings) {
193 char *src_string;
194
195 assert(node->type == NODE_UNARY_EXPRESSION);
196 assert(node->u.unary_expression.type == UNARY_STRING);
197 assert((node->u.unary_expression.link == UNARY_LINK_UNKNOWN)
198 ^ (i != 0))
199 switch (node->u.unary_expression.link) {
200 case UNARY_DOTLINK:
201 g_string_append(str, ".")
202 break;
203 case UNARY_ARROWLINK:
204 g_string_append(str, "->")
205 break;
206 case UNARY_DOTDOTDOT:
207 g_string_append(str, "...")
208 break;
209 }
210 src_string = u.unary_expression.u.string;
211 g_string_append(str, src_string);
212 i++;
213 }
214 return g_string_free(str, FALSE);
215 }
216
217 static
218 int get_unary_unsigned(struct list_head *head, uint64_t *value)
219 {
220 struct ctf_node *node;
221 int i = 0;
222
223 cds_list_for_each_entry(node, head, siblings) {
224 assert(node->type == NODE_UNARY_EXPRESSION);
225 assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT);
226 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
227 assert(i == 0);
228 *value = node->u.unary_expression.unsigned_constant
229 i++;
230 }
231 return 0;
232 }
233
234 static
235 int get_unary_uuid(struct list_head *head, uuid_t *uuid)
236 {
237 struct ctf_node *node;
238 int i = 0;
239 int ret = -1;
240
241 cds_list_for_each_entry(node, head, siblings) {
242 const char *src_string;
243
244 assert(node->type == NODE_UNARY_EXPRESSION);
245 assert(node->u.unary_expression.type == UNARY_STRING);
246 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
247 assert(i == 0);
248 src_string = u.unary_expression.u.string;
249 ret = uuid_parse(u.unary_expression.u.string, *uuid);
250 }
251 return ret;
252 }
253
254 static
255 struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
256 {
257 if (trace->streams->len <= stream_id)
258 return NULL;
259 return g_ptr_array_index(trace->streams, stream_id);
260 }
261
262 /*
263 * Also add named variant, struct or enum to the current declaration scope.
264 */
265 static
266 struct ctf_declaration *ctf_declaration_specifier_visit(FILE *fd,
267 int depth, struct list_head *head,
268 struct declaration_scope *declaration_scope)
269 {
270 struct ctf_declaration *declaration;
271 struct node *first;
272
273 first = _cds_list_first_entry(head, struct node, siblings);
274
275 switch (first->type) {
276 case NODE_STRUCT:
277 /*
278 * For named struct (without body), lookup in
279 * declaration scope and create declaration copy.
280 */
281 /* For named struct (with body), create type and add to declaration scope */
282 /* For unnamed struct, create type */
283 break;
284 case NODE_VARIANT:
285 /*
286 * For named variant (without body), lookup in
287 * declaration scope and create declaration copy.
288 */
289 /* For named variant (with body), create type and add to declaration scope */
290 /* For unnamed variant, create type */
291 /* If variant has a tag field specifier, assign tag name. */
292 break;
293 case NODE_ENUM:
294 /*
295 * For named enum (without body), lookup in declaration
296 * scope and create declaration copy.
297 */
298 /* For named enum (with body), create type and add to declaration scope */
299 /* For unnamed enum, create type */
300 /* Enumerations need to have their size/type specifier (< >). */
301 break;
302 case NODE_INTEGER:
303 /*
304 * Create an integer declaration.
305 */
306 break;
307 case NODE_FLOATING_POINT:
308 /*
309 * Create a floating point declaration.
310 */
311 break;
312 case NODE_STRING:
313 /*
314 * Create a string declaration.
315 */
316 break;
317 case NODE_TYPE_SPECIFIER:
318 /*
319 * Lookup named type in typedef declarations (in
320 * declaration scope). Create a copy of the declaration.
321 */
322 break;
323
324 }
325 }
326
327 static
328 int ctf_typedef_declarator_visit(FILE *fd, int depth,
329 struct list_head *declaration_specifier,
330 struct node *type_declarator,
331 struct declaration_scope *declaration_scope)
332 {
333 /*
334 * Build the type using declaration specifier (creating
335 * declaration from type_specifier), then apply type declarator,
336 * add the resulting type to the current declaration scope.
337 */
338 cds_list_for_each_entry(iter, declaration_specifier, siblings) {
339
340
341 }
342 return 0;
343 }
344
345 static
346 int ctf_typedef_visit(FILE *fd, int depth,
347 struct list_head *declaration_specifier,
348 struct list_head *type_declarators,
349 struct declaration_scope *declaration_scope)
350 {
351 struct ctf_node *iter;
352
353 cds_list_for_each_entry(iter, type_declarators, siblings) {
354 ret = ctf_typedef_declarator_visit(fd, depth + 1,
355 &node->u._typedef.declaration_specifier, iter,
356 declaration_scope);
357 if (ret)
358 return ret;
359 }
360 return 0;
361 }
362
363 static
364 int ctf_typealias_visit(FILE *fd, int depth, struct ctf_node *target,
365 struct ctf_node *alias,
366 struct declaration_scope *declaration_scope)
367 {
368 /*
369 * Build target type, check that it is reachable in current
370 * declaration scope.
371 */
372
373 /* Only one type declarator is allowed */
374
375 /* Build alias type, add to current declaration scope. */
376 /* Only one type declarator is allowed */
377 }
378
379 static
380 int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_event *event, struct ctf_trace *trace)
381 {
382 int ret = 0;
383
384 switch (node->type) {
385 case NODE_TYPEDEF:
386 ret = ctf_typedef_visit(fd, depth + 1,
387 &node->u._typedef.declaration_specifier,
388 &node->u._typedef.type_declarators,
389 event->declaration_scope);
390 if (ret)
391 return ret;
392 break;
393 case NODE_TYPEALIAS:
394 ret = ctf_typealias_visit(fd, depth + 1,
395 &node->u.typealias.target, &node->u.typealias.alias
396 event->declaration_scope);
397 if (ret)
398 return ret;
399 break;
400 case NODE_CTF_EXPRESSION:
401 {
402 char *left;
403
404 left = concatenate_unary_strings(&node->u.ctf_expression.left);
405 if (!strcmp(left, "name")) {
406 char *right;
407
408 if (CTF_EVENT_FIELD_IS_SET(event, name))
409 return -EPERM;
410 right = concatenate_unary_strings(&node->u.ctf_expression.right);
411 if (!right) {
412 fprintf(stderr, "[error] %s: unexpected unary expression for event name\n", __func__);
413 return -EINVAL;
414 }
415 event->name = g_quark_from_string(right);
416 g_free(right);
417 CTF_EVENT_SET_FIELD(event, name);
418 } else if (!strcmp(left, "id")) {
419 if (CTF_EVENT_FIELD_IS_SET(event, id))
420 return -EPERM;
421 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->id);
422 if (ret) {
423 fprintf(stderr, "[error] %s: unexpected unary expression for event id\n", __func__);
424 return -EINVAL;
425 }
426 CTF_EVENT_SET_FIELD(event, id);
427 } else if (!strcmp(left, "stream_id")) {
428 if (CTF_EVENT_FIELD_IS_SET(event, stream_id))
429 return -EPERM;
430 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
431 if (ret) {
432 fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
433 return -EINVAL;
434 }
435 event->stream = trace_stream_lookup(trace, event->stream_id);
436 if (!event->stream) {
437 fprintf(stderr, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id);
438 return -EINVAL;
439 }
440 CTF_EVENT_SET_FIELD(event, stream_id);
441 } else if (!strcmp(left, "context")) {
442 struct declaration *declaration;
443
444 if (!event->definition_scope)
445 return -EPERM;
446 declaration = ctf_declaration_specifier_visit(fd, depth,
447 &node->u.ctf_expression.right,
448 event->declaration_scope);
449 if (!declaration)
450 return -EPERM;
451 if (declaration->type->id != CTF_TYPE_STRUCT)
452 return -EPERM;
453 event->context_decl = container_of(declaration, struct declaration_struct, p);
454 } else if (!strcmp(left, "fields")) {
455 struct declaration *declaration;
456
457 if (!event->definition_scope)
458 return -EPERM;
459 declaration = ctf_declaration_specifier_visit(fd, depth,
460 &node->u.ctf_expression.right,
461 event->declaration_scope);
462 if (!declaration)
463 return -EPERM;
464 if (declaration->type->id != CTF_TYPE_STRUCT)
465 return -EPERM;
466 event->fields_decl = container_of(declaration, struct declaration_struct, p);
467 }
468 g_free(left);
469 break;
470 }
471 default:
472 return -EPERM;
473 /* TODO: declaration specifier should be added. */
474 }
475
476 return 0;
477 }
478
479 static
480 int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
481 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
482 {
483 int ret = 0;
484 struct ctf_node *iter;
485 struct ctf_event *event;
486 struct definition_scope *parent_def_scope;
487
488 event = g_new0(struct ctf_event, 1);
489 event->declaration_scope = new_declaration_scope(parent_declaration_scope);
490 cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) {
491 ret = ctf_event_declaration_visit(fd, depth + 1, iter, event, trace);
492 if (ret)
493 goto error;
494 }
495 if (!CTF_EVENT_FIELD_IS_SET(event, name)) {
496 ret = -EPERM;
497 goto error;
498 }
499 if (!CTF_EVENT_FIELD_IS_SET(event, id)) {
500 ret = -EPERM;
501 goto error;
502 }
503 if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
504 ret = -EPERM;
505 goto error;
506 }
507 if (event->stream->events_by_id->len <= event->id)
508 g_ptr_array_set_size(event->stream->events_by_id, event->id + 1);
509 g_ptr_array_index(event->stream->events_by_id, event->id) = event;
510 g_hash_table_insert(event->stream->event_quark_to_id,
511 (gpointer)(unsigned long) event->name,
512 &event->id);
513 parent_def_scope = stream->definition_scope;
514 if (event->context_decl) {
515 event->context =
516 event->context_decl->definition_new(event->context_decl,
517 parent_def_scope, 0, 0);
518 set_dynamic_definition_scope(&event->context->p,
519 event->context->scope,
520 "event.context");
521 parent_def_scope = event->context->scope;
522 declaration_unref(event->context_decl);
523 }
524 if (event->fields_decl) {
525 event->fields =
526 event->fields_decl->definition_new(event->fields_decl,
527 parent_def_scope, 0, 0);
528 set_dynamic_definition_scope(&event->fields->p,
529 event->fields->scope,
530 "event.fields");
531 parent_def_scope = event->fields->scope;
532 declaration_unref(event->fields_decl);
533 }
534 return 0;
535
536 error:
537 declaration_unref(event->fields_decl);
538 declaration_unref(event->context_decl);
539 free_definition_scope(event->definition_scope);
540 free_declaration_scope(event->declaration_scope);
541 g_free(event);
542 return ret;
543 }
544
545
546 static
547 int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace)
548 {
549 int ret = 0;
550
551 switch (node->type) {
552 case NODE_TYPEDEF:
553 ret = ctf_typedef_visit(fd, depth + 1,
554 &node->u._typedef.declaration_specifier,
555 &node->u._typedef.type_declarators,
556 stream->declaration_scope);
557 if (ret)
558 return ret;
559 break;
560 case NODE_TYPEALIAS:
561 ret = ctf_typealias_visit(fd, depth + 1,
562 &node->u.typealias.target, &node->u.typealias.alias
563 stream->declaration_scope);
564 if (ret)
565 return ret;
566 break;
567 case NODE_CTF_EXPRESSION:
568 {
569 char *left;
570
571 left = concatenate_unary_strings(&node->u.ctf_expression.left);
572 if (!strcmp(left, "stream_id")) {
573 if (CTF_EVENT_FIELD_IS_SET(event, stream_id))
574 return -EPERM;
575 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
576 if (ret) {
577 fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
578 return -EINVAL;
579 }
580 CTF_EVENT_SET_FIELD(event, stream_id);
581 } else if (!strcmp(left, "event.header")) {
582 struct declaration *declaration;
583
584 declaration = ctf_declaration_specifier_visit(fd, depth,
585 &node->u.ctf_expression.right,
586 stream->declaration_scope, stream->definition_scope);
587 if (!declaration)
588 return -EPERM;
589 if (declaration->type->id != CTF_TYPE_STRUCT)
590 return -EPERM;
591 stream->event_header_decl = container_of(declaration, struct declaration_struct, p);
592 } else if (!strcmp(left, "event.context")) {
593 struct declaration *declaration;
594
595 declaration = ctf_declaration_specifier_visit(fd, depth,
596 &node->u.ctf_expression.right,
597 stream->declaration_scope);
598 if (!declaration)
599 return -EPERM;
600 if (declaration->type->id != CTF_TYPE_STRUCT)
601 return -EPERM;
602 stream->event_context_decl = container_of(declaration, struct declaration_struct, p);
603 } else if (!strcmp(left, "packet.context")) {
604 struct declaration *declaration;
605
606 declaration = ctf_declaration_specifier_visit(fd, depth,
607 &node->u.ctf_expression.right,
608 stream->declaration_scope);
609 if (!declaration)
610 return -EPERM;
611 if (declaration->type->id != CTF_TYPE_STRUCT)
612 return -EPERM;
613 stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
614 }
615 g_free(left);
616 break;
617 }
618 default:
619 return -EPERM;
620 /* TODO: declaration specifier should be added. */
621 }
622
623 return 0;
624 }
625
626 static
627 int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
628 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
629 {
630 int ret = 0;
631 struct ctf_node *iter;
632 struct ctf_stream *stream;
633 struct definition_scope *parent_def_scope;
634
635 stream = g_new0(struct ctf_stream, 1);
636 stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
637 stream->events_by_id = g_ptr_array_new();
638 stream->event_quark_to_id = g_hash_table_new(g_int_hash, g_int_equal);
639 cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
640 ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
641 if (ret)
642 goto error;
643 }
644 if (!CTF_EVENT_FIELD_IS_SET(stream, stream_id)) {
645 ret = -EPERM;
646 goto error;
647 }
648 if (trace->streams->len <= stream->stream_id)
649 g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
650 g_ptr_array_index(trace->streams, stream->stream_id) = stream;
651
652 parent_def_scope = NULL;
653 if (stream->packet_context_decl) {
654 stream->packet_context =
655 stream->packet_context_decl->definition_new(stream->packet_context_decl,
656 parent_def_scope, 0, 0);
657 set_dynamic_definition_scope(&stream->packet_context->p,
658 stream->packet_context->scope,
659 "stream.packet.context");
660 parent_def_scope = stream->packet_context->scope;
661 declaration_unref(stream->packet_context_decl);
662 }
663 if (stream->event_header_decl) {
664 stream->event_header =
665 stream->event_header_decl->definition_new(stream->event_header_decl,
666 parent_def_scope, 0, 0);
667 set_dynamic_definition_scope(&stream->event_header->p,
668 stream->event_header->scope,
669 "stream.event.header");
670 parent_def_scope = stream->event_header->scope;
671 declaration_unref(stream->event_header_decl);
672 }
673 if (stream->event_context_decl) {
674 stream->event_context =
675 stream->event_context_decl->definition_new(stream->event_context_decl,
676 parent_def_scope, 0, 0);
677 set_dynamic_definition_scope(&stream->event_context->p,
678 stream->event_context->scope,
679 "stream.event.context");
680 parent_def_scope = stream->event_context->scope;
681 declaration_unref(stream->event_context_decl);
682 }
683 stream->definition_scope = parent_def_scope;
684
685 return 0;
686
687 error:
688 declaration_unref(stream->event_header);
689 declaration_unref(stream->event_context);
690 declaration_unref(stream->packet_context);
691 g_ptr_array_free(stream->events_by_id, TRUE);
692 g_hash_table_free(stream->event_quark_to_id);
693 free_definition_scope(stream->definition_scope);
694 free_declaration_scope(stream->declaration_scope);
695 g_free(stream);
696 return ret;
697 }
698
699 static
700 int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
701 {
702 int ret = 0;
703
704 switch (node->type) {
705 case NODE_TYPEDEF:
706 ret = ctf_typedef_visit(fd, depth + 1,
707 &node->u._typedef.declaration_specifier,
708 &node->u._typedef.type_declarators,
709 trace->declaration_scope);
710 if (ret)
711 return ret;
712 break;
713 case NODE_TYPEALIAS:
714 ret = ctf_typealias_visit(fd, depth + 1,
715 &node->u.typealias.target, &node->u.typealias.alias
716 trace->declaration_scope);
717 if (ret)
718 return ret;
719 break;
720 case NODE_CTF_EXPRESSION:
721 {
722 char *left;
723
724 left = concatenate_unary_strings(&node->u.ctf_expression.left);
725 if (!strcmp(left, "major")) {
726 if (CTF_EVENT_FIELD_IS_SET(trace, major))
727 return -EPERM;
728 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->major);
729 if (ret) {
730 fprintf(stderr, "[error] %s: unexpected unary expression for trace major number\n", __func__);
731 return -EINVAL;
732 }
733 CTF_EVENT_SET_FIELD(trace, major);
734 } else if (!strcmp(left, "minor")) {
735 if (CTF_EVENT_FIELD_IS_SET(trace, minor))
736 return -EPERM;
737 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->minor);
738 if (ret) {
739 fprintf(stderr, "[error] %s: unexpected unary expression for trace minor number\n", __func__);
740 return -EINVAL;
741 }
742 CTF_EVENT_SET_FIELD(trace, minor);
743 } else if (!strcmp(left, "word_size")) {
744 if (CTF_EVENT_FIELD_IS_SET(trace, word_size))
745 return -EPERM;
746 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->word_size);
747 if (ret) {
748 fprintf(stderr, "[error] %s: unexpected unary expression for trace word_size\n", __func__);
749 return -EINVAL;
750 }
751 CTF_EVENT_SET_FIELD(trace, word_size);
752 } else if (!strcmp(left, "uuid")) {
753 if (CTF_EVENT_FIELD_IS_SET(trace, uuid))
754 return -EPERM;
755 ret = get_unary_uuid(&node->u.ctf_expression.right, &trace->uuid);
756 if (ret) {
757 fprintf(stderr, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
758 return -EINVAL;
759 }
760 CTF_EVENT_SET_FIELD(trace, uuid);
761 }
762 g_free(left);
763 break;
764 }
765 default:
766 return -EPERM;
767 /* TODO: declaration specifier should be added. */
768 }
769
770 return 0;
771 }
772
773
774 static
775 int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
776 {
777 int ret = 0;
778 struct ctf_node *iter;
779
780 if (trace->declaration_scope)
781 return -EEXIST;
782 trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope);
783 trace->definition_scope = new_dynamic_definition_scope(trace->root_definition_scope);
784 trace->streams = g_ptr_array_new();
785 cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) {
786 ret = ctf_trace_declaration_visit(fd, depth + 1, iter, trace);
787 if (ret)
788 goto error;
789 }
790 if (!CTF_EVENT_FIELD_IS_SET(trace, major)) {
791 ret = -EPERM;
792 goto error;
793 }
794 if (!CTF_EVENT_FIELD_IS_SET(trace, minor)) {
795 ret = -EPERM;
796 goto error;
797 }
798 if (!CTF_EVENT_FIELD_IS_SET(trace, uuid)) {
799 ret = -EPERM;
800 goto error;
801 }
802 if (!CTF_EVENT_FIELD_IS_SET(trace, word_size)) {
803 ret = -EPERM;
804 goto error;
805 }
806 return 0;
807
808 error:
809 g_ptr_array_free(trace->streams, TRUE);
810 free_definition_scope(stream->definition_scope);
811 free_declaration_scope(stream->declaration_scope);
812 return ret;
813 }
814
815 int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
816 {
817 int ret = 0;
818 struct ctf_node *iter;
819
820 switch (node->type) {
821 case NODE_ROOT:
822 cds_list_for_each_entry(iter, &node->u.root._typedef,
823 siblings) {
824 ret = ctf_typedef_visit(fd, depth + 1,
825 &iter->u._typedef.declaration_specifier,
826 &iter->u._typedef.type_declarators,
827 trace->root_declaration_scope);
828 if (ret)
829 return ret;
830 }
831 cds_list_for_each_entry(iter, &node->u.root.typealias,
832 siblings) {
833 ret = ctf_typealias_visit(fd, depth + 1,
834 &iter->u.typealias.target, &iter->u.typealias.alias
835 trace->root_declaration_scope);
836 if (ret)
837 return ret;
838 }
839 cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) {
840 ret = ctf_declaration_specifier_visit(fd, depth, iter,
841 trace->root_declaration_scope);
842 if (ret)
843 return ret;
844 }
845 cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
846 ret = ctf_trace_visit(fd, depth + 1, iter, trace);
847 if (ret)
848 return ret;
849 }
850 cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
851 ret = ctf_stream_visit(fd, depth + 1, iter,
852 trace->root_declaration_scope, trace);
853 if (ret)
854 return ret;
855 }
856 cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
857 ret = ctf_event_visit(fd, depth + 1, iter,
858 trace->root_declaration_scope, trace);
859 if (ret)
860 return ret;
861 }
862 break;
863
864 case NODE_TYPEALIAS_TARGET:
865 print_tabs(fd, depth);
866 fprintf(fd, "<target>\n");
867 depth++;
868
869 print_tabs(fd, depth);
870 fprintf(fd, "<declaration_specifier>\n");
871 cds_list_for_each_entry(iter, &node->u.typealias_target.declaration_specifier, siblings) {
872 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
873 if (ret)
874 return ret;
875 }
876 print_tabs(fd, depth);
877 fprintf(fd, "</declaration_specifier>\n");
878
879 print_tabs(fd, depth);
880 fprintf(fd, "<type_declarators>\n");
881 cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) {
882 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
883 if (ret)
884 return ret;
885 }
886 print_tabs(fd, depth);
887 fprintf(fd, "</type_declarators>\n");
888
889 depth--;
890 print_tabs(fd, depth);
891 fprintf(fd, "</target>\n");
892 break;
893 case NODE_TYPEALIAS_ALIAS:
894 print_tabs(fd, depth);
895 fprintf(fd, "<alias>\n");
896 depth++;
897
898 print_tabs(fd, depth);
899 fprintf(fd, "<declaration_specifier>\n");
900 cds_list_for_each_entry(iter, &node->u.typealias_alias.declaration_specifier, siblings) {
901 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
902 if (ret)
903 return ret;
904 }
905 print_tabs(fd, depth);
906 fprintf(fd, "</declaration_specifier>\n");
907
908 print_tabs(fd, depth);
909 fprintf(fd, "<type_declarators>\n");
910 cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) {
911 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
912 if (ret)
913 return ret;
914 }
915 print_tabs(fd, depth);
916 fprintf(fd, "</type_declarators>\n");
917
918 depth--;
919 print_tabs(fd, depth);
920 fprintf(fd, "</alias>\n");
921 break;
922 case NODE_TYPEALIAS:
923 print_tabs(fd, depth);
924 fprintf(fd, "<typealias>\n");
925 ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.target);
926 if (ret)
927 return ret;
928 ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.alias);
929 if (ret)
930 return ret;
931 print_tabs(fd, depth);
932 fprintf(fd, "</typealias>\n");
933 break;
934
935 case NODE_TYPE_SPECIFIER:
936 ret = ctf_visitor_print_type_specifier(fd, depth, node);
937 if (ret)
938 return ret;
939 break;
940 case NODE_POINTER:
941 print_tabs(fd, depth);
942 if (node->u.pointer.const_qualifier)
943 fprintf(fd, "<const_pointer />\n");
944 else
945 fprintf(fd, "<pointer />\n");
946 break;
947 case NODE_TYPE_DECLARATOR:
948 ret = ctf_visitor_print_type_declarator(fd, depth, node);
949 if (ret)
950 return ret;
951 break;
952
953 case NODE_FLOATING_POINT:
954 print_tabs(fd, depth);
955 fprintf(fd, "<floating_point>\n");
956 cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) {
957 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
958 if (ret)
959 return ret;
960 }
961 print_tabs(fd, depth);
962 fprintf(fd, "</floating_point>\n");
963 break;
964 case NODE_INTEGER:
965 print_tabs(fd, depth);
966 fprintf(fd, "<integer>\n");
967 cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) {
968 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
969 if (ret)
970 return ret;
971 }
972 print_tabs(fd, depth);
973 fprintf(fd, "</integer>\n");
974 break;
975 case NODE_STRING:
976 print_tabs(fd, depth);
977 fprintf(fd, "<string>\n");
978 cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) {
979 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
980 if (ret)
981 return ret;
982 }
983 print_tabs(fd, depth);
984 fprintf(fd, "</string>\n");
985 break;
986 case NODE_ENUMERATOR:
987 print_tabs(fd, depth);
988 fprintf(fd, "<enumerator");
989 if (node->u.enumerator.id)
990 fprintf(fd, " id=\"%s\"", node->u.enumerator.id);
991 fprintf(fd, ">\n");
992 cds_list_for_each_entry(iter, &node->u.enumerator.values, siblings) {
993 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
994 if (ret)
995 return ret;
996 }
997 print_tabs(fd, depth);
998 fprintf(fd, "</enumerator>\n");
999 break;
1000 case NODE_ENUM:
1001 print_tabs(fd, depth);
1002 if (node->u._struct.name)
1003 fprintf(fd, "<enum name=\"%s\">\n",
1004 node->u._enum.enum_id);
1005 else
1006 fprintf(fd, "<enum >\n");
1007 depth++;
1008
1009 if (node->u._enum.container_type) {
1010 print_tabs(fd, depth);
1011 fprintf(fd, "<container_type>\n");
1012 ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type);
1013 if (ret)
1014 return ret;
1015 print_tabs(fd, depth);
1016 fprintf(fd, "</container_type>\n");
1017 }
1018
1019 print_tabs(fd, depth);
1020 fprintf(fd, "<enumerator_list>\n");
1021 cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) {
1022 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1023 if (ret)
1024 return ret;
1025 }
1026 print_tabs(fd, depth);
1027 fprintf(fd, "</enumerator_list>\n");
1028
1029 depth--;
1030 print_tabs(fd, depth);
1031 fprintf(fd, "</enum>\n");
1032 break;
1033 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1034 print_tabs(fd, depth);
1035 fprintf(fd, "<declaration_specifier>\n");
1036 cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.declaration_specifier, siblings) {
1037 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1038 if (ret)
1039 return ret;
1040 }
1041 print_tabs(fd, depth);
1042 fprintf(fd, "</declaration_specifier>\n");
1043
1044 print_tabs(fd, depth);
1045 fprintf(fd, "<type_declarators>\n");
1046 cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) {
1047 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1048 if (ret)
1049 return ret;
1050 }
1051 print_tabs(fd, depth);
1052 fprintf(fd, "</type_declarators>\n");
1053 break;
1054 case NODE_VARIANT:
1055 print_tabs(fd, depth);
1056 fprintf(fd, "<variant");
1057 if (node->u.variant.name)
1058 fprintf(fd, " name=\"%s\"", node->u.variant.name);
1059 if (node->u.variant.choice)
1060 fprintf(fd, " choice=\"%s\"", node->u.variant.choice);
1061 fprintf(fd, ">\n");
1062 cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) {
1063 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1064 if (ret)
1065 return ret;
1066 }
1067 print_tabs(fd, depth);
1068 fprintf(fd, "</variant>\n");
1069 break;
1070 case NODE_STRUCT:
1071 print_tabs(fd, depth);
1072 if (node->u._struct.name)
1073 fprintf(fd, "<struct name=\"%s\">\n",
1074 node->u._struct.name);
1075 else
1076 fprintf(fd, "<struct>\n");
1077 cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) {
1078 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1079 if (ret)
1080 return ret;
1081 }
1082 print_tabs(fd, depth);
1083 fprintf(fd, "</struct>\n");
1084 break;
1085
1086 case NODE_UNKNOWN:
1087 default:
1088 fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
1089 (int) node->type);
1090 return -EINVAL;
1091 }
1092 return ret;
1093 }
This page took 0.05255 seconds and 5 git commands to generate.