Definition scope: update
[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->scope,
519 g_quark_from_string("event.context"));
520 parent_def_scope = event->context->scope;
521 declaration_unref(event->context_decl);
522 }
523 if (event->fields_decl) {
524 event->fields =
525 event->fields_decl->definition_new(event->fields_decl,
526 parent_def_scope, 0, 0);
527 set_dynamic_definition_scope(event->fields->scope,
528 g_quark_from_string("event.fields"));
529 parent_def_scope = event->fields->scope;
530 declaration_unref(event->fields_decl);
531 }
532 return 0;
533
534 error:
535 declaration_unref(event->fields_decl);
536 declaration_unref(event->context_decl);
537 free_definition_scope(event->definition_scope);
538 free_declaration_scope(event->declaration_scope);
539 g_free(event);
540 return ret;
541 }
542
543
544 static
545 int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace)
546 {
547 int ret = 0;
548
549 switch (node->type) {
550 case NODE_TYPEDEF:
551 ret = ctf_typedef_visit(fd, depth + 1,
552 &node->u._typedef.declaration_specifier,
553 &node->u._typedef.type_declarators,
554 stream->declaration_scope);
555 if (ret)
556 return ret;
557 break;
558 case NODE_TYPEALIAS:
559 ret = ctf_typealias_visit(fd, depth + 1,
560 &node->u.typealias.target, &node->u.typealias.alias
561 stream->declaration_scope);
562 if (ret)
563 return ret;
564 break;
565 case NODE_CTF_EXPRESSION:
566 {
567 char *left;
568
569 left = concatenate_unary_strings(&node->u.ctf_expression.left);
570 if (!strcmp(left, "stream_id")) {
571 if (CTF_EVENT_FIELD_IS_SET(event, stream_id))
572 return -EPERM;
573 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
574 if (ret) {
575 fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
576 return -EINVAL;
577 }
578 CTF_EVENT_SET_FIELD(event, stream_id);
579 } else if (!strcmp(left, "event.header")) {
580 struct declaration *declaration;
581
582 declaration = ctf_declaration_specifier_visit(fd, depth,
583 &node->u.ctf_expression.right,
584 stream->declaration_scope, stream->definition_scope);
585 if (!declaration)
586 return -EPERM;
587 if (declaration->type->id != CTF_TYPE_STRUCT)
588 return -EPERM;
589 stream->event_header_decl = container_of(declaration, struct declaration_struct, p);
590 } else if (!strcmp(left, "event.context")) {
591 struct declaration *declaration;
592
593 declaration = ctf_declaration_specifier_visit(fd, depth,
594 &node->u.ctf_expression.right,
595 stream->declaration_scope);
596 if (!declaration)
597 return -EPERM;
598 if (declaration->type->id != CTF_TYPE_STRUCT)
599 return -EPERM;
600 stream->event_context_decl = container_of(declaration, struct declaration_struct, p);
601 } else if (!strcmp(left, "packet.context")) {
602 struct declaration *declaration;
603
604 declaration = ctf_declaration_specifier_visit(fd, depth,
605 &node->u.ctf_expression.right,
606 stream->declaration_scope);
607 if (!declaration)
608 return -EPERM;
609 if (declaration->type->id != CTF_TYPE_STRUCT)
610 return -EPERM;
611 stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
612 }
613 g_free(left);
614 break;
615 }
616 default:
617 return -EPERM;
618 /* TODO: declaration specifier should be added. */
619 }
620
621 return 0;
622 }
623
624 static
625 int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
626 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
627 {
628 int ret = 0;
629 struct ctf_node *iter;
630 struct ctf_stream *stream;
631 struct definition_scope *parent_def_scope;
632
633 stream = g_new0(struct ctf_stream, 1);
634 stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
635 stream->events_by_id = g_ptr_array_new();
636 stream->event_quark_to_id = g_hash_table_new(g_int_hash, g_int_equal);
637 cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
638 ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
639 if (ret)
640 goto error;
641 }
642 if (!CTF_EVENT_FIELD_IS_SET(stream, stream_id)) {
643 ret = -EPERM;
644 goto error;
645 }
646 if (trace->streams->len <= stream->stream_id)
647 g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
648 g_ptr_array_index(trace->streams, stream->stream_id) = stream;
649
650 parent_def_scope = NULL;
651 if (stream->packet_context_decl) {
652 stream->packet_context =
653 stream->packet_context_decl->definition_new(stream->packet_context_decl,
654 parent_def_scope, 0, 0);
655 set_dynamic_definition_scope(stream->packet_context->scope,
656 g_quark_from_string("stream.packet.context"));
657 parent_def_scope = stream->packet_context->scope;
658 declaration_unref(stream->packet_context_decl);
659 }
660 if (stream->event_header_decl) {
661 stream->event_header =
662 stream->event_header_decl->definition_new(stream->event_header_decl,
663 parent_def_scope, 0, 0);
664 set_dynamic_definition_scope(stream->event_header->scope,
665 g_quark_from_string("stream.event.header"));
666 parent_def_scope = stream->event_header->scope;
667 declaration_unref(stream->event_header_decl);
668 }
669 if (stream->event_context_decl) {
670 stream->event_context =
671 stream->event_context_decl->definition_new(stream->event_context_decl,
672 parent_def_scope, 0, 0);
673 set_dynamic_definition_scope(stream->event_context_scope,
674 g_quark_from_string("stream.event.context"));
675 parent_def_scope = stream->event_context->scope;
676 declaration_unref(stream->event_context_decl);
677 }
678 stream->definition_scope = parent_def_scope;
679
680 return 0;
681
682 error:
683 declaration_unref(stream->event_header);
684 declaration_unref(stream->event_context);
685 declaration_unref(stream->packet_context);
686 g_ptr_array_free(stream->events_by_id, TRUE);
687 g_hash_table_free(stream->event_quark_to_id);
688 free_definition_scope(stream->definition_scope);
689 free_declaration_scope(stream->declaration_scope);
690 g_free(stream);
691 return ret;
692 }
693
694 static
695 int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
696 {
697 int ret = 0;
698
699 switch (node->type) {
700 case NODE_TYPEDEF:
701 ret = ctf_typedef_visit(fd, depth + 1,
702 &node->u._typedef.declaration_specifier,
703 &node->u._typedef.type_declarators,
704 trace->declaration_scope);
705 if (ret)
706 return ret;
707 break;
708 case NODE_TYPEALIAS:
709 ret = ctf_typealias_visit(fd, depth + 1,
710 &node->u.typealias.target, &node->u.typealias.alias
711 trace->declaration_scope);
712 if (ret)
713 return ret;
714 break;
715 case NODE_CTF_EXPRESSION:
716 {
717 char *left;
718
719 left = concatenate_unary_strings(&node->u.ctf_expression.left);
720 if (!strcmp(left, "major")) {
721 if (CTF_EVENT_FIELD_IS_SET(trace, major))
722 return -EPERM;
723 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->major);
724 if (ret) {
725 fprintf(stderr, "[error] %s: unexpected unary expression for trace major number\n", __func__);
726 return -EINVAL;
727 }
728 CTF_EVENT_SET_FIELD(trace, major);
729 } else if (!strcmp(left, "minor")) {
730 if (CTF_EVENT_FIELD_IS_SET(trace, minor))
731 return -EPERM;
732 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->minor);
733 if (ret) {
734 fprintf(stderr, "[error] %s: unexpected unary expression for trace minor number\n", __func__);
735 return -EINVAL;
736 }
737 CTF_EVENT_SET_FIELD(trace, minor);
738 } else if (!strcmp(left, "word_size")) {
739 if (CTF_EVENT_FIELD_IS_SET(trace, word_size))
740 return -EPERM;
741 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->word_size);
742 if (ret) {
743 fprintf(stderr, "[error] %s: unexpected unary expression for trace word_size\n", __func__);
744 return -EINVAL;
745 }
746 CTF_EVENT_SET_FIELD(trace, word_size);
747 } else if (!strcmp(left, "uuid")) {
748 if (CTF_EVENT_FIELD_IS_SET(trace, uuid))
749 return -EPERM;
750 ret = get_unary_uuid(&node->u.ctf_expression.right, &trace->uuid);
751 if (ret) {
752 fprintf(stderr, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
753 return -EINVAL;
754 }
755 CTF_EVENT_SET_FIELD(trace, uuid);
756 }
757 g_free(left);
758 break;
759 }
760 default:
761 return -EPERM;
762 /* TODO: declaration specifier should be added. */
763 }
764
765 return 0;
766 }
767
768
769 static
770 int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
771 {
772 int ret = 0;
773 struct ctf_node *iter;
774
775 if (trace->declaration_scope)
776 return -EEXIST;
777 trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope);
778 trace->definition_scope = new_dynamic_definition_scope(trace->root_definition_scope);
779 trace->streams = g_ptr_array_new();
780 cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) {
781 ret = ctf_trace_declaration_visit(fd, depth + 1, iter, trace);
782 if (ret)
783 goto error;
784 }
785 if (!CTF_EVENT_FIELD_IS_SET(trace, major)) {
786 ret = -EPERM;
787 goto error;
788 }
789 if (!CTF_EVENT_FIELD_IS_SET(trace, minor)) {
790 ret = -EPERM;
791 goto error;
792 }
793 if (!CTF_EVENT_FIELD_IS_SET(trace, uuid)) {
794 ret = -EPERM;
795 goto error;
796 }
797 if (!CTF_EVENT_FIELD_IS_SET(trace, word_size)) {
798 ret = -EPERM;
799 goto error;
800 }
801 return 0;
802
803 error:
804 g_ptr_array_free(trace->streams, TRUE);
805 free_definition_scope(stream->definition_scope);
806 free_declaration_scope(stream->declaration_scope);
807 return ret;
808 }
809
810 int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
811 {
812 int ret = 0;
813 struct ctf_node *iter;
814
815 switch (node->type) {
816 case NODE_ROOT:
817 cds_list_for_each_entry(iter, &node->u.root._typedef,
818 siblings) {
819 ret = ctf_typedef_visit(fd, depth + 1,
820 &iter->u._typedef.declaration_specifier,
821 &iter->u._typedef.type_declarators,
822 trace->declaration_scope);
823 if (ret)
824 return ret;
825 }
826 cds_list_for_each_entry(iter, &node->u.root.typealias,
827 siblings) {
828 ret = ctf_typealias_visit(fd, depth + 1,
829 &iter->u.typealias.target, &iter->u.typealias.alias
830 trace->declaration_scope);
831 if (ret)
832 return ret;
833 }
834 cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) {
835 ret = ctf_declaration_specifier_visit(fd, depth, iter,
836 trace->root_declaration_scope);
837 if (ret)
838 return ret;
839 }
840 cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
841 ret = ctf_trace_visit(fd, depth + 1, iter, trace);
842 if (ret)
843 return ret;
844 }
845 cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
846 ret = ctf_stream_visit(fd, depth + 1, iter,
847 trace->root_declaration_scope, trace);
848 if (ret)
849 return ret;
850 }
851 cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
852 ret = ctf_event_visit(fd, depth + 1, iter,
853 trace->root_declaration_scope, trace);
854 if (ret)
855 return ret;
856 }
857 break;
858
859 case NODE_TYPEALIAS_TARGET:
860 print_tabs(fd, depth);
861 fprintf(fd, "<target>\n");
862 depth++;
863
864 print_tabs(fd, depth);
865 fprintf(fd, "<declaration_specifier>\n");
866 cds_list_for_each_entry(iter, &node->u.typealias_target.declaration_specifier, siblings) {
867 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
868 if (ret)
869 return ret;
870 }
871 print_tabs(fd, depth);
872 fprintf(fd, "</declaration_specifier>\n");
873
874 print_tabs(fd, depth);
875 fprintf(fd, "<type_declarators>\n");
876 cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) {
877 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
878 if (ret)
879 return ret;
880 }
881 print_tabs(fd, depth);
882 fprintf(fd, "</type_declarators>\n");
883
884 depth--;
885 print_tabs(fd, depth);
886 fprintf(fd, "</target>\n");
887 break;
888 case NODE_TYPEALIAS_ALIAS:
889 print_tabs(fd, depth);
890 fprintf(fd, "<alias>\n");
891 depth++;
892
893 print_tabs(fd, depth);
894 fprintf(fd, "<declaration_specifier>\n");
895 cds_list_for_each_entry(iter, &node->u.typealias_alias.declaration_specifier, siblings) {
896 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
897 if (ret)
898 return ret;
899 }
900 print_tabs(fd, depth);
901 fprintf(fd, "</declaration_specifier>\n");
902
903 print_tabs(fd, depth);
904 fprintf(fd, "<type_declarators>\n");
905 cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) {
906 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
907 if (ret)
908 return ret;
909 }
910 print_tabs(fd, depth);
911 fprintf(fd, "</type_declarators>\n");
912
913 depth--;
914 print_tabs(fd, depth);
915 fprintf(fd, "</alias>\n");
916 break;
917 case NODE_TYPEALIAS:
918 print_tabs(fd, depth);
919 fprintf(fd, "<typealias>\n");
920 ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.target);
921 if (ret)
922 return ret;
923 ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.alias);
924 if (ret)
925 return ret;
926 print_tabs(fd, depth);
927 fprintf(fd, "</typealias>\n");
928 break;
929
930 case NODE_TYPE_SPECIFIER:
931 ret = ctf_visitor_print_type_specifier(fd, depth, node);
932 if (ret)
933 return ret;
934 break;
935 case NODE_POINTER:
936 print_tabs(fd, depth);
937 if (node->u.pointer.const_qualifier)
938 fprintf(fd, "<const_pointer />\n");
939 else
940 fprintf(fd, "<pointer />\n");
941 break;
942 case NODE_TYPE_DECLARATOR:
943 ret = ctf_visitor_print_type_declarator(fd, depth, node);
944 if (ret)
945 return ret;
946 break;
947
948 case NODE_FLOATING_POINT:
949 print_tabs(fd, depth);
950 fprintf(fd, "<floating_point>\n");
951 cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) {
952 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
953 if (ret)
954 return ret;
955 }
956 print_tabs(fd, depth);
957 fprintf(fd, "</floating_point>\n");
958 break;
959 case NODE_INTEGER:
960 print_tabs(fd, depth);
961 fprintf(fd, "<integer>\n");
962 cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) {
963 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
964 if (ret)
965 return ret;
966 }
967 print_tabs(fd, depth);
968 fprintf(fd, "</integer>\n");
969 break;
970 case NODE_STRING:
971 print_tabs(fd, depth);
972 fprintf(fd, "<string>\n");
973 cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) {
974 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
975 if (ret)
976 return ret;
977 }
978 print_tabs(fd, depth);
979 fprintf(fd, "</string>\n");
980 break;
981 case NODE_ENUMERATOR:
982 print_tabs(fd, depth);
983 fprintf(fd, "<enumerator");
984 if (node->u.enumerator.id)
985 fprintf(fd, " id=\"%s\"", node->u.enumerator.id);
986 fprintf(fd, ">\n");
987 cds_list_for_each_entry(iter, &node->u.enumerator.values, siblings) {
988 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
989 if (ret)
990 return ret;
991 }
992 print_tabs(fd, depth);
993 fprintf(fd, "</enumerator>\n");
994 break;
995 case NODE_ENUM:
996 print_tabs(fd, depth);
997 if (node->u._struct.name)
998 fprintf(fd, "<enum name=\"%s\">\n",
999 node->u._enum.enum_id);
1000 else
1001 fprintf(fd, "<enum >\n");
1002 depth++;
1003
1004 if (node->u._enum.container_type) {
1005 print_tabs(fd, depth);
1006 fprintf(fd, "<container_type>\n");
1007 ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type);
1008 if (ret)
1009 return ret;
1010 print_tabs(fd, depth);
1011 fprintf(fd, "</container_type>\n");
1012 }
1013
1014 print_tabs(fd, depth);
1015 fprintf(fd, "<enumerator_list>\n");
1016 cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) {
1017 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1018 if (ret)
1019 return ret;
1020 }
1021 print_tabs(fd, depth);
1022 fprintf(fd, "</enumerator_list>\n");
1023
1024 depth--;
1025 print_tabs(fd, depth);
1026 fprintf(fd, "</enum>\n");
1027 break;
1028 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1029 print_tabs(fd, depth);
1030 fprintf(fd, "<declaration_specifier>\n");
1031 cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.declaration_specifier, siblings) {
1032 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1033 if (ret)
1034 return ret;
1035 }
1036 print_tabs(fd, depth);
1037 fprintf(fd, "</declaration_specifier>\n");
1038
1039 print_tabs(fd, depth);
1040 fprintf(fd, "<type_declarators>\n");
1041 cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) {
1042 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1043 if (ret)
1044 return ret;
1045 }
1046 print_tabs(fd, depth);
1047 fprintf(fd, "</type_declarators>\n");
1048 break;
1049 case NODE_VARIANT:
1050 print_tabs(fd, depth);
1051 fprintf(fd, "<variant");
1052 if (node->u.variant.name)
1053 fprintf(fd, " name=\"%s\"", node->u.variant.name);
1054 if (node->u.variant.choice)
1055 fprintf(fd, " choice=\"%s\"", node->u.variant.choice);
1056 fprintf(fd, ">\n");
1057 cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) {
1058 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1059 if (ret)
1060 return ret;
1061 }
1062 print_tabs(fd, depth);
1063 fprintf(fd, "</variant>\n");
1064 break;
1065 case NODE_STRUCT:
1066 print_tabs(fd, depth);
1067 if (node->u._struct.name)
1068 fprintf(fd, "<struct name=\"%s\">\n",
1069 node->u._struct.name);
1070 else
1071 fprintf(fd, "<struct>\n");
1072 cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) {
1073 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
1074 if (ret)
1075 return ret;
1076 }
1077 print_tabs(fd, depth);
1078 fprintf(fd, "</struct>\n");
1079 break;
1080
1081 case NODE_UNKNOWN:
1082 default:
1083 fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
1084 (int) node->type);
1085 return -EINVAL;
1086 }
1087 return ret;
1088 }
This page took 0.050898 seconds and 5 git commands to generate.