Work in progress generate io struct
[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 <endian.h>
27 #include <errno.h>
28 #include <babeltrace/list.h>
29 #include <uuid/uuid.h>
30 #include "ctf-scanner.h"
31 #include "ctf-parser.h"
32 #include "ctf-ast.h"
33
34 #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
35
36 #define _cds_list_first_entry(ptr, type, member) \
37 cds_list_entry((ptr)->next, type, member)
38
39 static
40 struct declaration *ctf_declaration_specifier_visit(FILE *fd,
41 int depth, struct cds_list_head *head,
42 struct declaration_scope *declaration_scope);
43
44 /*
45 * String returned must be freed by the caller using g_free.
46 */
47 static
48 char *concatenate_unary_strings(struct cds_list_head *head)
49 {
50 struct ctf_node *node;
51 GString *str;
52 int i = 0;
53
54 str = g_string_new();
55 cds_list_for_each_entry(node, head, siblings) {
56 char *src_string;
57
58 assert(node->type == NODE_UNARY_EXPRESSION);
59 assert(node->u.unary_expression.type == UNARY_STRING);
60 assert((node->u.unary_expression.link == UNARY_LINK_UNKNOWN)
61 ^ (i != 0))
62 switch (node->u.unary_expression.link) {
63 case UNARY_DOTLINK:
64 g_string_append(str, ".")
65 break;
66 case UNARY_ARROWLINK:
67 g_string_append(str, "->")
68 break;
69 case UNARY_DOTDOTDOT:
70 g_string_append(str, "...")
71 break;
72 }
73 src_string = u.unary_expression.u.string;
74 g_string_append(str, src_string);
75 i++;
76 }
77 return g_string_free(str, FALSE);
78 }
79
80 static
81 int get_unary_unsigned(struct cds_list_head *head, uint64_t *value)
82 {
83 struct ctf_node *node;
84 int i = 0;
85
86 cds_list_for_each_entry(node, head, siblings) {
87 assert(node->type == NODE_UNARY_EXPRESSION);
88 assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT);
89 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
90 assert(i == 0);
91 *value = node->u.unary_expression.unsigned_constant
92 i++;
93 }
94 return 0;
95 }
96
97 static
98 int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
99 {
100 struct ctf_node *node;
101 int i = 0;
102 int ret = -1;
103
104 cds_list_for_each_entry(node, head, siblings) {
105 const char *src_string;
106
107 assert(node->type == NODE_UNARY_EXPRESSION);
108 assert(node->u.unary_expression.type == UNARY_STRING);
109 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
110 assert(i == 0);
111 src_string = u.unary_expression.u.string;
112 ret = uuid_parse(u.unary_expression.u.string, *uuid);
113 }
114 return ret;
115 }
116
117 static
118 struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
119 {
120 if (trace->streams->len <= stream_id)
121 return NULL;
122 return g_ptr_array_index(trace->streams, stream_id);
123 }
124
125 static
126 void visit_declaration_specifier(struct cds_list_head *declaration_specifier, GString *str)
127 {
128 struct ctf_node *iter;
129 int alias_item_nr = 0;
130 int err;
131
132 cds_list_for_each_entry(iter, declaration_specifier, siblings) {
133 if (alias_item_nr != 0)
134 g_string_append(str, " ");
135 alias_item_nr++;
136
137 switch (iter->type) {
138 case NODE_TYPE_SPECIFIER:
139 switch (iter->u.type_specifier.type) {
140 case TYPESPEC_VOID:
141 g_string_append(str, "void");
142 break;
143 case TYPESPEC_CHAR:
144 g_string_append(str, "char");
145 break;
146 case TYPESPEC_SHORT:
147 g_string_append(str, "short");
148 break;
149 case TYPESPEC_INT:
150 g_string_append(str, "int");
151 break;
152 case TYPESPEC_LONG:
153 g_string_append(str, "long");
154 break;
155 case TYPESPEC_FLOAT:
156 g_string_append(str, "float");
157 break;
158 case TYPESPEC_DOUBLE:
159 g_string_append(str, "double");
160 break;
161 case TYPESPEC_SIGNED:
162 g_string_append(str, "signed");
163 break;
164 case TYPESPEC_UNSIGNED:
165 g_string_append(str, "unsigned");
166 break;
167 case TYPESPEC_BOOL:
168 g_string_append(str, "bool");
169 break;
170 case TYPESPEC_COMPLEX:
171 g_string_append(str, "_Complex");
172 break;
173 case TYPESPEC_IMAGINARY:
174 g_string_append(str, "_Imaginary");
175 break;
176 case TYPESPEC_CONST:
177 g_string_append(str, "const");
178 break;
179 case TYPESPEC_ID_TYPE:
180 if (iter->u.type_specifier.id_type)
181 g_string_append(str, iter->u.type_specifier.id_type);
182 break;
183 default:
184 fprintf(stderr, "[error] %s: unknown specifier\n", __func__);
185 err = -EINVAL;
186 goto error;
187 }
188 break;
189 case NODE_ENUM:
190 if (!iter->u._enum.enum_id) {
191 fprintf(stderr, "[error] %s: unexpected empty enum ID\n", __func__);
192 err = -EINVAL;
193 goto error;
194 }
195 g_string_append(str, "enum ");
196 g_string_append(str, iter->u._enum.enum_id);
197 break;
198 case NODE_VARIANT:
199 if (!iter->u.variant.name) {
200 fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__);
201 err = -EINVAL;
202 goto error;
203 }
204 g_string_append(str, "variant ");
205 g_string_append(str, iter->u.variant.name);
206 break;
207 case NODE_STRUCT:
208 if (!iter->u._struct.name) {
209 fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__);
210 err = -EINVAL;
211 goto error;
212 }
213 g_string_append(str, "struct ");
214 g_string_append(str, iter->u._struct.name);
215 break;
216 default:
217 fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
218 err = -EINVAL;
219 goto error;
220 }
221 }
222 return 0;
223 error:
224 return err;
225 }
226
227 static
228 GQuark create_typealias_identifier(int fd, int depth,
229 struct cds_list_head *declaration_specifier,
230 struct ctf_node *node_type_declarator)
231 {
232 GString *str;
233 const char *str_c;
234 GQuark alias_q;
235 int ret;
236
237 str = g_string_new();
238 ret = visit_declaration_specifier(declaration_specifier, str);
239 if (ret) {
240 g_string_free(str, TRUE);
241 return 0;
242 }
243 cds_list_for_each_entry(iter, &node_type_declarator->u.type_declarator.pointers, siblings) {
244 g_string_append(str, " *");
245 if (iter->u.pointer.const_qualifier)
246 g_string_append(str, " const");
247 }
248 str_c = g_string_free(str, FALSE);
249 alias_q = g_quark_from_string(str_c);
250 g_free(str_c);
251 return alias_q;
252 }
253
254 static
255 struct declaration *ctf_type_declarator_visit(int fd, int depth,
256 struct cds_list_head *declaration_specifier,
257 GQuark *field_name,
258 struct ctf_node *node_type_declarator,
259 struct declaration_scope *declaration_scope,
260 struct declaration *nested_declaration)
261 {
262 /*
263 * Visit type declarator by first taking care of sequence/array
264 * (recursively). Then, when we get to the identifier, take care
265 * of pointers.
266 */
267
268 assert(node_type_declarator->u.type_declarator.type != TYPEDEC_UNKNOWN);
269
270 /* TODO: gcc bitfields not supported yet. */
271 if (node_type_declarator->u.type_declarator.bitfield_len != NULL) {
272 fprintf(stderr, "[error] %s: gcc bitfields are not supported yet.\n", __func__);
273 return NULL;
274 }
275
276 if (!nested_declaration) {
277 if (!cds_list_empty(&node_type_declarator->u.type_declarator.pointers)) {
278 GQuark alias_q;
279
280 /*
281 * If we have a pointer declarator, it _has_ to be present in
282 * the typealiases (else fail).
283 */
284 alias_q = create_typealias_identifier(fd, depth,
285 declaration_specifier, node_type_declarator);
286 nested_declaration = lookup_declaration(alias_q, declaration_scope);
287 if (!nested_declaration) {
288 fprintf(stderr, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q));
289 return NULL;
290 }
291 } else {
292 nested_declaration = /* parse declaration_specifier */;
293 }
294 }
295
296 if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) {
297 if (node_type_declarator->u.type_declarator.u.id)
298 *field_name = g_quark_from_string(node_type_declarator->u.type_declarator.u.id);
299 else
300 *field_name = 0;
301 return nested_declaration;
302 } else {
303 struct declaration *declaration;
304 struct node *length;
305
306 /* TYPEDEC_NESTED */
307
308 /* create array/sequence, pass nested_declaration as child. */
309 length = node_type_declarator->u.type_declarator.u.nested.length;
310 if (length) {
311 switch (length->type) {
312 case NODE_UNARY_EXPRESSION:
313 /* Array */
314 /* TODO */
315 .............
316 declaration = /* create array */;
317 break;
318 case NODE_TYPE_SPECIFIER:
319 /* Sequence */
320 declaration = /* create sequence */;
321 break;
322 default:
323 assert(0);
324 }
325 }
326
327 /* Pass it as content of outer container */
328 declaration = ctf_type_declarator_visit(fd, depth,
329 declaration_specifier, field_name,
330 node_type_declarator->u.type_declarator.u.nested.type_declarator,
331 declaration_scope, declaration);
332 return declaration;
333 }
334 }
335
336 static
337 int ctf_struct_type_declarators_visit(int fd, int depth,
338 struct declaration_struct *struct_declaration,
339 struct cds_list_head *declaration_specifier,
340 struct cds_list_head *type_declarators,
341 struct declaration_scope *declaration_scope)
342 {
343 struct ctf_node *iter;
344 GQuark field_name;
345
346 cds_list_for_each_entry(iter, type_declarators, siblings) {
347 struct declaration *field_declaration;
348
349 field_declaration = ctf_type_declarator_visit(fd, depth,
350 declaration_specifier,
351 &field_name, iter,
352 struct_declaration->scope,
353 NULL);
354 struct_declaration_add_field(struct_declaration,
355 g_quark_to_string(field_name),
356 field_declaration);
357 }
358 return 0;
359 }
360
361 static
362 int ctf_variant_type_declarators_visit(int fd, int depth,
363 struct declaration_variant *variant_declaration,
364 struct cds_list_head *declaration_specifier,
365 struct cds_list_head *type_declarators,
366 struct declaration_scope *declaration_scope)
367 {
368 struct ctf_node *iter;
369 GQuark field_name;
370
371 cds_list_for_each_entry(iter, type_declarators, siblings) {
372 struct declaration *field_declaration;
373
374 field_declaration = ctf_type_declarator_visit(fd, depth,
375 declaration_specifier,
376 &field_name, iter,
377 variant_declaration->scope,
378 NULL);
379 variant_declaration_add_field(variant_declaration,
380 g_quark_to_string(field_name),
381 field_declaration);
382 }
383 return 0;
384 }
385
386 static
387 int ctf_typedef_visit(int fd, int depth, struct declaration_scope *scope,
388 struct cds_list_head *declaration_specifier,
389 struct cds_list_head *type_declarators)
390 {
391 struct ctf_node *iter;
392 GQuark identifier;
393
394 cds_list_for_each_entry(iter, type_declarators, siblings) {
395 struct declaration *type_declaration;
396 int ret;
397
398 type_declaration = ctf_type_declarator_visit(fd, depth,
399 declaration_specifier,
400 &identifier, iter,
401 scope, NULL);
402 ret = register_declaration(identifier, type_declaration, scope);
403 if (ret) {
404 type_declaration->declaration_free(type_declaration);
405 return ret;
406 }
407 }
408 return 0;
409 }
410
411 static
412 int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope,
413 struct ctf_node *target, struct ctf_node *alias)
414 {
415 struct declaration *type_declaration;
416 struct ctf_node *iter, *node;
417 GQuark dummy_id;
418 GQuark alias_q;
419
420 /* See ctf_visitor_type_declarator() in the semantic validator. */
421
422 /*
423 * Create target type declaration.
424 */
425
426 type_declaration = ctf_type_declarator_visit(fd, depth,
427 &target->u.typealias_target.declaration_specifier,
428 &dummy_id, &target->u.typealias_target.type_declarators,
429 scope, NULL);
430 if (!type_declaration) {
431 fprintf(stderr, "[error] %s: problem creating type declaration\n", __func__);
432 err = -EINVAL;
433 goto error;
434 }
435 /*
436 * The semantic validator does not check whether the target is
437 * abstract or not (if it has an identifier). Check it here.
438 */
439 if (dummy_id != 0) {
440 fprintf(stderr, "[error] %s: expecting empty identifier\n", __func__);
441 err = -EINVAL;
442 goto error;
443 }
444 /*
445 * Create alias identifier.
446 */
447
448 node = _cds_list_first_entry(&alias->u.typealias_alias.type_declarators,
449 struct node, siblings);
450 alias_q = create_typealias_identifier(fd, depth,
451 &alias->u.typealias_alias.declaration_specifier, node);
452 ret = register_declaration(alias_q, type_declaration, scope);
453 if (ret)
454 goto error;
455 return 0;
456
457 error:
458 type_declaration->declaration_free(type_declaration);
459 return ret;
460 }
461
462 static
463 int ctf_struct_declaration_list_visit(int fd, int depth,
464 struct ctf_node *iter, struct declaration_struct *struct_declaration)
465 {
466 struct declaration *declaration;
467 int ret;
468
469 switch (iter->type) {
470 case NODE_TYPEDEF:
471 /* For each declarator, declare type and add type to struct declaration scope */
472 ret = ctf_typedef_visit(fd, depth,
473 struct_declaration->scope,
474 &iter->u._typedef.declaration_specifier,
475 &iter->u._typedef.type_declarators);
476 if (ret)
477 return ret;
478 break;
479 case NODE_TYPEALIAS:
480 /* Declare type with declarator and add type to struct declaration scope */
481 ret = ctf_typealias_visit(fd, depth,
482 struct_declaration->scope,
483 iter->u.typealias.target,
484 iter->u.typealias.alias);
485 if (ret)
486 return ret;
487 break;
488 case NODE_STRUCT_OR_VARIANT_DECLARATION:
489 /* Add field to structure declaration */
490 ret = ctf_struct_type_declarators_visit(fd, depth,
491 struct_declaration,
492 &iter->u.struct_or_variant_declaration.declaration_specifier,
493 &iter->u.struct_or_variant_declaration.type_declarators);
494 if (ret)
495 return ret;
496 break;
497 default:
498 fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
499 assert(0);
500 }
501 return 0;
502 }
503
504 static
505 int ctf_variant_declaration_list_visit(int fd, int depth,
506 struct ctf_node *iter, struct declaration_variant *variant_declaration)
507 {
508 struct declaration *declaration;
509 int ret;
510
511 switch (iter->type) {
512 case NODE_TYPEDEF:
513 /* For each declarator, declare type and add type to variant declaration scope */
514 ret = ctf_typedef_visit(fd, depth,
515 variant_declaration->scope,
516 &iter->u._typedef.declaration_specifier,
517 &iter->u._typedef.type_declarators);
518 if (ret)
519 return ret;
520 break;
521 case NODE_TYPEALIAS:
522 /* Declare type with declarator and add type to variant declaration scope */
523 ret = ctf_typealias_visit(fd, depth,
524 variant_declaration->scope,
525 iter->u.typealias.target,
526 iter->u.typealias.alias);
527 if (ret)
528 return ret;
529 break;
530 case NODE_STRUCT_OR_VARIANT_DECLARATION:
531 /* Add field to structure declaration */
532 ret = ctf_variant_type_declarators_visit(fd, depth,
533 variant_declaration,
534 &iter->u.struct_or_variant_declaration.declaration_specifier,
535 &iter->u.struct_or_variant_declaration.type_declarators);
536 if (ret)
537 return ret;
538 break;
539 default:
540 fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
541 assert(0);
542 }
543 return 0;
544 }
545
546 static
547 struct declaration_struct *ctf_declaration_struct_visit(FILE *fd,
548 int depth, const char *name, struct cds_list_head *declaration_list,
549 int has_body, struct declaration_scope *declaration_scope)
550 {
551 struct declaration *declaration;
552 struct declaration_struct *struct_declaration;
553 struct ctf_node *iter;
554
555 /*
556 * For named struct (without body), lookup in
557 * declaration scope. Don't take reference on struct
558 * declaration: ref is only taken upon definition.
559 */
560 if (!has_body) {
561 assert(name);
562 struct_declaration =
563 lookup_struct_declaration(g_quark_from_string(name),
564 declaration_scope);
565 return struct_declaration;
566 } else {
567 /* For unnamed struct, create type */
568 /* For named struct (with body), create type and add to declaration scope */
569 if (name) {
570 if (lookup_struct_declaration(g_quark_from_string(name),
571 declaration_scope)) {
572
573 fprintf(stderr, "[error] %s: struct %s already declared in scope\n", __func__, name);
574 return NULL;
575 }
576 }
577 struct_declaration = struct_declaration_new(name, declaration_scope);
578 cds_list_for_each_entry(iter, declaration_list, siblings) {
579 ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter, struct_declaration);
580 if (ret)
581 goto error;
582 }
583 if (name) {
584 ret = register_struct_declaration(g_quark_from_string(name),
585 struct_declaration,
586 declaration_scope);
587 assert(!ret);
588 }
589 return struct_declaration;
590 }
591 error:
592 struct_declaration->p.declaration_free(&struct_declaration->p);
593 return NULL;
594 }
595
596 static
597 struct declaration_variant *ctf_declaration_variant_visit(FILE *fd,
598 int depth, const char *name, struct cds_list_head *declaration_list,
599 int has_body, struct declaration_scope *declaration_scope)
600 {
601 struct declaration *declaration;
602 struct declaration_variant *variant_declaration;
603 struct ctf_node *iter;
604
605 /*
606 * For named variant (without body), lookup in
607 * declaration scope. Don't take reference on variant
608 * declaration: ref is only taken upon definition.
609 */
610 if (!has_body) {
611 assert(name);
612 variant_declaration =
613 lookup_variant_declaration(g_quark_from_string(name),
614 declaration_scope);
615 return variant_declaration;
616 } else {
617 /* For unnamed variant, create type */
618 /* For named variant (with body), create type and add to declaration scope */
619 if (name) {
620 if (lookup_variant_declaration(g_quark_from_string(name),
621 declaration_scope)) {
622
623 fprintf(stderr, "[error] %s: variant %s already declared in scope\n", __func__, name);
624 return NULL;
625 }
626 }
627 variant_declaration = variant_declaration_new(name, declaration_scope);
628 cds_list_for_each_entry(iter, declaration_list, siblings) {
629 ret = ctf_variant_declaration_list_visit(fd, depth + 1, iter, variant_declaration);
630 if (ret)
631 goto error;
632 }
633 if (name) {
634 ret = register_variant_declaration(g_quark_from_string(name),
635 variant_declaration,
636 declaration_scope);
637 assert(!ret);
638 }
639 return variant_declaration;
640 }
641 error:
642 variant_declaration->p.declaration_free(&variant_declaration->p);
643 return NULL;
644 }
645
646 static
647 int ctf_enumerator_list_visit(int fd, int depth,
648 struct ctf_node *enumerator,
649 struct declaration_enum *enum_declaration)
650 {
651 /* TODO */
652 ........
653 return 0;
654 }
655
656 static
657 struct declaration *ctf_declaration_enum_visit(int fd, int depth,
658 const char *name,
659 struct ctf_node *container_type,
660 struct cds_list_head *enumerator_list,
661 int has_body)
662 {
663 struct declaration *declaration;
664 struct declaration_enum *enum_declaration;
665 struct declaration_integer *integer_declaration;
666 struct ctf_node *iter;
667
668 /*
669 * For named enum (without body), lookup in
670 * declaration scope. Don't take reference on enum
671 * declaration: ref is only taken upon definition.
672 */
673 if (!has_body) {
674 assert(name);
675 enum_declaration =
676 lookup_enum_declaration(g_quark_from_string(name),
677 declaration_scope);
678 return enum_declaration;
679 } else {
680 /* For unnamed enum, create type */
681 /* For named enum (with body), create type and add to declaration scope */
682 if (name) {
683 if (lookup_enum_declaration(g_quark_from_string(name),
684 declaration_scope)) {
685
686 fprintf(stderr, "[error] %s: enum %s already declared in scope\n", __func__, name);
687 return NULL;
688 }
689 }
690
691 /* TODO CHECK Enumerations need to have their size/type specifier (< >). */
692 integer_declaration = integer_declaration_new(); /* TODO ... */
693 .....
694 enum_declaration = enum_declaration_new(name, integer_declaration);
695 declaration_unref(&integer_declaration->p); /* leave ref to enum */
696 cds_list_for_each_entry(iter, enumerator_list, siblings) {
697 ret = ctf_enumerator_list_visit(fd, depth + 1, iter, enum_declaration);
698 if (ret)
699 goto error;
700 }
701 if (name) {
702 ret = register_enum_declaration(g_quark_from_string(name),
703 enum_declaration,
704 declaration_scope);
705 assert(!ret);
706 }
707 return enum_declaration;
708 }
709 error:
710 enum_declaration->p.declaration_free(&enum_declaration->p);
711 return NULL;
712 }
713
714 static
715 struct declaration *ctf_declaration_type_specifier_visit(int fd, int depth,
716 struct cds_list_head *declaration_specifier,
717 struct declaration_scope *declaration_scope)
718 {
719 GString *str;
720 struct declaration *declaration;
721 const char *str_c;
722
723 str = g_string_new();
724 ret = visit_declaration_specifier(declaration_specifier, str);
725 if (ret)
726 return NULL;
727 str_c = g_string_free(str, FALSE);
728 id_q = g_quark_from_string(str_c);
729 g_free(str_c);
730 declaration = lookup_declaration(id_q, declaration_scope);
731 return declaration;
732 }
733
734 static
735 struct declaration *ctf_declaration_integer_visit(int fd, int depth,
736 struct cds_list_head *expressions)
737 {
738 struct node *expression;
739 uint64_t alignment, size, byte_order = trace->native_bo, signedness = 0;
740 int has_alignment = 0, has_size = 0;
741 struct declaration_integer *integer_declaration;
742
743 cds_list_for_each_entry(expression, expressions, siblings) {
744 struct node *left, *right;
745
746 left = expression->u.ctf_expression.left;
747 right = expression->u.ctf_expression.right;
748 assert(left->u.unary_expression.type == UNARY_STRING);
749 if (!strcmp(left->u.unary_expression.u.string, "signed")) {
750 /* TODO */
751 ...........
752 } else if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
753
754 } else if (!strcmp(left->u.unary_expression.u.string, "size")) {
755 has_size = 1;
756 } else if (!strcmp(left->u.unary_expression.u.string, "align")) {
757 has_alignment = 1;
758 } else {
759 fprintf(stderr, "[error] %s: unknown attribute name %s\n",
760 __func__, left->u.unary_expression.u.string);
761 return NULL;
762 }
763 }
764 if (!has_alignment) {
765 fprintf(stderr, "[error] %s: missing alignment attribute\n", __func__);
766 return NULL;
767 }
768 if (!has_size) {
769 fprintf(stderr, "[error] %s: missing size attribute\n", __func__);
770 return NULL;
771 }
772 integer_declaration = integer_declaration_new(size,
773 byte_order, signedness, alignment);
774 return &integer_declaration->p;
775 }
776
777 /*
778 * Also add named variant, struct or enum to the current declaration scope.
779 */
780 static
781 struct declaration *ctf_declaration_specifier_visit(FILE *fd,
782 int depth, struct cds_list_head *head,
783 struct declaration_scope *declaration_scope)
784 {
785 struct declaration *declaration;
786 struct node *first;
787
788 first = _cds_list_first_entry(head, struct node, siblings);
789
790 switch (first->type) {
791 case NODE_STRUCT:
792 return ctf_declaration_struct_visit(fd, depth,
793 first->u._struct.name,
794 &first->u._struct.declaration_list,
795 first->u._struct.has_body,
796 declaration_scope);
797 case NODE_VARIANT:
798 return ctf_declaration_variant_visit(fd, depth,
799 first->u.variant.name,
800 &first->u.variant.declaration_list,
801 first->u.variant.has_body,
802 declaration_scope);
803 case NODE_ENUM:
804 return ctf_declaration_enum_visit(fd, depth,
805 first->u._enum.enum_id,
806 first->u._enum.container_type,
807 &first->u._enum.enumerator_list,
808 first->u._enum.has_body);
809 case NODE_INTEGER:
810 return ctf_declaration_integer_visit(fd, depth,
811 &first->u.integer.expressions);
812 case NODE_FLOATING_POINT: /* TODO */
813 return ctf_declaration_floating_point_visit(fd, depth,
814 &first->u.floating_point.expressions);
815 case NODE_STRING: /* TODO */
816 return ctf_declaration_string_visit(fd, depth,
817 &first->u.string.expressions);
818 case NODE_TYPE_SPECIFIER:
819 return ctf_declaration_type_specifier_visit(fd, depth,
820 head, declaration_scope);
821 }
822 }
823
824 static
825 int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_event *event, struct ctf_trace *trace)
826 {
827 int ret = 0;
828
829 switch (node->type) {
830 case NODE_TYPEDEF:
831 ret = ctf_typedef_visit(fd, depth + 1,
832 &node->u._typedef.declaration_specifier,
833 &node->u._typedef.type_declarators,
834 event->declaration_scope);
835 if (ret)
836 return ret;
837 break;
838 case NODE_TYPEALIAS:
839 ret = ctf_typealias_visit(fd, depth + 1,
840 &node->u.typealias.target, &node->u.typealias.alias
841 event->declaration_scope);
842 if (ret)
843 return ret;
844 break;
845 case NODE_CTF_EXPRESSION:
846 {
847 char *left;
848
849 left = concatenate_unary_strings(&node->u.ctf_expression.left);
850 if (!strcmp(left, "name")) {
851 char *right;
852
853 if (CTF_EVENT_FIELD_IS_SET(event, name))
854 return -EPERM;
855 right = concatenate_unary_strings(&node->u.ctf_expression.right);
856 if (!right) {
857 fprintf(stderr, "[error] %s: unexpected unary expression for event name\n", __func__);
858 return -EINVAL;
859 }
860 event->name = g_quark_from_string(right);
861 g_free(right);
862 CTF_EVENT_SET_FIELD(event, name);
863 } else if (!strcmp(left, "id")) {
864 if (CTF_EVENT_FIELD_IS_SET(event, id))
865 return -EPERM;
866 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->id);
867 if (ret) {
868 fprintf(stderr, "[error] %s: unexpected unary expression for event id\n", __func__);
869 return -EINVAL;
870 }
871 CTF_EVENT_SET_FIELD(event, id);
872 } else if (!strcmp(left, "stream_id")) {
873 if (CTF_EVENT_FIELD_IS_SET(event, stream_id))
874 return -EPERM;
875 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
876 if (ret) {
877 fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
878 return -EINVAL;
879 }
880 event->stream = trace_stream_lookup(trace, event->stream_id);
881 if (!event->stream) {
882 fprintf(stderr, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id);
883 return -EINVAL;
884 }
885 CTF_EVENT_SET_FIELD(event, stream_id);
886 } else if (!strcmp(left, "context")) {
887 struct declaration *declaration;
888
889 if (!event->definition_scope)
890 return -EPERM;
891 declaration = ctf_declaration_specifier_visit(fd, depth,
892 &node->u.ctf_expression.right,
893 event->declaration_scope);
894 if (!declaration)
895 return -EPERM;
896 if (declaration->type->id != CTF_TYPE_STRUCT)
897 return -EPERM;
898 event->context_decl = container_of(declaration, struct declaration_struct, p);
899 } else if (!strcmp(left, "fields")) {
900 struct declaration *declaration;
901
902 if (!event->definition_scope)
903 return -EPERM;
904 declaration = ctf_declaration_specifier_visit(fd, depth,
905 &node->u.ctf_expression.right,
906 event->declaration_scope);
907 if (!declaration)
908 return -EPERM;
909 if (declaration->type->id != CTF_TYPE_STRUCT)
910 return -EPERM;
911 event->fields_decl = container_of(declaration, struct declaration_struct, p);
912 }
913 g_free(left);
914 break;
915 }
916 default:
917 return -EPERM;
918 /* TODO: declaration specifier should be added. */
919 }
920
921 return 0;
922 }
923
924 static
925 int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
926 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
927 {
928 int ret = 0;
929 struct ctf_node *iter;
930 struct ctf_event *event;
931 struct definition_scope *parent_def_scope;
932
933 event = g_new0(struct ctf_event, 1);
934 event->declaration_scope = new_declaration_scope(parent_declaration_scope);
935 cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) {
936 ret = ctf_event_declaration_visit(fd, depth + 1, iter, event, trace);
937 if (ret)
938 goto error;
939 }
940 if (!CTF_EVENT_FIELD_IS_SET(event, name)) {
941 ret = -EPERM;
942 goto error;
943 }
944 if (!CTF_EVENT_FIELD_IS_SET(event, id)) {
945 ret = -EPERM;
946 goto error;
947 }
948 if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
949 ret = -EPERM;
950 goto error;
951 }
952 if (event->stream->events_by_id->len <= event->id)
953 g_ptr_array_set_size(event->stream->events_by_id, event->id + 1);
954 g_ptr_array_index(event->stream->events_by_id, event->id) = event;
955 g_hash_table_insert(event->stream->event_quark_to_id,
956 (gpointer)(unsigned long) event->name,
957 &event->id);
958 parent_def_scope = stream->definition_scope;
959 if (event->context_decl) {
960 event->context =
961 event->context_decl->definition_new(event->context_decl,
962 parent_def_scope, 0, 0);
963 set_dynamic_definition_scope(&event->context->p,
964 event->context->scope,
965 "event.context");
966 parent_def_scope = event->context->scope;
967 declaration_unref(event->context_decl);
968 }
969 if (event->fields_decl) {
970 event->fields =
971 event->fields_decl->definition_new(event->fields_decl,
972 parent_def_scope, 0, 0);
973 set_dynamic_definition_scope(&event->fields->p,
974 event->fields->scope,
975 "event.fields");
976 parent_def_scope = event->fields->scope;
977 declaration_unref(event->fields_decl);
978 }
979 return 0;
980
981 error:
982 declaration_unref(event->fields_decl);
983 declaration_unref(event->context_decl);
984 free_definition_scope(event->definition_scope);
985 free_declaration_scope(event->declaration_scope);
986 g_free(event);
987 return ret;
988 }
989
990
991 static
992 int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace)
993 {
994 int ret = 0;
995
996 switch (node->type) {
997 case NODE_TYPEDEF:
998 ret = ctf_typedef_visit(fd, depth + 1,
999 &node->u._typedef.declaration_specifier,
1000 &node->u._typedef.type_declarators,
1001 stream->declaration_scope);
1002 if (ret)
1003 return ret;
1004 break;
1005 case NODE_TYPEALIAS:
1006 ret = ctf_typealias_visit(fd, depth + 1,
1007 &node->u.typealias.target, &node->u.typealias.alias
1008 stream->declaration_scope);
1009 if (ret)
1010 return ret;
1011 break;
1012 case NODE_CTF_EXPRESSION:
1013 {
1014 char *left;
1015
1016 left = concatenate_unary_strings(&node->u.ctf_expression.left);
1017 if (!strcmp(left, "stream_id")) {
1018 if (CTF_EVENT_FIELD_IS_SET(event, stream_id))
1019 return -EPERM;
1020 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
1021 if (ret) {
1022 fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
1023 return -EINVAL;
1024 }
1025 CTF_EVENT_SET_FIELD(event, stream_id);
1026 } else if (!strcmp(left, "event.header")) {
1027 struct declaration *declaration;
1028
1029 declaration = ctf_declaration_specifier_visit(fd, depth,
1030 &node->u.ctf_expression.right,
1031 stream->declaration_scope, stream->definition_scope);
1032 if (!declaration)
1033 return -EPERM;
1034 if (declaration->type->id != CTF_TYPE_STRUCT)
1035 return -EPERM;
1036 stream->event_header_decl = container_of(declaration, struct declaration_struct, p);
1037 } else if (!strcmp(left, "event.context")) {
1038 struct declaration *declaration;
1039
1040 declaration = ctf_declaration_specifier_visit(fd, depth,
1041 &node->u.ctf_expression.right,
1042 stream->declaration_scope);
1043 if (!declaration)
1044 return -EPERM;
1045 if (declaration->type->id != CTF_TYPE_STRUCT)
1046 return -EPERM;
1047 stream->event_context_decl = container_of(declaration, struct declaration_struct, p);
1048 } else if (!strcmp(left, "packet.context")) {
1049 struct declaration *declaration;
1050
1051 declaration = ctf_declaration_specifier_visit(fd, depth,
1052 &node->u.ctf_expression.right,
1053 stream->declaration_scope);
1054 if (!declaration)
1055 return -EPERM;
1056 if (declaration->type->id != CTF_TYPE_STRUCT)
1057 return -EPERM;
1058 stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
1059 }
1060 g_free(left);
1061 break;
1062 }
1063 default:
1064 return -EPERM;
1065 /* TODO: declaration specifier should be added. */
1066 }
1067
1068 return 0;
1069 }
1070
1071 static
1072 int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
1073 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
1074 {
1075 int ret = 0;
1076 struct ctf_node *iter;
1077 struct ctf_stream *stream;
1078 struct definition_scope *parent_def_scope;
1079
1080 stream = g_new0(struct ctf_stream, 1);
1081 stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
1082 stream->events_by_id = g_ptr_array_new();
1083 stream->event_quark_to_id = g_hash_table_new(g_int_hash, g_int_equal);
1084 cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
1085 ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
1086 if (ret)
1087 goto error;
1088 }
1089 if (!CTF_EVENT_FIELD_IS_SET(stream, stream_id)) {
1090 ret = -EPERM;
1091 goto error;
1092 }
1093 if (trace->streams->len <= stream->stream_id)
1094 g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
1095 g_ptr_array_index(trace->streams, stream->stream_id) = stream;
1096
1097 parent_def_scope = NULL;
1098 if (stream->packet_context_decl) {
1099 stream->packet_context =
1100 stream->packet_context_decl->definition_new(stream->packet_context_decl,
1101 parent_def_scope, 0, 0);
1102 set_dynamic_definition_scope(&stream->packet_context->p,
1103 stream->packet_context->scope,
1104 "stream.packet.context");
1105 parent_def_scope = stream->packet_context->scope;
1106 declaration_unref(stream->packet_context_decl);
1107 }
1108 if (stream->event_header_decl) {
1109 stream->event_header =
1110 stream->event_header_decl->definition_new(stream->event_header_decl,
1111 parent_def_scope, 0, 0);
1112 set_dynamic_definition_scope(&stream->event_header->p,
1113 stream->event_header->scope,
1114 "stream.event.header");
1115 parent_def_scope = stream->event_header->scope;
1116 declaration_unref(stream->event_header_decl);
1117 }
1118 if (stream->event_context_decl) {
1119 stream->event_context =
1120 stream->event_context_decl->definition_new(stream->event_context_decl,
1121 parent_def_scope, 0, 0);
1122 set_dynamic_definition_scope(&stream->event_context->p,
1123 stream->event_context->scope,
1124 "stream.event.context");
1125 parent_def_scope = stream->event_context->scope;
1126 declaration_unref(stream->event_context_decl);
1127 }
1128 stream->definition_scope = parent_def_scope;
1129
1130 return 0;
1131
1132 error:
1133 declaration_unref(stream->event_header);
1134 declaration_unref(stream->event_context);
1135 declaration_unref(stream->packet_context);
1136 g_ptr_array_free(stream->events_by_id, TRUE);
1137 g_hash_table_free(stream->event_quark_to_id);
1138 free_definition_scope(stream->definition_scope);
1139 free_declaration_scope(stream->declaration_scope);
1140 g_free(stream);
1141 return ret;
1142 }
1143
1144 static
1145 int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
1146 {
1147 int ret = 0;
1148
1149 switch (node->type) {
1150 case NODE_TYPEDEF:
1151 ret = ctf_typedef_visit(fd, depth + 1,
1152 &node->u._typedef.declaration_specifier,
1153 &node->u._typedef.type_declarators,
1154 trace->declaration_scope);
1155 if (ret)
1156 return ret;
1157 break;
1158 case NODE_TYPEALIAS:
1159 ret = ctf_typealias_visit(fd, depth + 1,
1160 &node->u.typealias.target, &node->u.typealias.alias
1161 trace->declaration_scope);
1162 if (ret)
1163 return ret;
1164 break;
1165 case NODE_CTF_EXPRESSION:
1166 {
1167 char *left;
1168
1169 left = concatenate_unary_strings(&node->u.ctf_expression.left);
1170 if (!strcmp(left, "major")) {
1171 if (CTF_EVENT_FIELD_IS_SET(trace, major))
1172 return -EPERM;
1173 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->major);
1174 if (ret) {
1175 fprintf(stderr, "[error] %s: unexpected unary expression for trace major number\n", __func__);
1176 return -EINVAL;
1177 }
1178 CTF_EVENT_SET_FIELD(trace, major);
1179 } else if (!strcmp(left, "minor")) {
1180 if (CTF_EVENT_FIELD_IS_SET(trace, minor))
1181 return -EPERM;
1182 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->minor);
1183 if (ret) {
1184 fprintf(stderr, "[error] %s: unexpected unary expression for trace minor number\n", __func__);
1185 return -EINVAL;
1186 }
1187 CTF_EVENT_SET_FIELD(trace, minor);
1188 } else if (!strcmp(left, "word_size")) {
1189 if (CTF_EVENT_FIELD_IS_SET(trace, word_size))
1190 return -EPERM;
1191 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->word_size);
1192 if (ret) {
1193 fprintf(stderr, "[error] %s: unexpected unary expression for trace word_size\n", __func__);
1194 return -EINVAL;
1195 }
1196 CTF_EVENT_SET_FIELD(trace, word_size);
1197 } else if (!strcmp(left, "uuid")) {
1198 if (CTF_EVENT_FIELD_IS_SET(trace, uuid))
1199 return -EPERM;
1200 ret = get_unary_uuid(&node->u.ctf_expression.right, &trace->uuid);
1201 if (ret) {
1202 fprintf(stderr, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
1203 return -EINVAL;
1204 }
1205 CTF_EVENT_SET_FIELD(trace, uuid);
1206 }
1207 g_free(left);
1208 break;
1209 }
1210 default:
1211 return -EPERM;
1212 /* TODO: declaration specifier should be added. */
1213 }
1214
1215 return 0;
1216 }
1217
1218 static
1219 int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
1220 {
1221 int ret = 0;
1222 struct ctf_node *iter;
1223
1224 if (trace->declaration_scope)
1225 return -EEXIST;
1226 trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope);
1227 trace->definition_scope = new_dynamic_definition_scope(trace->root_definition_scope);
1228 trace->streams = g_ptr_array_new();
1229 cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) {
1230 ret = ctf_trace_declaration_visit(fd, depth + 1, iter, trace);
1231 if (ret)
1232 goto error;
1233 }
1234 if (!CTF_EVENT_FIELD_IS_SET(trace, major)) {
1235 ret = -EPERM;
1236 goto error;
1237 }
1238 if (!CTF_EVENT_FIELD_IS_SET(trace, minor)) {
1239 ret = -EPERM;
1240 goto error;
1241 }
1242 if (!CTF_EVENT_FIELD_IS_SET(trace, uuid)) {
1243 ret = -EPERM;
1244 goto error;
1245 }
1246 if (!CTF_EVENT_FIELD_IS_SET(trace, word_size)) {
1247 ret = -EPERM;
1248 goto error;
1249 }
1250 return 0;
1251
1252 error:
1253 g_ptr_array_free(trace->streams, TRUE);
1254 free_definition_scope(stream->definition_scope);
1255 free_declaration_scope(stream->declaration_scope);
1256 return ret;
1257 }
1258
1259 int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
1260 {
1261 int ret = 0;
1262 struct ctf_node *iter;
1263
1264 switch (node->type) {
1265 case NODE_ROOT:
1266 cds_list_for_each_entry(iter, &node->u.root._typedef,
1267 siblings) {
1268 ret = ctf_typedef_visit(fd, depth + 1,
1269 &iter->u._typedef.declaration_specifier,
1270 &iter->u._typedef.type_declarators,
1271 trace->root_declaration_scope);
1272 if (ret)
1273 return ret;
1274 }
1275 cds_list_for_each_entry(iter, &node->u.root.typealias,
1276 siblings) {
1277 ret = ctf_typealias_visit(fd, depth + 1,
1278 &iter->u.typealias.target, &iter->u.typealias.alias
1279 trace->root_declaration_scope);
1280 if (ret)
1281 return ret;
1282 }
1283 cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) {
1284 ret = ctf_declaration_specifier_visit(fd, depth, iter,
1285 trace->root_declaration_scope);
1286 if (ret)
1287 return ret;
1288 }
1289 cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
1290 ret = ctf_trace_visit(fd, depth + 1, iter, trace);
1291 if (ret)
1292 return ret;
1293 }
1294 cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
1295 ret = ctf_stream_visit(fd, depth + 1, iter,
1296 trace->root_declaration_scope, trace);
1297 if (ret)
1298 return ret;
1299 }
1300 cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
1301 ret = ctf_event_visit(fd, depth + 1, iter,
1302 trace->root_declaration_scope, trace);
1303 if (ret)
1304 return ret;
1305 }
1306 break;
1307 case NODE_UNKNOWN:
1308 default:
1309 fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
1310 (int) node->type);
1311 return -EINVAL;
1312 }
1313 return ret;
1314 }
This page took 0.099668 seconds and 4 git commands to generate.