Show env. in verbose mode
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
... / ...
CommitLineData
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/babeltrace-internal.h>
29#include <babeltrace/list.h>
30#include <babeltrace/types.h>
31#include <babeltrace/ctf/metadata.h>
32#include <uuid/uuid.h>
33#include "ctf-scanner.h"
34#include "ctf-parser.h"
35#include "ctf-ast.h"
36
37#define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
38
39#define _cds_list_first_entry(ptr, type, member) \
40 cds_list_entry((ptr)->next, type, member)
41
42static
43struct declaration *ctf_type_specifier_list_visit(FILE *fd,
44 int depth, struct ctf_node *type_specifier_list,
45 struct declaration_scope *declaration_scope,
46 struct ctf_trace *trace);
47
48static
49int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
50 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace);
51
52/*
53 * String returned must be freed by the caller using g_free.
54 */
55static
56char *concatenate_unary_strings(struct cds_list_head *head)
57{
58 struct ctf_node *node;
59 GString *str;
60 int i = 0;
61
62 str = g_string_new("");
63 cds_list_for_each_entry(node, head, siblings) {
64 char *src_string;
65
66 assert(node->type == NODE_UNARY_EXPRESSION);
67 assert(node->u.unary_expression.type == UNARY_STRING);
68 assert((node->u.unary_expression.link == UNARY_LINK_UNKNOWN)
69 ^ (i != 0));
70 switch (node->u.unary_expression.link) {
71 case UNARY_DOTLINK:
72 g_string_append(str, ".");
73 break;
74 case UNARY_ARROWLINK:
75 g_string_append(str, "->");
76 break;
77 case UNARY_DOTDOTDOT:
78 g_string_append(str, "...");
79 break;
80 default:
81 break;
82 }
83 src_string = node->u.unary_expression.u.string;
84 g_string_append(str, src_string);
85 i++;
86 }
87 return g_string_free(str, FALSE);
88}
89
90static
91GQuark get_map_clock_name_value(struct cds_list_head *head)
92{
93 struct ctf_node *node;
94 const char *name = NULL;
95 int i = 0;
96
97 cds_list_for_each_entry(node, head, siblings) {
98 char *src_string;
99
100 assert(node->type == NODE_UNARY_EXPRESSION);
101 assert(node->u.unary_expression.type == UNARY_STRING);
102 assert((node->u.unary_expression.link == UNARY_LINK_UNKNOWN)
103 ^ (i != 0));
104 /* needs to be chained with . */
105 switch (node->u.unary_expression.link) {
106 case UNARY_DOTLINK:
107 break;
108 case UNARY_ARROWLINK:
109 case UNARY_DOTDOTDOT:
110 return 0;
111 default:
112 break;
113 }
114 src_string = node->u.unary_expression.u.string;
115 switch (i) {
116 case 0: if (strcmp("clock", src_string) != 0) {
117 return 0;
118 }
119 break;
120 case 1: name = src_string;
121 break;
122 case 2: if (strcmp("value", src_string) != 0) {
123 return 0;
124 }
125 break;
126 default:
127 return 0; /* extra identifier, unknown */
128 }
129 i++;
130 }
131 return g_quark_from_string(name);
132}
133
134static
135int get_unary_unsigned(struct cds_list_head *head, uint64_t *value)
136{
137 struct ctf_node *node;
138 int i = 0;
139
140 cds_list_for_each_entry(node, head, siblings) {
141 assert(node->type == NODE_UNARY_EXPRESSION);
142 assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT);
143 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
144 assert(i == 0);
145 *value = node->u.unary_expression.u.unsigned_constant;
146 i++;
147 }
148 return 0;
149}
150
151static
152int get_unary_signed(struct cds_list_head *head, int64_t *value)
153{
154 struct ctf_node *node;
155 int i = 0;
156
157 cds_list_for_each_entry(node, head, siblings) {
158 assert(node->type == NODE_UNARY_EXPRESSION);
159 assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT
160 || node->u.unary_expression.type == UNARY_SIGNED_CONSTANT);
161 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
162 assert(i == 0);
163 switch (node->u.unary_expression.type) {
164 case UNARY_UNSIGNED_CONSTANT:
165 *value = (int64_t) node->u.unary_expression.u.unsigned_constant;
166 break;
167 case UNARY_SIGNED_CONSTANT:
168 *value = node->u.unary_expression.u.signed_constant;
169 break;
170 default:
171 assert(0);
172 }
173 i++;
174 }
175 return 0;
176}
177
178static
179int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
180{
181 struct ctf_node *node;
182 int i = 0;
183 int ret = -1;
184
185 cds_list_for_each_entry(node, head, siblings) {
186 const char *src_string;
187
188 assert(node->type == NODE_UNARY_EXPRESSION);
189 assert(node->u.unary_expression.type == UNARY_STRING);
190 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
191 assert(i == 0);
192 src_string = node->u.unary_expression.u.string;
193 ret = uuid_parse(src_string, *uuid);
194 }
195 return ret;
196}
197
198static
199struct ctf_stream_class *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
200{
201 if (trace->streams->len <= stream_id)
202 return NULL;
203 return g_ptr_array_index(trace->streams, stream_id);
204}
205
206static
207struct ctf_clock *trace_clock_lookup(struct ctf_trace *trace, GQuark clock_name)
208{
209 return g_hash_table_lookup(trace->clocks, (gpointer) (unsigned long) clock_name);
210}
211
212static
213int visit_type_specifier(FILE *fd, struct ctf_node *type_specifier, GString *str)
214{
215 assert(type_specifier->type == NODE_TYPE_SPECIFIER);
216
217 switch (type_specifier->u.type_specifier.type) {
218 case TYPESPEC_VOID:
219 g_string_append(str, "void");
220 break;
221 case TYPESPEC_CHAR:
222 g_string_append(str, "char");
223 break;
224 case TYPESPEC_SHORT:
225 g_string_append(str, "short");
226 break;
227 case TYPESPEC_INT:
228 g_string_append(str, "int");
229 break;
230 case TYPESPEC_LONG:
231 g_string_append(str, "long");
232 break;
233 case TYPESPEC_FLOAT:
234 g_string_append(str, "float");
235 break;
236 case TYPESPEC_DOUBLE:
237 g_string_append(str, "double");
238 break;
239 case TYPESPEC_SIGNED:
240 g_string_append(str, "signed");
241 break;
242 case TYPESPEC_UNSIGNED:
243 g_string_append(str, "unsigned");
244 break;
245 case TYPESPEC_BOOL:
246 g_string_append(str, "bool");
247 break;
248 case TYPESPEC_COMPLEX:
249 g_string_append(str, "_Complex");
250 break;
251 case TYPESPEC_IMAGINARY:
252 g_string_append(str, "_Imaginary");
253 break;
254 case TYPESPEC_CONST:
255 g_string_append(str, "const");
256 break;
257 case TYPESPEC_ID_TYPE:
258 if (type_specifier->u.type_specifier.id_type)
259 g_string_append(str, type_specifier->u.type_specifier.id_type);
260 break;
261 case TYPESPEC_STRUCT:
262 {
263 struct ctf_node *node = type_specifier->u.type_specifier.node;
264
265 if (!node->u._struct.name) {
266 fprintf(fd, "[error] %s: unexpected empty variant name\n", __func__);
267 return -EINVAL;
268 }
269 g_string_append(str, "struct ");
270 g_string_append(str, node->u._struct.name);
271 break;
272 }
273 case TYPESPEC_VARIANT:
274 {
275 struct ctf_node *node = type_specifier->u.type_specifier.node;
276
277 if (!node->u.variant.name) {
278 fprintf(fd, "[error] %s: unexpected empty variant name\n", __func__);
279 return -EINVAL;
280 }
281 g_string_append(str, "variant ");
282 g_string_append(str, node->u.variant.name);
283 break;
284 }
285 case TYPESPEC_ENUM:
286 {
287 struct ctf_node *node = type_specifier->u.type_specifier.node;
288
289 if (!node->u._enum.enum_id) {
290 fprintf(fd, "[error] %s: unexpected empty enum ID\n", __func__);
291 return -EINVAL;
292 }
293 g_string_append(str, "enum ");
294 g_string_append(str, node->u._enum.enum_id);
295 break;
296 }
297 case TYPESPEC_FLOATING_POINT:
298 case TYPESPEC_INTEGER:
299 case TYPESPEC_STRING:
300 default:
301 fprintf(fd, "[error] %s: unknown specifier\n", __func__);
302 return -EINVAL;
303 }
304 return 0;
305}
306
307static
308int visit_type_specifier_list(FILE *fd, struct ctf_node *type_specifier_list, GString *str)
309{
310 struct ctf_node *iter;
311 int alias_item_nr = 0;
312 int ret;
313
314 cds_list_for_each_entry(iter, &type_specifier_list->u.type_specifier_list.head, siblings) {
315 if (alias_item_nr != 0)
316 g_string_append(str, " ");
317 alias_item_nr++;
318 ret = visit_type_specifier(fd, iter, str);
319 if (ret)
320 return ret;
321 }
322 return 0;
323}
324
325static
326GQuark create_typealias_identifier(FILE *fd, int depth,
327 struct ctf_node *type_specifier_list,
328 struct ctf_node *node_type_declarator)
329{
330 struct ctf_node *iter;
331 GString *str;
332 char *str_c;
333 GQuark alias_q;
334 int ret;
335
336 str = g_string_new("");
337 ret = visit_type_specifier_list(fd, type_specifier_list, str);
338 if (ret) {
339 g_string_free(str, TRUE);
340 return 0;
341 }
342 cds_list_for_each_entry(iter, &node_type_declarator->u.type_declarator.pointers, siblings) {
343 g_string_append(str, " *");
344 if (iter->u.pointer.const_qualifier)
345 g_string_append(str, " const");
346 }
347 str_c = g_string_free(str, FALSE);
348 alias_q = g_quark_from_string(str_c);
349 g_free(str_c);
350 return alias_q;
351}
352
353static
354struct declaration *ctf_type_declarator_visit(FILE *fd, int depth,
355 struct ctf_node *type_specifier_list,
356 GQuark *field_name,
357 struct ctf_node *node_type_declarator,
358 struct declaration_scope *declaration_scope,
359 struct declaration *nested_declaration,
360 struct ctf_trace *trace)
361{
362 /*
363 * Visit type declarator by first taking care of sequence/array
364 * (recursively). Then, when we get to the identifier, take care
365 * of pointers.
366 */
367
368 if (node_type_declarator) {
369 assert(node_type_declarator->u.type_declarator.type != TYPEDEC_UNKNOWN);
370
371 /* TODO: gcc bitfields not supported yet. */
372 if (node_type_declarator->u.type_declarator.bitfield_len != NULL) {
373 fprintf(fd, "[error] %s: gcc bitfields are not supported yet.\n", __func__);
374 return NULL;
375 }
376 }
377
378 if (!nested_declaration) {
379 if (node_type_declarator && !cds_list_empty(&node_type_declarator->u.type_declarator.pointers)) {
380 GQuark alias_q;
381
382 /*
383 * If we have a pointer declarator, it _has_ to be present in
384 * the typealiases (else fail).
385 */
386 alias_q = create_typealias_identifier(fd, depth,
387 type_specifier_list, node_type_declarator);
388 nested_declaration = lookup_declaration(alias_q, declaration_scope);
389 if (!nested_declaration) {
390 fprintf(fd, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q));
391 return NULL;
392 }
393 if (nested_declaration->id == CTF_TYPE_INTEGER) {
394 struct declaration_integer *integer_declaration =
395 container_of(nested_declaration, struct declaration_integer, p);
396 /* For base to 16 for pointers (expected pretty-print) */
397 if (!integer_declaration->base) {
398 /*
399 * We need to do a copy of the
400 * integer declaration to modify it. There could be other references to
401 * it.
402 */
403 integer_declaration = integer_declaration_new(integer_declaration->len,
404 integer_declaration->byte_order, integer_declaration->signedness,
405 integer_declaration->p.alignment, 16, integer_declaration->encoding,
406 integer_declaration->clock);
407 nested_declaration = &integer_declaration->p;
408 }
409 }
410 } else {
411 nested_declaration = ctf_type_specifier_list_visit(fd, depth,
412 type_specifier_list, declaration_scope, trace);
413 }
414 }
415
416 if (!node_type_declarator)
417 return nested_declaration;
418
419 if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) {
420 if (node_type_declarator->u.type_declarator.u.id)
421 *field_name = g_quark_from_string(node_type_declarator->u.type_declarator.u.id);
422 else
423 *field_name = 0;
424 return nested_declaration;
425 } else {
426 struct declaration *declaration;
427 struct ctf_node *first;
428
429 /* TYPEDEC_NESTED */
430
431 if (!nested_declaration) {
432 fprintf(fd, "[error] %s: nested type is unknown.\n", __func__);
433 return NULL;
434 }
435
436 /* create array/sequence, pass nested_declaration as child. */
437 if (cds_list_empty(&node_type_declarator->u.type_declarator.u.nested.length)) {
438 fprintf(fd, "[error] %s: expecting length field reference or value.\n", __func__);
439 return NULL;
440 }
441 first = _cds_list_first_entry(&node_type_declarator->u.type_declarator.u.nested.length,
442 struct ctf_node, siblings);
443 assert(first->type == NODE_UNARY_EXPRESSION);
444
445 switch (first->u.unary_expression.type) {
446 case UNARY_UNSIGNED_CONSTANT:
447 {
448 struct declaration_array *array_declaration;
449 size_t len;
450
451 len = first->u.unary_expression.u.unsigned_constant;
452 array_declaration = array_declaration_new(len, nested_declaration,
453 declaration_scope);
454
455 if (!array_declaration) {
456 fprintf(fd, "[error] %s: cannot create array declaration.\n", __func__);
457 return NULL;
458 }
459 declaration = &array_declaration->p;
460 break;
461 }
462 case UNARY_STRING:
463 {
464 /* Lookup unsigned integer definition, create sequence */
465 char *length_name = concatenate_unary_strings(&node_type_declarator->u.type_declarator.u.nested.length);
466 struct declaration_sequence *sequence_declaration;
467
468 sequence_declaration = sequence_declaration_new(length_name, nested_declaration, declaration_scope);
469 if (!sequence_declaration) {
470 fprintf(fd, "[error] %s: cannot create sequence declaration.\n", __func__);
471 return NULL;
472 }
473 declaration = &sequence_declaration->p;
474 break;
475 }
476 default:
477 assert(0);
478 }
479
480 /* Pass it as content of outer container */
481 declaration = ctf_type_declarator_visit(fd, depth,
482 type_specifier_list, field_name,
483 node_type_declarator->u.type_declarator.u.nested.type_declarator,
484 declaration_scope, declaration, trace);
485 return declaration;
486 }
487}
488
489static
490int ctf_struct_type_declarators_visit(FILE *fd, int depth,
491 struct declaration_struct *struct_declaration,
492 struct ctf_node *type_specifier_list,
493 struct cds_list_head *type_declarators,
494 struct declaration_scope *declaration_scope,
495 struct ctf_trace *trace)
496{
497 struct ctf_node *iter;
498 GQuark field_name;
499
500 cds_list_for_each_entry(iter, type_declarators, siblings) {
501 struct declaration *field_declaration;
502
503 field_declaration = ctf_type_declarator_visit(fd, depth,
504 type_specifier_list,
505 &field_name, iter,
506 struct_declaration->scope,
507 NULL, trace);
508 if (!field_declaration) {
509 fprintf(fd, "[error] %s: unable to find struct field declaration type\n", __func__);
510 return -EINVAL;
511 }
512
513 /* Check if field with same name already exists */
514 if (struct_declaration_lookup_field_index(struct_declaration, field_name) >= 0) {
515 fprintf(fd, "[error] %s: duplicate field %s in struct\n", __func__, g_quark_to_string(field_name));
516 return -EINVAL;
517 }
518
519 struct_declaration_add_field(struct_declaration,
520 g_quark_to_string(field_name),
521 field_declaration);
522 }
523 return 0;
524}
525
526static
527int ctf_variant_type_declarators_visit(FILE *fd, int depth,
528 struct declaration_untagged_variant *untagged_variant_declaration,
529 struct ctf_node *type_specifier_list,
530 struct cds_list_head *type_declarators,
531 struct declaration_scope *declaration_scope,
532 struct ctf_trace *trace)
533{
534 struct ctf_node *iter;
535 GQuark field_name;
536
537 cds_list_for_each_entry(iter, type_declarators, siblings) {
538 struct declaration *field_declaration;
539
540 field_declaration = ctf_type_declarator_visit(fd, depth,
541 type_specifier_list,
542 &field_name, iter,
543 untagged_variant_declaration->scope,
544 NULL, trace);
545 if (!field_declaration) {
546 fprintf(fd, "[error] %s: unable to find variant field declaration type\n", __func__);
547 return -EINVAL;
548 }
549
550 if (untagged_variant_declaration_get_field_from_tag(untagged_variant_declaration, field_name) != NULL) {
551 fprintf(fd, "[error] %s: duplicate field %s in variant\n", __func__, g_quark_to_string(field_name));
552 return -EINVAL;
553 }
554
555
556 untagged_variant_declaration_add_field(untagged_variant_declaration,
557 g_quark_to_string(field_name),
558 field_declaration);
559 }
560 return 0;
561}
562
563static
564int ctf_typedef_visit(FILE *fd, int depth, struct declaration_scope *scope,
565 struct ctf_node *type_specifier_list,
566 struct cds_list_head *type_declarators,
567 struct ctf_trace *trace)
568{
569 struct ctf_node *iter;
570 GQuark identifier;
571
572 cds_list_for_each_entry(iter, type_declarators, siblings) {
573 struct declaration *type_declaration;
574 int ret;
575
576 type_declaration = ctf_type_declarator_visit(fd, depth,
577 type_specifier_list,
578 &identifier, iter,
579 scope, NULL, trace);
580 if (!type_declaration) {
581 fprintf(fd, "[error] %s: problem creating type declaration\n", __func__);
582 return -EINVAL;
583 }
584 /*
585 * Don't allow typedef and typealias of untagged
586 * variants.
587 */
588 if (type_declaration->id == CTF_TYPE_UNTAGGED_VARIANT) {
589 fprintf(fd, "[error] %s: typedef of untagged variant is not permitted.\n", __func__);
590 declaration_unref(type_declaration);
591 return -EPERM;
592 }
593 ret = register_declaration(identifier, type_declaration, scope);
594 if (ret) {
595 type_declaration->declaration_free(type_declaration);
596 return ret;
597 }
598 }
599 return 0;
600}
601
602static
603int ctf_typealias_visit(FILE *fd, int depth, struct declaration_scope *scope,
604 struct ctf_node *target, struct ctf_node *alias,
605 struct ctf_trace *trace)
606{
607 struct declaration *type_declaration;
608 struct ctf_node *node;
609 GQuark dummy_id;
610 GQuark alias_q;
611 int err;
612
613 /* See ctf_visitor_type_declarator() in the semantic validator. */
614
615 /*
616 * Create target type declaration.
617 */
618
619 if (cds_list_empty(&target->u.typealias_target.type_declarators))
620 node = NULL;
621 else
622 node = _cds_list_first_entry(&target->u.typealias_target.type_declarators,
623 struct ctf_node, siblings);
624 type_declaration = ctf_type_declarator_visit(fd, depth,
625 target->u.typealias_target.type_specifier_list,
626 &dummy_id, node,
627 scope, NULL, trace);
628 if (!type_declaration) {
629 fprintf(fd, "[error] %s: problem creating type declaration\n", __func__);
630 err = -EINVAL;
631 goto error;
632 }
633 /*
634 * Don't allow typedef and typealias of untagged
635 * variants.
636 */
637 if (type_declaration->id == CTF_TYPE_UNTAGGED_VARIANT) {
638 fprintf(fd, "[error] %s: typedef of untagged variant is not permitted.\n", __func__);
639 declaration_unref(type_declaration);
640 return -EPERM;
641 }
642 /*
643 * The semantic validator does not check whether the target is
644 * abstract or not (if it has an identifier). Check it here.
645 */
646 if (dummy_id != 0) {
647 fprintf(fd, "[error] %s: expecting empty identifier\n", __func__);
648 err = -EINVAL;
649 goto error;
650 }
651 /*
652 * Create alias identifier.
653 */
654
655 node = _cds_list_first_entry(&alias->u.typealias_alias.type_declarators,
656 struct ctf_node, siblings);
657 alias_q = create_typealias_identifier(fd, depth,
658 alias->u.typealias_alias.type_specifier_list, node);
659 err = register_declaration(alias_q, type_declaration, scope);
660 if (err)
661 goto error;
662 return 0;
663
664error:
665 if (type_declaration) {
666 type_declaration->declaration_free(type_declaration);
667 }
668 return err;
669}
670
671static
672int ctf_struct_declaration_list_visit(FILE *fd, int depth,
673 struct ctf_node *iter, struct declaration_struct *struct_declaration,
674 struct ctf_trace *trace)
675{
676 int ret;
677
678 switch (iter->type) {
679 case NODE_TYPEDEF:
680 /* For each declarator, declare type and add type to struct declaration scope */
681 ret = ctf_typedef_visit(fd, depth,
682 struct_declaration->scope,
683 iter->u._typedef.type_specifier_list,
684 &iter->u._typedef.type_declarators, trace);
685 if (ret)
686 return ret;
687 break;
688 case NODE_TYPEALIAS:
689 /* Declare type with declarator and add type to struct declaration scope */
690 ret = ctf_typealias_visit(fd, depth,
691 struct_declaration->scope,
692 iter->u.typealias.target,
693 iter->u.typealias.alias, trace);
694 if (ret)
695 return ret;
696 break;
697 case NODE_STRUCT_OR_VARIANT_DECLARATION:
698 /* Add field to structure declaration */
699 ret = ctf_struct_type_declarators_visit(fd, depth,
700 struct_declaration,
701 iter->u.struct_or_variant_declaration.type_specifier_list,
702 &iter->u.struct_or_variant_declaration.type_declarators,
703 struct_declaration->scope, trace);
704 if (ret)
705 return ret;
706 break;
707 default:
708 fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
709 assert(0);
710 }
711 return 0;
712}
713
714static
715int ctf_variant_declaration_list_visit(FILE *fd, int depth,
716 struct ctf_node *iter,
717 struct declaration_untagged_variant *untagged_variant_declaration,
718 struct ctf_trace *trace)
719{
720 int ret;
721
722 switch (iter->type) {
723 case NODE_TYPEDEF:
724 /* For each declarator, declare type and add type to variant declaration scope */
725 ret = ctf_typedef_visit(fd, depth,
726 untagged_variant_declaration->scope,
727 iter->u._typedef.type_specifier_list,
728 &iter->u._typedef.type_declarators, trace);
729 if (ret)
730 return ret;
731 break;
732 case NODE_TYPEALIAS:
733 /* Declare type with declarator and add type to variant declaration scope */
734 ret = ctf_typealias_visit(fd, depth,
735 untagged_variant_declaration->scope,
736 iter->u.typealias.target,
737 iter->u.typealias.alias, trace);
738 if (ret)
739 return ret;
740 break;
741 case NODE_STRUCT_OR_VARIANT_DECLARATION:
742 /* Add field to structure declaration */
743 ret = ctf_variant_type_declarators_visit(fd, depth,
744 untagged_variant_declaration,
745 iter->u.struct_or_variant_declaration.type_specifier_list,
746 &iter->u.struct_or_variant_declaration.type_declarators,
747 untagged_variant_declaration->scope, trace);
748 if (ret)
749 return ret;
750 break;
751 default:
752 fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
753 assert(0);
754 }
755 return 0;
756}
757
758static
759struct declaration *ctf_declaration_struct_visit(FILE *fd,
760 int depth, const char *name, struct cds_list_head *declaration_list,
761 int has_body, struct cds_list_head *min_align,
762 struct declaration_scope *declaration_scope,
763 struct ctf_trace *trace)
764{
765 struct declaration_struct *struct_declaration;
766 struct ctf_node *iter;
767 int ret;
768
769 /*
770 * For named struct (without body), lookup in
771 * declaration scope. Don't take reference on struct
772 * declaration: ref is only taken upon definition.
773 */
774 if (!has_body) {
775 assert(name);
776 struct_declaration =
777 lookup_struct_declaration(g_quark_from_string(name),
778 declaration_scope);
779 return &struct_declaration->p;
780 } else {
781 uint64_t min_align_value = 0;
782
783 /* For unnamed struct, create type */
784 /* For named struct (with body), create type and add to declaration scope */
785 if (name) {
786 if (lookup_struct_declaration(g_quark_from_string(name),
787 declaration_scope)) {
788
789 fprintf(fd, "[error] %s: struct %s already declared in scope\n", __func__, name);
790 return NULL;
791 }
792 }
793 if (!cds_list_empty(min_align)) {
794 ret = get_unary_unsigned(min_align, &min_align_value);
795 if (ret) {
796 fprintf(fd, "[error] %s: unexpected unary expression for structure \"align\" attribute\n", __func__);
797 ret = -EINVAL;
798 goto error;
799 }
800 }
801 struct_declaration = struct_declaration_new(declaration_scope,
802 min_align_value);
803 cds_list_for_each_entry(iter, declaration_list, siblings) {
804 ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter,
805 struct_declaration, trace);
806 if (ret)
807 goto error_free_declaration;
808 }
809 if (name) {
810 ret = register_struct_declaration(g_quark_from_string(name),
811 struct_declaration,
812 declaration_scope);
813 assert(!ret);
814 }
815 return &struct_declaration->p;
816 }
817error_free_declaration:
818 struct_declaration->p.declaration_free(&struct_declaration->p);
819error:
820 return NULL;
821}
822
823static
824struct declaration *ctf_declaration_variant_visit(FILE *fd,
825 int depth, const char *name, const char *choice,
826 struct cds_list_head *declaration_list,
827 int has_body, struct declaration_scope *declaration_scope,
828 struct ctf_trace *trace)
829{
830 struct declaration_untagged_variant *untagged_variant_declaration;
831 struct declaration_variant *variant_declaration;
832 struct ctf_node *iter;
833 int ret;
834
835 /*
836 * For named variant (without body), lookup in
837 * declaration scope. Don't take reference on variant
838 * declaration: ref is only taken upon definition.
839 */
840 if (!has_body) {
841 assert(name);
842 untagged_variant_declaration =
843 lookup_variant_declaration(g_quark_from_string(name),
844 declaration_scope);
845 } else {
846 /* For unnamed variant, create type */
847 /* For named variant (with body), create type and add to declaration scope */
848 if (name) {
849 if (lookup_variant_declaration(g_quark_from_string(name),
850 declaration_scope)) {
851
852 fprintf(fd, "[error] %s: variant %s already declared in scope\n", __func__, name);
853 return NULL;
854 }
855 }
856 untagged_variant_declaration = untagged_variant_declaration_new(declaration_scope);
857 cds_list_for_each_entry(iter, declaration_list, siblings) {
858 ret = ctf_variant_declaration_list_visit(fd, depth + 1, iter,
859 untagged_variant_declaration, trace);
860 if (ret)
861 goto error;
862 }
863 if (name) {
864 ret = register_variant_declaration(g_quark_from_string(name),
865 untagged_variant_declaration,
866 declaration_scope);
867 assert(!ret);
868 }
869 }
870 /*
871 * if tagged, create tagged variant and return. else return
872 * untagged variant.
873 */
874 if (!choice) {
875 return &untagged_variant_declaration->p;
876 } else {
877 variant_declaration = variant_declaration_new(untagged_variant_declaration, choice);
878 if (!variant_declaration)
879 goto error;
880 declaration_unref(&untagged_variant_declaration->p);
881 return &variant_declaration->p;
882 }
883error:
884 untagged_variant_declaration->p.declaration_free(&untagged_variant_declaration->p);
885 return NULL;
886}
887
888static
889int ctf_enumerator_list_visit(FILE *fd, int depth,
890 struct ctf_node *enumerator,
891 struct declaration_enum *enum_declaration)
892{
893 GQuark q;
894 struct ctf_node *iter;
895
896 q = g_quark_from_string(enumerator->u.enumerator.id);
897 if (enum_declaration->integer_declaration->signedness) {
898 int64_t start, end;
899 int nr_vals = 0;
900
901 cds_list_for_each_entry(iter, &enumerator->u.enumerator.values, siblings) {
902 int64_t *target;
903
904 assert(iter->type == NODE_UNARY_EXPRESSION);
905 if (nr_vals == 0)
906 target = &start;
907 else
908 target = &end;
909
910 switch (iter->u.unary_expression.type) {
911 case UNARY_SIGNED_CONSTANT:
912 *target = iter->u.unary_expression.u.signed_constant;
913 break;
914 case UNARY_UNSIGNED_CONSTANT:
915 *target = iter->u.unary_expression.u.unsigned_constant;
916 break;
917 default:
918 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
919 return -EINVAL;
920 }
921 if (nr_vals > 1) {
922 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
923 return -EINVAL;
924 }
925 nr_vals++;
926 }
927 if (nr_vals == 1)
928 end = start;
929 enum_signed_insert(enum_declaration, start, end, q);
930 } else {
931 uint64_t start, end;
932 int nr_vals = 0;
933
934 cds_list_for_each_entry(iter, &enumerator->u.enumerator.values, siblings) {
935 uint64_t *target;
936
937 assert(iter->type == NODE_UNARY_EXPRESSION);
938 if (nr_vals == 0)
939 target = &start;
940 else
941 target = &end;
942
943 switch (iter->u.unary_expression.type) {
944 case UNARY_UNSIGNED_CONSTANT:
945 *target = iter->u.unary_expression.u.unsigned_constant;
946 break;
947 case UNARY_SIGNED_CONSTANT:
948 /*
949 * We don't accept signed constants for enums with unsigned
950 * container type.
951 */
952 fprintf(fd, "[error] %s: invalid enumerator (signed constant encountered, but enum container type is unsigned)\n", __func__);
953 return -EINVAL;
954 default:
955 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
956 return -EINVAL;
957 }
958 if (nr_vals > 1) {
959 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
960 return -EINVAL;
961 }
962 nr_vals++;
963 }
964 if (nr_vals == 1)
965 end = start;
966 enum_unsigned_insert(enum_declaration, start, end, q);
967 }
968 return 0;
969}
970
971static
972struct declaration *ctf_declaration_enum_visit(FILE *fd, int depth,
973 const char *name,
974 struct ctf_node *container_type,
975 struct cds_list_head *enumerator_list,
976 int has_body,
977 struct declaration_scope *declaration_scope,
978 struct ctf_trace *trace)
979{
980 struct declaration *declaration;
981 struct declaration_enum *enum_declaration;
982 struct declaration_integer *integer_declaration;
983 struct ctf_node *iter;
984 GQuark dummy_id;
985 int ret;
986
987 /*
988 * For named enum (without body), lookup in
989 * declaration scope. Don't take reference on enum
990 * declaration: ref is only taken upon definition.
991 */
992 if (!has_body) {
993 assert(name);
994 enum_declaration =
995 lookup_enum_declaration(g_quark_from_string(name),
996 declaration_scope);
997 return &enum_declaration->p;
998 } else {
999 /* For unnamed enum, create type */
1000 /* For named enum (with body), create type and add to declaration scope */
1001 if (name) {
1002 if (lookup_enum_declaration(g_quark_from_string(name),
1003 declaration_scope)) {
1004
1005 fprintf(fd, "[error] %s: enum %s already declared in scope\n", __func__, name);
1006 return NULL;
1007 }
1008 }
1009 if (!container_type) {
1010 declaration = lookup_declaration(g_quark_from_static_string("int"),
1011 declaration_scope);
1012 if (!declaration) {
1013 fprintf(fd, "[error] %s: \"int\" type declaration missing for enumeration\n", __func__);
1014 return NULL;
1015 }
1016 } else {
1017 declaration = ctf_type_declarator_visit(fd, depth,
1018 container_type,
1019 &dummy_id, NULL,
1020 declaration_scope,
1021 NULL, trace);
1022 }
1023 if (!declaration) {
1024 fprintf(fd, "[error] %s: unable to create container type for enumeration\n", __func__);
1025 return NULL;
1026 }
1027 if (declaration->id != CTF_TYPE_INTEGER) {
1028 fprintf(fd, "[error] %s: container type for enumeration is not integer\n", __func__);
1029 return NULL;
1030 }
1031 integer_declaration = container_of(declaration, struct declaration_integer, p);
1032 enum_declaration = enum_declaration_new(integer_declaration);
1033 declaration_unref(&integer_declaration->p); /* leave ref to enum */
1034 cds_list_for_each_entry(iter, enumerator_list, siblings) {
1035 ret = ctf_enumerator_list_visit(fd, depth + 1, iter, enum_declaration);
1036 if (ret)
1037 goto error;
1038 }
1039 if (name) {
1040 ret = register_enum_declaration(g_quark_from_string(name),
1041 enum_declaration,
1042 declaration_scope);
1043 assert(!ret);
1044 }
1045 return &enum_declaration->p;
1046 }
1047error:
1048 enum_declaration->p.declaration_free(&enum_declaration->p);
1049 return NULL;
1050}
1051
1052static
1053struct declaration *ctf_declaration_type_specifier_visit(FILE *fd, int depth,
1054 struct ctf_node *type_specifier_list,
1055 struct declaration_scope *declaration_scope)
1056{
1057 GString *str;
1058 struct declaration *declaration;
1059 char *str_c;
1060 int ret;
1061 GQuark id_q;
1062
1063 str = g_string_new("");
1064 ret = visit_type_specifier_list(fd, type_specifier_list, str);
1065 if (ret)
1066 return NULL;
1067 str_c = g_string_free(str, FALSE);
1068 id_q = g_quark_from_string(str_c);
1069 g_free(str_c);
1070 declaration = lookup_declaration(id_q, declaration_scope);
1071 return declaration;
1072}
1073
1074/*
1075 * Returns 0/1 boolean, or < 0 on error.
1076 */
1077static
1078int get_boolean(FILE *fd, int depth, struct ctf_node *unary_expression)
1079{
1080 if (unary_expression->type != NODE_UNARY_EXPRESSION) {
1081 fprintf(fd, "[error] %s: expecting unary expression\n",
1082 __func__);
1083 return -EINVAL;
1084 }
1085 switch (unary_expression->u.unary_expression.type) {
1086 case UNARY_UNSIGNED_CONSTANT:
1087 if (unary_expression->u.unary_expression.u.unsigned_constant == 0)
1088 return 0;
1089 else
1090 return 1;
1091 case UNARY_SIGNED_CONSTANT:
1092 if (unary_expression->u.unary_expression.u.signed_constant == 0)
1093 return 0;
1094 else
1095 return 1;
1096 case UNARY_STRING:
1097 if (!strcmp(unary_expression->u.unary_expression.u.string, "true"))
1098 return 1;
1099 else if (!strcmp(unary_expression->u.unary_expression.u.string, "TRUE"))
1100 return 1;
1101 else if (!strcmp(unary_expression->u.unary_expression.u.string, "false"))
1102 return 0;
1103 else if (!strcmp(unary_expression->u.unary_expression.u.string, "FALSE"))
1104 return 0;
1105 else {
1106 fprintf(fd, "[error] %s: unexpected string \"%s\"\n",
1107 __func__, unary_expression->u.unary_expression.u.string);
1108 return -EINVAL;
1109 }
1110 break;
1111 default:
1112 fprintf(fd, "[error] %s: unexpected unary expression type\n",
1113 __func__);
1114 return -EINVAL;
1115 }
1116
1117}
1118
1119static
1120int get_trace_byte_order(FILE *fd, int depth, struct ctf_node *unary_expression)
1121{
1122 int byte_order;
1123
1124 if (unary_expression->u.unary_expression.type != UNARY_STRING) {
1125 fprintf(fd, "[error] %s: byte_order: expecting string\n",
1126 __func__);
1127 return -EINVAL;
1128 }
1129 if (!strcmp(unary_expression->u.unary_expression.u.string, "be"))
1130 byte_order = BIG_ENDIAN;
1131 else if (!strcmp(unary_expression->u.unary_expression.u.string, "le"))
1132 byte_order = LITTLE_ENDIAN;
1133 else {
1134 fprintf(fd, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n",
1135 __func__, unary_expression->u.unary_expression.u.string);
1136 return -EINVAL;
1137 }
1138 return byte_order;
1139}
1140
1141static
1142int get_byte_order(FILE *fd, int depth, struct ctf_node *unary_expression,
1143 struct ctf_trace *trace)
1144{
1145 int byte_order;
1146
1147 if (unary_expression->u.unary_expression.type != UNARY_STRING) {
1148 fprintf(fd, "[error] %s: byte_order: expecting string\n",
1149 __func__);
1150 return -EINVAL;
1151 }
1152 if (!strcmp(unary_expression->u.unary_expression.u.string, "native"))
1153 byte_order = trace->byte_order;
1154 else if (!strcmp(unary_expression->u.unary_expression.u.string, "network"))
1155 byte_order = BIG_ENDIAN;
1156 else if (!strcmp(unary_expression->u.unary_expression.u.string, "be"))
1157 byte_order = BIG_ENDIAN;
1158 else if (!strcmp(unary_expression->u.unary_expression.u.string, "le"))
1159 byte_order = LITTLE_ENDIAN;
1160 else {
1161 fprintf(fd, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n",
1162 __func__, unary_expression->u.unary_expression.u.string);
1163 return -EINVAL;
1164 }
1165 return byte_order;
1166}
1167
1168static
1169struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
1170 struct cds_list_head *expressions,
1171 struct ctf_trace *trace)
1172{
1173 struct ctf_node *expression;
1174 uint64_t alignment = 1, size = 0;
1175 int byte_order = trace->byte_order;
1176 int signedness = 0;
1177 int has_alignment = 0, has_size = 0;
1178 int base = 0;
1179 enum ctf_string_encoding encoding = CTF_STRING_NONE;
1180 struct ctf_clock *clock = NULL;
1181 struct declaration_integer *integer_declaration;
1182
1183 cds_list_for_each_entry(expression, expressions, siblings) {
1184 struct ctf_node *left, *right;
1185
1186 left = _cds_list_first_entry(&expression->u.ctf_expression.left, struct ctf_node, siblings);
1187 right = _cds_list_first_entry(&expression->u.ctf_expression.right, struct ctf_node, siblings);
1188 assert(left->u.unary_expression.type == UNARY_STRING);
1189 if (!strcmp(left->u.unary_expression.u.string, "signed")) {
1190 signedness = get_boolean(fd, depth, right);
1191 if (signedness < 0)
1192 return NULL;
1193 } else if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
1194 byte_order = get_byte_order(fd, depth, right, trace);
1195 if (byte_order < 0)
1196 return NULL;
1197 } else if (!strcmp(left->u.unary_expression.u.string, "size")) {
1198 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
1199 fprintf(fd, "[error] %s: size: expecting unsigned constant\n",
1200 __func__);
1201 return NULL;
1202 }
1203 size = right->u.unary_expression.u.unsigned_constant;
1204 has_size = 1;
1205 } else if (!strcmp(left->u.unary_expression.u.string, "align")) {
1206 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
1207 fprintf(fd, "[error] %s: align: expecting unsigned constant\n",
1208 __func__);
1209 return NULL;
1210 }
1211 alignment = right->u.unary_expression.u.unsigned_constant;
1212 /* Make sure alignment is a power of two */
1213 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
1214 fprintf(fd, "[error] %s: align: expecting power of two\n",
1215 __func__);
1216 return NULL;
1217 }
1218 has_alignment = 1;
1219 } else if (!strcmp(left->u.unary_expression.u.string, "base")) {
1220 switch (right->u.unary_expression.type) {
1221 case UNARY_UNSIGNED_CONSTANT:
1222 switch (right->u.unary_expression.u.unsigned_constant) {
1223 case 2:
1224 case 8:
1225 case 10:
1226 case 16:
1227 base = right->u.unary_expression.u.unsigned_constant;
1228 break;
1229 default:
1230 fprintf(fd, "[error] %s: base not supported (%" PRIu64 ")\n",
1231 __func__, right->u.unary_expression.u.unsigned_constant);
1232 return NULL;
1233 }
1234 break;
1235 case UNARY_STRING:
1236 {
1237 char *s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
1238 if (!s_right) {
1239 fprintf(fd, "[error] %s: unexpected unary expression for integer base\n", __func__);
1240 g_free(s_right);
1241 return NULL;
1242 }
1243 if (!strcmp(s_right, "decimal") || !strcmp(s_right, "dec") || !strcmp(s_right, "d")
1244 || !strcmp(s_right, "i") || !strcmp(s_right, "u")) {
1245 base = 10;
1246 } else if (!strcmp(s_right, "hexadecimal") || !strcmp(s_right, "hex")
1247 || !strcmp(s_right, "x") || !strcmp(s_right, "X")
1248 || !strcmp(s_right, "p")) {
1249 base = 16;
1250 } else if (!strcmp(s_right, "octal") || !strcmp(s_right, "oct")
1251 || !strcmp(s_right, "o")) {
1252 base = 8;
1253 } else if (!strcmp(s_right, "binary") || !strcmp(s_right, "b")) {
1254 base = 2;
1255 } else {
1256 fprintf(fd, "[error] %s: unexpected expression for integer base (%s)\n", __func__, s_right);
1257 g_free(s_right);
1258 return NULL;
1259 }
1260
1261 g_free(s_right);
1262 break;
1263 }
1264 default:
1265 fprintf(fd, "[error] %s: base: expecting unsigned constant or unary string\n",
1266 __func__);
1267 return NULL;
1268 }
1269 } else if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
1270 char *s_right;
1271
1272 if (right->u.unary_expression.type != UNARY_STRING) {
1273 fprintf(fd, "[error] %s: encoding: expecting unary string\n",
1274 __func__);
1275 return NULL;
1276 }
1277 s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
1278 if (!s_right) {
1279 fprintf(fd, "[error] %s: unexpected unary expression for integer base\n", __func__);
1280 g_free(s_right);
1281 return NULL;
1282 }
1283 if (!strcmp(s_right, "UTF8")
1284 || !strcmp(s_right, "utf8")
1285 || !strcmp(s_right, "utf-8")
1286 || !strcmp(s_right, "UTF-8"))
1287 encoding = CTF_STRING_UTF8;
1288 else if (!strcmp(s_right, "ASCII")
1289 || !strcmp(s_right, "ascii"))
1290 encoding = CTF_STRING_ASCII;
1291 else if (!strcmp(s_right, "none"))
1292 encoding = CTF_STRING_NONE;
1293 else {
1294 fprintf(fd, "[error] %s: unknown string encoding \"%s\"\n", __func__, s_right);
1295 g_free(s_right);
1296 return NULL;
1297 }
1298 g_free(s_right);
1299 } else if (!strcmp(left->u.unary_expression.u.string, "map")) {
1300 GQuark clock_name;
1301
1302 if (right->u.unary_expression.type != UNARY_STRING) {
1303 fprintf(fd, "[error] %s: map: expecting identifier\n",
1304 __func__);
1305 return NULL;
1306 }
1307 /* currently only support clock.name.value */
1308 clock_name = get_map_clock_name_value(&expression->u.ctf_expression.right);
1309 if (!clock_name) {
1310 char *s_right;
1311
1312 s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
1313 if (!s_right) {
1314 fprintf(fd, "[error] %s: unexpected unary expression for integer map\n", __func__);
1315 g_free(s_right);
1316 return NULL;
1317 }
1318 fprintf(fd, "[warning] %s: unknown map %s in integer declaration\n", __func__,
1319 s_right);
1320 g_free(s_right);
1321 continue;
1322 }
1323 clock = trace_clock_lookup(trace, clock_name);
1324 if (!clock) {
1325 fprintf(fd, "[error] %s: map: unable to find clock %s declaration\n",
1326 __func__, g_quark_to_string(clock_name));
1327 return NULL;
1328 }
1329 } else {
1330 fprintf(fd, "[warning] %s: unknown attribute name %s\n",
1331 __func__, left->u.unary_expression.u.string);
1332 /* Fall-through after warning */
1333 }
1334 }
1335 if (!has_size) {
1336 fprintf(fd, "[error] %s: missing size attribute\n", __func__);
1337 return NULL;
1338 }
1339 if (!has_alignment) {
1340 if (size % CHAR_BIT) {
1341 /* bit-packed alignment */
1342 alignment = 1;
1343 } else {
1344 /* byte-packed alignment */
1345 alignment = CHAR_BIT;
1346 }
1347 }
1348 integer_declaration = integer_declaration_new(size,
1349 byte_order, signedness, alignment,
1350 base, encoding, clock);
1351 return &integer_declaration->p;
1352}
1353
1354static
1355struct declaration *ctf_declaration_floating_point_visit(FILE *fd, int depth,
1356 struct cds_list_head *expressions,
1357 struct ctf_trace *trace)
1358{
1359 struct ctf_node *expression;
1360 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0,
1361 byte_order = trace->byte_order;
1362 int has_alignment = 0, has_exp_dig = 0, has_mant_dig = 0;
1363 struct declaration_float *float_declaration;
1364
1365 cds_list_for_each_entry(expression, expressions, siblings) {
1366 struct ctf_node *left, *right;
1367
1368 left = _cds_list_first_entry(&expression->u.ctf_expression.left, struct ctf_node, siblings);
1369 right = _cds_list_first_entry(&expression->u.ctf_expression.right, struct ctf_node, siblings);
1370 assert(left->u.unary_expression.type == UNARY_STRING);
1371 if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
1372 byte_order = get_byte_order(fd, depth, right, trace);
1373 if (byte_order < 0)
1374 return NULL;
1375 } else if (!strcmp(left->u.unary_expression.u.string, "exp_dig")) {
1376 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
1377 fprintf(fd, "[error] %s: exp_dig: expecting unsigned constant\n",
1378 __func__);
1379 return NULL;
1380 }
1381 exp_dig = right->u.unary_expression.u.unsigned_constant;
1382 has_exp_dig = 1;
1383 } else if (!strcmp(left->u.unary_expression.u.string, "mant_dig")) {
1384 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
1385 fprintf(fd, "[error] %s: mant_dig: expecting unsigned constant\n",
1386 __func__);
1387 return NULL;
1388 }
1389 mant_dig = right->u.unary_expression.u.unsigned_constant;
1390 has_mant_dig = 1;
1391 } else if (!strcmp(left->u.unary_expression.u.string, "align")) {
1392 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
1393 fprintf(fd, "[error] %s: align: expecting unsigned constant\n",
1394 __func__);
1395 return NULL;
1396 }
1397 alignment = right->u.unary_expression.u.unsigned_constant;
1398 /* Make sure alignment is a power of two */
1399 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
1400 fprintf(fd, "[error] %s: align: expecting power of two\n",
1401 __func__);
1402 return NULL;
1403 }
1404 has_alignment = 1;
1405 } else {
1406 fprintf(fd, "[warning] %s: unknown attribute name %s\n",
1407 __func__, left->u.unary_expression.u.string);
1408 /* Fall-through after warning */
1409 }
1410 }
1411 if (!has_mant_dig) {
1412 fprintf(fd, "[error] %s: missing mant_dig attribute\n", __func__);
1413 return NULL;
1414 }
1415 if (!has_exp_dig) {
1416 fprintf(fd, "[error] %s: missing exp_dig attribute\n", __func__);
1417 return NULL;
1418 }
1419 if (!has_alignment) {
1420 if ((mant_dig + exp_dig) % CHAR_BIT) {
1421 /* bit-packed alignment */
1422 alignment = 1;
1423 } else {
1424 /* byte-packed alignment */
1425 alignment = CHAR_BIT;
1426 }
1427 }
1428 float_declaration = float_declaration_new(mant_dig, exp_dig,
1429 byte_order, alignment);
1430 return &float_declaration->p;
1431}
1432
1433static
1434struct declaration *ctf_declaration_string_visit(FILE *fd, int depth,
1435 struct cds_list_head *expressions,
1436 struct ctf_trace *trace)
1437{
1438 struct ctf_node *expression;
1439 const char *encoding_c = NULL;
1440 enum ctf_string_encoding encoding = CTF_STRING_UTF8;
1441 struct declaration_string *string_declaration;
1442
1443 cds_list_for_each_entry(expression, expressions, siblings) {
1444 struct ctf_node *left, *right;
1445
1446 left = _cds_list_first_entry(&expression->u.ctf_expression.left, struct ctf_node, siblings);
1447 right = _cds_list_first_entry(&expression->u.ctf_expression.right, struct ctf_node, siblings);
1448 assert(left->u.unary_expression.type == UNARY_STRING);
1449 if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
1450 if (right->u.unary_expression.type != UNARY_STRING) {
1451 fprintf(fd, "[error] %s: encoding: expecting string\n",
1452 __func__);
1453 return NULL;
1454 }
1455 encoding_c = right->u.unary_expression.u.string;
1456 } else {
1457 fprintf(fd, "[warning] %s: unknown attribute name %s\n",
1458 __func__, left->u.unary_expression.u.string);
1459 /* Fall-through after warning */
1460 }
1461 }
1462 if (encoding_c && !strcmp(encoding_c, "ASCII"))
1463 encoding = CTF_STRING_ASCII;
1464 string_declaration = string_declaration_new(encoding);
1465 return &string_declaration->p;
1466}
1467
1468
1469static
1470struct declaration *ctf_type_specifier_list_visit(FILE *fd,
1471 int depth, struct ctf_node *type_specifier_list,
1472 struct declaration_scope *declaration_scope,
1473 struct ctf_trace *trace)
1474{
1475 struct ctf_node *first;
1476 struct ctf_node *node;
1477
1478 assert(type_specifier_list->type == NODE_TYPE_SPECIFIER_LIST);
1479
1480 first = _cds_list_first_entry(&type_specifier_list->u.type_specifier_list.head, struct ctf_node, siblings);
1481
1482 assert(first->type == NODE_TYPE_SPECIFIER);
1483
1484 node = first->u.type_specifier.node;
1485
1486 switch (first->u.type_specifier.type) {
1487 case TYPESPEC_FLOATING_POINT:
1488 return ctf_declaration_floating_point_visit(fd, depth,
1489 &node->u.floating_point.expressions, trace);
1490 case TYPESPEC_INTEGER:
1491 return ctf_declaration_integer_visit(fd, depth,
1492 &node->u.integer.expressions, trace);
1493 case TYPESPEC_STRING:
1494 return ctf_declaration_string_visit(fd, depth,
1495 &node->u.string.expressions, trace);
1496 case TYPESPEC_STRUCT:
1497 return ctf_declaration_struct_visit(fd, depth,
1498 node->u._struct.name,
1499 &node->u._struct.declaration_list,
1500 node->u._struct.has_body,
1501 &node->u._struct.min_align,
1502 declaration_scope,
1503 trace);
1504 case TYPESPEC_VARIANT:
1505 return ctf_declaration_variant_visit(fd, depth,
1506 node->u.variant.name,
1507 node->u.variant.choice,
1508 &node->u.variant.declaration_list,
1509 node->u.variant.has_body,
1510 declaration_scope,
1511 trace);
1512 case TYPESPEC_ENUM:
1513 return ctf_declaration_enum_visit(fd, depth,
1514 node->u._enum.enum_id,
1515 node->u._enum.container_type,
1516 &node->u._enum.enumerator_list,
1517 node->u._enum.has_body,
1518 declaration_scope,
1519 trace);
1520
1521 case TYPESPEC_VOID:
1522 case TYPESPEC_CHAR:
1523 case TYPESPEC_SHORT:
1524 case TYPESPEC_INT:
1525 case TYPESPEC_LONG:
1526 case TYPESPEC_FLOAT:
1527 case TYPESPEC_DOUBLE:
1528 case TYPESPEC_SIGNED:
1529 case TYPESPEC_UNSIGNED:
1530 case TYPESPEC_BOOL:
1531 case TYPESPEC_COMPLEX:
1532 case TYPESPEC_IMAGINARY:
1533 case TYPESPEC_CONST:
1534 case TYPESPEC_ID_TYPE:
1535 return ctf_declaration_type_specifier_visit(fd, depth,
1536 type_specifier_list, declaration_scope);
1537 default:
1538 fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) first->u.type_specifier.type);
1539 return NULL;
1540 }
1541}
1542
1543static
1544int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_event *event, struct ctf_trace *trace)
1545{
1546 int ret = 0;
1547
1548 switch (node->type) {
1549 case NODE_TYPEDEF:
1550 ret = ctf_typedef_visit(fd, depth + 1,
1551 event->declaration_scope,
1552 node->u._typedef.type_specifier_list,
1553 &node->u._typedef.type_declarators,
1554 trace);
1555 if (ret)
1556 return ret;
1557 break;
1558 case NODE_TYPEALIAS:
1559 ret = ctf_typealias_visit(fd, depth + 1,
1560 event->declaration_scope,
1561 node->u.typealias.target, node->u.typealias.alias,
1562 trace);
1563 if (ret)
1564 return ret;
1565 break;
1566 case NODE_CTF_EXPRESSION:
1567 {
1568 char *left;
1569
1570 left = concatenate_unary_strings(&node->u.ctf_expression.left);
1571 if (!strcmp(left, "name")) {
1572 char *right;
1573
1574 if (CTF_EVENT_FIELD_IS_SET(event, name)) {
1575 fprintf(fd, "[error] %s: name already declared in event declaration\n", __func__);
1576 ret = -EPERM;
1577 goto error;
1578 }
1579 right = concatenate_unary_strings(&node->u.ctf_expression.right);
1580 if (!right) {
1581 fprintf(fd, "[error] %s: unexpected unary expression for event name\n", __func__);
1582 ret = -EINVAL;
1583 goto error;
1584 }
1585 event->name = g_quark_from_string(right);
1586 g_free(right);
1587 CTF_EVENT_SET_FIELD(event, name);
1588 } else if (!strcmp(left, "id")) {
1589 if (CTF_EVENT_FIELD_IS_SET(event, id)) {
1590 fprintf(fd, "[error] %s: id already declared in event declaration\n", __func__);
1591 ret = -EPERM;
1592 goto error;
1593 }
1594 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->id);
1595 if (ret) {
1596 fprintf(fd, "[error] %s: unexpected unary expression for event id\n", __func__);
1597 ret = -EINVAL;
1598 goto error;
1599 }
1600 CTF_EVENT_SET_FIELD(event, id);
1601 } else if (!strcmp(left, "stream_id")) {
1602 if (CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
1603 fprintf(fd, "[error] %s: stream_id already declared in event declaration\n", __func__);
1604 ret = -EPERM;
1605 goto error;
1606 }
1607 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
1608 if (ret) {
1609 fprintf(fd, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
1610 ret = -EINVAL;
1611 goto error;
1612 }
1613 event->stream = trace_stream_lookup(trace, event->stream_id);
1614 if (!event->stream) {
1615 fprintf(fd, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id);
1616 ret = -EINVAL;
1617 goto error;
1618 }
1619 CTF_EVENT_SET_FIELD(event, stream_id);
1620 } else if (!strcmp(left, "context")) {
1621 struct declaration *declaration;
1622
1623 if (event->context_decl) {
1624 fprintf(fd, "[error] %s: context already declared in event declaration\n", __func__);
1625 ret = -EINVAL;
1626 goto error;
1627 }
1628 declaration = ctf_type_specifier_list_visit(fd, depth,
1629 _cds_list_first_entry(&node->u.ctf_expression.right,
1630 struct ctf_node, siblings),
1631 event->declaration_scope, trace);
1632 if (!declaration) {
1633 ret = -EPERM;
1634 goto error;
1635 }
1636 if (declaration->id != CTF_TYPE_STRUCT) {
1637 ret = -EPERM;
1638 goto error;
1639 }
1640 event->context_decl = container_of(declaration, struct declaration_struct, p);
1641 } else if (!strcmp(left, "fields")) {
1642 struct declaration *declaration;
1643
1644 if (event->fields_decl) {
1645 fprintf(fd, "[error] %s: fields already declared in event declaration\n", __func__);
1646 ret = -EINVAL;
1647 goto error;
1648 }
1649 declaration = ctf_type_specifier_list_visit(fd, depth,
1650 _cds_list_first_entry(&node->u.ctf_expression.right,
1651 struct ctf_node, siblings),
1652 event->declaration_scope, trace);
1653 if (!declaration) {
1654 ret = -EPERM;
1655 goto error;
1656 }
1657 if (declaration->id != CTF_TYPE_STRUCT) {
1658 ret = -EPERM;
1659 goto error;
1660 }
1661 event->fields_decl = container_of(declaration, struct declaration_struct, p);
1662 } else if (!strcmp(left, "loglevel")) {
1663 int64_t loglevel = -1;
1664
1665 if (CTF_EVENT_FIELD_IS_SET(event, loglevel)) {
1666 fprintf(fd, "[error] %s: loglevel already declared in event declaration\n", __func__);
1667 ret = -EPERM;
1668 goto error;
1669 }
1670 ret = get_unary_signed(&node->u.ctf_expression.right, &loglevel);
1671 if (ret) {
1672 fprintf(fd, "[error] %s: unexpected unary expression for event loglevel\n", __func__);
1673 ret = -EINVAL;
1674 goto error;
1675 }
1676 event->loglevel = (int) loglevel;
1677 CTF_EVENT_SET_FIELD(event, loglevel);
1678 } else {
1679 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
1680 /* Fall-through after warning */
1681 }
1682error:
1683 g_free(left);
1684 break;
1685 }
1686 default:
1687 return -EPERM;
1688 /* TODO: declaration specifier should be added. */
1689 }
1690
1691 return ret;
1692}
1693
1694static
1695int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
1696 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
1697{
1698 int ret = 0;
1699 struct ctf_node *iter;
1700 struct ctf_event *event;
1701
1702 event = g_new0(struct ctf_event, 1);
1703 event->declaration_scope = new_declaration_scope(parent_declaration_scope);
1704 event->loglevel = -1;
1705 cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) {
1706 ret = ctf_event_declaration_visit(fd, depth + 1, iter, event, trace);
1707 if (ret)
1708 goto error;
1709 }
1710 if (!CTF_EVENT_FIELD_IS_SET(event, name)) {
1711 ret = -EPERM;
1712 fprintf(fd, "[error] %s: missing name field in event declaration\n", __func__);
1713 goto error;
1714 }
1715 if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
1716 /* Allow missing stream_id if there is only a single stream */
1717 switch (trace->streams->len) {
1718 case 0: /* Create stream if there was none. */
1719 ret = ctf_stream_visit(fd, depth, NULL, trace->root_declaration_scope, trace);
1720 if (ret)
1721 goto error;
1722 /* Fall-through */
1723 case 1:
1724 event->stream_id = 0;
1725 event->stream = trace_stream_lookup(trace, event->stream_id);
1726 break;
1727 default:
1728 ret = -EPERM;
1729 fprintf(fd, "[error] %s: missing stream_id field in event declaration\n", __func__);
1730 goto error;
1731 }
1732 }
1733 /* Allow only one event without id per stream */
1734 if (!CTF_EVENT_FIELD_IS_SET(event, id)
1735 && event->stream->events_by_id->len != 0) {
1736 ret = -EPERM;
1737 fprintf(fd, "[error] %s: missing id field in event declaration\n", __func__);
1738 goto error;
1739 }
1740 if (event->stream->events_by_id->len <= event->id)
1741 g_ptr_array_set_size(event->stream->events_by_id, event->id + 1);
1742 g_ptr_array_index(event->stream->events_by_id, event->id) = event;
1743 g_hash_table_insert(event->stream->event_quark_to_id,
1744 (gpointer) (unsigned long) event->name,
1745 &event->id);
1746 return 0;
1747
1748error:
1749 if (event->fields_decl)
1750 declaration_unref(&event->fields_decl->p);
1751 if (event->context_decl)
1752 declaration_unref(&event->context_decl->p);
1753 free_declaration_scope(event->declaration_scope);
1754 g_free(event);
1755 return ret;
1756}
1757
1758
1759static
1760int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream_class *stream, struct ctf_trace *trace)
1761{
1762 int ret = 0;
1763
1764 switch (node->type) {
1765 case NODE_TYPEDEF:
1766 ret = ctf_typedef_visit(fd, depth + 1,
1767 stream->declaration_scope,
1768 node->u._typedef.type_specifier_list,
1769 &node->u._typedef.type_declarators,
1770 trace);
1771 if (ret)
1772 return ret;
1773 break;
1774 case NODE_TYPEALIAS:
1775 ret = ctf_typealias_visit(fd, depth + 1,
1776 stream->declaration_scope,
1777 node->u.typealias.target, node->u.typealias.alias,
1778 trace);
1779 if (ret)
1780 return ret;
1781 break;
1782 case NODE_CTF_EXPRESSION:
1783 {
1784 char *left;
1785
1786 left = concatenate_unary_strings(&node->u.ctf_expression.left);
1787 if (!strcmp(left, "id")) {
1788 if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) {
1789 fprintf(fd, "[error] %s: id already declared in stream declaration\n", __func__);
1790 ret = -EPERM;
1791 goto error;
1792 }
1793 ret = get_unary_unsigned(&node->u.ctf_expression.right, &stream->stream_id);
1794 if (ret) {
1795 fprintf(fd, "[error] %s: unexpected unary expression for stream id\n", __func__);
1796 ret = -EINVAL;
1797 goto error;
1798 }
1799 CTF_STREAM_SET_FIELD(stream, stream_id);
1800 } else if (!strcmp(left, "event.header")) {
1801 struct declaration *declaration;
1802
1803 if (stream->event_header_decl) {
1804 fprintf(fd, "[error] %s: event.header already declared in stream declaration\n", __func__);
1805 ret = -EINVAL;
1806 goto error;
1807 }
1808 declaration = ctf_type_specifier_list_visit(fd, depth,
1809 _cds_list_first_entry(&node->u.ctf_expression.right,
1810 struct ctf_node, siblings),
1811 stream->declaration_scope, trace);
1812 if (!declaration) {
1813 ret = -EPERM;
1814 goto error;
1815 }
1816 if (declaration->id != CTF_TYPE_STRUCT) {
1817 ret = -EPERM;
1818 goto error;
1819 }
1820 stream->event_header_decl = container_of(declaration, struct declaration_struct, p);
1821 } else if (!strcmp(left, "event.context")) {
1822 struct declaration *declaration;
1823
1824 if (stream->event_context_decl) {
1825 fprintf(fd, "[error] %s: event.context already declared in stream declaration\n", __func__);
1826 ret = -EINVAL;
1827 goto error;
1828 }
1829 declaration = ctf_type_specifier_list_visit(fd, depth,
1830 _cds_list_first_entry(&node->u.ctf_expression.right,
1831 struct ctf_node, siblings),
1832 stream->declaration_scope, trace);
1833 if (!declaration) {
1834 ret = -EPERM;
1835 goto error;
1836 }
1837 if (declaration->id != CTF_TYPE_STRUCT) {
1838 ret = -EPERM;
1839 goto error;
1840 }
1841 stream->event_context_decl = container_of(declaration, struct declaration_struct, p);
1842 } else if (!strcmp(left, "packet.context")) {
1843 struct declaration *declaration;
1844
1845 if (stream->packet_context_decl) {
1846 fprintf(fd, "[error] %s: packet.context already declared in stream declaration\n", __func__);
1847 ret = -EINVAL;
1848 goto error;
1849 }
1850 declaration = ctf_type_specifier_list_visit(fd, depth,
1851 _cds_list_first_entry(&node->u.ctf_expression.right,
1852 struct ctf_node, siblings),
1853 stream->declaration_scope, trace);
1854 if (!declaration) {
1855 ret = -EPERM;
1856 goto error;
1857 }
1858 if (declaration->id != CTF_TYPE_STRUCT) {
1859 ret = -EPERM;
1860 goto error;
1861 }
1862 stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
1863 } else {
1864 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left);
1865 /* Fall-through after warning */
1866 }
1867
1868error:
1869 g_free(left);
1870 break;
1871 }
1872 default:
1873 return -EPERM;
1874 /* TODO: declaration specifier should be added. */
1875 }
1876
1877 return ret;
1878}
1879
1880static
1881int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
1882 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
1883{
1884 int ret = 0;
1885 struct ctf_node *iter;
1886 struct ctf_stream_class *stream;
1887
1888 stream = g_new0(struct ctf_stream_class, 1);
1889 stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
1890 stream->events_by_id = g_ptr_array_new();
1891 stream->event_quark_to_id = g_hash_table_new(g_direct_hash, g_direct_equal);
1892 stream->streams = g_ptr_array_new();
1893 if (node) {
1894 cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
1895 ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
1896 if (ret)
1897 goto error;
1898 }
1899 }
1900 if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) {
1901 /* check that packet header has stream_id field. */
1902 if (!trace->packet_header_decl
1903 || struct_declaration_lookup_field_index(trace->packet_header_decl, g_quark_from_static_string("stream_id")) < 0) {
1904 ret = -EPERM;
1905 fprintf(fd, "[error] %s: missing stream_id field in packet header declaration, but stream_id attribute is declared for stream.\n", __func__);
1906 goto error;
1907 }
1908 } else {
1909 /* Allow only one id-less stream */
1910 if (trace->streams->len != 0) {
1911 ret = -EPERM;
1912 fprintf(fd, "[error] %s: missing id field in stream declaration\n", __func__);
1913 goto error;
1914 }
1915 stream->stream_id = 0;
1916 }
1917 if (trace->streams->len <= stream->stream_id)
1918 g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
1919 g_ptr_array_index(trace->streams, stream->stream_id) = stream;
1920 stream->trace = trace;
1921
1922 return 0;
1923
1924error:
1925 if (stream->event_header_decl)
1926 declaration_unref(&stream->event_header_decl->p);
1927 if (stream->event_context_decl)
1928 declaration_unref(&stream->event_context_decl->p);
1929 if (stream->packet_context_decl)
1930 declaration_unref(&stream->packet_context_decl->p);
1931 g_ptr_array_free(stream->streams, TRUE);
1932 g_ptr_array_free(stream->events_by_id, TRUE);
1933 g_hash_table_destroy(stream->event_quark_to_id);
1934 free_declaration_scope(stream->declaration_scope);
1935 g_free(stream);
1936 return ret;
1937}
1938
1939static
1940int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
1941{
1942 int ret = 0;
1943
1944 switch (node->type) {
1945 case NODE_TYPEDEF:
1946 ret = ctf_typedef_visit(fd, depth + 1,
1947 trace->declaration_scope,
1948 node->u._typedef.type_specifier_list,
1949 &node->u._typedef.type_declarators,
1950 trace);
1951 if (ret)
1952 return ret;
1953 break;
1954 case NODE_TYPEALIAS:
1955 ret = ctf_typealias_visit(fd, depth + 1,
1956 trace->declaration_scope,
1957 node->u.typealias.target, node->u.typealias.alias,
1958 trace);
1959 if (ret)
1960 return ret;
1961 break;
1962 case NODE_CTF_EXPRESSION:
1963 {
1964 char *left;
1965
1966 left = concatenate_unary_strings(&node->u.ctf_expression.left);
1967 if (!strcmp(left, "major")) {
1968 if (CTF_TRACE_FIELD_IS_SET(trace, major)) {
1969 fprintf(fd, "[error] %s: major already declared in trace declaration\n", __func__);
1970 ret = -EPERM;
1971 goto error;
1972 }
1973 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->major);
1974 if (ret) {
1975 fprintf(fd, "[error] %s: unexpected unary expression for trace major number\n", __func__);
1976 ret = -EINVAL;
1977 goto error;
1978 }
1979 CTF_TRACE_SET_FIELD(trace, major);
1980 } else if (!strcmp(left, "minor")) {
1981 if (CTF_TRACE_FIELD_IS_SET(trace, minor)) {
1982 fprintf(fd, "[error] %s: minor already declared in trace declaration\n", __func__);
1983 ret = -EPERM;
1984 goto error;
1985 }
1986 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->minor);
1987 if (ret) {
1988 fprintf(fd, "[error] %s: unexpected unary expression for trace minor number\n", __func__);
1989 ret = -EINVAL;
1990 goto error;
1991 }
1992 CTF_TRACE_SET_FIELD(trace, minor);
1993 } else if (!strcmp(left, "uuid")) {
1994 uuid_t uuid;
1995
1996 ret = get_unary_uuid(&node->u.ctf_expression.right, &uuid);
1997 if (ret) {
1998 fprintf(fd, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
1999 ret = -EINVAL;
2000 goto error;
2001 }
2002 if (CTF_TRACE_FIELD_IS_SET(trace, uuid)
2003 && uuid_compare(uuid, trace->uuid)) {
2004 fprintf(fd, "[error] %s: uuid mismatch\n", __func__);
2005 ret = -EPERM;
2006 goto error;
2007 } else {
2008 memcpy(trace->uuid, uuid, sizeof(uuid));
2009 }
2010 CTF_TRACE_SET_FIELD(trace, uuid);
2011 } else if (!strcmp(left, "byte_order")) {
2012 struct ctf_node *right;
2013 int byte_order;
2014
2015 right = _cds_list_first_entry(&node->u.ctf_expression.right, struct ctf_node, siblings);
2016 byte_order = get_trace_byte_order(fd, depth, right);
2017 if (byte_order < 0)
2018 return -EINVAL;
2019
2020 if (CTF_TRACE_FIELD_IS_SET(trace, byte_order)
2021 && byte_order != trace->byte_order) {
2022 fprintf(fd, "[error] %s: endianness mismatch\n", __func__);
2023 ret = -EPERM;
2024 goto error;
2025 } else {
2026 if (byte_order != trace->byte_order) {
2027 trace->byte_order = byte_order;
2028 /*
2029 * We need to restart
2030 * construction of the
2031 * intermediate representation.
2032 */
2033 trace->field_mask = 0;
2034 CTF_TRACE_SET_FIELD(trace, byte_order);
2035 ret = -EINTR;
2036 goto error;
2037 }
2038 }
2039 CTF_TRACE_SET_FIELD(trace, byte_order);
2040 } else if (!strcmp(left, "packet.header")) {
2041 struct declaration *declaration;
2042
2043 if (trace->packet_header_decl) {
2044 fprintf(fd, "[error] %s: packet.header already declared in trace declaration\n", __func__);
2045 ret = -EINVAL;
2046 goto error;
2047 }
2048 declaration = ctf_type_specifier_list_visit(fd, depth,
2049 _cds_list_first_entry(&node->u.ctf_expression.right,
2050 struct ctf_node, siblings),
2051 trace->declaration_scope, trace);
2052 if (!declaration) {
2053 ret = -EPERM;
2054 goto error;
2055 }
2056 if (declaration->id != CTF_TYPE_STRUCT) {
2057 ret = -EPERM;
2058 goto error;
2059 }
2060 trace->packet_header_decl = container_of(declaration, struct declaration_struct, p);
2061 } else {
2062 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left);
2063 }
2064
2065error:
2066 g_free(left);
2067 break;
2068 }
2069 default:
2070 return -EPERM;
2071 /* TODO: declaration specifier should be added. */
2072 }
2073
2074 return ret;
2075}
2076
2077static
2078int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
2079{
2080 int ret = 0;
2081 struct ctf_node *iter;
2082
2083 if (trace->declaration_scope)
2084 return -EEXIST;
2085 trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope);
2086 trace->streams = g_ptr_array_new();
2087 cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) {
2088 ret = ctf_trace_declaration_visit(fd, depth + 1, iter, trace);
2089 if (ret)
2090 goto error;
2091 }
2092 if (!CTF_TRACE_FIELD_IS_SET(trace, major)) {
2093 ret = -EPERM;
2094 fprintf(fd, "[error] %s: missing major field in trace declaration\n", __func__);
2095 goto error;
2096 }
2097 if (!CTF_TRACE_FIELD_IS_SET(trace, minor)) {
2098 ret = -EPERM;
2099 fprintf(fd, "[error] %s: missing minor field in trace declaration\n", __func__);
2100 goto error;
2101 }
2102 if (!CTF_TRACE_FIELD_IS_SET(trace, uuid)) {
2103 ret = -EPERM;
2104 fprintf(fd, "[error] %s: missing uuid field in trace declaration\n", __func__);
2105 goto error;
2106 }
2107 if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
2108 ret = -EPERM;
2109 fprintf(fd, "[error] %s: missing byte_order field in trace declaration\n", __func__);
2110 goto error;
2111 }
2112
2113 if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
2114 /* check that the packet header contains a "magic" field */
2115 if (!trace->packet_header_decl
2116 || struct_declaration_lookup_field_index(trace->packet_header_decl, g_quark_from_static_string("magic")) < 0) {
2117 ret = -EPERM;
2118 fprintf(fd, "[error] %s: missing both byte_order and packet header magic number in trace declaration\n", __func__);
2119 goto error;
2120 }
2121 }
2122 return 0;
2123
2124error:
2125 if (trace->packet_header_decl) {
2126 declaration_unref(&trace->packet_header_decl->p);
2127 trace->packet_header_decl = NULL;
2128 }
2129 g_ptr_array_free(trace->streams, TRUE);
2130 free_declaration_scope(trace->declaration_scope);
2131 trace->declaration_scope = NULL;
2132 return ret;
2133}
2134
2135static
2136int ctf_clock_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
2137 struct ctf_clock *clock, struct ctf_trace *trace)
2138{
2139 int ret = 0;
2140
2141 switch (node->type) {
2142 case NODE_CTF_EXPRESSION:
2143 {
2144 char *left;
2145
2146 left = concatenate_unary_strings(&node->u.ctf_expression.left);
2147 if (!strcmp(left, "name")) {
2148 char *right;
2149
2150 if (CTF_CLOCK_FIELD_IS_SET(clock, name)) {
2151 fprintf(fd, "[error] %s: name already declared in clock declaration\n", __func__);
2152 ret = -EPERM;
2153 goto error;
2154 }
2155 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2156 if (!right) {
2157 fprintf(fd, "[error] %s: unexpected unary expression for clock name\n", __func__);
2158 ret = -EINVAL;
2159 goto error;
2160 }
2161 clock->name = g_quark_from_string(right);
2162 g_free(right);
2163 CTF_EVENT_SET_FIELD(clock, name);
2164 } else if (!strcmp(left, "uuid")) {
2165 char *right;
2166
2167 if (clock->uuid) {
2168 fprintf(fd, "[error] %s: uuid already declared in clock declaration\n", __func__);
2169 ret = -EPERM;
2170 goto error;
2171 }
2172 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2173 if (!right) {
2174 fprintf(fd, "[error] %s: unexpected unary expression for clock uuid\n", __func__);
2175 ret = -EINVAL;
2176 goto error;
2177 }
2178 clock->uuid = g_quark_from_string(right);
2179 g_free(right);
2180 } else if (!strcmp(left, "description")) {
2181 char *right;
2182
2183 if (clock->description) {
2184 fprintf(fd, "[warning] %s: duplicated clock description\n", __func__);
2185 goto error; /* ret is 0, so not an actual error, just warn. */
2186 }
2187 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2188 if (!right) {
2189 fprintf(fd, "[warning] %s: unexpected unary expression for clock description\n", __func__);
2190 goto error; /* ret is 0, so not an actual error, just warn. */
2191 }
2192 clock->description = right;
2193 } else if (!strcmp(left, "freq")) {
2194 if (clock->freq) {
2195 fprintf(fd, "[error] %s: freq already declared in clock declaration\n", __func__);
2196 ret = -EPERM;
2197 goto error;
2198 }
2199 ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->freq);
2200 if (ret) {
2201 fprintf(fd, "[error] %s: unexpected unary expression for clock freq\n", __func__);
2202 ret = -EINVAL;
2203 goto error;
2204 }
2205 } else if (!strcmp(left, "precision")) {
2206 if (clock->precision) {
2207 fprintf(fd, "[error] %s: precision already declared in clock declaration\n", __func__);
2208 ret = -EPERM;
2209 goto error;
2210 }
2211 ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->precision);
2212 if (ret) {
2213 fprintf(fd, "[error] %s: unexpected unary expression for clock precision\n", __func__);
2214 ret = -EINVAL;
2215 goto error;
2216 }
2217 } else if (!strcmp(left, "offset_s")) {
2218 if (clock->offset_s) {
2219 fprintf(fd, "[error] %s: offset_s already declared in clock declaration\n", __func__);
2220 ret = -EPERM;
2221 goto error;
2222 }
2223 ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset_s);
2224 if (ret) {
2225 fprintf(fd, "[error] %s: unexpected unary expression for clock offset_s\n", __func__);
2226 ret = -EINVAL;
2227 goto error;
2228 }
2229 } else if (!strcmp(left, "offset")) {
2230 if (clock->offset) {
2231 fprintf(fd, "[error] %s: offset already declared in clock declaration\n", __func__);
2232 ret = -EPERM;
2233 goto error;
2234 }
2235 ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset);
2236 if (ret) {
2237 fprintf(fd, "[error] %s: unexpected unary expression for clock offset\n", __func__);
2238 ret = -EINVAL;
2239 goto error;
2240 }
2241 } else if (!strcmp(left, "absolute")) {
2242 struct ctf_node *right;
2243
2244 right = _cds_list_first_entry(&node->u.ctf_expression.right, struct ctf_node, siblings);
2245 ret = get_boolean(fd, depth, right);
2246 if (ret < 0) {
2247 fprintf(fd, "[error] %s: unexpected \"absolute\" right member\n", __func__);
2248 ret = -EINVAL;
2249 goto error;
2250 }
2251 clock->absolute = ret;
2252 } else {
2253 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in clock declaration.\n", __func__, left);
2254 }
2255
2256error:
2257 g_free(left);
2258 break;
2259 }
2260 default:
2261 return -EPERM;
2262 /* TODO: declaration specifier should be added. */
2263 }
2264
2265 return ret;
2266}
2267
2268static
2269int ctf_clock_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
2270{
2271 int ret = 0;
2272 struct ctf_node *iter;
2273 struct ctf_clock *clock;
2274
2275 clock = g_new0(struct ctf_clock, 1);
2276 cds_list_for_each_entry(iter, &node->u.clock.declaration_list, siblings) {
2277 ret = ctf_clock_declaration_visit(fd, depth + 1, iter, clock, trace);
2278 if (ret)
2279 goto error;
2280 }
2281 if (!CTF_CLOCK_FIELD_IS_SET(clock, name)) {
2282 ret = -EPERM;
2283 fprintf(fd, "[error] %s: missing namefield in clock declaration\n", __func__);
2284 goto error;
2285 }
2286 g_hash_table_insert(trace->clocks, (gpointer) (unsigned long) clock->name, clock);
2287 return 0;
2288
2289error:
2290 g_free(clock->description);
2291 g_free(clock);
2292 return ret;
2293}
2294
2295static
2296void clock_free(gpointer data)
2297{
2298 struct ctf_clock *clock = data;
2299
2300 g_free(clock->description);
2301 g_free(clock);
2302}
2303
2304static
2305int ctf_env_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
2306 struct ctf_trace *trace)
2307{
2308 int ret = 0;
2309 struct ctf_tracer_env *env = &trace->env;
2310
2311 switch (node->type) {
2312 case NODE_CTF_EXPRESSION:
2313 {
2314 char *left;
2315
2316 left = concatenate_unary_strings(&node->u.ctf_expression.left);
2317 if (!strcmp(left, "vpid")) {
2318 uint64_t v;
2319
2320 if (env->vpid != -1) {
2321 fprintf(fd, "[error] %s: vpid already declared in env declaration\n", __func__);
2322 goto error; /* ret is 0, so not an actual error, just warn. */
2323 }
2324 ret = get_unary_unsigned(&node->u.ctf_expression.right, &v);
2325 if (ret) {
2326 fprintf(fd, "[error] %s: unexpected unary expression for env vpid\n", __func__);
2327 goto error; /* ret is 0, so not an actual error, just warn. */
2328 }
2329 env->vpid = (int) v;
2330 printf_verbose("env.vpid = %d\n", env->vpid);
2331 } else if (!strcmp(left, "procname")) {
2332 char *right;
2333
2334 if (env->procname[0]) {
2335 fprintf(fd, "[warning] %s: duplicated env procname\n", __func__);
2336 goto error; /* ret is 0, so not an actual error, just warn. */
2337 }
2338 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2339 if (!right) {
2340 fprintf(fd, "[warning] %s: unexpected unary expression for env procname\n", __func__);
2341 goto error; /* ret is 0, so not an actual error, just warn. */
2342 }
2343 strncpy(env->procname, right, TRACER_ENV_LEN);
2344 env->procname[TRACER_ENV_LEN - 1] = '\0';
2345 printf_verbose("env.procname = %s\n", env->procname);
2346 } else if (!strcmp(left, "domain")) {
2347 char *right;
2348
2349 if (env->domain[0]) {
2350 fprintf(fd, "[warning] %s: duplicated env domain\n", __func__);
2351 goto error; /* ret is 0, so not an actual error, just warn. */
2352 }
2353 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2354 if (!right) {
2355 fprintf(fd, "[warning] %s: unexpected unary expression for env domain\n", __func__);
2356 goto error; /* ret is 0, so not an actual error, just warn. */
2357 }
2358 strncpy(env->domain, right, TRACER_ENV_LEN);
2359 env->domain[TRACER_ENV_LEN - 1] = '\0';
2360 printf_verbose("env.domain = %s\n", env->domain);
2361 } else if (!strcmp(left, "sysname")) {
2362 char *right;
2363
2364 if (env->sysname[0]) {
2365 fprintf(fd, "[warning] %s: duplicated env sysname\n", __func__);
2366 goto error; /* ret is 0, so not an actual error, just warn. */
2367 }
2368 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2369 if (!right) {
2370 fprintf(fd, "[warning] %s: unexpected unary expression for env sysname\n", __func__);
2371 goto error; /* ret is 0, so not an actual error, just warn. */
2372 }
2373 strncpy(env->sysname, right, TRACER_ENV_LEN);
2374 env->sysname[TRACER_ENV_LEN - 1] = '\0';
2375 printf_verbose("env.sysname = %s\n", env->sysname);
2376 } else if (!strcmp(left, "release")) {
2377 char *right;
2378
2379 if (env->release[0]) {
2380 fprintf(fd, "[warning] %s: duplicated env release\n", __func__);
2381 goto error; /* ret is 0, so not an actual error, just warn. */
2382 }
2383 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2384 if (!right) {
2385 fprintf(fd, "[warning] %s: unexpected unary expression for env release\n", __func__);
2386 goto error; /* ret is 0, so not an actual error, just warn. */
2387 }
2388 strncpy(env->release, right, TRACER_ENV_LEN);
2389 env->release[TRACER_ENV_LEN - 1] = '\0';
2390 printf_verbose("env.release = %s\n", env->release);
2391 } else if (!strcmp(left, "version")) {
2392 char *right;
2393
2394 if (env->version[0]) {
2395 fprintf(fd, "[warning] %s: duplicated env version\n", __func__);
2396 goto error; /* ret is 0, so not an actual error, just warn. */
2397 }
2398 right = concatenate_unary_strings(&node->u.ctf_expression.right);
2399 if (!right) {
2400 fprintf(fd, "[warning] %s: unexpected unary expression for env version\n", __func__);
2401 goto error; /* ret is 0, so not an actual error, just warn. */
2402 }
2403 strncpy(env->version, right, TRACER_ENV_LEN);
2404 env->version[TRACER_ENV_LEN - 1] = '\0';
2405 printf_verbose("env.version = %s\n", env->version);
2406 } else {
2407 printf_verbose("%s: attribute \"%s\" is unknown in environment declaration.\n", __func__, left);
2408 }
2409
2410error:
2411 g_free(left);
2412 break;
2413 }
2414 default:
2415 return -EPERM;
2416 }
2417
2418 return ret;
2419}
2420
2421static
2422int ctf_env_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
2423{
2424 int ret = 0;
2425 struct ctf_node *iter;
2426
2427 trace->env.vpid = -1;
2428 trace->env.procname[0] = '\0';
2429 trace->env.domain[0] = '\0';
2430 trace->env.sysname[0] = '\0';
2431 trace->env.release[0] = '\0';
2432 trace->env.version[0] = '\0';
2433 cds_list_for_each_entry(iter, &node->u.env.declaration_list, siblings) {
2434 ret = ctf_env_declaration_visit(fd, depth + 1, iter, trace);
2435 if (ret)
2436 goto error;
2437 }
2438error:
2439 return 0;
2440}
2441
2442static
2443int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
2444{
2445 int ret = 0;
2446
2447 switch (node->type) {
2448 case NODE_TYPEDEF:
2449 ret = ctf_typedef_visit(fd, depth + 1,
2450 trace->root_declaration_scope,
2451 node->u._typedef.type_specifier_list,
2452 &node->u._typedef.type_declarators,
2453 trace);
2454 if (ret)
2455 return ret;
2456 break;
2457 case NODE_TYPEALIAS:
2458 ret = ctf_typealias_visit(fd, depth + 1,
2459 trace->root_declaration_scope,
2460 node->u.typealias.target, node->u.typealias.alias,
2461 trace);
2462 if (ret)
2463 return ret;
2464 break;
2465 case NODE_TYPE_SPECIFIER_LIST:
2466 {
2467 struct declaration *declaration;
2468
2469 /*
2470 * Just add the type specifier to the root scope
2471 * declaration scope. Release local reference.
2472 */
2473 declaration = ctf_type_specifier_list_visit(fd, depth + 1,
2474 node, trace->root_declaration_scope, trace);
2475 if (!declaration)
2476 return -ENOMEM;
2477 declaration_unref(declaration);
2478 break;
2479 }
2480 default:
2481 return -EPERM;
2482 }
2483
2484 return 0;
2485}
2486
2487/* TODO: missing metadata "destroy" (memory leak) */
2488int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
2489 struct ctf_trace *trace, int byte_order)
2490{
2491 int ret = 0;
2492 struct ctf_node *iter;
2493 int env_clock_done = 0;
2494
2495 printf_verbose("CTF visitor: metadata construction... ");
2496 trace->byte_order = byte_order;
2497 trace->clocks = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2498 NULL, clock_free);
2499
2500retry:
2501 trace->root_declaration_scope = new_declaration_scope(NULL);
2502
2503 switch (node->type) {
2504 case NODE_ROOT:
2505 if (!env_clock_done) {
2506 /*
2507 * declarations need to query clock hash table,
2508 * so clock need to be treated first.
2509 */
2510 cds_list_for_each_entry(iter, &node->u.root.clock, siblings) {
2511 ret = ctf_clock_visit(fd, depth + 1, iter,
2512 trace);
2513 if (ret) {
2514 fprintf(fd, "[error] %s: clock declaration error\n", __func__);
2515 goto error;
2516 }
2517 }
2518 env_clock_done = 1;
2519 }
2520 cds_list_for_each_entry(iter, &node->u.root.declaration_list,
2521 siblings) {
2522 ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace);
2523 if (ret) {
2524 fprintf(fd, "[error] %s: root declaration error\n", __func__);
2525 goto error;
2526 }
2527 }
2528 cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
2529 ret = ctf_trace_visit(fd, depth + 1, iter, trace);
2530 if (ret == -EINTR) {
2531 free_declaration_scope(trace->root_declaration_scope);
2532 /*
2533 * Need to restart creation of type
2534 * definitions, aliases and
2535 * trace header declarations.
2536 */
2537 goto retry;
2538 }
2539 if (ret) {
2540 fprintf(fd, "[error] %s: trace declaration error\n", __func__);
2541 goto error;
2542 }
2543 }
2544 if (!trace->streams) {
2545 fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
2546 ret = -EINVAL;
2547 goto error;
2548 }
2549 cds_list_for_each_entry(iter, &node->u.root.env, siblings) {
2550 ret = ctf_env_visit(fd, depth + 1, iter, trace);
2551 if (ret) {
2552 fprintf(fd, "[error] %s: env declaration error\n", __func__);
2553 goto error;
2554 }
2555 }
2556 cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
2557 ret = ctf_stream_visit(fd, depth + 1, iter,
2558 trace->root_declaration_scope, trace);
2559 if (ret) {
2560 fprintf(fd, "[error] %s: stream declaration error\n", __func__);
2561 goto error;
2562 }
2563 }
2564 cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
2565 ret = ctf_event_visit(fd, depth + 1, iter,
2566 trace->root_declaration_scope, trace);
2567 if (ret) {
2568 fprintf(fd, "[error] %s: event declaration error\n", __func__);
2569 goto error;
2570 }
2571 }
2572 break;
2573 case NODE_UNKNOWN:
2574 default:
2575 fprintf(fd, "[error] %s: unknown node type %d\n", __func__,
2576 (int) node->type);
2577 ret = -EINVAL;
2578 goto error;
2579 }
2580 printf_verbose("done.\n");
2581 return ret;
2582
2583error:
2584 free_declaration_scope(trace->root_declaration_scope);
2585 g_hash_table_destroy(trace->clocks);
2586 return ret;
2587}
This page took 0.083776 seconds and 4 git commands to generate.