Show env. in verbose mode
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
CommitLineData
05628561
MD
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>
add40b62 26#include <endian.h>
05628561 27#include <errno.h>
70bd0a12 28#include <babeltrace/babeltrace-internal.h>
05628561 29#include <babeltrace/list.h>
a0720417
MD
30#include <babeltrace/types.h>
31#include <babeltrace/ctf/metadata.h>
41253107 32#include <uuid/uuid.h>
05628561
MD
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
de47353a
MD
39#define _cds_list_first_entry(ptr, type, member) \
40 cds_list_entry((ptr)->next, type, member)
05628561 41
a3cca9e9 42static
78af2bcd
MD
43struct declaration *ctf_type_specifier_list_visit(FILE *fd,
44 int depth, struct ctf_node *type_specifier_list,
ab4cf058
MD
45 struct declaration_scope *declaration_scope,
46 struct ctf_trace *trace);
a3cca9e9 47
33105c61
MD
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
05628561 52/*
41253107 53 * String returned must be freed by the caller using g_free.
05628561
MD
54 */
55static
add40b62 56char *concatenate_unary_strings(struct cds_list_head *head)
05628561 57{
41253107
MD
58 struct ctf_node *node;
59 GString *str;
60 int i = 0;
61
a0720417 62 str = g_string_new("");
41253107
MD
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)
a0720417 69 ^ (i != 0));
41253107
MD
70 switch (node->u.unary_expression.link) {
71 case UNARY_DOTLINK:
a0720417 72 g_string_append(str, ".");
41253107
MD
73 break;
74 case UNARY_ARROWLINK:
a0720417 75 g_string_append(str, "->");
41253107
MD
76 break;
77 case UNARY_DOTDOTDOT:
a0720417
MD
78 g_string_append(str, "...");
79 break;
80 default:
41253107
MD
81 break;
82 }
a0720417 83 src_string = node->u.unary_expression.u.string;
41253107
MD
84 g_string_append(str, src_string);
85 i++;
86 }
87 return g_string_free(str, FALSE);
05628561
MD
88}
89
56e60373
MD
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
05628561 134static
add40b62 135int get_unary_unsigned(struct cds_list_head *head, uint64_t *value)
05628561 136{
41253107
MD
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);
a0720417 145 *value = node->u.unary_expression.u.unsigned_constant;
41253107
MD
146 i++;
147 }
148 return 0;
05628561
MD
149}
150
d86d62f8
MD
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);
209209be
MD
159 assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT
160 || node->u.unary_expression.type == UNARY_SIGNED_CONSTANT);
d86d62f8
MD
161 assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
162 assert(i == 0);
209209be
MD
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 }
d86d62f8
MD
173 i++;
174 }
175 return 0;
176}
177
05628561 178static
add40b62 179int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
05628561 180{
41253107
MD
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);
a0720417 192 src_string = node->u.unary_expression.u.string;
5c551b40 193 ret = uuid_parse(src_string, *uuid);
41253107
MD
194 }
195 return ret;
05628561
MD
196}
197
198static
aa6bffae 199struct ctf_stream_class *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
05628561
MD
200{
201 if (trace->streams->len <= stream_id)
202 return NULL;
203 return g_ptr_array_index(trace->streams, stream_id);
204}
205
56e60373
MD
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
add40b62 212static
78af2bcd
MD
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)
add40b62
MD
309{
310 struct ctf_node *iter;
311 int alias_item_nr = 0;
78af2bcd 312 int ret;
add40b62 313
78af2bcd 314 cds_list_for_each_entry(iter, &type_specifier_list->u.type_specifier_list.head, siblings) {
add40b62
MD
315 if (alias_item_nr != 0)
316 g_string_append(str, " ");
317 alias_item_nr++;
78af2bcd
MD
318 ret = visit_type_specifier(fd, iter, str);
319 if (ret)
320 return ret;
add40b62
MD
321 }
322 return 0;
add40b62
MD
323}
324
325static
8fdba45b 326GQuark create_typealias_identifier(FILE *fd, int depth,
78af2bcd 327 struct ctf_node *type_specifier_list,
add40b62
MD
328 struct ctf_node *node_type_declarator)
329{
a0720417 330 struct ctf_node *iter;
add40b62 331 GString *str;
a0720417 332 char *str_c;
add40b62
MD
333 GQuark alias_q;
334 int ret;
335
a0720417 336 str = g_string_new("");
78af2bcd 337 ret = visit_type_specifier_list(fd, type_specifier_list, str);
add40b62
MD
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
a3cca9e9 353static
8fdba45b 354struct declaration *ctf_type_declarator_visit(FILE *fd, int depth,
78af2bcd 355 struct ctf_node *type_specifier_list,
a3cca9e9
MD
356 GQuark *field_name,
357 struct ctf_node *node_type_declarator,
add40b62 358 struct declaration_scope *declaration_scope,
e397791f
MD
359 struct declaration *nested_declaration,
360 struct ctf_trace *trace)
a3cca9e9
MD
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
e397791f
MD
368 if (node_type_declarator) {
369 assert(node_type_declarator->u.type_declarator.type != TYPEDEC_UNKNOWN);
add40b62 370
e397791f
MD
371 /* TODO: gcc bitfields not supported yet. */
372 if (node_type_declarator->u.type_declarator.bitfield_len != NULL) {
78af2bcd 373 fprintf(fd, "[error] %s: gcc bitfields are not supported yet.\n", __func__);
e397791f
MD
374 return NULL;
375 }
add40b62 376 }
a3cca9e9
MD
377
378 if (!nested_declaration) {
e397791f 379 if (node_type_declarator && !cds_list_empty(&node_type_declarator->u.type_declarator.pointers)) {
add40b62
MD
380 GQuark alias_q;
381
a3cca9e9
MD
382 /*
383 * If we have a pointer declarator, it _has_ to be present in
384 * the typealiases (else fail).
385 */
add40b62 386 alias_q = create_typealias_identifier(fd, depth,
78af2bcd 387 type_specifier_list, node_type_declarator);
add40b62
MD
388 nested_declaration = lookup_declaration(alias_q, declaration_scope);
389 if (!nested_declaration) {
78af2bcd 390 fprintf(fd, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q));
add40b62
MD
391 return NULL;
392 }
4d5fc303
MD
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) */
2527e149
MD
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,
56e60373
MD
405 integer_declaration->p.alignment, 16, integer_declaration->encoding,
406 integer_declaration->clock);
2527e149
MD
407 nested_declaration = &integer_declaration->p;
408 }
4d5fc303 409 }
a3cca9e9 410 } else {
78af2bcd
MD
411 nested_declaration = ctf_type_specifier_list_visit(fd, depth,
412 type_specifier_list, declaration_scope, trace);
a3cca9e9 413 }
a3cca9e9
MD
414 }
415
e397791f
MD
416 if (!node_type_declarator)
417 return nested_declaration;
418
a3cca9e9
MD
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;
98df1c9f 427 struct ctf_node *first;
a3cca9e9
MD
428
429 /* TYPEDEC_NESTED */
430
b5bf4179
MD
431 if (!nested_declaration) {
432 fprintf(fd, "[error] %s: nested type is unknown.\n", __func__);
433 return NULL;
434 }
435
a3cca9e9 436 /* create array/sequence, pass nested_declaration as child. */
98df1c9f
MD
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__);
a0720417
MD
439 return NULL;
440 }
98df1c9f
MD
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:
a0720417
MD
447 {
448 struct declaration_array *array_declaration;
449 size_t len;
450
98df1c9f 451 len = first->u.unary_expression.u.unsigned_constant;
a0720417
MD
452 array_declaration = array_declaration_new(len, nested_declaration,
453 declaration_scope);
98df1c9f
MD
454
455 if (!array_declaration) {
456 fprintf(fd, "[error] %s: cannot create array declaration.\n", __func__);
457 return NULL;
458 }
a0720417
MD
459 declaration = &array_declaration->p;
460 break;
461 }
98df1c9f 462 case UNARY_STRING:
a0720417 463 {
98df1c9f
MD
464 /* Lookup unsigned integer definition, create sequence */
465 char *length_name = concatenate_unary_strings(&node_type_declarator->u.type_declarator.u.nested.length);
a0720417 466 struct declaration_sequence *sequence_declaration;
a0720417 467
98df1c9f
MD
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__);
2dd46001
MD
471 return NULL;
472 }
a0720417
MD
473 declaration = &sequence_declaration->p;
474 break;
475 }
476 default:
477 assert(0);
a3cca9e9
MD
478 }
479
480 /* Pass it as content of outer container */
481 declaration = ctf_type_declarator_visit(fd, depth,
78af2bcd 482 type_specifier_list, field_name,
a3cca9e9 483 node_type_declarator->u.type_declarator.u.nested.type_declarator,
e397791f 484 declaration_scope, declaration, trace);
a3cca9e9
MD
485 return declaration;
486 }
487}
488
489static
8fdba45b 490int ctf_struct_type_declarators_visit(FILE *fd, int depth,
a3cca9e9 491 struct declaration_struct *struct_declaration,
78af2bcd 492 struct ctf_node *type_specifier_list,
a3cca9e9 493 struct cds_list_head *type_declarators,
e397791f
MD
494 struct declaration_scope *declaration_scope,
495 struct ctf_trace *trace)
a3cca9e9
MD
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,
78af2bcd 504 type_specifier_list,
a3cca9e9
MD
505 &field_name, iter,
506 struct_declaration->scope,
e397791f 507 NULL, trace);
2dd46001
MD
508 if (!field_declaration) {
509 fprintf(fd, "[error] %s: unable to find struct field declaration type\n", __func__);
510 return -EINVAL;
511 }
d3006d91
SM
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
a3cca9e9
MD
519 struct_declaration_add_field(struct_declaration,
520 g_quark_to_string(field_name),
521 field_declaration);
522 }
add40b62
MD
523 return 0;
524}
a3cca9e9 525
add40b62 526static
8fdba45b 527int ctf_variant_type_declarators_visit(FILE *fd, int depth,
a0720417 528 struct declaration_untagged_variant *untagged_variant_declaration,
78af2bcd 529 struct ctf_node *type_specifier_list,
add40b62 530 struct cds_list_head *type_declarators,
e397791f
MD
531 struct declaration_scope *declaration_scope,
532 struct ctf_trace *trace)
add40b62
MD
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,
78af2bcd 541 type_specifier_list,
add40b62 542 &field_name, iter,
a0720417 543 untagged_variant_declaration->scope,
e397791f 544 NULL, trace);
2dd46001
MD
545 if (!field_declaration) {
546 fprintf(fd, "[error] %s: unable to find variant field declaration type\n", __func__);
547 return -EINVAL;
548 }
43f9090c
SM
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
a0720417 556 untagged_variant_declaration_add_field(untagged_variant_declaration,
add40b62
MD
557 g_quark_to_string(field_name),
558 field_declaration);
559 }
a3cca9e9
MD
560 return 0;
561}
562
563static
8fdba45b 564int ctf_typedef_visit(FILE *fd, int depth, struct declaration_scope *scope,
78af2bcd 565 struct ctf_node *type_specifier_list,
e397791f
MD
566 struct cds_list_head *type_declarators,
567 struct ctf_trace *trace)
a3cca9e9
MD
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,
78af2bcd 577 type_specifier_list,
a3cca9e9 578 &identifier, iter,
e397791f 579 scope, NULL, trace);
2dd46001
MD
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 }
a3cca9e9
MD
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
8fdba45b 603int ctf_typealias_visit(FILE *fd, int depth, struct declaration_scope *scope,
e397791f
MD
604 struct ctf_node *target, struct ctf_node *alias,
605 struct ctf_trace *trace)
a3cca9e9
MD
606{
607 struct declaration *type_declaration;
a0720417 608 struct ctf_node *node;
add40b62 609 GQuark dummy_id;
a3cca9e9 610 GQuark alias_q;
a0720417 611 int err;
a3cca9e9
MD
612
613 /* See ctf_visitor_type_declarator() in the semantic validator. */
614
615 /*
616 * Create target type declaration.
617 */
618
427c09b7 619 if (cds_list_empty(&target->u.typealias_target.type_declarators))
a0720417
MD
620 node = NULL;
621 else
427c09b7 622 node = _cds_list_first_entry(&target->u.typealias_target.type_declarators,
a0720417 623 struct ctf_node, siblings);
a3cca9e9 624 type_declaration = ctf_type_declarator_visit(fd, depth,
78af2bcd 625 target->u.typealias_target.type_specifier_list,
a0720417 626 &dummy_id, node,
e397791f 627 scope, NULL, trace);
a3cca9e9 628 if (!type_declaration) {
78af2bcd 629 fprintf(fd, "[error] %s: problem creating type declaration\n", __func__);
a3cca9e9
MD
630 err = -EINVAL;
631 goto error;
632 }
2dd46001
MD
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 }
a3cca9e9
MD
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) {
78af2bcd 647 fprintf(fd, "[error] %s: expecting empty identifier\n", __func__);
a3cca9e9
MD
648 err = -EINVAL;
649 goto error;
650 }
651 /*
652 * Create alias identifier.
653 */
a3cca9e9
MD
654
655 node = _cds_list_first_entry(&alias->u.typealias_alias.type_declarators,
a0720417 656 struct ctf_node, siblings);
add40b62 657 alias_q = create_typealias_identifier(fd, depth,
78af2bcd 658 alias->u.typealias_alias.type_specifier_list, node);
a0720417
MD
659 err = register_declaration(alias_q, type_declaration, scope);
660 if (err)
a3cca9e9
MD
661 goto error;
662 return 0;
663
664error:
230da743
SM
665 if (type_declaration) {
666 type_declaration->declaration_free(type_declaration);
667 }
a0720417 668 return err;
a3cca9e9
MD
669}
670
671static
8fdba45b 672int ctf_struct_declaration_list_visit(FILE *fd, int depth,
e397791f
MD
673 struct ctf_node *iter, struct declaration_struct *struct_declaration,
674 struct ctf_trace *trace)
a3cca9e9 675{
a3cca9e9
MD
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,
78af2bcd 683 iter->u._typedef.type_specifier_list,
e397791f 684 &iter->u._typedef.type_declarators, trace);
a3cca9e9
MD
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,
e397791f 693 iter->u.typealias.alias, trace);
a3cca9e9
MD
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,
78af2bcd 701 iter->u.struct_or_variant_declaration.type_specifier_list,
a0720417
MD
702 &iter->u.struct_or_variant_declaration.type_declarators,
703 struct_declaration->scope, trace);
a3cca9e9
MD
704 if (ret)
705 return ret;
706 break;
707 default:
78af2bcd 708 fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
a3cca9e9
MD
709 assert(0);
710 }
711 return 0;
712}
713
add40b62 714static
8fdba45b 715int ctf_variant_declaration_list_visit(FILE *fd, int depth,
a0720417
MD
716 struct ctf_node *iter,
717 struct declaration_untagged_variant *untagged_variant_declaration,
e397791f 718 struct ctf_trace *trace)
add40b62 719{
add40b62
MD
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,
a0720417 726 untagged_variant_declaration->scope,
78af2bcd 727 iter->u._typedef.type_specifier_list,
e397791f 728 &iter->u._typedef.type_declarators, trace);
add40b62
MD
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,
a0720417 735 untagged_variant_declaration->scope,
add40b62 736 iter->u.typealias.target,
e397791f 737 iter->u.typealias.alias, trace);
add40b62
MD
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,
a0720417 744 untagged_variant_declaration,
78af2bcd 745 iter->u.struct_or_variant_declaration.type_specifier_list,
a0720417
MD
746 &iter->u.struct_or_variant_declaration.type_declarators,
747 untagged_variant_declaration->scope, trace);
add40b62
MD
748 if (ret)
749 return ret;
750 break;
751 default:
78af2bcd 752 fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
add40b62
MD
753 assert(0);
754 }
755 return 0;
756}
757
a3cca9e9 758static
a0720417 759struct declaration *ctf_declaration_struct_visit(FILE *fd,
a3cca9e9 760 int depth, const char *name, struct cds_list_head *declaration_list,
b7e35bad
MD
761 int has_body, struct cds_list_head *min_align,
762 struct declaration_scope *declaration_scope,
e397791f 763 struct ctf_trace *trace)
a3cca9e9 764{
a3cca9e9
MD
765 struct declaration_struct *struct_declaration;
766 struct ctf_node *iter;
a0720417 767 int ret;
a3cca9e9
MD
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);
a0720417 779 return &struct_declaration->p;
a3cca9e9 780 } else {
b7e35bad
MD
781 uint64_t min_align_value = 0;
782
a3cca9e9
MD
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
78af2bcd 789 fprintf(fd, "[error] %s: struct %s already declared in scope\n", __func__, name);
a3cca9e9
MD
790 return NULL;
791 }
792 }
b7e35bad
MD
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);
a3cca9e9 803 cds_list_for_each_entry(iter, declaration_list, siblings) {
e397791f
MD
804 ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter,
805 struct_declaration, trace);
a3cca9e9 806 if (ret)
5c551b40 807 goto error_free_declaration;
a3cca9e9
MD
808 }
809 if (name) {
810 ret = register_struct_declaration(g_quark_from_string(name),
811 struct_declaration,
812 declaration_scope);
813 assert(!ret);
814 }
a0720417 815 return &struct_declaration->p;
a3cca9e9 816 }
5c551b40 817error_free_declaration:
a3cca9e9 818 struct_declaration->p.declaration_free(&struct_declaration->p);
5c551b40 819error:
a3cca9e9
MD
820 return NULL;
821}
822
05628561 823static
a0720417
MD
824struct declaration *ctf_declaration_variant_visit(FILE *fd,
825 int depth, const char *name, const char *choice,
826 struct cds_list_head *declaration_list,
e397791f
MD
827 int has_body, struct declaration_scope *declaration_scope,
828 struct ctf_trace *trace)
05628561 829{
a0720417 830 struct declaration_untagged_variant *untagged_variant_declaration;
add40b62
MD
831 struct declaration_variant *variant_declaration;
832 struct ctf_node *iter;
a0720417 833 int ret;
de47353a 834
add40b62
MD
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);
a0720417 842 untagged_variant_declaration =
add40b62
MD
843 lookup_variant_declaration(g_quark_from_string(name),
844 declaration_scope);
add40b62 845 } else {
de47353a 846 /* For unnamed variant, create type */
add40b62
MD
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
78af2bcd 852 fprintf(fd, "[error] %s: variant %s already declared in scope\n", __func__, name);
add40b62
MD
853 return NULL;
854 }
855 }
a0720417 856 untagged_variant_declaration = untagged_variant_declaration_new(declaration_scope);
add40b62 857 cds_list_for_each_entry(iter, declaration_list, siblings) {
e397791f 858 ret = ctf_variant_declaration_list_visit(fd, depth + 1, iter,
a0720417 859 untagged_variant_declaration, trace);
add40b62
MD
860 if (ret)
861 goto error;
862 }
863 if (name) {
864 ret = register_variant_declaration(g_quark_from_string(name),
a0720417 865 untagged_variant_declaration,
add40b62
MD
866 declaration_scope);
867 assert(!ret);
868 }
a0720417
MD
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;
de47353a 882 }
add40b62 883error:
2dd46001 884 untagged_variant_declaration->p.declaration_free(&untagged_variant_declaration->p);
add40b62 885 return NULL;
05628561
MD
886}
887
05628561 888static
8fdba45b 889int ctf_enumerator_list_visit(FILE *fd, int depth,
add40b62
MD
890 struct ctf_node *enumerator,
891 struct declaration_enum *enum_declaration)
892{
1cfda062
MD
893 GQuark q;
894 struct ctf_node *iter;
895
896 q = g_quark_from_string(enumerator->u.enumerator.id);
a0720417 897 if (enum_declaration->integer_declaration->signedness) {
1cfda062
MD
898 int64_t start, end;
899 int nr_vals = 0;
900
a0720417 901 cds_list_for_each_entry(iter, &enumerator->u.enumerator.values, siblings) {
1cfda062
MD
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:
78af2bcd 918 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
1cfda062
MD
919 return -EINVAL;
920 }
921 if (nr_vals > 1) {
78af2bcd 922 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
1cfda062
MD
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);
a0720417 930 } else {
1cfda062
MD
931 uint64_t start, end;
932 int nr_vals = 0;
933
a0720417
MD
934 cds_list_for_each_entry(iter, &enumerator->u.enumerator.values, siblings) {
935 uint64_t *target;
1cfda062
MD
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 */
78af2bcd 952 fprintf(fd, "[error] %s: invalid enumerator (signed constant encountered, but enum container type is unsigned)\n", __func__);
1cfda062
MD
953 return -EINVAL;
954 default:
78af2bcd 955 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
1cfda062
MD
956 return -EINVAL;
957 }
958 if (nr_vals > 1) {
78af2bcd 959 fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
1cfda062
MD
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 }
add40b62
MD
968 return 0;
969}
970
971static
8fdba45b 972struct declaration *ctf_declaration_enum_visit(FILE *fd, int depth,
add40b62 973 const char *name,
78af2bcd 974 struct ctf_node *container_type,
add40b62 975 struct cds_list_head *enumerator_list,
1cfda062
MD
976 int has_body,
977 struct declaration_scope *declaration_scope,
978 struct ctf_trace *trace)
05628561 979{
add40b62
MD
980 struct declaration *declaration;
981 struct declaration_enum *enum_declaration;
982 struct declaration_integer *integer_declaration;
78af2bcd 983 struct ctf_node *iter;
1cfda062 984 GQuark dummy_id;
a0720417 985 int ret;
add40b62 986
05628561 987 /*
add40b62
MD
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.
05628561 991 */
add40b62
MD
992 if (!has_body) {
993 assert(name);
994 enum_declaration =
995 lookup_enum_declaration(g_quark_from_string(name),
996 declaration_scope);
a0720417 997 return &enum_declaration->p;
add40b62
MD
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
78af2bcd 1005 fprintf(fd, "[error] %s: enum %s already declared in scope\n", __func__, name);
add40b62
MD
1006 return NULL;
1007 }
1008 }
78af2bcd 1009 if (!container_type) {
6743829a
MD
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);
1cfda062 1022 }
30ea18a1
MD
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;
1cfda062 1030 }
30ea18a1 1031 integer_declaration = container_of(declaration, struct declaration_integer, p);
a0720417 1032 enum_declaration = enum_declaration_new(integer_declaration);
add40b62
MD
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 }
a0720417 1045 return &enum_declaration->p;
05628561 1046 }
add40b62
MD
1047error:
1048 enum_declaration->p.declaration_free(&enum_declaration->p);
1049 return NULL;
05628561
MD
1050}
1051
1052static
8fdba45b 1053struct declaration *ctf_declaration_type_specifier_visit(FILE *fd, int depth,
78af2bcd 1054 struct ctf_node *type_specifier_list,
d20f5e59 1055 struct declaration_scope *declaration_scope)
05628561 1056{
add40b62
MD
1057 GString *str;
1058 struct declaration *declaration;
a0720417
MD
1059 char *str_c;
1060 int ret;
1061 GQuark id_q;
05628561 1062
a0720417 1063 str = g_string_new("");
78af2bcd 1064 ret = visit_type_specifier_list(fd, type_specifier_list, str);
add40b62
MD
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
ab4cf058
MD
1074/*
1075 * Returns 0/1 boolean, or < 0 on error.
1076 */
1077static
a0720417 1078int get_boolean(FILE *fd, int depth, struct ctf_node *unary_expression)
ab4cf058
MD
1079{
1080 if (unary_expression->type != NODE_UNARY_EXPRESSION) {
78af2bcd 1081 fprintf(fd, "[error] %s: expecting unary expression\n",
ab4cf058
MD
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 {
78af2bcd 1106 fprintf(fd, "[error] %s: unexpected string \"%s\"\n",
ab4cf058
MD
1107 __func__, unary_expression->u.unary_expression.u.string);
1108 return -EINVAL;
1109 }
1110 break;
1111 default:
78af2bcd 1112 fprintf(fd, "[error] %s: unexpected unary expression type\n",
ab4cf058
MD
1113 __func__);
1114 return -EINVAL;
1115 }
1116
1117}
1118
0f980a35
MD
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
ab4cf058 1141static
a0720417
MD
1142int get_byte_order(FILE *fd, int depth, struct ctf_node *unary_expression,
1143 struct ctf_trace *trace)
ab4cf058
MD
1144{
1145 int byte_order;
1146
1147 if (unary_expression->u.unary_expression.type != UNARY_STRING) {
78af2bcd 1148 fprintf(fd, "[error] %s: byte_order: expecting string\n",
ab4cf058
MD
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 {
78af2bcd 1161 fprintf(fd, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n",
a0720417 1162 __func__, unary_expression->u.unary_expression.u.string);
ab4cf058
MD
1163 return -EINVAL;
1164 }
1165 return byte_order;
1166}
1167
add40b62 1168static
8fdba45b 1169struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
ab4cf058
MD
1170 struct cds_list_head *expressions,
1171 struct ctf_trace *trace)
add40b62 1172{
a0720417 1173 struct ctf_node *expression;
68262b11 1174 uint64_t alignment = 1, size = 0;
ab4cf058
MD
1175 int byte_order = trace->byte_order;
1176 int signedness = 0;
add40b62 1177 int has_alignment = 0, has_size = 0;
4d5fc303 1178 int base = 0;
81dee1bb 1179 enum ctf_string_encoding encoding = CTF_STRING_NONE;
56e60373 1180 struct ctf_clock *clock = NULL;
add40b62
MD
1181 struct declaration_integer *integer_declaration;
1182
1183 cds_list_for_each_entry(expression, expressions, siblings) {
a0720417 1184 struct ctf_node *left, *right;
add40b62 1185
a0720417
MD
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);
add40b62
MD
1188 assert(left->u.unary_expression.type == UNARY_STRING);
1189 if (!strcmp(left->u.unary_expression.u.string, "signed")) {
ab4cf058
MD
1190 signedness = get_boolean(fd, depth, right);
1191 if (signedness < 0)
1192 return NULL;
add40b62 1193 } else if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
a0720417 1194 byte_order = get_byte_order(fd, depth, right, trace);
ab4cf058
MD
1195 if (byte_order < 0)
1196 return NULL;
add40b62 1197 } else if (!strcmp(left->u.unary_expression.u.string, "size")) {
ab4cf058 1198 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
78af2bcd 1199 fprintf(fd, "[error] %s: size: expecting unsigned constant\n",
ab4cf058
MD
1200 __func__);
1201 return NULL;
1202 }
1203 size = right->u.unary_expression.u.unsigned_constant;
add40b62
MD
1204 has_size = 1;
1205 } else if (!strcmp(left->u.unary_expression.u.string, "align")) {
ab4cf058 1206 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
78af2bcd 1207 fprintf(fd, "[error] %s: align: expecting unsigned constant\n",
ab4cf058
MD
1208 __func__);
1209 return NULL;
1210 }
1211 alignment = right->u.unary_expression.u.unsigned_constant;
53532829
MD
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 }
add40b62 1218 has_alignment = 1;
164078da
MD
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 }
81dee1bb
MD
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;
b5bf4179
MD
1291 else if (!strcmp(s_right, "none"))
1292 encoding = CTF_STRING_NONE;
81dee1bb
MD
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);
73d15916 1299 } else if (!strcmp(left->u.unary_expression.u.string, "map")) {
56e60373 1300 GQuark clock_name;
73d15916
MD
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 }
56e60373
MD
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);
73d15916 1320 g_free(s_right);
56e60373
MD
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));
73d15916
MD
1327 return NULL;
1328 }
add40b62 1329 } else {
b3ab6665 1330 fprintf(fd, "[warning] %s: unknown attribute name %s\n",
add40b62 1331 __func__, left->u.unary_expression.u.string);
b3ab6665 1332 /* Fall-through after warning */
add40b62 1333 }
05628561 1334 }
add40b62 1335 if (!has_size) {
78af2bcd 1336 fprintf(fd, "[error] %s: missing size attribute\n", __func__);
add40b62
MD
1337 return NULL;
1338 }
ab4cf058
MD
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 }
add40b62 1348 integer_declaration = integer_declaration_new(size,
81dee1bb 1349 byte_order, signedness, alignment,
56e60373 1350 base, encoding, clock);
add40b62 1351 return &integer_declaration->p;
05628561
MD
1352}
1353
ab4cf058 1354static
8fdba45b 1355struct declaration *ctf_declaration_floating_point_visit(FILE *fd, int depth,
ab4cf058
MD
1356 struct cds_list_head *expressions,
1357 struct ctf_trace *trace)
1358{
a0720417 1359 struct ctf_node *expression;
5c551b40
MD
1360 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0,
1361 byte_order = trace->byte_order;
ab4cf058
MD
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) {
a0720417 1366 struct ctf_node *left, *right;
ab4cf058 1367
a0720417
MD
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);
ab4cf058
MD
1370 assert(left->u.unary_expression.type == UNARY_STRING);
1371 if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
a0720417 1372 byte_order = get_byte_order(fd, depth, right, trace);
ab4cf058
MD
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) {
78af2bcd 1377 fprintf(fd, "[error] %s: exp_dig: expecting unsigned constant\n",
ab4cf058
MD
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) {
78af2bcd 1385 fprintf(fd, "[error] %s: mant_dig: expecting unsigned constant\n",
ab4cf058
MD
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) {
78af2bcd 1393 fprintf(fd, "[error] %s: align: expecting unsigned constant\n",
ab4cf058
MD
1394 __func__);
1395 return NULL;
1396 }
1397 alignment = right->u.unary_expression.u.unsigned_constant;
53532829
MD
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 }
ab4cf058
MD
1404 has_alignment = 1;
1405 } else {
b3ab6665 1406 fprintf(fd, "[warning] %s: unknown attribute name %s\n",
ab4cf058 1407 __func__, left->u.unary_expression.u.string);
b3ab6665 1408 /* Fall-through after warning */
ab4cf058
MD
1409 }
1410 }
1411 if (!has_mant_dig) {
78af2bcd 1412 fprintf(fd, "[error] %s: missing mant_dig attribute\n", __func__);
ab4cf058
MD
1413 return NULL;
1414 }
1415 if (!has_exp_dig) {
78af2bcd 1416 fprintf(fd, "[error] %s: missing exp_dig attribute\n", __func__);
ab4cf058
MD
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
8fdba45b 1434struct declaration *ctf_declaration_string_visit(FILE *fd, int depth,
ab4cf058
MD
1435 struct cds_list_head *expressions,
1436 struct ctf_trace *trace)
1437{
a0720417 1438 struct ctf_node *expression;
ab4cf058
MD
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) {
a0720417 1444 struct ctf_node *left, *right;
ab4cf058 1445
a0720417
MD
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);
ab4cf058
MD
1448 assert(left->u.unary_expression.type == UNARY_STRING);
1449 if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
a0720417 1450 if (right->u.unary_expression.type != UNARY_STRING) {
78af2bcd 1451 fprintf(fd, "[error] %s: encoding: expecting string\n",
ab4cf058
MD
1452 __func__);
1453 return NULL;
1454 }
1455 encoding_c = right->u.unary_expression.u.string;
1456 } else {
b3ab6665 1457 fprintf(fd, "[warning] %s: unknown attribute name %s\n",
ab4cf058 1458 __func__, left->u.unary_expression.u.string);
b3ab6665 1459 /* Fall-through after warning */
ab4cf058
MD
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
05628561 1469static
78af2bcd
MD
1470struct declaration *ctf_type_specifier_list_visit(FILE *fd,
1471 int depth, struct ctf_node *type_specifier_list,
ab4cf058
MD
1472 struct declaration_scope *declaration_scope,
1473 struct ctf_trace *trace)
05628561 1474{
a0720417 1475 struct ctf_node *first;
78af2bcd 1476 struct ctf_node *node;
d20f5e59 1477
427c09b7
MD
1478 assert(type_specifier_list->type == NODE_TYPE_SPECIFIER_LIST);
1479
78af2bcd 1480 first = _cds_list_first_entry(&type_specifier_list->u.type_specifier_list.head, struct ctf_node, siblings);
05628561 1481
78af2bcd
MD
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,
5039b4cc 1495 &node->u.string.expressions, trace);
78af2bcd 1496 case TYPESPEC_STRUCT:
add40b62 1497 return ctf_declaration_struct_visit(fd, depth,
78af2bcd
MD
1498 node->u._struct.name,
1499 &node->u._struct.declaration_list,
1500 node->u._struct.has_body,
b7e35bad 1501 &node->u._struct.min_align,
ab4cf058
MD
1502 declaration_scope,
1503 trace);
78af2bcd 1504 case TYPESPEC_VARIANT:
add40b62 1505 return ctf_declaration_variant_visit(fd, depth,
78af2bcd
MD
1506 node->u.variant.name,
1507 node->u.variant.choice,
1508 &node->u.variant.declaration_list,
1509 node->u.variant.has_body,
ab4cf058
MD
1510 declaration_scope,
1511 trace);
78af2bcd 1512 case TYPESPEC_ENUM:
add40b62 1513 return ctf_declaration_enum_visit(fd, depth,
78af2bcd
MD
1514 node->u._enum.enum_id,
1515 node->u._enum.container_type,
1516 &node->u._enum.enumerator_list,
1517 node->u._enum.has_body,
1cfda062 1518 declaration_scope,
ab4cf058 1519 trace);
78af2bcd
MD
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:
add40b62 1535 return ctf_declaration_type_specifier_visit(fd, depth,
78af2bcd 1536 type_specifier_list, declaration_scope);
a0720417 1537 default:
78af2bcd 1538 fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) first->u.type_specifier.type);
a0720417 1539 return NULL;
add40b62 1540 }
05628561
MD
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,
a0720417 1551 event->declaration_scope,
78af2bcd 1552 node->u._typedef.type_specifier_list,
05628561 1553 &node->u._typedef.type_declarators,
a0720417 1554 trace);
05628561
MD
1555 if (ret)
1556 return ret;
1557 break;
1558 case NODE_TYPEALIAS:
1559 ret = ctf_typealias_visit(fd, depth + 1,
a0720417
MD
1560 event->declaration_scope,
1561 node->u.typealias.target, node->u.typealias.alias,
1562 trace);
05628561
MD
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
427c09b7
MD
1574 if (CTF_EVENT_FIELD_IS_SET(event, name)) {
1575 fprintf(fd, "[error] %s: name already declared in event declaration\n", __func__);
0f980a35
MD
1576 ret = -EPERM;
1577 goto error;
427c09b7 1578 }
05628561
MD
1579 right = concatenate_unary_strings(&node->u.ctf_expression.right);
1580 if (!right) {
78af2bcd 1581 fprintf(fd, "[error] %s: unexpected unary expression for event name\n", __func__);
0f980a35
MD
1582 ret = -EINVAL;
1583 goto error;
05628561
MD
1584 }
1585 event->name = g_quark_from_string(right);
41253107 1586 g_free(right);
05628561
MD
1587 CTF_EVENT_SET_FIELD(event, name);
1588 } else if (!strcmp(left, "id")) {
427c09b7
MD
1589 if (CTF_EVENT_FIELD_IS_SET(event, id)) {
1590 fprintf(fd, "[error] %s: id already declared in event declaration\n", __func__);
0f980a35
MD
1591 ret = -EPERM;
1592 goto error;
427c09b7 1593 }
05628561
MD
1594 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->id);
1595 if (ret) {
78af2bcd 1596 fprintf(fd, "[error] %s: unexpected unary expression for event id\n", __func__);
0f980a35
MD
1597 ret = -EINVAL;
1598 goto error;
05628561
MD
1599 }
1600 CTF_EVENT_SET_FIELD(event, id);
1601 } else if (!strcmp(left, "stream_id")) {
427c09b7
MD
1602 if (CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
1603 fprintf(fd, "[error] %s: stream_id already declared in event declaration\n", __func__);
0f980a35
MD
1604 ret = -EPERM;
1605 goto error;
427c09b7 1606 }
05628561
MD
1607 ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id);
1608 if (ret) {
78af2bcd 1609 fprintf(fd, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
0f980a35
MD
1610 ret = -EINVAL;
1611 goto error;
05628561
MD
1612 }
1613 event->stream = trace_stream_lookup(trace, event->stream_id);
1614 if (!event->stream) {
78af2bcd 1615 fprintf(fd, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id);
0f980a35
MD
1616 ret = -EINVAL;
1617 goto error;
05628561 1618 }
05628561
MD
1619 CTF_EVENT_SET_FIELD(event, stream_id);
1620 } else if (!strcmp(left, "context")) {
1621 struct declaration *declaration;
1622
427c09b7
MD
1623 if (event->context_decl) {
1624 fprintf(fd, "[error] %s: context already declared in event declaration\n", __func__);
0f980a35
MD
1625 ret = -EINVAL;
1626 goto error;
427c09b7 1627 }
78af2bcd
MD
1628 declaration = ctf_type_specifier_list_visit(fd, depth,
1629 _cds_list_first_entry(&node->u.ctf_expression.right,
1630 struct ctf_node, siblings),
ab4cf058 1631 event->declaration_scope, trace);
0f980a35
MD
1632 if (!declaration) {
1633 ret = -EPERM;
1634 goto error;
1635 }
1636 if (declaration->id != CTF_TYPE_STRUCT) {
1637 ret = -EPERM;
1638 goto error;
1639 }
9e29e16e 1640 event->context_decl = container_of(declaration, struct declaration_struct, p);
05628561
MD
1641 } else if (!strcmp(left, "fields")) {
1642 struct declaration *declaration;
1643
427c09b7
MD
1644 if (event->fields_decl) {
1645 fprintf(fd, "[error] %s: fields already declared in event declaration\n", __func__);
0f980a35
MD
1646 ret = -EINVAL;
1647 goto error;
427c09b7 1648 }
78af2bcd
MD
1649 declaration = ctf_type_specifier_list_visit(fd, depth,
1650 _cds_list_first_entry(&node->u.ctf_expression.right,
1651 struct ctf_node, siblings),
ab4cf058 1652 event->declaration_scope, trace);
0f980a35
MD
1653 if (!declaration) {
1654 ret = -EPERM;
1655 goto error;
1656 }
1657 if (declaration->id != CTF_TYPE_STRUCT) {
1658 ret = -EPERM;
1659 goto error;
1660 }
9e29e16e 1661 event->fields_decl = container_of(declaration, struct declaration_struct, p);
306eeaa6
MD
1662 } else if (!strcmp(left, "loglevel")) {
1663 int64_t loglevel = -1;
d86d62f8 1664
306eeaa6
MD
1665 if (CTF_EVENT_FIELD_IS_SET(event, loglevel)) {
1666 fprintf(fd, "[error] %s: loglevel already declared in event declaration\n", __func__);
d86d62f8
MD
1667 ret = -EPERM;
1668 goto error;
1669 }
306eeaa6 1670 ret = get_unary_signed(&node->u.ctf_expression.right, &loglevel);
d86d62f8 1671 if (ret) {
306eeaa6 1672 fprintf(fd, "[error] %s: unexpected unary expression for event loglevel\n", __func__);
d86d62f8
MD
1673 ret = -EINVAL;
1674 goto error;
1675 }
209209be 1676 event->loglevel = (int) loglevel;
306eeaa6 1677 CTF_EVENT_SET_FIELD(event, loglevel);
98df1c9f 1678 } else {
b3ab6665
MD
1679 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
1680 /* Fall-through after warning */
05628561 1681 }
0f980a35 1682error:
41253107 1683 g_free(left);
05628561
MD
1684 break;
1685 }
1686 default:
1687 return -EPERM;
1688 /* TODO: declaration specifier should be added. */
1689 }
1690
0f980a35 1691 return ret;
05628561
MD
1692}
1693
1694static
1695int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
d20f5e59 1696 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
05628561
MD
1697{
1698 int ret = 0;
1699 struct ctf_node *iter;
1700 struct ctf_event *event;
1701
1702 event = g_new0(struct ctf_event, 1);
d20f5e59 1703 event->declaration_scope = new_declaration_scope(parent_declaration_scope);
306eeaa6 1704 event->loglevel = -1;
05628561
MD
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;
427c09b7 1712 fprintf(fd, "[error] %s: missing name field in event declaration\n", __func__);
05628561
MD
1713 goto error;
1714 }
05628561 1715 if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
0f980a35 1716 /* Allow missing stream_id if there is only a single stream */
33105c61
MD
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:
0f980a35
MD
1724 event->stream_id = 0;
1725 event->stream = trace_stream_lookup(trace, event->stream_id);
33105c61
MD
1726 break;
1727 default:
0f980a35
MD
1728 ret = -EPERM;
1729 fprintf(fd, "[error] %s: missing stream_id field in event declaration\n", __func__);
1730 goto error;
1731 }
05628561 1732 }
8c572eba
MD
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 }
05628561
MD
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,
56e60373 1744 (gpointer) (unsigned long) event->name,
05628561
MD
1745 &event->id);
1746 return 0;
1747
1748error:
98df1c9f
MD
1749 if (event->fields_decl)
1750 declaration_unref(&event->fields_decl->p);
1751 if (event->context_decl)
1752 declaration_unref(&event->context_decl->p);
d20f5e59 1753 free_declaration_scope(event->declaration_scope);
05628561
MD
1754 g_free(event);
1755 return ret;
1756}
1757
1758
1759static
aa6bffae 1760int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream_class *stream, struct ctf_trace *trace)
05628561
MD
1761{
1762 int ret = 0;
1763
1764 switch (node->type) {
1765 case NODE_TYPEDEF:
1766 ret = ctf_typedef_visit(fd, depth + 1,
a0720417 1767 stream->declaration_scope,
78af2bcd 1768 node->u._typedef.type_specifier_list,
05628561 1769 &node->u._typedef.type_declarators,
a0720417 1770 trace);
05628561
MD
1771 if (ret)
1772 return ret;
1773 break;
1774 case NODE_TYPEALIAS:
1775 ret = ctf_typealias_visit(fd, depth + 1,
a0720417
MD
1776 stream->declaration_scope,
1777 node->u.typealias.target, node->u.typealias.alias,
1778 trace);
05628561
MD
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);
427c09b7
MD
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__);
0f980a35
MD
1790 ret = -EPERM;
1791 goto error;
427c09b7 1792 }
a0720417 1793 ret = get_unary_unsigned(&node->u.ctf_expression.right, &stream->stream_id);
05628561 1794 if (ret) {
427c09b7 1795 fprintf(fd, "[error] %s: unexpected unary expression for stream id\n", __func__);
0f980a35
MD
1796 ret = -EINVAL;
1797 goto error;
05628561 1798 }
a0720417 1799 CTF_STREAM_SET_FIELD(stream, stream_id);
9e29e16e 1800 } else if (!strcmp(left, "event.header")) {
05628561
MD
1801 struct declaration *declaration;
1802
427c09b7
MD
1803 if (stream->event_header_decl) {
1804 fprintf(fd, "[error] %s: event.header already declared in stream declaration\n", __func__);
0f980a35
MD
1805 ret = -EINVAL;
1806 goto error;
427c09b7 1807 }
78af2bcd
MD
1808 declaration = ctf_type_specifier_list_visit(fd, depth,
1809 _cds_list_first_entry(&node->u.ctf_expression.right,
1810 struct ctf_node, siblings),
a0720417 1811 stream->declaration_scope, trace);
0f980a35
MD
1812 if (!declaration) {
1813 ret = -EPERM;
1814 goto error;
1815 }
1816 if (declaration->id != CTF_TYPE_STRUCT) {
1817 ret = -EPERM;
1818 goto error;
1819 }
9e29e16e
MD
1820 stream->event_header_decl = container_of(declaration, struct declaration_struct, p);
1821 } else if (!strcmp(left, "event.context")) {
05628561
MD
1822 struct declaration *declaration;
1823
427c09b7
MD
1824 if (stream->event_context_decl) {
1825 fprintf(fd, "[error] %s: event.context already declared in stream declaration\n", __func__);
0f980a35
MD
1826 ret = -EINVAL;
1827 goto error;
427c09b7 1828 }
78af2bcd
MD
1829 declaration = ctf_type_specifier_list_visit(fd, depth,
1830 _cds_list_first_entry(&node->u.ctf_expression.right,
1831 struct ctf_node, siblings),
ab4cf058 1832 stream->declaration_scope, trace);
0f980a35
MD
1833 if (!declaration) {
1834 ret = -EPERM;
1835 goto error;
1836 }
1837 if (declaration->id != CTF_TYPE_STRUCT) {
1838 ret = -EPERM;
1839 goto error;
1840 }
9e29e16e
MD
1841 stream->event_context_decl = container_of(declaration, struct declaration_struct, p);
1842 } else if (!strcmp(left, "packet.context")) {
05628561
MD
1843 struct declaration *declaration;
1844
427c09b7
MD
1845 if (stream->packet_context_decl) {
1846 fprintf(fd, "[error] %s: packet.context already declared in stream declaration\n", __func__);
0f980a35
MD
1847 ret = -EINVAL;
1848 goto error;
427c09b7 1849 }
78af2bcd
MD
1850 declaration = ctf_type_specifier_list_visit(fd, depth,
1851 _cds_list_first_entry(&node->u.ctf_expression.right,
1852 struct ctf_node, siblings),
ab4cf058 1853 stream->declaration_scope, trace);
0f980a35
MD
1854 if (!declaration) {
1855 ret = -EPERM;
1856 goto error;
1857 }
1858 if (declaration->id != CTF_TYPE_STRUCT) {
1859 ret = -EPERM;
1860 goto error;
1861 }
9e29e16e 1862 stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
98df1c9f 1863 } else {
b3ab6665
MD
1864 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left);
1865 /* Fall-through after warning */
05628561 1866 }
98df1c9f 1867
0f980a35 1868error:
41253107 1869 g_free(left);
05628561
MD
1870 break;
1871 }
1872 default:
1873 return -EPERM;
1874 /* TODO: declaration specifier should be added. */
1875 }
1876
0f980a35 1877 return ret;
05628561
MD
1878}
1879
1880static
1881int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
d20f5e59 1882 struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace)
05628561
MD
1883{
1884 int ret = 0;
1885 struct ctf_node *iter;
aa6bffae 1886 struct ctf_stream_class *stream;
05628561 1887
aa6bffae 1888 stream = g_new0(struct ctf_stream_class, 1);
d20f5e59 1889 stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
05628561 1890 stream->events_by_id = g_ptr_array_new();
068665f5 1891 stream->event_quark_to_id = g_hash_table_new(g_direct_hash, g_direct_equal);
2d0bea29 1892 stream->streams = g_ptr_array_new();
33105c61
MD
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 }
05628561 1899 }
0f980a35
MD
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 }
8c572eba
MD
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;
05628561
MD
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;
82662ad4 1920 stream->trace = trace;
9e29e16e 1921
05628561
MD
1922 return 0;
1923
1924error:
98df1c9f
MD
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);
2d0bea29 1931 g_ptr_array_free(stream->streams, TRUE);
05628561 1932 g_ptr_array_free(stream->events_by_id, TRUE);
a0720417 1933 g_hash_table_destroy(stream->event_quark_to_id);
d20f5e59 1934 free_declaration_scope(stream->declaration_scope);
05628561
MD
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,
a0720417 1947 trace->declaration_scope,
78af2bcd 1948 node->u._typedef.type_specifier_list,
05628561 1949 &node->u._typedef.type_declarators,
a0720417 1950 trace);
05628561
MD
1951 if (ret)
1952 return ret;
1953 break;
1954 case NODE_TYPEALIAS:
1955 ret = ctf_typealias_visit(fd, depth + 1,
a0720417
MD
1956 trace->declaration_scope,
1957 node->u.typealias.target, node->u.typealias.alias,
1958 trace);
05628561
MD
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")) {
427c09b7
MD
1968 if (CTF_TRACE_FIELD_IS_SET(trace, major)) {
1969 fprintf(fd, "[error] %s: major already declared in trace declaration\n", __func__);
0f980a35
MD
1970 ret = -EPERM;
1971 goto error;
427c09b7 1972 }
05628561
MD
1973 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->major);
1974 if (ret) {
78af2bcd 1975 fprintf(fd, "[error] %s: unexpected unary expression for trace major number\n", __func__);
0f980a35
MD
1976 ret = -EINVAL;
1977 goto error;
05628561 1978 }
a0720417 1979 CTF_TRACE_SET_FIELD(trace, major);
05628561 1980 } else if (!strcmp(left, "minor")) {
427c09b7
MD
1981 if (CTF_TRACE_FIELD_IS_SET(trace, minor)) {
1982 fprintf(fd, "[error] %s: minor already declared in trace declaration\n", __func__);
0f980a35
MD
1983 ret = -EPERM;
1984 goto error;
427c09b7 1985 }
05628561
MD
1986 ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->minor);
1987 if (ret) {
78af2bcd 1988 fprintf(fd, "[error] %s: unexpected unary expression for trace minor number\n", __func__);
0f980a35
MD
1989 ret = -EINVAL;
1990 goto error;
05628561 1991 }
a0720417 1992 CTF_TRACE_SET_FIELD(trace, minor);
05628561 1993 } else if (!strcmp(left, "uuid")) {
b4c19c1e 1994 uuid_t uuid;
a0fe7d97
MD
1995
1996 ret = get_unary_uuid(&node->u.ctf_expression.right, &uuid);
05628561 1997 if (ret) {
78af2bcd 1998 fprintf(fd, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
0f980a35
MD
1999 ret = -EINVAL;
2000 goto error;
05628561 2001 }
b4c19c1e
MD
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;
a0fe7d97
MD
2007 } else {
2008 memcpy(trace->uuid, uuid, sizeof(uuid));
b4c19c1e 2009 }
a0720417 2010 CTF_TRACE_SET_FIELD(trace, uuid);
0f980a35
MD
2011 } else if (!strcmp(left, "byte_order")) {
2012 struct ctf_node *right;
2013 int byte_order;
2014
0f980a35
MD
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;
a0fe7d97
MD
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 {
fdce39de
MD
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 */
2e0c6b58
MD
2033 trace->field_mask = 0;
2034 CTF_TRACE_SET_FIELD(trace, byte_order);
2035 ret = -EINTR;
2036 goto error;
fdce39de 2037 }
a0fe7d97 2038 }
7c8a1386 2039 CTF_TRACE_SET_FIELD(trace, byte_order);
0f980a35
MD
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);
98df1c9f 2061 } else {
b3ab6665 2062 fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left);
05628561 2063 }
98df1c9f 2064
0f980a35 2065error:
41253107 2066 g_free(left);
05628561
MD
2067 break;
2068 }
2069 default:
2070 return -EPERM;
2071 /* TODO: declaration specifier should be added. */
2072 }
2073
0f980a35 2074 return ret;
05628561
MD
2075}
2076
05628561
MD
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
d20f5e59 2083 if (trace->declaration_scope)
05628561 2084 return -EEXIST;
d20f5e59 2085 trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope);
05628561
MD
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 }
a0720417 2092 if (!CTF_TRACE_FIELD_IS_SET(trace, major)) {
05628561 2093 ret = -EPERM;
427c09b7 2094 fprintf(fd, "[error] %s: missing major field in trace declaration\n", __func__);
05628561
MD
2095 goto error;
2096 }
a0720417 2097 if (!CTF_TRACE_FIELD_IS_SET(trace, minor)) {
05628561 2098 ret = -EPERM;
427c09b7 2099 fprintf(fd, "[error] %s: missing minor field in trace declaration\n", __func__);
05628561
MD
2100 goto error;
2101 }
a0720417 2102 if (!CTF_TRACE_FIELD_IS_SET(trace, uuid)) {
05628561 2103 ret = -EPERM;
427c09b7 2104 fprintf(fd, "[error] %s: missing uuid field in trace declaration\n", __func__);
05628561
MD
2105 goto error;
2106 }
dc48ecad
MD
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 }
0f980a35 2112
0f980a35
MD
2113 if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
2114 /* check that the packet header contains a "magic" field */
e28d4618 2115 if (!trace->packet_header_decl
0f980a35
MD
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__);
98df1c9f 2119 goto error;
0f980a35
MD
2120 }
2121 }
05628561
MD
2122 return 0;
2123
2124error:
0d72513f 2125 if (trace->packet_header_decl) {
98df1c9f 2126 declaration_unref(&trace->packet_header_decl->p);
0d72513f
MD
2127 trace->packet_header_decl = NULL;
2128 }
05628561 2129 g_ptr_array_free(trace->streams, TRUE);
a0720417 2130 free_declaration_scope(trace->declaration_scope);
fdce39de 2131 trace->declaration_scope = NULL;
05628561
MD
2132 return ret;
2133}
2134
50cb9c56
MD
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 }
11ac6674
MD
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;
50cb9c56
MD
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
cadd09e9
MD
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;
6070d2f1 2330 printf_verbose("env.vpid = %d\n", env->vpid);
cadd09e9
MD
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';
6070d2f1 2345 printf_verbose("env.procname = %s\n", env->procname);
cadd09e9
MD
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';
6070d2f1 2360 printf_verbose("env.domain = %s\n", env->domain);
cadd09e9
MD
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';
6070d2f1 2375 printf_verbose("env.sysname = %s\n", env->sysname);
cadd09e9
MD
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';
6070d2f1 2390 printf_verbose("env.release = %s\n", env->release);
cadd09e9
MD
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';
6070d2f1 2405 printf_verbose("env.version = %s\n", env->version);
cadd09e9
MD
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
e2c76a4d
MD
2421static
2422int ctf_env_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
2423{
cadd09e9
MD
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;
e2c76a4d
MD
2440}
2441
78af2bcd
MD
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
50cb9c56 2487/* TODO: missing metadata "destroy" (memory leak) */
ab4cf058
MD
2488int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
2489 struct ctf_trace *trace, int byte_order)
05628561
MD
2490{
2491 int ret = 0;
2492 struct ctf_node *iter;
e2c76a4d 2493 int env_clock_done = 0;
05628561 2494
c8b219a3 2495 printf_verbose("CTF visitor: metadata construction... ");
ab4cf058 2496 trace->byte_order = byte_order;
50cb9c56
MD
2497 trace->clocks = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2498 NULL, clock_free);
ab4cf058 2499
00f7c1a5
MD
2500retry:
2501 trace->root_declaration_scope = new_declaration_scope(NULL);
2502
05628561
MD
2503 switch (node->type) {
2504 case NODE_ROOT:
e2c76a4d 2505 if (!env_clock_done) {
56e60373
MD
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 }
e2c76a4d 2518 env_clock_done = 1;
56e60373 2519 }
3e11b713 2520 cds_list_for_each_entry(iter, &node->u.root.declaration_list,
05628561 2521 siblings) {
78af2bcd 2522 ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace);
427c09b7
MD
2523 if (ret) {
2524 fprintf(fd, "[error] %s: root declaration error\n", __func__);
a0fe7d97 2525 goto error;
427c09b7 2526 }
05628561
MD
2527 }
2528 cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
2529 ret = ctf_trace_visit(fd, depth + 1, iter, trace);
00f7c1a5
MD
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 }
427c09b7
MD
2539 if (ret) {
2540 fprintf(fd, "[error] %s: trace declaration error\n", __func__);
a0fe7d97 2541 goto error;
427c09b7 2542 }
05628561 2543 }
5039b4cc
MD
2544 if (!trace->streams) {
2545 fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
a0fe7d97
MD
2546 ret = -EINVAL;
2547 goto error;
5039b4cc 2548 }
cadd09e9
MD
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 }
05628561
MD
2556 cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
2557 ret = ctf_stream_visit(fd, depth + 1, iter,
41253107 2558 trace->root_declaration_scope, trace);
427c09b7
MD
2559 if (ret) {
2560 fprintf(fd, "[error] %s: stream declaration error\n", __func__);
a0fe7d97 2561 goto error;
427c09b7 2562 }
05628561
MD
2563 }
2564 cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
2565 ret = ctf_event_visit(fd, depth + 1, iter,
41253107 2566 trace->root_declaration_scope, trace);
427c09b7
MD
2567 if (ret) {
2568 fprintf(fd, "[error] %s: event declaration error\n", __func__);
a0fe7d97 2569 goto error;
427c09b7 2570 }
05628561
MD
2571 }
2572 break;
05628561
MD
2573 case NODE_UNKNOWN:
2574 default:
78af2bcd 2575 fprintf(fd, "[error] %s: unknown node type %d\n", __func__,
05628561 2576 (int) node->type);
a0fe7d97
MD
2577 ret = -EINVAL;
2578 goto error;
05628561 2579 }
c8b219a3 2580 printf_verbose("done.\n");
05628561 2581 return ret;
a0fe7d97
MD
2582
2583error:
2584 free_declaration_scope(trace->root_declaration_scope);
50cb9c56 2585 g_hash_table_destroy(trace->clocks);
a0fe7d97 2586 return ret;
05628561 2587}
This page took 0.274347 seconds and 4 git commands to generate.